Foundations
Tokens
Every color, size, radius, shadow, and duration is a CSS custom property on :root. Dark mode overrides those values under :root[data-theme="dark"]. Components read tokens — they never hardcode values.
Animation
Spring easing for entrances. Standard ease for micro-interactions. Four duration tiers from snappy to deliberate.
Easings
--ease-springcubic-bezier(0.16, 1, 0.3, 1) — overshoots slightly, feels alive
--ease-outease-out — clean deceleration
--ease-standardease — general-purpose transitions
Durations
--duration-fast0.15s — hover states, micro color changes
--duration-base0.22s — filter entrances, focus rings
--duration-moderate0.30s — modals, expandable regions
--duration-slow0.40s — page transitions, large surfaces
Colors
A warm neutral base with a cobalt brand, green reserved strictly for success/trust states, orange-red danger, and categorical data colors. All hues share a muted, slightly desaturated quality. Toggle the theme in the sidebar to see dark values.
Surfaces
Surface Subtle
--surface-subtle
Surface Page
--surface-page
Surface Muted
--surface-muted
Surface Inset
--surface-inset
Borders
Border Light
--border-light
Border Strong
--border-strong
Border Dashed
--border-dashed
Text
Secondary
--text-secondary
Brand — Cobalt
Status — Success (Green, reserved)
Success Light
--success-light
Success Dark
--success-dark
Status — Danger
Danger Light
--danger-light
Status — Warning
Warning Light
--warning-light
Status — Info & Accent
Accent Light
--accent-light
Data & Charts
Chart Violet
--chart-violet
Color conventions
Keep accents semantic, not decorative — every color should mean something:
- Green is reserved for trust.
--success means a verified-good state only — attested, approved, safe, healthy, running. Never spend green on chrome, actions, or decoration; that rarity is what makes the signal pop.
- Cobalt carries identity + interaction. Primary actions, links, focus, and selection use
--brand / --accent (same cobalt hue); info notices use --info. Solid fill reads as action, tinted container reads as info.
--warning is for caution only. Don't use the amber on neutral categories, filters, or counts — that reads as a false alarm. Use --text-secondary / --text-tertiary for plain labels.
- Brand logomark →
--logo. Your brand color in light, ink in dark — a saturated mark glows uncomfortably on dark surfaces. (Override --logo to your brand's hex.)
Radius
Six steps from sharp to pill. --radius (10px) is the default card radius; --radius-md (8px) is the default container radius.
Shadows
Subtle, layered shadows — never solid black, always transparent washes. Shadow tokens lift to higher opacity in dark mode to stay legible against the dark surface.
Spacing
A tight scale built for dense UI. Px-named so the value is always obvious. Used for padding, gap, margin, and any other length.
Typography
Bricolage Grotesque for headings, display, and numerics. DM Sans for all body and UI text. Both loaded from Google Fonts in a single request.
Font Families
--font-heading
Bricolage Grotesque
Display · Numerics · Headings · Slider values
--font-body
DM Sans
Body · Labels · UI text · Captions
Size Scale
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
Label caps · Section heading
Weights
--weight-lightLight 300 — light by definition
--weight-regularRegular 400 — body default
--weight-mediumMedium 500 — buttons, links
--weight-semiboldSemibold 600 — section headings
--weight-boldBold 700 — page titles, hero
Every token
The sections above explain the tokens that matter most. This table is all of them — rendered from lib/tokens.css by scripts/render-docs.py, so it cannot fall behind the file. Dark shows only where it differs from light.
Tier 1 — Primitives
| Token | Light | Dark |
--warm-0 | #FFFFFF | — |
--warm-50 | #F7F4F2 | — |
--warm-100 | #F1EDEB | — |
--warm-150 | #EBE6E3 | — |
--warm-200 | #E5DFDC | — |
--warm-300 | #D6CFCB | — |
--warm-400 | #C2B9B5 | — |
--warm-500 | #A89E99 | — |
--warm-600 | #8A7F7B | — |
--warm-700 | #6E625F | — |
--warm-800 | #5C504F | — |
--warm-900 | #3A302E | — |
--warm-950 | #1E1918 | — |
--cobalt-50 | #EEF1FB | #1A2342 |
--cobalt-100 | #DBE2F4 | — |
--cobalt-200 | #BCC9EA | #2E3F6B |
--cobalt-300 | #93A8DE | — |
--cobalt-400 | #6E86D2 | — |
--cobalt-500 | #4761BE | — |
--cobalt-600 | #2F4BA6 | #8AA0DE |
--cobalt-700 | #243B83 | #7E96D8 |
--cobalt-800 | #1C2F66 | — |
--cobalt-900 | #16244E | — |
--green-100 | #F2F6F2 | #1F2A1F |
--green-300 | #C8D9C7 | #3F603E |
--green-500 | #629460 | #8FB68D |
--green-700 | #3F603E | #C8D9C7 |
--clay-100 | #F4EFEA | #251D19 |
--clay-300 | #DCC9B5 | #4A3A24 |
--clay-600 | #9A6B33 | #C9A063 |
--clay-700 | #6B4B3E | — |
--red-100 | #FBEFEB | #2E1C13 |
--red-300 | #EBB39D | #6E3217 |
--red-500 | #CE430A | #E66B36 |
--azure-500 | #0EA5E9 | #3DBEF5 |
--azure-light | #EBF7FD | — |
--amber-chart | #B98326 | #D4A04A |
--violet-chart | #6B4B8A | #9F7CBC |
--elevation-sm | 0 1px 2px rgba(30,25,24,0.05), 0 1px 1px rgba(30,25,24,0.04) | 0 1px 2px rgba(0,0,0,0.40), 0 1px 1px rgba(0,0,0,0.30) |
--elevation-md | 0 2px 4px rgba(30,25,24,0.05), 0 6px 16px rgba(30,25,24,0.06) | 0 2px 4px rgba(0,0,0,0.40), 0 6px 16px rgba(0,0,0,0.40) |
--elevation-lg | 0 8px 24px rgba(30,25,24,0.10) | 0 8px 24px rgba(0,0,0,0.50) |
--elevation-xl | 0 16px 40px rgba(30,25,24,0.14), 0 2px 6px rgba(30,25,24,0.06) | 0 16px 40px rgba(0,0,0,0.60), 0 2px 6px rgba(0,0,0,0.30) |
Tier 2 — Semantic
| Token | Light | Dark |
--surface | var(--warm-0) | #1F1A18 |
--surface-subtle | var(--warm-50) | #19130F |
--surface-page | var(--warm-50) | #16110F |
--surface-muted | var(--warm-100) | #2A211E |
--surface-inset | var(--warm-150) | #322924 |
--border | var(--warm-300) | #3A312D |
--border-light | var(--warm-200) | #2E2722 |
--border-dashed | var(--warm-500) | #6B5C57 |
--border-strong | var(--warm-400) | #4D423D |
--border-hairline | color-mix(in srgb, var(--warm-950) 8%, transparent) | color-mix(in srgb, #F4EEEC 9%, transparent) |
--text-primary | var(--warm-950) | #F4EEEC |
--text-secondary | var(--warm-800) | #C5B6B2 |
--text-tertiary | var(--warm-700) | #A0928E |
--text-inverse | #FFFFFF | #1E1918 |
--text-disabled | #B5ABA8 | #756763 |
--brand | var(--cobalt-600) | — |
--brand-light | var(--cobalt-50) | — |
--brand-mid | var(--cobalt-200) | — |
--brand-dark | var(--cobalt-700) | — |
--brand-fg | #FFFFFF | #03131C |
--success | var(--green-500) | — |
--success-light | var(--green-100) | — |
--success-mid | var(--green-300) | — |
--success-dark | var(--green-700) | — |
--success-fg | #FFFFFF | #0E1A0D |
--logo | var(--brand) | var(--text-primary) |
--danger | var(--red-500) | — |
--danger-light | var(--red-100) | — |
--danger-mid | var(--red-300) | — |
--danger-fg | #FFFFFF | #190B05 |
--warning | var(--clay-600) | — |
--warning-light | var(--clay-100) | — |
--warning-mid | var(--clay-300) | — |
--warning-fg | #FFFFFF | #1A100C |
--info | var(--cobalt-700) | — |
--info-light | var(--cobalt-50) | — |
--info-mid | var(--cobalt-200) | — |
--info-fg | #FFFFFF | #06101F |
--accent | var(--cobalt-600) | — |
--accent-light | var(--cobalt-50) | — |
--accent-fg | #FFFFFF | #03131C |
--data-inflow | var(--red-500) | — |
--data-outflow | var(--green-500) | — |
--data-target | var(--warm-500) | #847671 |
--chart-blue | var(--cobalt-700) | — |
--chart-azure | var(--azure-500) | — |
--chart-amber | var(--amber-chart) | — |
--chart-violet | var(--violet-chart) | — |
--ring | color-mix(in srgb, var(--accent) 55%, transparent) | — |
--ring-offset | var(--surface) | — |
--font-heading | 'Bricolage Grotesque', system-ui, sans-serif | — |
--font-body | 'DM Sans', system-ui, sans-serif | — |
--font-mono | ui-monospace, 'SF Mono', Menlo, Consolas, monospace | — |
--text-2xs | 9px | — |
--text-xs | 10px | — |
--text-sm | 11px | — |
--text-md | 12px | — |
--text-base | 13px | — |
--text-lg | 16px | — |
--text-xl | 19px | — |
--text-2xl | 23px | — |
--text-3xl | 28px | — |
--text-4xl | 33px | — |
--text-5xl | 48px | — |
--weight-light | 300 | — |
--weight-regular | 400 | — |
--weight-medium | 500 | — |
--weight-semibold | 600 | — |
--weight-bold | 700 | — |
--leading-tight | 1 | — |
--leading-snug | 1.1 | — |
--leading-compact | 1.3 | — |
--leading-normal | 1.5 | — |
--tracking-tight | -0.02em | — |
--tracking-snug | -0.01em | — |
--tracking-slight | -0.005em | — |
--tracking-caps | 0.07em | — |
--numeric-tabular | "tnum" 1, "lnum" 1 | — |
--space-0 | 0px | — |
--space-2 | 2px | — |
--space-4 | 4px | — |
--space-5 | 4px | — |
--space-6 | 6px | — |
--space-7 | 8px | — |
--space-8 | 8px | — |
--space-10 | 10px | — |
--space-12 | 12px | — |
--space-14 | 14px | — |
--space-16 | 16px | — |
--space-18 | 18px | — |
--space-20 | 20px | — |
--space-24 | 24px | — |
--space-32 | 32px | — |
--space-40 | 40px | — |
--space-48 | 48px | — |
--space-64 | 64px | — |
--radius-2xs | 2px | — |
--radius-xs | 4px | — |
--radius-sm | 6px | — |
--radius-md | 8px | — |
--radius | 8px | — |
--radius-lg | 12px | — |
--radius-full | 9999px | — |
--shadow-card | var(--elevation-sm) | — |
--shadow-nav | var(--elevation-sm) | — |
--shadow-toggle | var(--elevation-sm) | — |
--shadow-hover | var(--elevation-md) | — |
--shadow-modal | var(--elevation-xl) | — |
--shadow-dropdown | var(--elevation-lg) | — |
--shadow-overlay | var(--elevation-lg) | — |
--shadow-focus | 0 0 0 3px var(--ring) | — |
--size-icon-sm | 13px | — |
--size-icon-base | 18px | — |
--size-icon-lg | 22px | — |
--size-avatar-sm | 24px | — |
--size-avatar-md | 30px | — |
--size-avatar-lg | 34px | — |
--size-control-sm | 24px | — |
--size-control-md | 32px | — |
--size-control-lg | 40px | — |
--size-status-dot-sm | 6px | — |
--size-status-dot-base | 7px | — |
--size-status-dot-lg | 8px | — |
--sidebar-w | 56px | — |
--topbar-h | 56px | — |
--ease-spring | cubic-bezier(0.16, 1, 0.3, 1) | — |
--ease-out | ease-out | — |
--ease-standard | ease | — |
--duration-fast | 0.15s | — |
--duration-base | 0.22s | — |
--duration-moderate | 0.30s | — |
--duration-slow | 0.40s | — |
--z-dropdown | 50 | — |
--z-sticky | 100 | — |
--z-overlay | 200 | — |
--z-modal | 300 | — |
--z-toast | 400 | — |
--z-tooltip | 500 | — |
Tier 3 — Component
| Token | Light | Dark |
--button-bg | var(--brand) | — |
--button-fg | var(--brand-fg) | — |
--card-bg | var(--surface) | — |
--card-shadow | var(--shadow-card) | — |
--input-bg | var(--surface) | — |
--input-border | var(--border) | — |