Tokens
docs/app/globals.css is generated from forge.config.json palette and is byte-identical in its token
lines to web/app/globals.css and deck/src/tokens.css. The docs use the unprefixed token names
directly, so the sibling comparison in scripts/token-pairs.json is 80 identity pairs (40 light, 40 dark).
npm run check:tokens prints check-tokens: ok (80 token values match) and the sibling pairs line
(repo-derived 2026-09-13).
Light (:root)
| Token | Hex | Token | Hex |
|---|---|---|---|
--background | #F7F9FD | --rail-bg | #121C38 |
--foreground | #121C38 | --rail-fg | #FFFFFF |
--card | #FFFFFF | --rail-muted | #E8EEFF |
--muted | #E8EEFF | --rail-hover | #1C2848 |
--muted-foreground | #515F77 | --rail-active | #26345C |
--border | #D8E0ED | --status-pass | #166B4F |
--primary | #2347F2 | --status-pass-bg | #E7F3EB |
--primary-hover | #1B39C4 | --status-review | #825600 |
--primary-foreground | #FFFFFF | --status-review-bg | #FFF3D6 |
--destructive | #A32E3B | --status-fail | #A32E3B |
--destructive-foreground | #FFFFFF | --status-fail-bg | #FCECEE |
--sidebar | #FFFFFF | --status-info | #245F93 |
--sidebar-accent | #E8EEFF | --status-info-bg | #EAF2FA |
--status-neutral | #515F77 | ||
--status-neutral-bg | #E8EEFF |
Dark (.dark)
| Token | Hex | Token | Hex |
|---|---|---|---|
--background | #121C38 | --rail-bg | #0C1329 |
--foreground | #FFFFFF | --rail-fg | #FFFFFF |
--card | #121C38 | --rail-muted | #E8EEFF |
--muted | #1C2848 | --rail-hover | #1C2848 |
--muted-foreground | #E8EEFF | --rail-active | #26345C |
--border | #515F77 | --status-pass | #166B4F |
--primary | #E8EEFF | --status-pass-bg | #E7F3EB |
--primary-hover | #FFFFFF | --status-review | #825600 |
--primary-foreground | #121C38 | --status-review-bg | #FFF3D6 |
--destructive | #A32E3B | --status-fail | #A32E3B |
--destructive-foreground | #FFFFFF | --status-fail-bg | #FCECEE |
--sidebar | #121C38 | --status-info | #245F93 |
--sidebar-accent | #1C2848 | --status-info-bg | #EAF2FA |
--status-neutral | #515F77 | ||
--status-neutral-bg | #E8EEFF |
Status pairs are identical in both themes by brand rule.
Products (--p-<slug>, --p-<slug>-tint, --p-<slug>-text)
| Product | Light | Dark |
|---|---|---|
| Evidence | #2347F2, #E8EEFF, #1B39C4 | #7D94FF, #2A3664, #E8EEFF |
| Plans | #1B39C4, #DDE4FB, #14289A | #A9B8FF, #333E64, #E8EEFF |
| Review | #515F77, #E6EAF1, #3F4B60 | #A7B4CC, #333D59, #E8EEFF |
| Progress | #121C38, #D8E0ED, #121C38 | #D8E0ED, #3E4760, #E8EEFF |
Geometry block
Appended after the palette and ignored by check-tokens and check-contrast:
| Token | Value |
|---|---|
--font-heading | "IBM Plex Sans", Arial, sans-serif |
--font-body | Inter, Arial, sans-serif |
--shape-radius | 4px |
--radius-panel | 8px |
--radius-graphic | 0 |
--motion-fast, --motion-normal, --motion-slow | 120ms, 180ms, 240ms (all 0ms under prefers-reduced-motion: reduce) |
--ease | cubic-bezier(0.2, 0, 0, 1) |
--focus-ring, --focus-offset | 2px solid var(--primary), 3px |
How the docs use them
app/theme.css references tokens only: chips use the --status-<tone> pairs, product badges the
--p-<slug> set, cards --card and --border with var(--radius-panel), controls
var(--shape-radius). Nextra’s primary hue is set from --primary (Cobalt in light, Ice in dark) and its
page background from --background.
Source: docs/app/globals.css, web/app/globals.css, forge.config.json, docs/scripts/check-tokens.mjs, docs/scripts/token-pairs.json