Design System

CSSdesigntokens

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

TokenValueUsage
--cork#8B6914Primary background. Body fill, modal-board bg, shelf-trigger tint. The cork board itself.
--cork-dark#7A5C0FUsed in body gradient (radial-gradient at 80% 70%, linear-gradient endpoint). Adds depth to cork texture.
--cork-light#9B7A20Used in body gradient (radial-gradient at 20% 30%, linear-gradient midpoint). Creates the warm highlight on cork.
--navy#1a1a2eBanner background, stat cards, journal text color. The “pinned paper” contrast color.
--gold#F0B847Accent everywhere: banner text, stat values, gold highlights, ribbon progress, spine tooltips, receipt stars. The connective thread across all palettes.

Font Stacks

TokenValueRole
--font-marker'Permanent Marker', cursiveHeadlines, titles, stamps. The “written in Sharpie” voice.
--font-bubble'Fredoka', 'Varela Round', sans-serifColumn headers, stat cards, footer, stamps. Friendly, rounded, structural.
--font-hand'Kalam', cursiveBody text on stickies, journal entries, subtitles, loading states. The “handwritten on a Post-it” voice. Default body font.
--font-print'Patrick Hand', cursiveTags, 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: body default, .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.

ColorHexContext
Cork base#8B6914Body background
Cork dark#7A5C0FGradient shadow regions
Cork light#9B7A20Gradient highlight regions
Navy#1a1a2eBanner, stat cards
Gold#F0B847Accent text, borders, highlights
White (subdued)rgba(255,255,255,0.5)Footer text

Sticky note colors (all use 135deg linear gradients, light-to-saturated):

ClassStartEndVisual
.y#FFF9A3#FFEF70Yellow
.g#B8F5C8#7EE8A2Green
.p#E8B4F8#D280F0Purple
.b#B4D4FF#7EB8F7Blue
.o#FFD4A3#FFBB70Orange
.r#FFB4B4#FF8080Red/Pink
.w#ffffff#f0f0f0White
.teal#B4F5EF#70E8DETeal

Catalog Modal Palette (Bookshelf)

Warmer, more saturated. Dark wood interior with amber/mahogany tones.

ElementColorNotes
Board background#3d2510 to #1f0e05Top-to-bottom gradient. Dark walnut.
Bookcase interior#1e0e04 to #130804Even darker. The recess behind books.
Frame border#C4782A3px solid. Warm brass/copper.
Shelf plank#8B4A1F to #3d1a045-stop gradient. Realistic wood grain.
Plank highlight#C47830Top border. The light catch on the shelf edge.
Title text#F0B847Gold, with amber glow text-shadow.
Subtitle textrgba(255,255,255,0.35)Ghostly, recessive.
Scrollbar#6b3a18 on #0f0a05Matches wood tones.

Spine colors (tiered by annotation count):

CountBackgroundTextName
0#f0ece0#bbb6a8Ghost/cream
1-2#e8d5b5#8a7a62Ivory
3-10#c4956a#fff8efWarm tan
11-25#a0522d#ffe8d0Sienna
26-60#7a3020#ffd4b8Deep rust
61+#4a1a1a#f0c090Near-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.

ElementColorNotes
Board background#2d1f14 to #1a0f08Darker than catalog. More charcoal than walnut.
Content area#180e06 to #120906Near-black. Maximum contrast for data viz.
Border#8B69142px solid. Cork-gold (not copper like catalog).
Content border-top#3d2510Separator between header and scrollable content.
Stat card bgrgba(240,184,71,0.08)Very faint gold glow.
Stat card borderrgba(240,184,71,0.15)Subtle gold outline.
Chart panel bgrgba(255,255,255,0.02)Barely visible container.
Chart panel borderrgba(255,255,255,0.06)Ghost border.
Receipt paper#fdfcf8Off-white. Thermal receipt paper.

Genre colors (used in wall-minis and bar-fills):

GenreColor
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.

