Evidence
Token reference
170 tokens, 126 of which carry a light and a dark value. This table is generated by reading the package's own stylesheet during the build — no value on it was typed by hand, and a token added to the package appears here with no edit to this page.
Reading the table
Tokens are grouped by name, not by a curated list, which is what makes the previous sentence true. Where a token is an alias — one name standing for another so a surface can be renamed without touching every call site — the target is shown beneath it and the value resolved to the end of the chain.
Values marked same in the dark column are theme-invariant: the scales for radius, duration, easing and stacking order are declared once and do not vary between themes, because nothing about a viewer's colour preference should change how far a sheet travels.
Colour is authored in OKLCH
Lightness in OKLCH is perceptual, so 0.6 means the same apparent brightness at
every hue. That is what makes a contrast budget tractable: a hue can be changed without
silently changing how light it reads, and the measured ratios on this site follow from the
values rather than from taste.
Geometry
One radius, six derived steps. Every corner in the products resolves to this scale.
| Token | Light | Dark |
|---|---|---|
--radius | 0.75rem | same |
--radius-sm | calc(var(--radius) - 4px) | same |
--radius-md | calc(var(--radius) - 2px) | same |
--radius-lg alias of --radius | 0.75rem | same |
--radius-xl | calc(var(--radius) + 4px) | same |
--radius-2xl | calc(var(--radius) + 12px) | same |
--radius-3xl | calc(var(--radius) + 20px) | same |
Shell layout
The fixed measurements the application shell is built on.
| Token | Light | Dark |
|---|---|---|
--sidebar-width | 16rem | same |
--sidebar-width-collapsed | 4rem | same |
--content-max | 72rem | same |
--content-max-narrow | 52rem | same |
Typography
Two stacks — one for display, one for body copy.
| Token | Light | Dark |
|---|---|---|
--font-display | "Satoshi", sans-serif | same |
--font-body | "Inter", sans-serif | same |
Duration scale
Every animated stop in the products picks from this scale. Raw millisecond values in component styles are a lint failure, not a preference.
| Token | Light | Dark |
|---|---|---|
--duration-instant | 50ms | same |
--duration-press | 80ms | same |
--duration-fast | 150ms | same |
--duration-base | 250ms | same |
--duration-medium | 300ms | same |
--duration-slow | 400ms | same |
--duration-slower | 600ms | same |
--duration-sheet-open | 380ms | same |
--duration-sheet-close | 240ms | same |
--duration-hero | 900ms | same |
--duration-settle | 2200ms | same |
--duration-skeleton-settle | 420ms | same |
Easing scale
Curves are named for the job they do, so a component cannot invent its own feel.
| Token | Light | Dark |
|---|---|---|
--ease-out-expo | cubic-bezier(0.16, 1, 0.3, 1) | same |
--ease-linear | linear | same |
--ease-out | cubic-bezier(0, 0, 0.2, 1) | same |
--ease-spring | cubic-bezier(0.34, 1.56, 0.64, 1) | same |
--ease-in-out | cubic-bezier(0.65, 0, 0.35, 1) | same |
--ease-water | cubic-bezier(0.22, 1, 0.36, 1) | same |
Z-index scale
Stacking order is enumerated, so nothing has to guess a number.
| Token | Light | Dark |
|---|---|---|
--z-base | 0 | same |
--z-dropdown | 10 | same |
--z-sticky | 20 | same |
--z-banner | 30 | same |
--z-overlay | 40 | same |
--z-modal | 50 | same |
--z-popover | 60 | same |
--z-toast | 70 | same |
--z-tooltip | 80 | same |
Interactive states
Hover, active and disabled are tokens, not opacity applied at the call site.
| Token | Light | Dark |
|---|---|---|
--text-disabled | oklch(0.7 0.005 60) | oklch(0.45 0.01 250) |
--primary-hover | oklch(0.7 0.13 220) | oklch(0.58 0.13 218) |
--primary-active | oklch(0.45 0.13 230) | oklch(0.46 0.13 225) |
--primary-disabled | oklch(0.5 0.13 230 / 40%) | oklch(0.52 0.13 220 / 40%) |
--destructive-hover | oklch(0.5 0.24 27) | oklch(0.66 0.19 22) |
--destructive-active | oklch(0.46 0.23 27) | oklch(0.62 0.19 22) |
--destructive-disabled | oklch(0.55 0.245 27.325 / 40%) | oklch(0.704 0.191 22.216 / 40%) |
--secondary-hover | oklch(0.88 0.005 60) | oklch(0.25 0.01 250) |
--secondary-active | oklch(0.84 0.005 60) | oklch(0.29 0.01 250) |
--secondary-disabled | oklch(0.92 0.005 60 / 50%) | oklch(0.21 0.01 250 / 50%) |
Chart colours
Data series only. Warm amber lives here and is never allowed to carry status meaning.
| Token | Light | Dark |
|---|---|---|
--chart-1 | oklch(0.78 0.13 70) | oklch(0.78 0.13 70) |
--chart-2 | oklch(0.6 0.118 184.704) | oklch(0.696 0.17 162.48) |
--chart-3 | oklch(0.398 0.07 227.392) | oklch(0.769 0.188 70.08) |
--chart-4 | oklch(0.828 0.189 84.429) | oklch(0.627 0.265 303.9) |
--chart-5 | oklch(0.769 0.188 70.08) | oklch(0.645 0.246 16.439) |
--chart-forecast alias of --primary | oklch(0.5 0.13 230) | oklch(0.52 0.13 220) |
--chart-actual | oklch(0.6 0.13 70) | oklch(0.78 0.13 70) |
--chart-confidence | oklch(0.5 0.13 230 / 8%) | oklch(0.56 0.13 220 / 8%) |
--chart-danger | oklch(0.65 0.22 25 / 20%) | oklch(0.65 0.22 25 / 25%) |
--chart-forecast-fill-mid | oklch(0.5 0.15 235 / 0.32) | oklch(0.5 0.15 235 / 0.32) |
--chart-tick | oklch(0.5 0.01 250) | oklch(0.63 0.01 250) |
--chart-favorable | oklch(0.55 0.16 160) | oklch(0.65 0.17 160) |
--chart-unfavorable | oklch(0.6 0.18 30) | oklch(0.65 0.2 30) |
Sidebar
The navigation surface keeps its own set so it can diverge from card surfaces.
| Token | Light | Dark |
|---|---|---|
--sidebar | oklch(0.94 0.008 60) | oklch(0.16 0.01 250) |
--sidebar-foreground alias of --card-foreground | oklch(0.12 0.01 30) | oklch(1 0 0) |
--sidebar-primary alias of --primary | oklch(0.5 0.13 230) | oklch(0.52 0.13 220) |
--sidebar-primary-foreground alias of --primary-foreground | oklch(1 0 0) | oklch(1 0 0) |
--sidebar-accent | oklch(0.9 0.01 240) | oklch(0.24 0.01 250) |
--sidebar-accent-foreground alias of --card-foreground | oklch(0.12 0.01 30) | oklch(1 0 0) |
--sidebar-border alias of --border | oklch(0.88 0.005 60) | oklch(1 0 0 / 10%) |
--sidebar-ring alias of --ring | oklch(0.5 0.13 230 / 40%) | oklch(0.56 0.13 220 / 50%) |
Domain accents
Per-section wayfinding hues. Gradient stops are not representable in the typed lens, so these are CSS-only by design.
| Token | Light | Dark |
|---|---|---|
--domain-pantry | oklch(0.74 0.16 75) | oklch(0.8 0.16 80) |
--domain-pantry-from | oklch(0.54 0.16 85) | oklch(0.54 0.16 85) |
--domain-pantry-to | oklch(0.46 0.16 60) | oklch(0.46 0.16 60) |
--domain-pantry-wash | oklch(0.98 0.025 90) | oklch(0.23 0.04 75) |
--domain-pantry-foreground | oklch(1 0 0) | oklch(1 0 0) |
--domain-list | oklch(0.6 0.14 235) | oklch(0.7 0.13 225) |
--domain-list-from | oklch(0.52 0.13 220) | oklch(0.52 0.13 220) |
--domain-list-to | oklch(0.44 0.16 255) | oklch(0.44 0.16 255) |
--domain-list-wash | oklch(0.975 0.02 240) | oklch(0.21 0.04 250) |
--domain-list-foreground | oklch(1 0 0) | oklch(1 0 0) |
--domain-trips | oklch(0.64 0.16 158) | oklch(0.72 0.16 156) |
--domain-trips-from | oklch(0.52 0.17 150) | oklch(0.52 0.17 150) |
--domain-trips-to | oklch(0.44 0.13 165) | oklch(0.44 0.13 165) |
--domain-trips-wash | oklch(0.975 0.03 158) | oklch(0.2 0.04 160) |
--domain-trips-foreground | oklch(1 0 0) | oklch(1 0 0) |
--domain-catalog | oklch(0.58 0.14 290) | oklch(0.7 0.14 292) |
--domain-catalog-from | oklch(0.56 0.15 295) | oklch(0.56 0.15 295) |
--domain-catalog-to | oklch(0.47 0.16 285) | oklch(0.47 0.16 285) |
--domain-catalog-wash | oklch(0.975 0.02 295) | oklch(0.21 0.04 290) |
--domain-catalog-foreground | oklch(1 0 0) | oklch(1 0 0) |
--domain-more | oklch(0.64 0.18 45) | oklch(0.72 0.18 48) |
--domain-more-from | oklch(0.55 0.18 55) | oklch(0.55 0.18 55) |
--domain-more-to | oklch(0.46 0.21 32) | oklch(0.46 0.21 32) |
--domain-more-wash | oklch(0.975 0.025 50) | oklch(0.22 0.05 45) |
--domain-more-foreground | oklch(1 0 0) | oklch(1 0 0) |
--fab-addtrip-from | oklch(0.52 0.1 190) | same |
--fab-addtrip-to | oklch(0.45 0.1 190) | same |
--fab-addtrip | oklch(0.6 0.1 190) | same |
--fab-addtrip-foreground | oklch(1 0 0) | same |
Status colour
Calm by intent. Each status carries an `-on-tint` variant for text sitting on its own wash, because the tint moves the background toward the text and drops the plain token below AA.
| Token | Light | Dark |
|---|---|---|
--destructive | oklch(0.55 0.245 27.325) | oklch(0.704 0.191 22.216) |
--destructive-foreground | oklch(0.98 0 0) | oklch(0.98 0 0) |
--destructive-on-tint | oklch(0.46 0.245 27.325) | oklch(0.704 0.191 22.216) |
--success-chip | color-mix(in srgb, var(--success) 10%, var(--card)) | color-mix(in srgb, var(--success) 10%, var(--card)) |
--warning-chip | color-mix(in srgb, var(--warning) 10%, var(--card)) | color-mix(in srgb, var(--warning) 10%, var(--card)) |
--destructive-chip | color-mix(in srgb, var(--destructive) 10%, var(--card)) | color-mix(in srgb, var(--destructive) 10%, var(--card)) |
--success | oklch(0.45 0.15 155) | oklch(0.72 0.17 155) |
--success-foreground | oklch(1 0 0) | oklch(0.1 0.03 155) |
--warning | oklch(0.5 0.16 75) | oklch(0.83 0.17 84) |
--warning-foreground | oklch(1 0 0) | oklch(0.15 0.05 84) |
--warning-on-tint | oklch(0.46 0.16 75) | oklch(0.7 0.17 84) |
--transfer | oklch(0.58 0.165 254.624) | oklch(0.77 0.165 254.624) |
--credit | oklch(0.54 0.18 293) | oklch(0.66 0.18 293) |
--credit-on-tint | oklch(0.48 0.18 293) | oklch(0.68 0.18 293) |
--destructive-surface | oklch(0.55 0.245 27.325) | oklch(0.44 0.2 22.216) |
Surfaces, glass and glow
Elevation expressed as tokens rather than as ad-hoc shadow and blur values.
| Token | Light | Dark |
|---|---|---|
--goal-liquid-foreground | oklch(0.43 0.01 40) | oklch(0.9 0.01 250) |
--surface-glass | oklch(0 0 0 / 8%) | oklch(1 0 0 / 7%) |
--surface-glass-top | oklch(0 0 0 / 5%) | oklch(1 0 0 / 8%) |
--glass-border | oklch(0 0 0 / 8%) | oklch(1 0 0 / 10%) |
--hero-number-gradient-from | oklch(0.32 0.13 230) | oklch(0.92 0.06 220) |
--hero-number-gradient-to | oklch(0.44 0.13 230 / 85%) | oklch(0.66 0.13 220) |
--hero-number-gradient-critical-from | oklch(0.36 0.2 27) | oklch(0.86 0.09 30) |
--hero-number-gradient-critical-to | oklch(0.44 0.21 25 / 85%) | oklch(0.68 0.19 25) |
--glow-color alias of --primary-glow | oklch(0.7 0.13 220) | oklch(0.62 0.13 218) |
--surface-base alias of --background | oklch(0.97 0.008 60) | oklch(0.14 0.03 265) |
--surface-raised alias of --card | oklch(1 0 0) | oklch(0.19 0.03 262) |
--surface-sunken | oklch(0.98 0.005 60) | oklch(0.11 0.01 250) |
--surface-overlay alias of --popover | oklch(1 0 0) | oklch(0.19 0.03 262) |
Shadows
Composite values, so elevation stays consistent across products.
| Token | Light | Dark |
|---|---|---|
--shadow-elevated | 0 8px 32px oklch(0 0 0 / 12%) | 0 8px 32px oklch(0 0 0 / 40%) |
--shadow-card | 0 4px 16px oklch(0 0 0 / 8%) | 0 4px 16px oklch(0 0 0 / 12%) |
--shadow-glow-primary | 0 0 16px oklch(0.7 0.13 220 / 30%) | 0 0 16px oklch(0.62 0.13 220 / 30%) |
--shadow-glow alias of --shadow-glow-primary | 0 0 16px oklch(0.7 0.13 220 / 30%) | 0 0 16px oklch(0.62 0.13 220 / 30%) |
Borders
Weight tokens for standard edges, plus the separate borders the glass surfaces need.
| Token | Light | Dark |
|---|---|---|
--border | oklch(0.88 0.005 60) | oklch(1 0 0 / 10%) |
--border-glass | oklch(0 0 0 / 10%) | oklch(1 0 0 / 10%) |
--border-glass-critical | oklch(0.55 0.245 27.325 / 35%) | oklch(0.704 0.191 22.216 / 35%) |
--border-subtle | oklch(0.94 0.005 60) | oklch(1 0 0 / 6%) |
--border-default alias of --border | oklch(0.88 0.005 60) | oklch(1 0 0 / 10%) |
--border-strong | oklch(0.82 0.005 60) | oklch(1 0 0 / 18%) |
Semantic text
Text colour by role rather than by hue.
| Token | Light | Dark |
|---|---|---|
--text-primary alias of --foreground | oklch(0.12 0.01 30) | oklch(1 0 0) |
--text-secondary alias of --muted-foreground | oklch(0.5 0.01 40) | oklch(0.63 0.01 250) |
--text-tertiary alias of --foreground-muted | oklch(0.5 0.01 30) | oklch(0.65 0.01 250) |
Base colours
The foundation both products build on.
| Token | Light | Dark |
|---|---|---|
--background | oklch(0.97 0.008 60) | oklch(0.14 0.03 265) |
--foreground | oklch(0.12 0.01 30) | oklch(1 0 0) |
--card | oklch(1 0 0) | oklch(0.19 0.03 262) |
--card-foreground | oklch(0.12 0.01 30) | oklch(1 0 0) |
--popover alias of --card | oklch(1 0 0) | oklch(0.19 0.03 262) |
--popover-foreground alias of --card-foreground | oklch(0.12 0.01 30) | oklch(1 0 0) |
--primary | oklch(0.5 0.13 230) | oklch(0.52 0.13 220) |
--primary-foreground | oklch(1 0 0) | oklch(1 0 0) |
--primary-text alias of --primary | oklch(0.5 0.13 230) | oklch(0.6 0.13 220) |
--primary-on-tint | oklch(0.42 0.13 230) | oklch(0.66 0.13 220) |
--secondary | oklch(0.92 0.005 60) | oklch(0.2 0.03 260) |
--secondary-foreground alias of --card-foreground | oklch(0.12 0.01 30) | oklch(1 0 0) |
--muted alias of --secondary | oklch(0.92 0.005 60) | oklch(0.2 0.03 260) |
--muted-foreground | oklch(0.5 0.01 40) | oklch(0.63 0.01 250) |
--muted-foreground-subtle | oklch(0.54 0.01 40) | oklch(0.6 0.01 250) |
--accent | oklch(0.92 0.01 40) | oklch(0.24 0.01 250) |
--accent-foreground alias of --card-foreground | oklch(0.12 0.01 30) | oklch(1 0 0) |
--input alias of --border | oklch(0.88 0.005 60) | oklch(1 0 0 / 12%) |
--ring | oklch(0.5 0.13 230 / 40%) | oklch(0.56 0.13 220 / 50%) |
--highlight-edge | oklch(0 0 0 / 8%) | oklch(1 0 0 / 15%) |
--accent-glow | oklch(0.5 0.13 230 / 12%) | oklch(0.56 0.13 220 / 18%) |
--blob-primary | oklch(0.5 0.13 230 / 8%) | oklch(0.56 0.13 220 / 12%) |
--blob-secondary | oklch(0.6 0.1 240 / 5%) | oklch(0.7 0.1 240 / 7%) |
--primary-glow | oklch(0.7 0.13 220) | oklch(0.62 0.13 218) |
--foreground-muted | oklch(0.5 0.01 30) | oklch(0.65 0.01 250) |
--modal-surface | oklch(0.94 0.005 60) | oklch(0.22 0.03 262) |
--backdrop | oklch(0 0 0 / 50%) | oklch(0 0 0 / 70%) |
--focus-ring alias of --ring | oklch(0.5 0.13 230 / 40%) | oklch(0.56 0.13 220 / 50%) |
--focus-ring-offset alias of --background | oklch(0.97 0.008 60) | oklch(0.14 0.03 265) |