Files
crashtestdev/.design/specs/design-tokens-2026-05-26.md
T
Ken a951c00e35 fix: purge AI slop from judgment essay, add voice linting pipeline
- Killed 16 em-dashes (Claude fingerprint, 15.9/1000 words -> 0)
- Replaced all clause-dash-elaboration patterns with periods, colons, restructuring
- Removed 'The One-Sentence Version' section (restated the intro, voice anti-pattern)
- Broke tricolon at lines 56-58 (too-clean parallel structure)
- Collapsed 'How to Actually Help' listicle into connective prose
- Added receipt link for ~100x inference cost claim
- Heading dashes replaced with colons (Tradesman Analogy, Excellence vs Functional)

New tooling:
- scripts/lint-voice.sh: mechanical anti-slop linter (em-dashes, trigger words,
  hedging, filler, receipts, sentence uniformity)
- .amplifier/skills/voice-check/SKILL.md: LLM-as-judge voice authenticity check
  (8 dimensions against VOICE.md profile)
- .amplifier/AGENTS.md: standing rule requiring both checks before any publish

🤖 Generated with Amplifier

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
2026-05-27 00:42:18 +00:00

29 KiB

feature, date, status, project, tags, related
feature date status project tags related
DesignTokenSystem 2026-05-26 planned crash-test-dev
tokens
system
color
typography
spacing
layout
AESTHETIC-GUIDE.md

Design Token System — Crash Test Dev

User's Spark (preserved)

A well-used workshop. Not a pristine showroom — the one where someone actually builds things. Tools are organized because disorganization wastes time. The wood has warmth. The light is good because you need to see details. There's a coffee cup somewhere.

Metaphor: The workbench, not the gallery. Materials vocabulary: Paper, ink, wood, stone, iron. Personality: Dry warmth. Quiet confidence. Evidence over performance.


Complete Token System