ElementColorNotes
Page background#faf8f2Warm off-white. Aged paper.
Spine (left bar)#1a0f08 to #2d1f14Dark leather binding.
Ruled lines#e8e4d61px, every 1.75rem. Notebook paper.
Margin linergba(200,180,140,0.25)Vertical, at 3rem. Red-ish margin like school paper.
Entry border#d4c9b0Dashed. Separates passages.
TOC panel#f0ecdeSlightly darker than page. Index card color.
Gold highlighterrgba(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-bodywhite-space: pre-line to render \n from JSON
  • .sticky-tag — Inline-block pill. rgba(0,0,0,0.12) background. Patrick Hand font. 0.75rem.

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, white X. 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. .red and .blue variants. 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.redradial-gradient(circle at 35% 35%, #ff6b6b, #c0392b), positioned left: 40px
  • .pin.blueradial-gradient(circle at 35% 35%, #74b9ff, #2980b9), positioned right: 40px
  • .pin.yellowradial-gradient(circle at 35% 35%, #ffeaa7, #f39c12), positioned left: 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.leftleft: 20%; rotate(3deg)
  • .tape.rightleft: 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-labelwriting-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%).

VariantBackgroundMeaning
.div-bar (default)#bb8fceFemale authors
.div-bar-m#2c3e50Male authors
.div-bar-n#1abc9cNon-binary authors
.div-bar-poc#e67e22Authors of color (yes)
.div-bar-nopoc#34495eNot POC

Active state: .div-bar-activebrightness(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-rowdisplay: flex; justify-content: space-between
  • .receipt-total — Bold variant of receipt-row
  • .receipt-tear — 8px tall zigzag clip-path pattern. 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:

ClassBackgroundTextMeaning
.bl-badge-frgba(187,143,206,0.25)#d4a5ecFemale author
.bl-badge-mrgba(93,173,226,0.2)#7fbfeaMale author
.bl-badge-nrgba(26,188,156,0.25)#48c9b0Non-binary author
.bl-badge-pocrgba(230,126,34,0.2)#e9a265Author of color

Clickable rows: .bl-clickablecursor: 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-stackflex-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-dimopacity: 0.15. Applied to non-matching books during cross-highlight.
  • .wall-mini.wall-highlightopacity: 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:

  1. Vertical margin line at 3rem (rgba(200,180,140,0.25))
  2. 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

ElementPropertyDurationEasing
.stickytransform0.2sdefault
.book-spinetransform, box-shadow, filter0.18sease
.bar-fillwidth0.5sease
.div-barflex0.5sease
.wall-miniopacity, transform0.15sdefault
.journal-ribbonheight0.1slinear
.st-bar (tooltip)width0.15sease
.qotd-bookcolor0.15sdefault
.je-dogearborder-width0.2sease
.modal-closebackground0.15sdefault
#shelf-triggeropacity, transform0.3sdefault
.bl-rowbackground0.12sdefault
.bl-searchborder-color0.15sdefault
.toc-itembackground0.1sdefault

Hover Effects

ElementEffect
.sticky:hoverscale(1.02) rotate(0deg) — flattens rotation, slight grow
.link-sticky:hoverscale(1.06) rotate(0deg) — more dramatic grow
.book-spine:hovertranslateY(-18px) scaleX(1.04) — pulls up off shelf
.book-spine:hoverfilter: brightness(1.12) — subtle lightening
.wall-mini:hoverscale(1.3) — pops out of stack
#shelf-trigger:hoverrotate(-8deg) scale(1.15); opacity: 0.6
.top-clickable:hoverbackground: 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-columns changes from 1fr 1fr to 1fr (genre bars and diversity/book-list stack vertically)
  • Reading bottom row: grid-template-columns changes from auto 1fr to 1fr (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:

  1. Grid lines — Two repeating-linear-gradient layers create a faint 40px grid (horizontal at 8% opacity, vertical at 5%)
  2. Depth gradients — Two radial-gradient layers create light/shadow variation across the surface
  3. Base gradient — A linear-gradient(135deg) from cork through cork-dark to cork-light
  4. Noise texture — A ::before pseudo-element on body applies 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 (::after triangle).
  • 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

FilePurpose
src/layouts/Layout.astroGlobal reset, :root tokens, body cork texture, font imports
src/pages/index.astroAll page markup, all JS (inline), all component CSS (<style is:global>)
src/pages/404.astroError page with fallen sticky note metaphor
src/data/sprint.jsonSprint board content (stickies, columns, stats, bottom row)
src/data/kaomojis.tsKaomoji pool for daily rotation
src/data/bookmarks.clean.jsonBook highlights for QOTD + catalog + journal
src/data/reading-log.json150-book reading year dataset