Foundations

The foundations are the design tokens every component reads from. They are plain CSS custom properties declared once on :root in styles.css — no preprocessor, no theme compiler. Change a token, reload, and every component that consumes it updates. Components must never hard-code a colour, radius, or shadow; they reference a token so the system stays coherent and themeable.

Status legend — ✅ shipped · 🟡 partial · ⬜ planned. Foundations marked ⬜ are tokens we intend to add as the system grows; they are named here so components can be specified against them before they land.

Colour ✅

Surfaces, from furthest-back to nearest-front, then text, then semantic accents. The palette is dark-first; a light theme is a second :root token set (⬜).

--bg        #0a0c11   page background (deepest)
--bg-2      #0f131b   recessed background
--panel     #141925   raised surface (cards, inputs)
--panel-2   #1a2030   raised surface, one step up
--border    #232b3b   hairline divider / control border
--border-2  #2c3650   stronger border (hover, emphasis)
--fg        #e7ebf3   primary text
--muted     #8a93a8   secondary text, labels
--dim       #5c647a   tertiary text, disabled
--accent    #5b8cff   brand / primary action
--accent-2  #8a6bff   gradient companion to --accent
--ok        #3ddc84   success
--warn      #f5b945   warning
--info      #58b2ff   info
--danger    #ff6b6b   error / destructive

Usage rule — text colour comes from --fg / --muted / --dim; never set a raw hex in a component. Semantic colours (--ok/--warn/--info/--danger) are only for status meaning, never decoration. Tints are derived live with color-mix(in srgb, var(--ok) 10%, var(--panel)) rather than hand-mixed hexes.

Typography 🟡

One system font stack today; a token-driven type scale is planned so headings, body, and captions all snap to fixed steps.

--font-sans  ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif   ✅
--mono       ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace                ✅

--text-xs    12px / 1.4     ⬜    captions, eyebrows, table headers
--text-sm    13px / 1.5     ⬜    labels, secondary
--text-base  16px / 1.65    ⬜    body (current default)
--text-lg    19px / 1.5     ⬜    lede
--text-xl    24px / 1.2     ⬜    section titles
--text-2xl   30px / 1.15    ⬜    page titles
--text-3xl   clamp(34px,6vw,60px) ⬜  hero

Usage rule — body sets font: 16px/1.65 var(--font-sans). Headings use negative letter-spacing (-0.02em to -0.03em) for tightness. Code uses var(--mono) at ~0.88em of its context.

Spacing ⬜

The grid is implicit today (per-component padding). We want one 4px-based scale so gaps and padding are never arbitrary.

--space-1   4px      --space-4   16px     --space-8   48px
--space-2   8px      --space-5   24px     --space-10  64px
--space-3   12px     --space-6   32px     --space-12  88px

Usage rule — once shipped, every gap/padding/margin resolves to a --space-* step. Component demos already cluster at 12/14/18/24px — those become --space-3/--space-4/--space-5.

Radius ✅

--radius      14px    ✅   cards, panels, large surfaces
--radius-sm   9px     🟡   inputs, small controls (in use, not yet tokenised)
--radius-btn  10px    🟡   buttons (in use, not yet tokenised)
--radius-pill 999px   🟡   badges, pills, status dots

Usage rule — promote the in-use literals (9px/10px/999px) to tokens so the whole system rounds consistently.

Elevation & shadow ✅

--shadow   0 24px 60px -28px #000   ✅   floating panels, dropdowns, modals

Buttons and inputs carry their own focal glow rather than a drop shadow: box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent) for focus, 0 10px 26px -12px var(--accent) for the primary button. A small set of elevation steps (--shadow-sm/-md/-lg) is planned ⬜.

Motion ⬜

Interactions today use ad-hoc durations (transform .04s, filter .15s). We want a motion scale so every transition feels of one piece.

--ease       cubic-bezier(.2, .7, .3, 1)   ⬜
--dur-fast   80ms     ⬜    press, hover
--dur-base   150ms    ⬜    colour / background
--dur-slow   240ms    ⬜    overlays entering

Usage rule — respect prefers-reduced-motion; overlays and toasts must drop to opacity-only transitions when it is set.

Z-index ⬜

A named stacking order prevents overlay wars. Current literals: nav 20. Target:

--z-base      0       --z-dropdown  1000     --z-toast     1200
--z-sticky    20      --z-overlay   1100      --z-tooltip   1300

Breakpoints 🟡

One breakpoint exists today; we name the rest for responsive component specs.

sm   ≤ 640px    ⬜
md   ≤ 820px    ✅   (the current grid-collapse point)
lg   ≤ 1080px   🟡   (container max-width)
xl   ≥ 1280px   ⬜

Theming ⬜

Because everything is tokens on :root, a theme is just an alternate token set. Planned: a [data-theme="light"] block overriding the colour tokens, toggled with one attribute on <html> and no JavaScript framework. Per-tenant brand themes (an AkurAI use case) become a single generated :root override file.