Design System
A personal developer site built as a cork board sprint tracker, book highlights catalog, reading journal, and reading year dashboard. The entire UI is a skeuomorphic metaphor: sticky notes pinned to cork, book spines on wooden shelves, handwritten journals on ruled paper, and thermal receipts.
Stack: Astro 5, vanilla CSS (no framework), Google Fonts, zero JS dependencies
1. Design Tokens
All CSS custom properties are defined in :root inside Layout.astro.
Colors
| Token | Value | Usage |
|---|---|---|
--cork | #8B6914 | Primary background. Body fill, modal-board bg, shelf-trigger tint. The cork board itself. |
--cork-dark | #7A5C0F | Used in body gradient (radial-gradient at 80% 70%, linear-gradient endpoint). Adds depth to cork texture. |
--cork-light | #9B7A20 | Used in body gradient (radial-gradient at 20% 30%, linear-gradient midpoint). Creates the warm highlight on cork. |
--navy | #1a1a2e | Banner background, stat cards, journal text color. The “pinned paper” contrast color. |
--gold | #F0B847 | Accent everywhere: banner text, stat values, gold highlights, ribbon progress, spine tooltips, receipt stars. The connective thread across all palettes. |
Font Stacks
| Token | Value | Role |
|---|---|---|
--font-marker | 'Permanent Marker', cursive | Headlines, titles, stamps. The “written in Sharpie” voice. |
--font-bubble | 'Fredoka', 'Varela Round', sans-serif | Column headers, stat cards, footer, stamps. Friendly, rounded, structural. |
--font-hand | 'Kalam', cursive | Body text on stickies, journal entries, subtitles, loading states. The “handwritten on a Post-it” voice. Default body font. |
--font-print | 'Patrick Hand', cursive | Tags, metadata, spine labels, book list, small print. Neater than Kalam but still hand-drawn. |
2. Typography
Permanent Marker
- Where:
.banner,.qotd-label,.catalog-title,.reading-title,.modal-title,.journal-book-title,.rs-card strong,.wall-count,.bar-val,.toc-toggle-btn,.banner-404,.footer-404 - Why: The “Sharpie on cardboard” typeface. Used for anything that would be written in bold marker on a real cork board — section titles, modal headers, the sprint banner. Creates immediate visual hierarchy.
- Weights used: 400 (only weight available)
Fredoka
- Where:
.stat-card,.column-header,.stamp,.footer,.find-me-header - Why: Rounded, bubbly sans-serif. Used for structural/informational elements — stat cards, column headers, status stamps. It reads as “typed on a label maker” rather than handwritten. Provides contrast against the hand-drawn fonts.
- Weights used: 400, 500, 600
Kalam
- Where:
bodydefault,.sticky(all note body text),.qotd-text,.qotd-loading,.journal-book-author,.je-text,.je-date,.st-title,.st-teaser,.catalog-subtitle,.reading-subtitle,.reading-scribble,.reading-loading,.chart-label,.reading-wall-label,.div-label,.div-note,.bl-genre,.rt-meta,.rt-body,.top-meta,.rs-card span - Why: The primary handwriting font. Natural, slightly irregular letterforms that sell the “scribbled on a sticky note” feeling. Used for all conversational, body-level text.
- Weights used: 300, 400, 700
Patrick Hand
- Where:
.sticky-tag,.qotd-book,.qotd-author,.qotd-date,.spine-label,.journal-pg,.toc-item,.je-number,.bar-label,.wall-label,.div-bar span,.bl-search,.bl-title,.bl-badge,.bl-stars(via parent),.rt-title,.top-title,.st-author,.st-count - Why: Neater, more uniform handwriting. Used for metadata, labels, and small informational text — anything that would be “printed carefully” rather than scrawled. The precision counterpart to Kalam.
- Weights used: 400 (only weight available)
3. Color Palettes
Cork Board Palette (Main Page)
The base page is a realistic cork board. Colors are warm, earthy, and sunlit.
| Color | Hex | Context |
|---|---|---|
| Cork base | #8B6914 | Body background |
| Cork dark | #7A5C0F | Gradient shadow regions |
| Cork light | #9B7A20 | Gradient highlight regions |
| Navy | #1a1a2e | Banner, stat cards |
| Gold | #F0B847 | Accent text, borders, highlights |
| White (subdued) | rgba(255,255,255,0.5) | Footer text |
Sticky note colors (all use 135deg linear gradients, light-to-saturated):
| Class | Start | End | Visual |
|---|---|---|---|
.y | #FFF9A3 | #FFEF70 | Yellow |
.g | #B8F5C8 | #7EE8A2 | Green |
.p | #E8B4F8 | #D280F0 | Purple |
.b | #B4D4FF | #7EB8F7 | Blue |
.o | #FFD4A3 | #FFBB70 | Orange |
.r | #FFB4B4 | #FF8080 | Red/Pink |
.w | #ffffff | #f0f0f0 | White |
.teal | #B4F5EF | #70E8DE | Teal |
Catalog Modal Palette (Bookshelf)
Warmer, more saturated. Dark wood interior with amber/mahogany tones.
| Element | Color | Notes |
|---|---|---|
| Board background | #3d2510 to #1f0e05 | Top-to-bottom gradient. Dark walnut. |
| Bookcase interior | #1e0e04 to #130804 | Even darker. The recess behind books. |
| Frame border | #C4782A | 3px solid. Warm brass/copper. |
| Shelf plank | #8B4A1F to #3d1a04 | 5-stop gradient. Realistic wood grain. |
| Plank highlight | #C47830 | Top border. The light catch on the shelf edge. |
| Title text | #F0B847 | Gold, with amber glow text-shadow. |
| Subtitle text | rgba(255,255,255,0.35) | Ghostly, recessive. |
| Scrollbar | #6b3a18 on #0f0a05 | Matches wood tones. |
Spine colors (tiered by annotation count):
| Count | Background | Text | Name |
|---|---|---|---|
| 0 | #f0ece0 | #bbb6a8 | Ghost/cream |
| 1-2 | #e8d5b5 | #8a7a62 | Ivory |
| 3-10 | #c4956a | #fff8ef | Warm tan |
| 11-25 | #a0522d | #ffe8d0 | Sienna |
| 26-60 | #7a3020 | #ffd4b8 | Deep rust |
| 61+ | #4a1a1a | #f0c090 | Near-black mahogany |
Books with 26+ annotations get .spine-gold — a diagonal gold shimmer overlay (rgba(240,184,71,0.22) at center).
Reading Year Modal Palette (Dashboard)
Cooler and darker than the catalog. Deep espresso/charcoal interior.
| Element | Color | Notes |
|---|---|---|
| Board background | #2d1f14 to #1a0f08 | Darker than catalog. More charcoal than walnut. |
| Content area | #180e06 to #120906 | Near-black. Maximum contrast for data viz. |
| Border | #8B6914 | 2px solid. Cork-gold (not copper like catalog). |
| Content border-top | #3d2510 | Separator between header and scrollable content. |
| Stat card bg | rgba(240,184,71,0.08) | Very faint gold glow. |
| Stat card border | rgba(240,184,71,0.15) | Subtle gold outline. |
| Chart panel bg | rgba(255,255,255,0.02) | Barely visible container. |
| Chart panel border | rgba(255,255,255,0.06) | Ghost border. |
| Receipt paper | #fdfcf8 | Off-white. Thermal receipt paper. |
Genre colors (used in wall-minis and bar-fills):
| Genre | Color |
|---|---|
| Fantasy | #4ecdc4 |
| History | #5dade2 |
| Contemporary | #f0b847 |
| Autobiography | #bb8fce |
| Technology Studies | #5499c7 |
| Productivity | #f5b041 |
| Race Studies | #ec7063 |
| Science Fiction | #48c9b0 |
| Philosophy | #af7ac5 |
| Sociology | #f1948a |
| Psychology | #f7dc6f |
| Mythology | #45b39d |
| Historical Fiction | #e59866 |
| Medical | #76d7c4 |
| Graphic Novel | #aed6f1 |
| Poetry | #d2b4de |
| Horror | #cd6155 |
| Fallback | #8B6914 (cork) |
Reading Journal Palette
Warm paper/book interior. Lighter than the modals.
| Element | Color | Notes |
|---|---|---|
| Page background | #faf8f2 | Warm off-white. Aged paper. |
| Spine (left bar) | #1a0f08 to #2d1f14 | Dark leather binding. |
| Ruled lines | #e8e4d6 | 1px, every 1.75rem. Notebook paper. |
| Margin line | rgba(200,180,140,0.25) | Vertical, at 3rem. Red-ish margin like school paper. |
| Entry border | #d4c9b0 | Dashed. Separates passages. |
| TOC panel | #f0ecde | Slightly darker than page. Index card color. |
| Gold highlighter | rgba(240,184,71,0.32) | Applied to first sentence of each passage via .je-first. |
How the Palettes Relate
All four palettes share #F0B847 gold as the accent color. This is the single thread that ties the cork board, the dark wood catalog, the charcoal dashboard, and the paper journal together. The palettes move along two axes:
- Lightness: Cork (mid) > Journal (light) > Catalog (dark) > Reading Year (darkest)
- Temperature: Catalog (warmest, amber/copper) > Cork (warm, earthy) > Reading Year (cooler, charcoal-tinged) > Journal (neutral, paper-white)
4. Component Library
Sticky Notes
Base class: .sticky
padding: 14px 16px;
border-radius: 3px;
box-shadow: 3px 3px 8px rgba(0,0,0,0.3), inset 0 -2px 4px rgba(0,0,0,0.08);
font-family: 'Kalam', cursive;
font-size: 0.95rem;
transition: transform 0.2s;
Every sticky has a ::after pseudo-element that creates a folded-corner shadow (bottom-right triangle, 12px).
Color variants: .y, .g, .p, .b, .o, .r, .w, .teal — each applies a linear-gradient(135deg, ...).
Rotation variants: .r1 through .r7 — slight CSS rotate() values from -2.3deg to 2.1deg. Applied via data in sprint.json to make notes look casually pinned.
Size variants: .big — larger padding (18px 20px) and font-size (1.05rem).
State variants:
.blocker— red border (3px solid #e74c3c) with red box-shadow glow. Marks blockers..link-sticky— max-width 200px,text-decoration: none, enhanced hover scale (1.06). Used in “WHO IS THIS GUY” section for external links..reading-trigger— button variant.text-align: left,cursor: pointer.
Hover behavior: All stickies scale to 1.02 and flatten rotation on hover (rotate(0deg) !important).
Sub-elements:
.sticky-title— Bold (700), slightly larger (1.05rem), dark (#1a1a1a).sticky-body—white-space: pre-lineto render\nfrom JSON.sticky-tag— Inline-block pill.rgba(0,0,0,0.12)background. Patrick Hand font. 0.75rem.
Modal System
Backdrop: .modal-backdrop
position: fixed; inset: 0; z-index: 1000;
background: rgba(0,0,0,0.65);
backdrop-filter: blur(3px);
display: flex; align-items: flex-start; justify-content: center;
padding: 40px 20px; overflow-y: auto;
Uses [hidden] attribute for show/hide (not class toggling). All three modals share this backdrop.
Cork modal: .modal-board — repeats the cork texture from body. Max-width 860px. Used as a generic board (not currently instantiated on the main page but available).
Catalog modal: .catalog-board
background: linear-gradient(to bottom, #3d2510, #1f0e05);
box-shadow: 0 20px 60px rgba(0,0,0,0.6), 0 0 0 3px #C4782A, 0 0 40px rgba(196,120,42,0.15);
max-width: 1100px;
Three-layer box-shadow: depth shadow + copper frame + ambient glow.
Reading year modal: .reading-board
background: linear-gradient(to bottom, #2d1f14, #1a0f08);
box-shadow: 0 20px 60px rgba(0,0,0,0.7), 0 0 0 2px #8B6914;
max-width: 1100px;
Similar structure but cooler tones and cork-gold border instead of copper.
Journal modal: .journal-wrap
display: flex;
max-width: 820px; height: 85vh;
background: #faf8f2;
Not a “board” — it is a book. Left spine (40px dark leather) + scrollable ruled pages.
Common modal elements:
.modal-close— 28px circle,rgba(0,0,0,0.3)bg, whiteX. Hover turns red (rgba(231,76,60,0.7))..modal-tape— Translucent yellow strip centered at top. 70px wide, 20px tall..modal-pin— 14px circle with radial gradient..redand.bluevariants. Smaller than cork board pins (18px).
All modals animate in with @keyframes modal-in (see Animation section).
Pins and Tape
Cork board pins: .pin
width: 18px; height: 18px; border-radius: 50%;
position: absolute; top: -9px;
box-shadow: 0 2px 4px rgba(0,0,0,0.5), inset 0 1px 2px rgba(255,255,255,0.3);
Three color variants:
.pin.red—radial-gradient(circle at 35% 35%, #ff6b6b, #c0392b), positionedleft: 40px.pin.blue—radial-gradient(circle at 35% 35%, #74b9ff, #2980b9), positionedright: 40px.pin.yellow—radial-gradient(circle at 35% 35%, #ffeaa7, #f39c12), positionedleft: 50%
The 35% 35% offset on the radial gradient creates a realistic 3D “light catch” on the pin head.
Tape strips: .tape
position: absolute; top: -10px; left: 50%;
transform: translateX(-50%) rotate(-2deg);
width: 50px; height: 20px;
background: rgba(255,255,200,0.45);
border-top/bottom: 1px solid rgba(200,200,100,0.3);
Positional variants:
.tape.left—left: 20%; rotate(3deg).tape.right—left: 75%; rotate(-4deg)
The QOTD card has a tape-like ::before pseudo-element (80px wide, slightly different opacity). The spine tooltip also has one (44px wide).
Stamps
Base: .stamp
position: absolute; top: 8px; right: 8px;
color: #27ae60; border: 2px solid #27ae60;
font-family: 'Fredoka'; font-size: 0.72rem; font-weight: 600;
transform: rotate(8deg); opacity: 0.8;
Looks like a rubber stamp in the corner of a sticky note.
WIP variant: .stamp.wip — orange color (#e67e22) instead of green. Applied to any stamp text that is not “DONE”.
Book Spines
Base: .book-spine
height: 155px;
border-radius: 1px 2px 0 0;
display: flex; align-items: center; justify-content: center;
transition: transform 0.18s ease, box-shadow 0.18s ease, filter 0.18s ease;
box-shadow: inset 2px 0 4px rgba(0,0,0,0.25), inset -1px 0 3px rgba(0,0,0,0.15), 1px 0 2px rgba(0,0,0,0.3);
Width, background, and text color are set inline by JS based on annotation count (40px to 72px width, cream to near-black background).
::before — 3px highlight strip at top (rgba(255,255,255,0.18)). Simulates light reflection on spine edge.
Hover: translateY(-18px) scaleX(1.04) — book pulls up off shelf. Enhanced shadow + brightness(1.12).
Gold shimmer: .spine-gold::after — diagonal gradient overlay with rgba(240,184,71,0.22) at center. Applied to books with 26+ annotations.
Sub-elements:
.spine-label—writing-mode: vertical-rl; transform: rotate(180deg). Patrick Hand, 0.75rem. Text runs bottom-to-top along the spine..spine-mark-dot— 4px gold circle at bottom of spine. Opacity scales with annotation count (count / 30, capped at 1).
Shelf System
Row: .shelf-row — flex column. Contains .shelf-spines + .shelf-plank.
Spines container: .shelf-spines — flex row, align-items: flex-end, 2px gap, min-height: 170px. Books sit on the plank and align to the bottom.
Plank: .shelf-plank
height: 18px;
background: linear-gradient(to bottom, #8B4A1F 0%, #9B5524 35%, #7A3A12 60%, #5E2C08 80%, #3d1a04 100%);
border-top: 2px solid #C47830;
box-shadow: 0 6px 18px rgba(0,0,0,0.6), 0 2px 4px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,180,80,0.30);
Has two pseudo-elements:
::before— Subtle vertical grain lines every 60px (rgba(0,0,0,0.04))::after— Drop shadow below the shelf (12px gradient to transparent)
Bar Charts (Genre Bars)
Row: .bar-row — flex, 8px gap, 4px margin-bottom.
Label: .bar-label — Patrick Hand, 0.72rem, right-aligned, fixed 120px width. White at 55% opacity.
Track: .bar-track — flex: 1, 12px height, rgba(255,255,255,0.06) background, 3px border-radius.
Fill: .bar-fill — height 100%, width set inline. Color set inline per genre. transition: width 0.5s ease.
Value: .bar-val — Permanent Marker, 0.7rem, gold at 70% opacity.
Active state: .bar-row.bar-active — faint gold background, fill gets box-shadow: 0 0 8px currentColor, value brightens to full gold.
Diversity Bars
Container: .div-bars — flex row, 28px height, 4px border-radius, 2px gap.
Segments: .div-bar — flex-based width (set via style="flex:N"). Centered label text (Patrick Hand, 0.7rem, white at 90%).
| Variant | Background | Meaning |
|---|---|---|
.div-bar (default) | #bb8fce | Female authors |
.div-bar-m | #2c3e50 | Male authors |
.div-bar-n | #1abc9c | Non-binary authors |
.div-bar-poc | #e67e22 | Authors of color (yes) |
.div-bar-nopoc | #34495e | Not POC |
Active state: .div-bar-active — brightness(1.3), box-shadow: 0 0 10px currentColor, white inner glow.
Note: .div-note — Kalam italic, 0.7rem, white at 20% opacity. Contextual footnote.
Receipt
Container: .reading-receipt
background: #fdfcf8;
color: #333;
font-family: 'Courier New', monospace;
font-size: 0.78rem;
padding: 20px 24px;
max-width: 360px;
transform: rotate(1deg);
box-shadow: 2px 4px 12px rgba(0,0,0,0.4);
The only monospace font in the entire system. Deliberately breaks the handwritten aesthetic to look like a real thermal receipt.
Sub-elements:
.receipt-header— Bold, centered, 0.8rem.receipt-line— Dashed divider (color: #bbb, content is literal dashes).receipt-row—display: flex; justify-content: space-between.receipt-total— Bold variant of receipt-row.receipt-tear— 8px tall zigzagclip-pathpattern. Simulates torn receipt edge.
Book List
Search: .bl-search — Full-width input. rgba(255,255,255,0.04) background, Patrick Hand, 0.75rem. Focus state adds gold border.
Row: .bl-row — flex, baseline-aligned, 3px 6px padding, 3px border-radius. Hover/active adds rgba(240,184,71,0.08) background.
Sub-elements:
.bl-stars— 0.6rem, gold, -1px letter-spacing. Renders star characters..bl-title— Patrick Hand, 0.72rem, white at 65%. Truncated with ellipsis. Turns gold on hover..bl-genre— Kalam, 0.6rem, color set inline per genre..bl-badges— flex container for small pills.
Badge variants:
| Class | Background | Text | Meaning |
|---|---|---|---|
.bl-badge-f | rgba(187,143,206,0.25) | #d4a5ec | Female author |
.bl-badge-m | rgba(93,173,226,0.2) | #7fbfea | Male author |
.bl-badge-n | rgba(26,188,156,0.25) | #48c9b0 | Non-binary author |
.bl-badge-poc | rgba(230,126,34,0.2) | #e9a265 | Author of color |
Clickable rows: .bl-clickable — cursor: pointer, title gets dotted gold underline that solidifies on hover.
Tooltips
Spine tooltip: .spine-tooltip
position: fixed; z-index: 2000;
width: 230px;
background: #fffef5;
border-top: 4px solid #F0B847;
box-shadow: 0 8px 28px rgba(0,0,0,0.5), 0 2px 8px rgba(0,0,0,0.3), 0 0 0 1px rgba(139,105,20,0.3);
pointer-events: none;
Has a tape-like ::before pseudo-element. Follows cursor position via JS (clamped to viewport). Contains title (Kalam bold), author (Patrick Hand italic), marks count + progress bar, and teaser quote.
Review tooltip: .review-tooltip
position: fixed; z-index: 2000;
background: #1a0f08;
border: 1px solid rgba(240,184,71,0.25);
border-radius: 6px;
max-width: 420px;
animation: modal-in 0.12s ease;
Dark background (matches reading year palette). Contains title (Patrick Hand, gold), meta (Kalam, faint white), and scrollable review body (Kalam, white at 65%).
Quote of the Day Card
Container: .qotd-card
background: linear-gradient(135deg, #fffef0, #fff9d6);
border-left: 5px solid #F0B847;
box-shadow: 4px 4px 12px rgba(0,0,0,0.35), inset 0 -3px 6px rgba(0,0,0,0.06);
Has a tape ::before and a folded-corner ::after. The quote text gets ::before/::after large curly quotes in gold (Georgia serif, 2.5rem).
Monthly Wall
Wall: .reading-wall — flex row, align-items: flex-end. Scrollable horizontally.
Month column: .wall-month — flex column, centered, min-width 50px, flex: 1.
Book stack: .wall-stack — flex-direction: column-reverse (books stack upward).
Mini book: .wall-mini — 36px x 10px, colored per genre, slight random rotation via inline transform. Hover scales to 1.3.
Interaction states:
.wall-mini.wall-dim—opacity: 0.15. Applied to non-matching books during cross-highlight..wall-mini.wall-highlight—opacity: 1; scale(1.4); box-shadow: 0 0 6px rgba(240,184,71,0.5).
Journal Components
Pages: .journal-pages — Ruled paper background using two background-image layers:
- Vertical margin line at 3rem (
rgba(200,180,140,0.25)) - Horizontal rules every 1.75rem (
#e8e4d6)
Entry: .journal-entry — Relative positioned, left padding 3.5rem (past the margin).
Number: .je-number — Faint (40% opacity), absolute left. Patrick Hand 0.6rem.
Date: .je-date — Vertical text (writing-mode: vertical-rl; rotate(180deg)). Sits in the margin.
Gold highlight: .je-first — Background gradient that paints gold from 55% to 90% of line height, creating a “highlighter pen” effect.
Dog-ear: .je-dogear — A CSS-only triangular button (border trick). Hidden by default, appears on hover (22px, neutral), turns gold when toggled on (28px, #F0B847). State persisted in localStorage.
Ribbon: .journal-ribbon — 10px wide, gold fill. Height tracks scroll progress (0-100%).
TOC panel: .journal-toc-panel — Slide-over from the left (200px wide), #f0ecde background. Contains .toc-item buttons.
5. Animation
Keyframes
modal-in — Used by all modals (catalog, journal, reading year, review tooltip):
@keyframes modal-in {
from { transform: translateY(-16px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
Duration varies: modals use 0.2s-0.25s, review tooltip uses 0.12s.
Transitions
| Element | Property | Duration | Easing |
|---|---|---|---|
.sticky | transform | 0.2s | default |
.book-spine | transform, box-shadow, filter | 0.18s | ease |
.bar-fill | width | 0.5s | ease |
.div-bar | flex | 0.5s | ease |
.wall-mini | opacity, transform | 0.15s | default |
.journal-ribbon | height | 0.1s | linear |
.st-bar (tooltip) | width | 0.15s | ease |
.qotd-book | color | 0.15s | default |
.je-dogear | border-width | 0.2s | ease |
.modal-close | background | 0.15s | default |
#shelf-trigger | opacity, transform | 0.3s | default |
.bl-row | background | 0.12s | default |
.bl-search | border-color | 0.15s | default |
.toc-item | background | 0.1s | default |
Hover Effects
| Element | Effect |
|---|---|
.sticky:hover | scale(1.02) rotate(0deg) — flattens rotation, slight grow |
.link-sticky:hover | scale(1.06) rotate(0deg) — more dramatic grow |
.book-spine:hover | translateY(-18px) scaleX(1.04) — pulls up off shelf |
.book-spine:hover | filter: brightness(1.12) — subtle lightening |
.wall-mini:hover | scale(1.3) — pops out of stack |
#shelf-trigger:hover | rotate(-8deg) scale(1.15); opacity: 0.6 |
.top-clickable:hover | background: rgba(240,184,71,0.06) |
6. Responsive Breakpoints
1100px (max-width: 1100px)
Sprint columns: Grid drops from repeat(5, 1fr) to repeat(3, 1fr). The 5-column Kanban board (Shipped, Building, Blocked, Planning, Thinking) wraps into 3 columns.
700px (max-width: 700px)
- Sprint columns: Grid drops to
repeat(2, 1fr) - Banner: Font-size shrinks from 2.8rem to 1.8rem
- Link stickies: Gap shrinks (18px to 12px), max-width shrinks (200px to 160px), font-size drops to 0.85rem
- Reading charts:
grid-template-columnschanges from1fr 1frto1fr(genre bars and diversity/book-list stack vertically) - Reading bottom row:
grid-template-columnschanges fromauto 1frto1fr(receipt and top books stack vertically)
Note: The catalog bookshelf and journal modals have no explicit breakpoints — they use max-width: 1100px and max-width: 820px respectively with width: 100%, so they scale down naturally. The spine width and book height are fixed (no responsive resizing).
7. Design Philosophy
The Cork Board Metaphor
The entire site is a physical cork board. The body background is not just a solid color — it is a multi-layer composite:
- Grid lines — Two
repeating-linear-gradientlayers create a faint 40px grid (horizontal at 8% opacity, vertical at 5%) - Depth gradients — Two
radial-gradientlayers create light/shadow variation across the surface - Base gradient — A
linear-gradient(135deg)from cork through cork-dark to cork-light - Noise texture — A
::beforepseudo-element onbodyapplies a fixed SVG dot pattern (tiny circles at 0.3-0.5px radius) to simulate cork grain
This five-layer composite creates a convincing cork texture without any image files.
Hand-Drawn Aesthetic
Every visual element reinforces the “things pinned to a board” metaphor:
- Slight rotations — Nothing is perfectly aligned. Seven rotation classes provide variety.
- Tape and pins — Physical attachment metaphors. Tape is translucent yellow; pins have 3D radial gradients.
- Corner folds — Every sticky note and the QOTD card have a subtle bottom-right corner fold (
::aftertriangle). - Imperfect shadows — Shadows are large and offset (3-4px), not the tight 1-2px of modern flat design.
- Hand-drawn fonts — Four typefaces, all cursive/handwritten. No sans-serif body text.
- Stamps — Rubber stamp aesthetic for status indicators (rotated, bordered, slightly transparent).
Dark Modal Interiors
When you open a modal, the visual language shifts from “cork board in daylight” to “dark interior space”:
- The catalog is a dark wood cabinet. The background gradient, copper border, wooden shelf planks, and amber glow on the title all evoke opening a bookcase in a dimly lit library.
- The reading year dashboard is even darker — a data visualization space where bright genre colors and gold accents pop against near-black backgrounds.
- The journal is a physical book — cream paper with ruled lines and a leather spine.
This contrast is intentional: the cork board is the public-facing, playful surface. The modals are intimate, focused spaces for reading and reflection. The gold accent color (#F0B847) is the constant that bridges both worlds.
Hidden Interactions
The site has intentional discovery moments:
- The hidden pin (
#shelf-trigger) — A barely-visible pushpin emoji (25% opacity) in the bottom-right corner. Opens the card catalog. Careful eyes only. - Dog-ear persistence — Journal passage dog-ears are saved to
localStorage. They persist across visits. - Cross-highlighting — Hovering a book in the book list highlights the corresponding wall-mini, genre bar, and diversity bar simultaneously. Clicking a wall-mini locks the highlight for 4 seconds and scrolls the book list.
- QOTD-to-journal — Clicking the book title in the quote of the day jumps directly to that book’s journal, bypassing the catalog.
- Daily kaomojis — Kaomoji faces rotate daily via a date-seeded hash. Same day = same faces worldwide. Changes at midnight with no deploy needed.
File Map
| File | Purpose |
|---|---|
src/layouts/Layout.astro | Global reset, :root tokens, body cork texture, font imports |
src/pages/index.astro | All page markup, all JS (inline), all component CSS (<style is:global>) |
src/pages/404.astro | Error page with fallen sticky note metaphor |
src/data/sprint.json | Sprint board content (stickies, columns, stats, bottom row) |
src/data/kaomojis.ts | Kaomoji pool for daily rotation |
src/data/bookmarks.clean.json | Book highlights for QOTD + catalog + journal |
src/data/reading-log.json | 150-book reading year dataset |