Foundations
Color
A warm neutral canvas with one accent color — Ember Orange. Every token has a semantic name that adapts across light and dark; the hex values below are the light-theme reference. Only the brand orange keeps one unified hex in both themes.
01 — Backgrounds
Surface stack
Five background tokens on a cream canvas: page for the document root, surface / surface-2 / surface-3 for raised and nested layers, and bg-ink-1 for charcoal tooltips and dark-fill cards.
| Token | Hex | Role | Contrast |
|---|---|---|---|
bg-page | #f7f7f4 | Document canvas — outermost background | |
bg-surface | #ffffff | Cards, panels, raised containers | |
bg-surface-2 | #fafaf7 | Hover states, nested sections | |
bg-surface-3 | #f1f0eb | Deepest surface — active rows, selected cells | |
bg-ink-1 | #26251e | Dark surface — tooltips, install blocks, inverse cards | 16.1:1 AA |
Contrast ratio is measured against white (bg-surface) as the reference point for the inverse token; all others are informational.
02 — Brand
Ember Orange
One accent color, shared across light and dark. Use it for exactly four jobs — no more.
| Token | Hex | Role | Contrast |
|---|---|---|---|
color-brand | #e04a00 | CTA, active nav indicator, brand mark, data accent | 3.80:1 UI ✓ |
color-brand-hover | #cc4200 | Hover / pressed state | 4.29:1 UI ✓ |
color-brand-strong | #b43800 | Active / selected state with small text | 5.48:1 AA ✓ |
color-brand-muted | rgba(224,74,0,.06) | Tinted backgrounds, selected-row highlight (→ brand-overlay-08) |
01 · CTA
Primary buttons and main call-to-action elements
02 · Active nav
The sliding indicator behind the active PillNav item
03 · Brand mark
Logo lockup only — not decorative orange anywhere else
04 · Data accent
Score passing tier and chart highlight — one series only
03 — Brand ramp
Orange scale
Eight stops from cream-tinted white to near-black charcoal orange. Only the four tokens above are in the semantic layer.
04 — Borders
Stroke tokens
Two border families: alpha structural strokes for dividers and containers, and opaque control borders for form fields. Don't invent ad-hoc alphas — the eye can't distinguish near-identical alpha variants.
Structural strokes
border-glass-border
~0.06α
Panel dividers, section separators
border-stroke
0.15α
Cards, pills, message bubbles
border-stroke-2
0.22α
Hover, interactive emphasis
Form-control borders
--input-border
→ color-border-strong · #8c8a78
Inputs, selects, textareas — resting
--input-border-focus
→ color-brand · #e04a00
Active form control + 3px brand ring
05 — Text hierarchy
Ink scale
On light surfaces
| Token | Hex | Role | Contrast |
|---|---|---|---|
text-ink-1 | #26251e | Headings, key labels, strong emphasis | 16.1:1 AA |
text-ink-2 | #5a5852 | Body copy, descriptions, secondary content | 6.84:1 AA |
text-ink-3 | #67645d | Captions, metadata, placeholder text | 5.50:1 AA |
On filled surfaces
Use these when text sits on a dark or brand-colored fill. Never use text-ink-* on filled surfaces — contrast collapses in dark mode.
on-ink
text-on-ink
--color-on-ink
Cream on dark — primary buttons, install blocks
on-brand CTA
--color-on-brand
White on orange — large, bold CTA labels only
06 — Status
Feedback colors
Semantic status pairs — a surface fill and a text foreground. Always use the token pair together; never mix a solid from one role with a surface from another.
| Status | Solid | Surface | Text token | Live example | Contrast |
|---|---|---|---|---|---|
| Success | color-success-text | Verified | 7.2:1 AA | ||
| Warning | color-warning-text | Review | 6.8:1 AA | ||
| Error | color-error-text | Failed | 7.5:1 AA | ||
| Info | color-info-text | In progress | 8.1:1 AA |
07 — Greyscale
Neutral ramp
The whole neutral system — backgrounds, borders, and ink — is one warm-grey scale from bone to charcoal.
| Token | Hex | Role |
|---|---|---|
bg-page | #f7f7f4 | Document canvas — outermost background |
bg-surface | #ffffff | Cards, panels, raised containers |
bg-surface-2 | #fafaf7 | Hover states, nested sections |
bg-surface-3 | #f1f0eb | Deepest surface — active rows, selected cells |
color-border | #e6e5e0 | Default opaque border — dividers, card edges |
color-border-strong | #8c8a78 | Stronger opaque border — inputs, emphasis (WCAG 1.4.11) |
text-ink-3 | #67645d | Captions, metadata, placeholder text |
text-ink-2 | #5a5852 | Body copy, descriptions, secondary content |
text-ink-1 | #26251e | Headings, key labels · also bg-ink-1 |
08 — Hue map
Reserved hues
Each hue band is reserved for a semantic purpose. Before adding a new color token, identify its zone. If the zone is already claimed, reuse the existing token.
Brand + score tier ramp
Success only
Warning
Error
Category swatches + neutral ramp
Banned — do not use
09 — Score tier
Evaluation tiers
Three tiers for scoring outputs on a 0–5 scale. Passing uses Ember Orange — the same brand accent — reinforcing that improvement is the goal.
Below
< 3.0
Needs significant work. Warm grey signals an unscored state without alarming red.
Approaching
3.0 – 3.4
Making progress. Amber signals proximity to the passing bar.
Passing
≥ 3.5
Meets the standard. Ember Orange connects achievement to the brand.
| Token | Hex | Role | Contrast |
|---|---|---|---|
color-score-below | #cfcdc4 | Bar fill for scores below 3.0 | |
color-score-approaching | #f7a06e | Bar fill for scores 3.0–3.4 | |
color-score-passing | #e04a00 | Bar fill for scores ≥ 3.5 — same as color-brand | 3.80:1 UI ✓ |
Text variants (color-score-*-text) are same-hue lighter cousins of their bar fill — use them for labels and numeric readouts, not the bar token.