Design tokens + agent iteration hardening

- tokens.css: full token layer (type scale rem-based, palette, spacing, radii)
- App.css rebuilt token-driven; zero hardcoded colors/px font sizes
- readability preset: --root-font-size 112%; button matrix scrolls when narrow
- App.tsx split into real components (Hero, CodeSample, RightRail + reflow)
- light theme via [data-theme=light] overrides; topbar sun/moon toggle persisted
- scripts/check-tokens.mjs + npm run check (lint, token guard, tsc, build)
- AGENTS.md: token contract, check gate, preview workflow
This commit is contained in:
mats committed 2026-09-12 10:07:07 +00:00
1 parent b1049d5ded
commit 47127db84b
20 files changed
+874 -57

No files matched your search

+129
View File
@@ -0,0 +1,129 @@
/* ─────────────────────────────────────────────────────────────
Northstar design tokens — single source of truth.
App.css (and every future stylesheet) consumes ONLY these
variables. Change a token here and the whole UI follows.
Key one-liners:
• global text density ......... --root-font-size (e.g. 112%)
• "small text a bit larger" ... bump --text-xs / --text-2xs
• new color ................... add a token, never a hex
• accent washes ............... color-mix(in srgb, var(--accent) N%, transparent)
───────────────────────────────────────────────────────────── */
:root {
/* Global amplifier: every token-driven font size scales from
the root size. 100% = 16px. Readability preset: 112%. */
--root-font-size: 112%;
/* ── Type scale (rem-based, snaps to the 9→28px grid) ───── */
--text-3xs: 0.5625rem; /* 9px micro labels */
--text-2xs: 0.625rem; /* 10px eyebrows, meta */
--text-xs: 0.6875rem; /* 11px buttons, nav */
--text-sm: 0.75rem; /* 12px inputs, copy */
--text-md: 0.875rem; /* 14px longform body */
--text-base: 1rem; /* 16px ledes, brand */
--text-lg: 1.3125rem; /* 21px card headings */
--text-xl: 1.5625rem; /* 25px sub-headlines */
--text-2xl: 1.75rem; /* 28px section titles */
--text-hero: clamp(2.625rem, 5vw, 4.375rem); /* 42→70px display */
/* ── Type families ──────────────────────────────────────── */
--font-sans: 'Manrope', sans-serif;
--font-mono: 'DM Mono', monospace;
/* ── Surfaces ───────────────────────────────────────────── */
--bg: #0b0b10; /* page base */
--bg-deep: #0d0d13; /* code blocks, editor, sidebar wash */
--panel: #111118; /* cards */
--panel-2: #16161f; /* inputs, tabs */
--panel-3: #1b1b25; /* raised panels, hovers */
--panel-hover: #191923; /* interactive surfaces on hover */
--panel-active: #252535;/* pressed / selected surfaces */
/* ── Lines ──────────────────────────────────────────────── */
--line: #292933; /* default border */
--line-soft: #202029; /* hairlines inside dense grids */
--line-hover: #4a4760; /* border on hover / accent-tinted */
--line-focus: #5b5486; /* focused inputs, search */
/* ── Text ───────────────────────────────────────────────── */
--text: #f1f0f7; /* primary */
--text-bright: #f5f3ff; /* active nav, tab-selected */
--text-soft: #b8b6c4; /* longform body */
--text-code: #c8c5d2; /* code blocks */
--muted: #92919e; /* secondary */
--subtle: #666572; /* tertiary, disabled */
/* ── Accents & status ───────────────────────────────────── */
--accent: #a69bff;
--accent-contrast: #171526; /* text/icons placed on accent */
--positive: #73dfae;
--warning: #ffc777;
--critical: #ff8585;
--pink: #e58bff;
--blue: #9bcbff;
/* ── Spacing (4px rhythm; 1 = 4px … 11 = 80px) ──────────── */
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 0.75rem;
--space-4: 1rem;
--space-5: 1.25rem;
--space-6: 1.5rem;
--space-7: 2rem;
--space-8: 2.5rem;
--space-9: 3rem;
--space-10: 4rem;
--space-11: 5rem;
/* ── Radii ──────────────────────────────────────────────── */
--radius-sm: 5px; /* kbd, inputs */
--radius-md: 6px; /* buttons, nav items */
--radius-lg: 9px; /* cards, showcases */
--radius-xl: 12px; /* brand mark, orbit core */
--radius-2xl: 14px; /* callouts */
--radius-pill: 20px; /* toggles */
/* ── Focus ──────────────────────────────────────────────── */
--focus-ring: 2px solid var(--accent);
--focus-offset: 3px;
}
/* ── Light theme ──────────────────────────────────────────────
Same token names, daylight values. Components never know the
difference — they only ever read var(--*). Toggle via
document.documentElement.dataset.theme = 'light' (Topbar does
this and persists to localStorage under 'ns-theme'). */
:root[data-theme='light'] {
--bg: #f6f5fb;
--bg-deep: #efedf6;
--panel: #ffffff;
--panel-2: #f3f1f9;
--panel-3: #eae7f4;
--panel-hover: #e7e4f1;
--panel-active: #dedbf0;
--line: #d8d5e7;
--line-soft: #e4e2ee;
--line-hover: #b3abda;
--line-focus: #8d82cf;
--text: #1e1a30;
--text-bright: #141126;
--text-soft: #4b4665;
--text-code: #383354;
--muted: #625d7d;
--subtle: #8d89a3;
/* Deeper accent + saturated status colors for light-surface contrast */
--accent: #6b46e5;
--accent-contrast: #ffffff;
--positive: #178a5c;
--warning: #a05f00;
--critical: #d14141;
--pink: #bb2fc0;
--blue: #2f66c9;
}
html { font-size: var(--root-font-size); }