Add design/ contract extracted from the as-built UI
Inventory the as-built recaps.cc look and distill it into a durable, vendor-neutral design contract: design/DESIGN.md (nine-section brand brief) + design/tokens.tokens.json (W3C DTCG tokens), plus brand icon and provenance notes. Canonical calls reconciled with the owner: indigo #818cf8 as the single interactive accent, purple #a855f7 for premium only, the #0a0e1a->#111827->#0f172a surface ladder, and a normalized type scale. Wire the AGENTS.md Design line and record the contract-vs-code drift as a cleanup backlog in ROADMAP.md.
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
{
|
||||
"$schema": "https://tr.designtokens.org/format/",
|
||||
"$description": "Recap design tokens (W3C DTCG). Extracted from the as-built recaps.cc UI and reconciled 2026-06-16. Canonical roles only; see design/DESIGN.md for usage. Composite shadows and tint scales are documented strings, not strict DTCG primitives.",
|
||||
|
||||
"color": {
|
||||
"$type": "color",
|
||||
|
||||
"surface": {
|
||||
"$description": "Warm/cool elevation ladder over the navy base. Legacy darks #0a0e17/#0b1120 fold into base; #020617 folds into inset.",
|
||||
"base": { "$value": "#0a0e1a", "$description": "Page, body, sticky bars, full-height side panels. Also PWA theme_color/background_color." },
|
||||
"card": { "$value": "#111827", "$description": "Warm gray-900. Raised cards, modals, popovers, toasts, icon-buttons, steps, skeletons." },
|
||||
"inset": { "$value": "#0f172a", "$description": "Cool slate-900. Recessed fields & list rows: inputs, queue/sub items, model buttons, expanded chunk." },
|
||||
"raised-field": { "$value": "#1e293b", "$description": "Primary URL input only — lighter than inset so the hero field pops." }
|
||||
},
|
||||
|
||||
"border": {
|
||||
"default": { "$value": "#1e293b", "$description": "Slate-800. Default hairline — primary surface separator." },
|
||||
"hover": { "$value": "#334155", "$description": "Slate-700. Border on hover/active." },
|
||||
"strong": { "$value": "#475569", "$description": "Slate-600. Strongest hover border." }
|
||||
},
|
||||
|
||||
"accent": {
|
||||
"$description": "Indigo — THE single interactive accent.",
|
||||
"default": { "$value": "#818cf8", "$description": "Indigo-400. Submit/active fills, links, focus ring, timestamps, active marks." },
|
||||
"hover": { "$value": "#a5b4fc", "$description": "Indigo-300. Accent hover (lighter), active-line emphasis." },
|
||||
"legacy-500": { "$value": "#6366f1", "$description": "DEMOTED indigo-500 dup — migrate to accent.default. Do not introduce new." },
|
||||
"legacy-600": { "$value": "#4f46e5", "$description": "DEMOTED legacy hover for #6366f1 — migrate away." }
|
||||
},
|
||||
|
||||
"premium": {
|
||||
"$description": "Purple — RESERVED for paid/upgrade UI only. Never in non-premium surfaces.",
|
||||
"default": { "$value": "#a855f7", "$description": "Purple-500. Upgrade button, highlighted tier, buy badge, primary buy CTA." },
|
||||
"hover": { "$value": "#c084fc", "$description": "Purple-400." },
|
||||
"deep": { "$value": "#9333ea", "$description": "Purple-600. Pro-CTA hover." },
|
||||
"text": { "$value": "#c4b5fd", "$description": "Purple-300. Tier-badge & Pro text." },
|
||||
"text-soft": { "$value": "#d8b4fe", "$description": "Purple-200." }
|
||||
},
|
||||
|
||||
"text": {
|
||||
"primary": { "$value": "#e2e8f0", "$description": "Slate-200. Primary body/UI text." },
|
||||
"strong": { "$value": "#f1f5f9", "$description": "Slate-100. Headings/emphasis near-white. Canonical — fold stray #f5f9ff into this." },
|
||||
"body": { "$value": "#cbd5e1", "$description": "Slate-300. Running body copy (transcript, descriptions, bullets)." },
|
||||
"muted": { "$value": "#94a3b8", "$description": "Slate-400. Secondary/muted." },
|
||||
"label": { "$value": "#64748b", "$description": "Slate-500. Labels & placeholders." },
|
||||
"faint": { "$value": "#475569", "$description": "Slate-600. Faint meta, timestamps." },
|
||||
"dim": { "$value": "#334155", "$description": "Slate-700. Dimmest text (doubles as border.hover)." },
|
||||
"on-accent": { "$value": "#ffffff", "$description": "White — only on filled accent/premium buttons." }
|
||||
},
|
||||
|
||||
"status": {
|
||||
"$description": "Semantic status ramps. Use the tinted-triplet pattern for chips (see tint.*).",
|
||||
"success": { "$value": "#22c55e" },
|
||||
"success-text": { "$value": "#4ade80" },
|
||||
"success-soft": { "$value": "#86efac" },
|
||||
"success-deep": { "$value": "#16a34a" },
|
||||
"error": { "$value": "#ef4444" },
|
||||
"error-text": { "$value": "#f87171" },
|
||||
"error-soft": { "$value": "#fca5a5" },
|
||||
"error-deep": { "$value": "#dc2626" },
|
||||
"warning": { "$value": "#fbbf24" },
|
||||
"warning-soft": { "$value": "#fcd34d" },
|
||||
"warning-faint": { "$value": "#fde68a" },
|
||||
"warning-deep": { "$value": "#f59e0b" },
|
||||
"info": { "$value": "#3b82f6", "$description": "Blue-500. Info/status only (+ legacy auth accent). Not a primary interactive color in-app." },
|
||||
"info-mid": { "$value": "#60a5fa" },
|
||||
"info-soft": { "$value": "#93c5fd" }
|
||||
},
|
||||
|
||||
"speaker": {
|
||||
"$description": "8-hue categorical set for diarized speaker chips A–H. Rendered as the tinted triplet (bg α≈.18 / this text / border α≈.35).",
|
||||
"a": { "$value": "#fca5a5", "$description": "red — base rgb(239,68,68)" },
|
||||
"b": { "$value": "#93c5fd", "$description": "blue — base rgb(59,130,246)" },
|
||||
"c": { "$value": "#86efac", "$description": "green — base rgb(34,197,94)" },
|
||||
"d": { "$value": "#fcd34d", "$description": "amber — base rgb(245,158,11)" },
|
||||
"e": { "$value": "#d8b4fe", "$description": "purple — base rgb(168,85,247)" },
|
||||
"f": { "$value": "#7dd3fc", "$description": "sky — base rgb(14,165,233)" },
|
||||
"g": { "$value": "#f9a8d4", "$description": "pink — base rgb(236,72,153)" },
|
||||
"h": { "$value": "#cbd5e1", "$description": "slate — base rgb(100,116,139)" }
|
||||
}
|
||||
},
|
||||
|
||||
"tint": {
|
||||
"$type": "color",
|
||||
"$description": "Recurring translucent washes. Stored as documented rgba strings — they are tints of the named hues, not standalone primitives.",
|
||||
"accent-wash": { "$value": "rgba(129,140,248,0.06)", "$description": "Hover/active wash of accent.default. Family: .06 .08 .10 .15 .20." },
|
||||
"accent-active": { "$value": "rgba(129,140,248,0.08)", "$description": "Active background of accent.default." },
|
||||
"accent-ring": { "$value": "rgba(129,140,248,0.15)", "$description": "Focus-ring color → box-shadow 0 0 0 3px." },
|
||||
"chip-bg": { "$value": "rgba(34,197,94,0.10)", "$description": "Representative tinted-triplet background (α≈.10) — swap the hue per status/category." },
|
||||
"chip-border": { "$value": "rgba(34,197,94,0.20)", "$description": "Representative tinted-triplet border (α≈.20)." },
|
||||
"scrim": { "$value": "rgba(0,0,0,0.6)", "$description": "Overlay scrim behind modals; family .4 .5 .6 .65." }
|
||||
},
|
||||
|
||||
"font": {
|
||||
"family": {
|
||||
"$type": "fontFamily",
|
||||
"sans": { "$value": ["-apple-system", "BlinkMacSystemFont", "Segoe UI", "Roboto", "sans-serif"], "$description": "System stack — no web fonts." },
|
||||
"mono": { "$value": ["ui-monospace", "SF Mono", "Menlo", "Consolas", "monospace"], "$description": "Timestamps, license keys, URLs, code. Canonical — snap near-variants to this." }
|
||||
},
|
||||
"size": {
|
||||
"$type": "dimension",
|
||||
"$description": "Normalized scale (px). Snap strays 15→16, 24→22, 12.5/11.5→12, 10.5/9→10.",
|
||||
"10": { "$value": "10px", "$description": "micro labels, badges, meta, section labels" },
|
||||
"11": { "$value": "11px", "$description": "small labels, pills, hints, queue meta" },
|
||||
"12": { "$value": "12px", "$description": "secondary UI default — buttons, labels, stats" },
|
||||
"13": { "$value": "13px", "$description": "body default — descriptions, list items" },
|
||||
"14": { "$value": "14px", "$description": "emphasis / larger body, drawer & settings headers" },
|
||||
"16": { "$value": "16px", "$description": "input text, modal h2, section heads" },
|
||||
"18": { "$value": "18px", "$description": "sub-headers, logo wordmark, large numerals" },
|
||||
"20": { "$value": "20px", "$description": "headings" },
|
||||
"22": { "$value": "22px", "$description": "large headings, modal/activation titles, tier names" },
|
||||
"28": { "$value": "28px", "$description": "display — price" }
|
||||
},
|
||||
"weight": {
|
||||
"$type": "fontWeight",
|
||||
"$description": "Snap 650→600, 680→700.",
|
||||
"normal": { "$value": 400 },
|
||||
"medium": { "$value": 500 },
|
||||
"semibold": { "$value": 600, "$description": "The UI default weight." },
|
||||
"bold": { "$value": 700, "$description": "Headings, badges." },
|
||||
"extrabold": { "$value": 800, "$description": "Tier badge, big numerals." }
|
||||
},
|
||||
"lineHeight": {
|
||||
"$type": "number",
|
||||
"body": { "$value": 1.5 },
|
||||
"reading": { "$value": 1.55, "$description": "Denser reading blocks." },
|
||||
"title": { "$value": 1.3 },
|
||||
"title-large": { "$value": 1.25 },
|
||||
"single": { "$value": 1, "$description": "Single-line badges/controls." }
|
||||
},
|
||||
"letterSpacing": {
|
||||
"$type": "dimension",
|
||||
"label": { "$value": "0.05em", "$description": "Uppercase micro-labels." },
|
||||
"badge": { "$value": "0.04em" },
|
||||
"tracked": { "$value": "0.06em", "$description": "Tier/section labels (up to 0.08em)." },
|
||||
"tight": { "$value": "-0.01em", "$description": "Large display titles." }
|
||||
}
|
||||
},
|
||||
|
||||
"radius": {
|
||||
"$type": "dimension",
|
||||
"$description": "Snap strays 3→4, 5→6, 7→6|8, 9→8|10, 11→10|12.",
|
||||
"4": { "$value": "4px", "$description": "tiny chips, badges, drop-zones, skeleton lines" },
|
||||
"6": { "$value": "6px", "$description": "default small controls — buttons, chips, menu items" },
|
||||
"8": { "$value": "8px", "$description": "default medium — inputs, buttons, pills" },
|
||||
"10": { "$value": "10px", "$description": "larger cards/chunks, status bars" },
|
||||
"12": { "$value": "12px", "$description": "modals, popovers, menus" },
|
||||
"14": { "$value": "14px", "$description": "big cards, video embed, activation card" },
|
||||
"16": { "$value": "16px", "$description": "settings / buy modal" },
|
||||
"18": { "$value": "18px", "$description": "listen panel" },
|
||||
"pill": { "$value": "999px", "$description": "fully-rounded badges" },
|
||||
"circle": { "$value": "50%", "$description": "avatars, dots, play controls, spinner" }
|
||||
},
|
||||
|
||||
"space": {
|
||||
"$type": "dimension",
|
||||
"$description": "De-facto dense scale (px). Not a strict 4/8 grid; prefer these steps over new in-between values.",
|
||||
"4": { "$value": "4px" },
|
||||
"6": { "$value": "6px" },
|
||||
"8": { "$value": "8px" },
|
||||
"10": { "$value": "10px" },
|
||||
"12": { "$value": "12px" },
|
||||
"14": { "$value": "14px", "$description": "card margin" },
|
||||
"16": { "$value": "16px", "$description": "split-screen gap" },
|
||||
"20": { "$value": "20px" },
|
||||
"24": { "$value": "24px", "$description": "container horizontal padding" },
|
||||
"28": { "$value": "28px", "$description": "section padding" },
|
||||
"32": { "$value": "32px" },
|
||||
"36": { "$value": "36px", "$description": "landing container vertical padding" }
|
||||
},
|
||||
|
||||
"shadow": {
|
||||
"$type": "shadow",
|
||||
"$description": "Flat-by-default — shadows only for floating surfaces. Composite/glow values kept as documented strings.",
|
||||
"toast": { "$value": "0 8px 24px rgba(0,0,0,0.3)" },
|
||||
"drawer": { "$value": "0 8px 32px rgba(0,0,0,0.4)", "$description": "Video embed; side drawers use ±8px 0 32px." },
|
||||
"menu": { "$value": "0 12px 32px rgba(0,0,0,0.5)" },
|
||||
"panel": { "$value": "0 20px 60px rgba(0,0,0,0.5)", "$description": "Listen panel, activation card." },
|
||||
"modal": { "$value": "0 24px 64px rgba(0,0,0,0.5)", "$description": "Settings/buy modal (up to ...0.6)." },
|
||||
"glow-accent": { "$value": "0 4px 24px rgba(129,140,248,0.3)", "$description": "Submit button — signals primary." },
|
||||
"glow-accent-faint": { "$value": "0 2px 16px rgba(129,140,248,0.06)", "$description": "Expanded chunk." },
|
||||
"ring-accent": { "$value": "0 0 0 3px rgba(129,140,248,0.15)", "$description": "Input focus ring." },
|
||||
"glow-premium": { "$value": "0 12px 40px rgba(168,85,247,0.25)", "$description": "Highlighted premium tier." }
|
||||
},
|
||||
|
||||
"motion": {
|
||||
"$description": "Transitions are quick and functional. Durations as documented strings.",
|
||||
"duration": {
|
||||
"fast": { "$value": "0.15s", "$description": "Default control transition (transition: all 0.15s)." },
|
||||
"base": { "$value": "0.2s", "$description": "Cards, layout shifts." },
|
||||
"slow": { "$value": "0.4s", "$description": "Chunk-body max-height expand." }
|
||||
},
|
||||
"overlay-blur": { "$value": "blur(4px)", "$description": "Modal/overlay backdrop-filter; 4–6px range." }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user