{
  "colors": {
    "_meta": {
      "temperature": "warm across all values — no blue-grays, no cool neutrals",
      "philosophy": "Aged paper, brown-black ink, fired earth, tarnished brass. Every color drawn from the workbench vocabulary: materials that have been used, heated, and cooled."
    },

    "surface": {
      "base":  { "value": "#F5F0E8", "description": "Page background. Heavy unbleached paper stock — warm off-white, not pure white, not yellow." },
      "card":  { "value": "#FEFCF7", "description": "Reading surface. White card stock laid on the paper base — for article bodies, elevated panels." },
      "code":  { "value": "#EEEAE2", "description": "Code block background. Heavier paper weight — subtle warm-gray shift from prose background." },
      "inset": { "value": "#E8E3DA", "description": "Callout/aside background. Slightly recessed surface, like a different stock weight." }
    },

    "text": {
      "primary":   { "value": "#2B2421", "description": "Body text. Warm near-black — brown-black ink, NOT blue-black digital default.", "contrastOnBase": "13.44:1 (AAA)", "contrastOnCard": "14.87:1 (AAA)" },
      "secondary": { "value": "#6B5F55", "description": "Metadata, captions, bylines. Warm mid-gray with stone undertone.", "contrastOnBase": "5.46:1 (AA)", "contrastOnCard": "6.04:1 (AA)" },
      "tertiary":  { "value": "#948880", "description": "Timestamps, tags, disabled text. Lighter warm gray.", "contrastOnBase": "3.04:1 (AA-UI)", "contrastOnCard": "3.36:1 (AA-UI)" }
    },

    "accent": {
      "primary":      { "value": "#A0522D", "description": "Links, emphasis, code block left-edge accent. Muted terracotta/sienna — fired earth, not bright red.", "contrastOnBase": "4.95:1 (AA)", "contrastOnCard": "5.48:1 (AA)" },
      "primaryHover":  { "value": "#8B4726", "description": "Link hover state. Darker rust — the terracotta after more firing.", "contrastOnBase": "6.12:1 (AA)" },
      "secondary":     { "value": "#7D6C2F", "description": "Special callouts, highlights. Tarnished brass/dark gold — aged metal.", "contrastOnBase": "4.56:1 (AA)", "contrastOnCard": "5.05:1 (AA)" },
      "secondaryHover": { "value": "#6B5C28", "description": "Brass hover state. Darker, more patinated." }
    },

    "code": {
      "text": { "value": "#3D342E", "description": "Code text. Warm dark brown, slightly lighter than body text for the different register.", "contrastOnCode": "10.12:1 (AAA)" }
    },

    "border": {
      "subtle":  { "value": "#DDD7CD", "description": "Decorative score lines, faint dividers. Barely there — like a fold in paper. No contrast requirement (decorative)." },
      "default": { "value": "#C2BAA9", "description": "General-purpose separators, card edges. Visible but quiet." },
      "strong":  { "value": "#8E857A", "description": "Functional UI borders (form inputs, focused elements). Meets 3:1 on both base and card.", "contrastOnBase": "3.20:1 (AA-UI)", "contrastOnCard": "3.54:1 (AA-UI)" }
    },

    "focus": {
      "ring": { "value": "#A0522D", "description": "Keyboard focus indicator. Terracotta — visible, warm, consistent with accent.", "contrastOnBase": "4.95:1 (AA-UI)" }
    },

    "state": {
      "success": {
        "bg":     { "value": "#E8EDDF", "description": "Warm sage green tint." },
        "text":   { "value": "#4A5E3A", "description": "Dark moss green.", "contrastOnBg": "5.96:1 (AA)" },
        "border": { "value": "#B5C4A0", "description": "Muted sage border." }
      },
      "warning": {
        "bg":     { "value": "#F2E8D0", "description": "Warm amber tint." },
        "text":   { "value": "#7A5C1F", "description": "Dark warm amber.", "contrastOnBg": "5.10:1 (AA)" },
        "border": { "value": "#D4BC7C", "description": "Muted gold border." }
      },
      "error": {
        "bg":     { "value": "#F2DED6", "description": "Warm rose/clay tint." },
        "text":   { "value": "#8B3A2A", "description": "Dark terracotta.", "contrastOnBg": "5.92:1 (AA)" },
        "border": { "value": "#CFA090", "description": "Muted clay border." }
      },
      "info": {
        "bg":     { "value": "#E5E2DA", "description": "Warm neutral tint." },
        "text":   { "value": "#4A4540", "description": "Warm dark gray.", "contrastOnBg": "7.32:1 (AAA)" },
        "border": { "value": "#B8B2A8", "description": "Warm mid gray border." }
      }
    },

    "shadow": {
      "color": { "value": "rgba(43, 36, 33, 0.06)", "description": "Warm-toned shadow base. Derived from text-primary. Barely-there desk shadow." }
    }
  },

  "typography": {
    "_meta": {
      "philosophy": "Three voices, three jobs. Serif for prose (Ken's voice). Sans for structure (navigation, headings). Mono for evidence (code, proof). The reader always knows which voice is speaking.",
      "scaleRatio": 1.25,
      "scaleName": "Major Third",
      "scaleBase": "18px"
    },

    "families": {
      "prose":     { "value": "'Source Serif 4', 'Source Serif Pro', Georgia, 'Times New Roman', serif", "role": "Reading voice — body text, blockquotes, long-form prose" },
      "structure": { "value": "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif", "role": "Navigation voice — headings, UI labels, metadata" },
      "evidence":  { "value": "'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, monospace", "role": "Proof voice — code blocks, terminal output, file paths" }
    },

    "scale": {
      "xs":   { "value": "0.75rem",   "px": 12, "step": -2, "use": "footnotes, legal text" },
      "sm":   { "value": "0.875rem",  "px": 14, "step": -1, "use": "captions, meta, timestamps, tags" },
      "base": { "value": "1.125rem",  "px": 18, "step":  0, "use": "body prose" },
      "lg":   { "value": "1.375rem",  "px": 22, "step":  1, "use": "h4 headings" },
      "xl":   { "value": "1.75rem",   "px": 28, "step":  2, "use": "h3 headings" },
      "2xl":  { "value": "2.25rem",   "px": 36, "step":  3, "use": "h2 headings — section titles" },
      "3xl":  { "value": "2.75rem",   "px": 44, "step":  4, "use": "h1 headings — article title" }
    },

    "lineHeight": {
      "tight":   { "value": 1.15, "use": "display headings (h1)" },
      "snug":    { "value": 1.25, "use": "headings (h2, h3)" },
      "heading": { "value": 1.35, "use": "smaller headings (h4)" },
      "normal":  { "value": 1.5,  "use": "UI text, captions" },
      "relaxed": { "value": 1.6,  "use": "code blocks, blockquotes" },
      "prose":   { "value": 1.7,  "use": "body prose — generous for dense technical narrative" }
    },

    "weight": {
      "regular":  { "value": 400, "use": "body prose, code" },
      "medium":   { "value": 500, "use": "UI labels, caption emphasis" },
      "semibold": { "value": 600, "use": "headings, inline emphasis in prose" },
      "bold":     { "value": 700, "use": "h1 title, strong emphasis" }
    },

    "styles": {
      "body": {
        "fontFamily": "prose",
        "fontSize": "1.125rem",
        "fontWeight": 400,
        "lineHeight": 1.7,
        "letterSpacing": "normal",
        "description": "Ken's voice on the page. 18px Source Serif 4 at generous line-height for sustained technical reading."
      },
      "bodySmall": {
        "fontFamily": "prose",
        "fontSize": "0.875rem",
        "fontWeight": 400,
        "lineHeight": 1.6,
        "letterSpacing": "0.005em",
        "description": "Footnotes, secondary prose passages. Still serif — still Ken's voice, just quieter."
      },
      "h1": {
        "fontFamily": "structure",
        "fontSize": "2.75rem",
        "fontWeight": 700,
        "lineHeight": 1.15,
        "letterSpacing": "-0.02em",
        "description": "Article title. 44px Inter Bold — confident, unhurried. Negative tracking tightens at display size."
      },
      "h2": {
        "fontFamily": "structure",
        "fontSize": "2.25rem",
        "fontWeight": 600,
        "lineHeight": 1.25,
        "letterSpacing": "-0.015em",
        "description": "Section heading. 36px Inter Semibold — chapter breaks in the narrative."
      },
      "h3": {
        "fontFamily": "structure",
        "fontSize": "1.75rem",
        "fontWeight": 600,
        "lineHeight": 1.3,
        "letterSpacing": "-0.01em",
        "description": "Subsection heading. 28px Inter Semibold — organizes without competing with prose."
      },
      "h4": {
        "fontFamily": "structure",
        "fontSize": "1.375rem",
        "fontWeight": 600,
        "lineHeight": 1.35,
        "letterSpacing": "-0.005em",
        "description": "Minor heading. 22px Inter Semibold — just enough hierarchy shift to signal structure."
      },
      "blockquote": {
        "fontFamily": "prose",
        "fontSize": "1.25rem",
        "fontWeight": 400,
        "lineHeight": 1.6,
        "letterSpacing": "normal",
        "fontStyle": "italic",
        "description": "Pull quotes, cited text. 20px Source Serif 4 italic — a gentle size step up signals 'someone else's words' without shouting."
      },
      "caption": {
        "fontFamily": "structure",
        "fontSize": "0.875rem",
        "fontWeight": 500,
        "lineHeight": 1.5,
        "letterSpacing": "0.01em",
        "description": "Image captions, metadata labels, timestamps, tags. 14px Inter Medium — the structure voice at small scale."
      },
      "codeInline": {
        "fontFamily": "evidence",
        "fontSize": "0.9em",
        "fontWeight": 400,
        "lineHeight": "inherit",
        "letterSpacing": "normal",
        "description": "Inline code within prose. 0.9em relative to parent — the evidence voice embedded in narrative."
      },
      "codeBlock": {
        "fontFamily": "evidence",
        "fontSize": "1rem",
        "fontWeight": 400,
        "lineHeight": 1.6,
        "letterSpacing": "normal",
        "description": "Code blocks. 16px JetBrains Mono — factual, verifiable, this-is-what-actually-happened."
      }
    }
  },

  "spacing": {
    "_meta": {
      "base": "8px",
      "philosophy": "The page breathes like a well-set book. Generous vertical rhythm for dense technical narrative. Space above H2 is a full breath — section breaks are chapter breaks."
    },

    "scale": {
      "0":  { "value": "0",     "px": 0 },
      "px": { "value": "1px",   "px": 1 },
      "0.5":{ "value": "0.25rem", "px": 4,  "gridMultiple": "0.5x" },
      "1":  { "value": "0.5rem",  "px": 8,  "gridMultiple": "1x" },
      "1.5":{ "value": "0.75rem", "px": 12, "gridMultiple": "1.5x" },
      "2":  { "value": "1rem",    "px": 16, "gridMultiple": "2x" },
      "2.5":{ "value": "1.25rem", "px": 20, "gridMultiple": "2.5x" },
      "3":  { "value": "1.5rem",  "px": 24, "gridMultiple": "3x" },
      "4":  { "value": "2rem",    "px": 32, "gridMultiple": "4x" },
      "5":  { "value": "2.5rem",  "px": 40, "gridMultiple": "5x" },
      "6":  { "value": "3rem",    "px": 48, "gridMultiple": "6x" },
      "8":  { "value": "4rem",    "px": 64, "gridMultiple": "8x" },
      "10": { "value": "5rem",    "px": 80, "gridMultiple": "10x" },
      "12": { "value": "6rem",    "px": 96, "gridMultiple": "12x" }
    },

    "semantic": {
      "paragraphGap":      { "value": "1.5rem",  "px": 24, "note": "~1.33em at 18px body. Generous — lets ideas land." },
      "headingAboveH2":    { "value": "4rem",    "px": 64, "note": "Section breaks are chapter breaks. Full breath between sections." },
      "headingBelowH2":    { "value": "1rem",    "px": 16, "note": "Tight — the heading belongs to its content, not the space above." },
      "headingAboveH3":    { "value": "2.5rem",  "px": 40, "note": "Sub-section breath. Less than H2, still generous." },
      "headingBelowH3":    { "value": "0.75rem", "px": 12, "note": "Snug — content follows immediately." },
      "headingAboveH4":    { "value": "2rem",    "px": 32, "note": "Minor heading spacing." },
      "headingBelowH4":    { "value": "0.5rem",  "px": 8,  "note": "Very tight — H4 is almost inline with its content." },
      "codeBlockVertical": { "value": "2.5rem",  "px": 40, "note": "Code blocks as exhibited artifacts — generous vertical clearance." },
      "codeBlockPadding":  { "value": "1.5rem",  "px": 24, "note": "Internal padding of code blocks." },
      "codeBlockAccentWidth": { "value": "3px",  "note": "Left-edge accent line on code blocks." },
      "listItemGap":       { "value": "0.5rem",  "px": 8,  "note": "Breathing room between list items." },
      "blockquoteIndent":  { "value": "1.5rem",  "px": 24, "note": "Left indent/border offset for blockquotes." },
      "sectionDivider":    { "value": "3rem",    "px": 48, "note": "Vertical space when using a horizontal rule." }
    }
  },

  "rounded": {
    "_meta": {
      "philosophy": "Workshop surfaces have worn edges, not machined radii. Just enough softness to not feel sharp, not enough to feel 'designed.'"
    },
    "none": { "value": "0" },
    "sm":   { "value": "2px",    "use": "inline code, small tags, badges" },
    "md":   { "value": "4px",    "use": "code blocks, buttons, small elements" },
    "lg":   { "value": "6px",    "use": "cards, callout boxes" },
    "xl":   { "value": "8px",    "use": "larger panels, modals (if ever needed)" },
    "full": { "value": "9999px", "use": "pills, avatars, toggle tracks" }
  },

  "layout": {
    "_meta": {
      "philosophy": "Prose lives in a reading column. Code breaks wider. The width shift signals the register change from narrative to evidence."
    },
    "prose":      { "value": "45rem",   "px": 720,  "approxCh": "~65ch at 18px serif", "description": "Reading column max-width. Sweet spot for sustained reading." },
    "codeBreak":  { "value": "52.5rem", "px": 840,  "description": "Code block max-width. Wider breakout creates narrow-wide-narrow rhythm." },
    "container":  { "value": "68.75rem","px": 1100, "description": "Outer container max-width. Provides margin for the prose column." },
    "sideGutter": { "value": "1.5rem",  "px": 24,   "description": "Minimum horizontal padding on small screens." }
  },

  "shadows": {
    "_meta": {
      "philosophy": "Nothing gleams. Nothing floats. If something casts a shadow, it's the small soft shadow of a card sitting on a desk — barely there."
    },
    "sm":   { "value": "0 1px 3px rgba(43, 36, 33, 0.04)", "use": "Subtle lift — barely perceptible. Cards at rest." },
    "md":   { "value": "0 2px 8px rgba(43, 36, 33, 0.06)", "use": "Card on a desk — the maximum depth in this system." },
    "none": { "value": "none", "use": "Explicit no-shadow override." }
  },

  "motion": {
    "_meta": {
      "philosophy": "Fast, barely-there. The confidence of something that doesn't need to announce itself. Reduce to zero for prefers-reduced-motion."
    },
    "duration": {
      "instant": { "value": "0ms",   "use": "Reduced motion fallback." },
      "fast":    { "value": "100ms", "use": "Color transitions (hover, focus)." },
      "normal":  { "value": "150ms", "use": "Standard interactions — the site's default." },
      "slow":    { "value": "250ms", "use": "Layout shifts, expand/collapse (rare)." }
    },
    "easing": {
      "default":  { "value": "cubic-bezier(0.25, 0.1, 0.25, 1.0)", "use": "Standard ease — smooth, natural deceleration." },
      "inOut":    { "value": "cubic-bezier(0.45, 0.05, 0.55, 0.95)", "use": "Symmetric transitions." }
    },
    "reducedMotion": {
      "rule": "@media (prefers-reduced-motion: reduce)",
      "behavior": "All durations set to 0ms. All transitions disabled. Non-negotiable."
    }
  },

  "rationale": {
    "colorPhilosophy": {
      "title": "Why these specific colors",
      "explanation": [
        "The surface-base (#F5F0E8) was tuned to sit precisely between 'warm' and 'yellow.' Its RGB channels (245, 240, 232) taper from R→G→B, placing the warmth in the red channel without letting it become cream or beige. It reads as 'good light on heavy paper' — the brief's exact intent.",
        "Text-primary (#2B2421) avoids the blue-black of browser defaults (which typically live around #1a1a2e or #333). The brown-black comes from keeping R > G > B at the dark end: (43, 36, 33). This is ink with warmth, not ink with coldness.",
        "The accent-primary (#A0522D, CSS 'sienna') is a historically grounded earth pigment — literally fired earth. At 4.95:1 contrast on base, it passes AA for body text and works as link color without being 'red' or 'alarming.' The hover state (#8B4726) darkens toward the earth rather than toward black.",
        "Accent-secondary (#7D6C2F) captures tarnished brass — the green-gold of aged copper alloy, not the bright gold of decoration. It needed darkening from the first candidate to meet AA (4.56:1), but the constraint improved the color: real tarnished brass IS darker than you'd first guess.",
        "State colors (success, warning, error, info) were designed within the warm palette. No saturated primaries. Success uses sage-moss (#4A5E3A on #E8EDDF), warning uses amber (#7A5C1F on #F2E8D0), error uses deeper terracotta (#8B3A2A on #F2DED6). Even the info state avoids blue entirely — it's warm neutral (#4A4540 on #E5E2DA)."
      ]
    },

    "contrastStrategy": {
      "title": "How we exceeded WCAG requirements",
      "explanation": [
        "The brief demanded WCAG AAA (7:1) for body text on base. We achieved 13.44:1 — nearly double the requirement. This provides comfortable reading even in imperfect lighting conditions or on devices with lower contrast ratios.",
        "Secondary text at 5.46:1 (AA requires 4.5:1) gives comfortable headroom. Tertiary text at 3.04:1 meets AA-UI (3:1) — appropriate since it's used only for supplementary information like timestamps and tags, never for essential content.",
        "Code text (#3D342E) on the code surface (#EEEAE2) achieves 10.12:1 (AAA). Code is evidence — it must be maximally readable.",
        "Border tokens are split into three tiers: subtle (decorative, no contrast requirement — the 'score line'), default (separators), and strong (#8E857A at 3.20:1, for functional UI elements). This acknowledges that a publishing site's dividers are decorative, not interactive, while still providing accessible borders when needed."
      ]
    },

    "typographyRationale": {
      "title": "Three voices, mathematically grounded",
      "explanation": [
        "The Major Third ratio (1.25) was chosen because the brief explicitly asked for conservative hierarchy. At 1.25, the jump from body (18px) to H4 (22px) is perceptible but not dramatic — the family change from serif to sans does most of the work. Weight and family, not size, create the hierarchy.",
        "Heading sizes round to clean values: 22, 28, 36, 44px. Each pair's ratio stays within 1.17-1.29 of true Major Third — close enough for mathematical coherence, rounded enough for pixel clarity.",
        "The 18px body base was set by the brief, and it's correct for sustained technical reading in a serif face. At 1.125rem, it inherits browser zoom gracefully.",
        "Code at 16px (1rem / 0.9em of body) respects the 'different register' described in the aesthetic guide. JetBrains Mono at 16px with 1.6 line-height gives comfortable code reading without competing with the prose voice.",
        "Letter-spacing uses negative tracking for headings (-0.02em at h1, tapering to -0.005em at h4) because Inter at display sizes needs tightening to feel intentional. Body prose and code use normal tracking — the fonts were designed for these sizes.",
        "Blockquote at 20px italic is the only off-scale value — sitting between base (18) and lg (22). This is deliberate: a pull quote should feel like a different register, not a heading. The italic + size shift + left border treatment (defined in spacing) makes the voice unmistakable."
      ]
    },

    "spacingRationale": {
      "title": "Book typography meets code breakout",
      "explanation": [
        "The 8px grid provides the full range from fine-grain (4px component padding) to macro (96px section spacing). All semantic tokens map onto grid multiples.",
        "H2 above-spacing (64px / 4rem) creates the 'chapter break' the aesthetic guide describes. At nearly 4x the paragraph gap, it creates a decisive pause in the scroll. H2 below-spacing (16px / 1rem) is deliberately tight — the heading belongs to what follows, not what precedes it.",
        "Paragraph gap (24px) is ~1.33em at 18px base — within the 1.2-1.5em range specified, and landing on the 8px grid (3x base).",
        "Code block vertical margin (40px / 2.5rem) positions code as 'exhibited artifacts' — clearly separated from prose without creating visual gaps. The 3px left accent line in terracotta signals the register change from narrative to evidence.",
        "The prose column at 720px (45rem) produces ~65 characters per line at 18px Source Serif 4 — the typographic sweet spot for sustained reading. Code breaks to 840px (52.5rem) creating the narrow-wide-narrow rhythm described in the aesthetic guide."
      ]
    },

    "borderRadiusRationale": {
      "title": "Worn edges, not machined radii",
      "explanation": [
        "Four meaningful stops: 2px (inline code), 4px (code blocks, buttons), 6px (cards), 8px (larger panels). The progression feels like increasingly worn edges on workshop materials — slight softening, never roundness.",
        "No radius exceeds 8px except 'full' (pills/avatars). Nothing on this site should look like a mobile app button or a glassmorphism card."
      ]
    },

    "motionRationale": {
      "title": "Fast, barely-there, respectful",
      "explanation": [
        "150ms is the site's default transition — fast enough to feel instant, slow enough to not be jarring. Color transitions (hover, focus) at 100ms. Layout transitions at 250ms (rare — this is a reading site, not an app).",
        "prefers-reduced-motion reduces all durations to 0ms, no exceptions. This is non-negotiable.",
        "Only GPU-accelerated properties (transform, opacity) should be animated. Color transitions are the exception — they're so fast (100ms) that the CPU cost is negligible."
      ]
    },

    "whatWeDidNotDo": {
      "title": "Intentional omissions",
      "explanation": [
        "No dark mode tokens. The aesthetic guide explicitly says 'Ken's work happens in daylight.' Dark mode can be added later if needed — the semantic naming makes it straightforward.",
        "No elevation system. The brief says 'nothing floats.' Two shadow tokens (sm, md) are the maximum depth vocabulary.",
        "No animation choreography. A publishing site doesn't need entrance animations, scroll-triggered effects, or page transitions. Links change color. That's it.",
        "No breakpoint tokens. The layout is a single column that narrows gracefully. The prose column (720px) and code breakout (840px) handle their own responsive behavior within the 1100px container.",
        "No z-index scale. Nothing overlaps. The page is flat paper with ink on it."
      ]
    }
  }
}

