Colors
Four palettes — Iron Night, Birch Mist, Forest, Bloom — organised by role. A two-layer token architecture separates raw palette values from semantic aliases, so components never need to know which theme mode they are in.
Palette Tokens
Raw palette tokens are defined once and never change. Use them directly only for brand moments and design showcases — all production components reference the semantic layer instead.
Iron Night — Dark Surfaces
--in0-void#0D1117--in1-iron#374151--in2-slate#4B5563--in3-ash#6B7280| Token | Hex | Role |
|---|---|---|
--in0-void | #0D1117 | Primary background (dark mode) |
--in1-iron | #374151 | Elevated surfaces — panels, cards on dark |
--in2-slate | #4B5563 | Active lines, selections, highlights |
--in3-ash | #6B7280 | Secondary text, placeholders (AA-large only) |
Birch Mist — Light Surfaces
--bm0-sand#D5D2C7--bm1-mist#E9E6DC--bm2-birch#F7F6F3| Token | Hex | Role |
|---|---|---|
--bm0-sand | #D5D2C7 | Elevated UI (light), input fills, sunken surfaces |
--bm1-mist | #E9E6DC | Card fill, hover states, tinted sections |
--bm2-birch | #F7F6F3 | Primary background (light) / primary text (dark) |
Forest — Accent
--fo0-sage#5C9E86--fo1-fern#3E7A62--fo2-forest#2D5E4A--fo3-deepwater#254D5A| Token | Hex | Role |
|---|---|---|
--fo0-sage | #5C9E86 | Supporting accent, dark-mode hover state for Fern |
--fo1-fern | #3E7A62 | Primary accent — buttons, links, CTAs (both modes) |
--fo2-forest | #2D5E4A | Accent hover, secondary emphasis |
--fo3-deepwater | #254D5A | Code block backgrounds (light pages), blockquote accent |
Bloom — Semantic States
--bl0-ember#C5414C--bl1-ochre#AB5A2B--bl2-grain#8D6B20--bl3-moss#567A37--bl4-heather#885DB4| Token | Hex | Role |
|---|---|---|
--bl0-ember | #C5414C | Error, destructive actions |
--bl1-ochre | #AB5A2B | Annotation, decorator-weight info |
--bl2-grain | #8D6B20 | Warning, draft, pending |
--bl3-moss | #567A37 | Success, published, active |
--bl4-heather | #885DB4 | Special states, beta, experimental |
Semantic Token Layer
Components always reference semantic tokens — never palette tokens directly. The semantic layer resolves to the correct palette value per theme mode automatically.
Light Mode (default)
:root,
[data-theme="light"] {
--color-bg: var(--bm2-birch); /* Page background */
--color-bg-panel: var(--bm1-mist); /* Cards, panels */
--color-bg-inset: var(--bm0-sand); /* Input fills */
--color-bg-code: var(--fo3-deepwater); /* Code block background */
--color-text: var(--in0-void); /* Primary text */
--color-text-secondary: var(--in2-slate); /* Supporting text */
--color-text-tertiary: var(--in3-ash); /* Placeholders, captions */
--color-border: var(--in3-ash); /* Default border */
--color-border-strong: var(--in1-iron); /* Prominent dividers */
--color-border-subtle: rgba(55,65,81,0.12); /* Hairline borders */
--color-ghost-border: rgba(55,65,81,0.25); /* Ghost button border */
--color-accent: var(--fo1-fern); /* Primary CTA, links */
--color-accent-hover: var(--fo2-forest); /* Accent hover */
--color-accent-text: var(--bm2-birch); /* Text on accent bg */
--color-error: var(--bl0-ember); /* Error, destructive */
--color-warning: var(--bl2-grain); /* Warning, draft */
--color-success: var(--bl3-moss); /* Success, published */
} Dark Mode
[data-theme="dark"] {
--color-bg: var(--in0-void);
--color-bg-panel: var(--in1-iron);
--color-bg-inset: var(--in2-slate);
--color-bg-code: var(--in1-iron);
--color-text: var(--bm2-birch);
--color-text-secondary: var(--bm1-mist);
--color-text-tertiary: var(--bm0-sand);
--color-border: var(--in2-slate);
--color-border-strong: var(--bm0-sand);
--color-border-subtle: rgba(75,85,99,0.25);
--color-ghost-border: rgba(247,246,243,0.25);
--color-accent: var(--fo1-fern);
--color-accent-hover: var(--fo0-sage);
--color-accent-text: var(--bm2-birch);
--color-error: var(--bl0-ember);
--color-warning: var(--bl2-grain);
--color-success: var(--bl3-moss);
} Surface Depth
Apply data-surface to set a depth level on any element. All surfaces are relative — they adapt when the page theme switches. Use data-theme on an element to force a specific theme context.
<section data-surface="base"> … </section> <!-- page-level -->
<section data-surface="layer"> … </section> <!-- cards, panels -->
<section data-surface="overlay"> … </section> <!-- modals, dropdowns -->
<section data-theme="dark" data-surface="layer"> … </section> <!-- forced dark panel --> Accessibility
Full contrast matrix for all semantic foreground/background token pairs. Ratings follow WCAG 2.1: AAA ≥ 7:1 · AA ≥ 4.5:1 · AA Large ≥ 3:1 (≥ 24 px regular, or ≥ 19 px bold) · Fail < 3:1.
Light mode
| Foreground token | on --color-bg | on --color-bg-elevated | on --color-bg-sunken |
|---|---|---|---|
--color-text | 17.51:1 AAA | 15.15:1 AAA | 12.50:1 AAA |
--color-text-secondary | 6.99:1 AA | 6.05:1 AA | 4.99:1 AA |
--color-text-tertiary | 4.47:1 AA Large | 3.87:1 AA Large | 3.19:1 AA Large |
--color-accent | 4.67:1 AA | 4.04:1 AA Large | 3.33:1 AA Large |
--color-accent-hover | 6.91:1 AA | 5.98:1 AA | 4.93:1 AA |
--color-accent-text † | 1.00:1 Fail | 1.16:1 Fail | 1.40:1 Fail |
--color-error | 4.59:1 AA | 3.97:1 AA Large | 3.28:1 AA Large |
--color-warning | 4.57:1 AA | 3.95:1 AA Large | 3.26:1 AA Large |
--color-success | 4.59:1 AA | 3.97:1 AA Large | 3.28:1 AA Large |
Dark mode
| Foreground token | on --color-bg | on --color-bg-elevated | on --color-bg-sunken |
|---|---|---|---|
--color-text | 17.51:1 AAA | 9.54:1 AAA | 17.51:1 AAA |
--color-text-secondary | 15.15:1 AAA | 8.25:1 AAA | 15.15:1 AAA |
--color-text-tertiary | 12.50:1 AAA | 6.81:1 AA | 12.50:1 AAA |
--color-accent | 3.75:1 AA Large | 2.04:1 Fail | 3.75:1 AA Large |
--color-accent-hover | 6.03:1 AA | 3.28:1 AA Large | 6.03:1 AA |
--color-accent-text | 17.51:1 AAA | 9.54:1 AAA | 17.51:1 AAA |
--color-error † | 3.82:1 AA Large | 2.08:1 Fail | 3.82:1 AA Large |
--color-warning † | 3.84:1 AA Large | 2.09:1 Fail | 3.84:1 AA Large |
--color-success † | 3.82:1 AA Large | 2.08:1 Fail | 3.82:1 AA Large |
† --color-accent-text (light mode) is designed for text on --color-accent button backgrounds — Fail against page surfaces is by design. State tokens (error/warning/success) marked † fall below 3:1 on --color-bg-elevated in dark mode; pair with an icon or use on --color-bg/--color-bg-sunken instead. Note: in dark mode --color-bg and --color-bg-sunken both resolve to --in0-void, so those two columns are identical by design. --color-text-tertiary is AA Large only in all light-mode contexts — never use it for body-size text; restrict to ≥ 24 px regular or ≥ 19 px bold.
Usage Rules
- Never use Bloom colours as decorative accents — reserve them for semantic states only (error, warning, success, annotation).
- Iron Night tones must not appear as foreground text on light backgrounds — contrast is too low.
- Primary CTA:
--fo1-fernbackground with--bm2-birchtext (4.67:1 ✓). - Dark mode accent shifts Fern → Sage automatically. Both are the same palette family — the shift is imperceptible as a brand change but improves legibility.
- Components reference semantic tokens only. Palette tokens are for brand moments and one-off elements.