Color Tokens
All tokens are defined in ui/src/styles/base.css under :root (dark mode default) and :root[data-theme-mode="light"] (light override). Theme families may override accent tokens while keeping shared surface tokens.
Contrast ratios are measured against --bg (#0e1015) in dark mode using WCAG relative luminance formula. AA requires ≥4.5:1 for normal text, ≥3:1 for large text and UI components.
Background Scale
| Token |
Dark Value |
Light Value |
Use |
Don't |
--bg |
#0e1015 |
#faf9f7 |
Page root, deepest layer |
Never use on elevated surfaces |
--bg-accent |
#13151b |
#f4f1ec |
Sidebar, secondary panels |
Not for interactive card hover |
--bg-elevated |
#191c24 |
#ffffff |
Raised panels, modals |
Not for inline elements |
--bg-hover |
#1f2330 |
#efebe4 |
List item hover state |
Not for default state |
--bg-muted |
#1f2330 |
#efebe4 |
Subtle fills, disabled states |
Not for focus states |
Light mode uses a warm paper palette: ivory backgrounds, warm gray borders (#e8e4dc), and a terracotta accent (#bd4531, ≈4.9:1 on --bg). Dark mode keeps the signature coral red.
Surface / Card
| Token |
Dark Value |
Light Value |
Use |
Don't |
--card |
#161920 |
#ffffff |
Card backgrounds, composer |
Avoid as border |
--card-foreground |
#f0f0f2 |
#211e1a |
Text on cards |
— |
--card-highlight |
rgba(255,255,255,0.04) |
rgba(60,42,24,0.03) |
Inner highlight on hover |
Not for text |
--popover |
#191c24 |
#ffffff |
Dropdown, tooltip backgrounds |
— |
--popover-foreground |
#f0f0f2 |
#211e1a |
Text inside popovers |
— |
Text
| Token |
Dark Value |
Contrast on --bg |
Use |
--text |
#d4d4d8 |
~12.9:1 ✅ |
Body copy, labels |
--text-strong |
#f4f4f5 |
~17.3:1 ✅ |
Headings, emphasis |
--muted |
#838387 |
~5.0:1 ✅ |
Placeholder, metadata |
--muted-strong |
#75757d |
~4.2:1 |
Secondary text, captions; avoid for normal body text |
Accent (Primary — Red)
| Token |
Value |
Use |
Don't |
--accent |
#ff5c5c |
Primary CTA, send button, active tab indicator |
Don't use for large filled backgrounds |
--accent-hover |
#ff7070 |
Hover state of accent elements |
— |
--accent-muted |
#ff5c5c |
Same as accent (aliased) |
— |
--accent-subtle |
rgba(255,92,92,0.1) |
Badge backgrounds, tinted fills |
Not for text on dark bg (fails contrast) |
--accent-glow |
rgba(255,92,92,0.2) |
Focus rings, glow effects |
Not as background |
--primary |
#ff5c5c |
Component library primary alias |
— |
Accent 2 (Teal)
| Token |
Value |
Use |
--accent-2 |
#14b8a6 |
Success-adjacent status, secondary badges |
--accent-2-muted |
rgba(20,184,166,0.7) |
Subtle teal fills |
--accent-2-subtle |
rgba(20,184,166,0.1) |
Tinted teal background |
Semantic
| Token |
Dark Value |
Light Value |
Contrast on --bg |
Use |
--ok |
#22c55e |
#15803d |
~8.4:1 ✅ |
Success states, token meter low |
--warn |
#f59e0b |
#d97706 |
~8.9:1 ✅ |
Warnings, degraded states |
--danger |
#ef4444 |
#dc2626 |
~5.1:1 ✅ |
Errors, destructive actions, token meter high |
--info |
#3b82f6 |
#2563eb |
~5.2:1 ✅ |
Informational, token meter mid |
--destructive |
#ef4444 |
— |
~5.1:1 ✅ |
Destructive action labels |
Border
| Token |
Value |
Use |
--border |
#1e2028 |
Default subtle borders, dividers |
--border-strong |
#2e3040 |
Active/focused borders |
--border-hover |
#3e4050 |
Hover-state borders |
Focus
| Token |
Value |
Use |
--ring |
#ff5c5c |
Focus ring colour |
--focus-ring |
0 0 0 2px var(--bg), 0 0 0 3px color-mix(in srgb, var(--ring) 80%, transparent) |
Standard focus ring box-shadow |
--focus-glow |
0 0 0 2px var(--bg), 0 0 0 3px var(--ring), 0 0 16px var(--accent-glow) |
Elevated interactive elements |
Anti-Patterns
- ❌ Hardcoded hex colours in component CSS — always use tokens
- ❌
--accent-subtle as text colour — fails contrast on dark backgrounds
- ❌ Mixing
--ok and --accent-2 for "green success" — use --ok only
- ❌ Using
--danger for non-error states (e.g. "hot feature") — reserve for errors and destructive actions
- ❌
--muted-strong for normal body text — below 4.5:1 on dark --bg; use --text instead