Contrast Audit Results

Every text/background pairing was tested computationally. Full results:

Body Text (WCAG AAA — 7:1 required)

Pairing Ratio Result
text-primary (#2B2421) on surface-base (#F5F0E8) 13.44:1 PASS
text-primary (#2B2421) on surface-card (#FEFCF7) 14.87:1 PASS
text-primary (#2B2421) on surface-code (#EEEAE2) 12.71:1 PASS
text-primary (#2B2421) on surface-inset (#E8E3DA) 11.93:1 PASS

Secondary Text (WCAG AA — 4.5:1 required)

Pairing Ratio Result
text-secondary (#6B5F55) on surface-base (#F5F0E8) 5.46:1 PASS
text-secondary (#6B5F55) on surface-card (#FEFCF7) 6.04:1 PASS
text-secondary (#6B5F55) on surface-code (#EEEAE2) 5.16:1 PASS

Tertiary Text (WCAG AA UI — 3:1 required)

Pairing Ratio Result
text-tertiary (#948880) on surface-base (#F5F0E8) 3.04:1 PASS
text-tertiary (#948880) on surface-card (#FEFCF7) 3.36:1 PASS
Pairing Ratio Result
accent-primary (#A0522D) on surface-base (#F5F0E8) 4.95:1 PASS
accent-primary (#A0522D) on surface-card (#FEFCF7) 5.48:1 PASS
accent-primary (#A0522D) on surface-code (#EEEAE2) 4.68:1 PASS
accent-primaryHover (#8B4726) on surface-base (#F5F0E8) 6.12:1 PASS
accent-secondary (#7D6C2F) on surface-base (#F5F0E8) 4.56:1 PASS
accent-secondary (#7D6C2F) on surface-card (#FEFCF7) 5.05:1 PASS

Code Text (WCAG AAA — 7:1 required)

Pairing Ratio Result
code-text (#3D342E) on surface-code (#EEEAE2) 10.12:1 PASS

State Colors (WCAG AA — 4.5:1 required)

Pairing Ratio Result
success-text (#4A5E3A) on success-bg (#E8EDDF) 5.96:1 PASS
warning-text (#7A5C1F) on warning-bg (#F2E8D0) 5.10:1 PASS
error-text (#8B3A2A) on error-bg (#F2DED6) 5.92:1 PASS
info-text (#4A4540) on info-bg (#E5E2DA) 7.32:1 PASS

Functional Borders (WCAG AA UI — 3:1 required)

Pairing Ratio Result
border-strong (#8E857A) on surface-base (#F5F0E8) 3.20:1 PASS
border-strong (#8E857A) on surface-card (#FEFCF7) 3.54:1 PASS

Note: border-subtle and border-default are decorative (score lines, separators) and do not carry WCAG contrast requirements per WCAG 1.4.11 Non-text Contrast — decorative borders that don't convey information are exempt. border-strong is provided for any functional UI borders that DO need 3:1.


Implementation Notes

:root {
  /* Surfaces */
  --surface-base: #F5F0E8;
  --surface-card: #FEFCF7;
  --surface-code: #EEEAE2;
  --surface-inset: #E8E3DA;

  /* Text */
  --text-primary: #2B2421;
  --text-secondary: #6B5F55;
  --text-tertiary: #948880;

  /* Accents */
  --accent-primary: #A0522D;
  --accent-primary-hover: #8B4726;
  --accent-secondary: #7D6C2F;
  --accent-secondary-hover: #6B5C28;

  /* Code */
  --code-text: #3D342E;

  /* Borders */
  --border-subtle: #DDD7CD;
  --border-default: #C2BAA9;
  --border-strong: #8E857A;

  /* Focus */
  --focus-ring: #A0522D;

  /* State: Success */
  --success-bg: #E8EDDF;
  --success-text: #4A5E3A;
  --success-border: #B5C4A0;

  /* State: Warning */
  --warning-bg: #F2E8D0;
  --warning-text: #7A5C1F;
  --warning-border: #D4BC7C;

  /* State: Error */
  --error-bg: #F2DED6;
  --error-text: #8B3A2A;
  --error-border: #CFA090;

  /* State: Info */
  --info-bg: #E5E2DA;
  --info-text: #4A4540;
  --info-border: #B8B2A8;

  /* Shadows */
  --shadow-sm: 0 1px 3px rgba(43, 36, 33, 0.04);
  --shadow-md: 0 2px 8px rgba(43, 36, 33, 0.06);

  /* Typography families */
  --font-prose: 'Source Serif 4', 'Source Serif Pro', Georgia, 'Times New Roman', serif;
  --font-structure: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-evidence: 'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, monospace;

  /* Spacing */
  --space-0: 0;
  --space-px: 1px;
  --space-0-5: 0.25rem;
  --space-1: 0.5rem;
  --space-1-5: 0.75rem;
  --space-2: 1rem;
  --space-2-5: 1.25rem;
  --space-3: 1.5rem;
  --space-4: 2rem;
  --space-5: 2.5rem;
  --space-6: 3rem;
  --space-8: 4rem;
  --space-10: 5rem;
  --space-12: 6rem;

  /* Border radius */
  --rounded-none: 0;
  --rounded-sm: 2px;
  --rounded-md: 4px;
  --rounded-lg: 6px;
  --rounded-xl: 8px;
  --rounded-full: 9999px;

  /* Layout */
  --width-prose: 45rem;
  --width-code: 52.5rem;
  --width-container: 68.75rem;
  --gutter: 1.5rem;

  /* Motion */
  --duration-fast: 100ms;
  --duration-normal: 150ms;
  --duration-slow: 250ms;
  --ease-default: cubic-bezier(0.25, 0.1, 0.25, 1.0);
  --ease-in-out: cubic-bezier(0.45, 0.05, 0.55, 0.95);
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 0ms;
    --duration-normal: 0ms;
    --duration-slow: 0ms;
  }
}
<!-- Preconnect -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

<!-- Fonts — load only weights used -->
<link href="https://fonts.googleapis.com/css2?family=Source+Serif+4:ital,wght@0,400;0,600;1,400&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400&display=swap" rel="stylesheet">

Success Criteria

  • Functional: All tokens resolve to concrete CSS values. Zero undefined variables.
  • Aesthetic: Every color reads warm. The page feels like paper and ink under good light.
  • Accessibility: AAA body text (13.44:1), AA secondary (5.46:1), AA accent links (4.95:1). All verified.
  • Performance: Three fonts, minimal weights. No heavy shadow/blur calculations.
  • Longevity: Nothing here will look dated in 5 years. Paper, ink, and careful spacing don't go out of style.