All tokens

All 144 custom properties Deck declares on :root, grouped by family. Every preview on this page is the token applied to something — a background, a width, a shadow, an animation — so what you are looking at is the value in effect rather than a picture of it.

Using a token

Tokens are plain CSS custom properties. Read one with var() in your own rules, and set one anywhere in the tree to change it from that element down.

@layer app.pages {
  .invoice-total { font-size: var(--text-xl); color: var(--text); }
}

<!-- one tenant, one number, no rebuild -->
<html style="--hue-brand: 265">

<!-- or scoped to a subtree -->
<section class="card" style="--brand-soft: var(--good-100)">

Reach for the semantic roles before the ramps. --surface resolves to a different step of the neutral ramp in light and dark; --ink-0 is the same colour in both, and using it directly is how a component ends up unreadable in dark mode.

Where the tokens are declared
Declared inTokens
src/01-tokens.css 131
src/16-motion.css 13

Hue and chroma

The five numbers the whole palette is generated from. Change one and every shade, border, focus ring and shadow that derives from it follows, with no rebuild and no second stylesheet. This is the retheming story in ten tokens.

Design tokens this component reads
Token Live Declared value Declared in
--hue-brand 196 01-tokens.css:11
--hue-accent 42 01-tokens.css:11
--hue-good 152 01-tokens.css:11
--hue-warn 74 01-tokens.css:11
--hue-bad 24 01-tokens.css:11
--hue-neutral 232 01-tokens.css:11
--chroma-brand — .118 01-tokens.css:11
--chroma-accent — .142 01-tokens.css:11
--chroma-status — .132 01-tokens.css:11
--chroma-neutral — .012 01-tokens.css:11

Brand ramp

Eleven steps in OKLCH, computed from --hue-brand and --chroma-brand. The numbers are perceptual lightness, so 500 is the same apparent lightness at every hue — which is what stops a yellow brand from looking washed out where a blue one looks solid.

Design tokens this component reads
Token Live Declared value Declared in
--brand-50 oklch(97.4% calc(var(--chroma-brand) * .16) var(--hue-brand)) 01-tokens.css:11
--brand-100 oklch(94.2% calc(var(--chroma-brand) * .30) var(--hue-brand)) 01-tokens.css:11
--brand-200 oklch(88.6% calc(var(--chroma-brand) * .48) var(--hue-brand)) 01-tokens.css:11
--brand-300 oklch(80.4% calc(var(--chroma-brand) * .70) var(--hue-brand)) 01-tokens.css:11
--brand-400 oklch(70.2% calc(var(--chroma-brand) * .90) var(--hue-brand)) 01-tokens.css:11
--brand-500 oklch(60.8% var(--chroma-brand) var(--hue-brand)) 01-tokens.css:11
--brand-600 oklch(51.6% var(--chroma-brand) var(--hue-brand)) 01-tokens.css:11
--brand-700 oklch(43.4% calc(var(--chroma-brand) * .92) var(--hue-brand)) 01-tokens.css:11
--brand-800 oklch(35.6% calc(var(--chroma-brand) * .78) var(--hue-brand)) 01-tokens.css:11
--brand-900 oklch(28.2% calc(var(--chroma-brand) * .62) var(--hue-brand)) 01-tokens.css:11
--brand-950 oklch(20.4% calc(var(--chroma-brand) * .46) var(--hue-brand)) 01-tokens.css:11

Neutral ramp

Fifteen steps of near-grey, tinted toward --hue-neutral rather than pure grey. A truly neutral grey beside a saturated brand reads as dirty; a grey carrying a little of the brand hue reads as deliberate.

Design tokens this component reads
Token Live Declared value Declared in
--ink-0 oklch(100% 0 0) 01-tokens.css:11
--ink-25 oklch(99.1% calc(var(--chroma-neutral) * .5) var(--hue-neutral)) 01-tokens.css:11
--ink-50 oklch(97.8% var(--chroma-neutral) var(--hue-neutral)) 01-tokens.css:11
--ink-100 oklch(95.4% calc(var(--chroma-neutral) * 1.4) var(--hue-neutral)) 01-tokens.css:11
--ink-200 oklch(91.2% calc(var(--chroma-neutral) * 1.8) var(--hue-neutral)) 01-tokens.css:11
--ink-300 oklch(84.6% calc(var(--chroma-neutral) * 2.2) var(--hue-neutral)) 01-tokens.css:11
--ink-400 oklch(70.8% calc(var(--chroma-neutral) * 2.6) var(--hue-neutral)) 01-tokens.css:11
--ink-500 oklch(58.4% calc(var(--chroma-neutral) * 2.8) var(--hue-neutral)) 01-tokens.css:11
--ink-600 oklch(47.6% calc(var(--chroma-neutral) * 2.8) var(--hue-neutral)) 01-tokens.css:11
--ink-700 oklch(38.2% calc(var(--chroma-neutral) * 2.6) var(--hue-neutral)) 01-tokens.css:11
--ink-800 oklch(29.4% calc(var(--chroma-neutral) * 2.4) var(--hue-neutral)) 01-tokens.css:11
--ink-900 oklch(22.6% calc(var(--chroma-neutral) * 2.2) var(--hue-neutral)) 01-tokens.css:11
--ink-950 oklch(16.2% calc(var(--chroma-neutral) * 2.0) var(--hue-neutral)) 01-tokens.css:11
--ink-1000 oklch(11.4% calc(var(--chroma-neutral) * 1.8) var(--hue-neutral)) 01-tokens.css:11

Status ramps

Good, warn, bad and accent, at the steps that actually get used: 100 for a fill, 500 for an icon or a border, 600 and 700 for text. Deliberately not a full eleven-step ramp each — the missing steps are ones nothing needed.

Design tokens this component reads
Token Live Declared value Declared in
--good-100 oklch(94% calc(var(--chroma-status) * .3) var(--hue-good)) 01-tokens.css:11
--good-500 oklch(62% var(--chroma-status) var(--hue-good)) 01-tokens.css:11
--good-600 oklch(52% var(--chroma-status) var(--hue-good)) 01-tokens.css:11
--good-700 oklch(44% var(--chroma-status) var(--hue-good)) 01-tokens.css:11
--warn-100 oklch(95% calc(var(--chroma-status) * .32) var(--hue-warn)) 01-tokens.css:11
--warn-500 oklch(76% var(--chroma-status) var(--hue-warn)) 01-tokens.css:11
--warn-700 oklch(50% var(--chroma-status) var(--hue-warn)) 01-tokens.css:11
--bad-100 oklch(94.5% calc(var(--chroma-status) * .3) var(--hue-bad)) 01-tokens.css:11
--bad-500 oklch(58% calc(var(--chroma-status) * 1.25) var(--hue-bad)) 01-tokens.css:11
--bad-600 oklch(52% calc(var(--chroma-status) * 1.25) var(--hue-bad)) 01-tokens.css:11
--bad-700 oklch(44% calc(var(--chroma-status) * 1.1) var(--hue-bad)) 01-tokens.css:11
--accent-100 oklch(95% calc(var(--chroma-accent) * .3) var(--hue-accent)) 01-tokens.css:11
--accent-500 oklch(74% var(--chroma-accent) var(--hue-accent)) 01-tokens.css:11
--accent-700 oklch(52% calc(var(--chroma-accent) * .9) var(--hue-accent)) 01-tokens.css:11

Semantic roles

The tokens you should actually be reaching for. Each one names a job rather than a colour, and each resolves through light-dark() — which is why the entire dark theme is one attribute rather than a second set of rules. Reference --surface, not --ink-0, and dark mode comes free.

Design tokens this component reads
Token Live Declared value Declared in
--bg light-dark(var(--ink-50), var(--ink-1000)) 01-tokens.css:11
--bg-sunken light-dark(var(--ink-100), oklch(8.6% .012 var(--hue-neutral))) 01-tokens.css:11
--surface light-dark(var(--ink-0), var(--ink-950)) 01-tokens.css:11
--surface-2 light-dark(var(--ink-25), var(--ink-900)) 01-tokens.css:11
--surface-hover light-dark(var(--ink-50), var(--ink-900)) 01-tokens.css:11
--line light-dark(var(--ink-200), oklch(28% .016 var(--hue-neutral))) 01-tokens.css:11
--line-strong light-dark(var(--ink-300), oklch(36% .018 var(--hue-neutral))) 01-tokens.css:11
--text light-dark(var(--ink-900), var(--ink-100)) 01-tokens.css:11
--text-muted light-dark(var(--ink-600), var(--ink-400)) 01-tokens.css:11
--text-faint light-dark(var(--ink-500), var(--ink-500)) 01-tokens.css:11
--text-on-brand oklch(99% .01 var(--hue-brand)) 01-tokens.css:11
--text-on-accent oklch(24% .06 var(--hue-accent)) 01-tokens.css:11
--text-on-good oklch(99% .01 var(--hue-good)) 01-tokens.css:11
--text-on-warn oklch(24% .06 var(--hue-warn)) 01-tokens.css:11
--text-on-bad oklch(99% .01 var(--hue-bad)) 01-tokens.css:11
--brand light-dark(var(--brand-600), var(--brand-400)) 01-tokens.css:11
--brand-hover light-dark(var(--brand-700), var(--brand-300)) 01-tokens.css:11
--brand-soft light-dark(var(--brand-50), oklch(26% .05 var(--hue-brand))) 01-tokens.css:11
--brand-soft-text light-dark(var(--brand-800), var(--brand-200)) 01-tokens.css:11
--focus light-dark(var(--brand-500), var(--brand-300)) 01-tokens.css:11
--scrim linear-gradient(to top, oklch(12% .02 var(--hue-neutral) / .82) 0%, oklch(12% .02 var(--hue-neutral) / .62) 22%, oklch(12% .02 var(--hue-neutral) / .28) 48%, transparent 78%) 01-tokens.css:11

Space

A 4px base in rem, plus two fluid steps for page rhythm. Seven of these have utilities; the rest are for your own rules. The scale is explained in full on the spacing reference.

Design tokens this component reads
Token Live Declared value Declared in
--space-0 0 01-tokens.css:11
--space-px 1px 01-tokens.css:11
--space-1 .25rem 01-tokens.css:11
--space-2 .5rem 01-tokens.css:11
--space-3 .75rem 01-tokens.css:11
--space-4 1rem 01-tokens.css:11
--space-5 1.25rem 01-tokens.css:11
--space-6 1.5rem 01-tokens.css:11
--space-8 2rem 01-tokens.css:11
--space-10 2.5rem 01-tokens.css:11
--space-12 3rem 01-tokens.css:11
--space-16 4rem 01-tokens.css:11
--space-20 5rem 01-tokens.css:11
--space-24 6rem 01-tokens.css:11
--space-section clamp(2.5rem, 1.4rem + 5.5vw, 6rem) 01-tokens.css:11
--space-gutter clamp(1rem, .55rem + 2.2vw, 2rem) 01-tokens.css:11

Radius

Five steps in px rather than rem, because a corner is a property of the shape and should not grow when a reader raises their base font size.

Design tokens this component reads
Token Live Declared value Declared in
--r-xs 4px 01-tokens.css:11
--r-sm 7px 01-tokens.css:11
--r-md 12px 01-tokens.css:11
--r-lg 18px 01-tokens.css:11
--r-full 999px 01-tokens.css:11

Shadow and ring

Four elevations, an inset highlight, and the focus ring. The shadow colour is tinted toward the neutral hue rather than being black at low alpha, which is what keeps it from going muddy over a coloured surface.

Design tokens this component reads
Token Live Declared value Declared in
--shadow-color — var(--hue-neutral) 01-tokens.css:11
--shadow-1 0 1px 2px oklch(20% .03 var(--shadow-color) / .06), 0 1px 1px oklch(20% .03 var(--shadow-color) / .04) 01-tokens.css:11
--shadow-2 0 2px 4px oklch(20% .03 var(--shadow-color) / .05), 0 4px 12px oklch(20% .03 var(--shadow-color) / .07) 01-tokens.css:11
--shadow-3 0 4px 8px oklch(20% .03 var(--shadow-color) / .06), 0 12px 28px oklch(20% .03 var(--shadow-color) / .10) 01-tokens.css:11
--shadow-4 0 8px 16px oklch(20% .03 var(--shadow-color) / .08), 0 24px 56px oklch(20% .03 var(--shadow-color) / .14) 01-tokens.css:11
--shadow-inset inset 0 1px 0 oklch(100% 0 0 / .6) 01-tokens.css:11
--ring 0 0 0 3px light-dark(oklch(from var(--focus) l c h / .32), oklch(from var(--focus) l c h / .42)) 01-tokens.css:11

Type

Three families, ten sizes and four line heights. The top five sizes are clamp() expressions, so display type scales with the viewport between a floor and a ceiling instead of stepping at a breakpoint.

Design tokens this component reads
Token Live Declared value Declared in
--font-sans Ag 0123 ui-sans-serif, system-ui, -apple-system, "Segoe UI Variable Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif 01-tokens.css:11
--font-mono Ag 0123 ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, Consolas, monospace 01-tokens.css:11
--font-display Ag 0123 var(--font-sans) 01-tokens.css:11
--text-2xs .6875rem 01-tokens.css:11
--text-xs .75rem 01-tokens.css:11
--text-sm .8125rem 01-tokens.css:11
--text-base .9375rem 01-tokens.css:11
--text-md 1.0625rem 01-tokens.css:11
--text-lg clamp(1.125rem, 1.06rem + .32vw, 1.3125rem) 01-tokens.css:11
--text-xl clamp(1.3125rem, 1.19rem + .62vw, 1.625rem) 01-tokens.css:11
--text-2xl clamp(1.5625rem, 1.33rem + 1.16vw, 2.125rem) 01-tokens.css:11
--text-3xl clamp(1.875rem, 1.44rem + 2.16vw, 2.875rem) 01-tokens.css:11
--text-4xl clamp(2.25rem, 1.5rem + 3.75vw, 3.75rem) 01-tokens.css:11
--leading-tight — 1.12 01-tokens.css:11
--leading-snug — 1.3 01-tokens.css:11
--leading-normal — 1.55 01-tokens.css:11
--leading-loose — 1.72 01-tokens.css:11
--measure 68ch 01-tokens.css:11

Motion

Seven durations and ten easing curves, three of which are linear() springs — a real spring feel with no JavaScript. Thirteen of these live in src/16-motion.css rather than the token sheet, which is why they were missing from this reference until the extractor stopped selecting tokens by filename.

Design tokens this component reads
Token Live Declared value Declared in
--ease-out cubic-bezier(.22, 1, .36, 1) 01-tokens.css:11
--ease-in-out cubic-bezier(.65, 0, .35, 1) 01-tokens.css:11
--ease-spring linear(0, .18 6%, .53 14%, .89 24%, 1.04 32%, 1.06 40%, 1) 01-tokens.css:11
--dur-1 110ms 01-tokens.css:11
--dur-2 190ms 01-tokens.css:11
--dur-3 300ms 01-tokens.css:11
--ease-in cubic-bezier(.55, 0, 1, .45) 16-motion.css:21
--ease-emphasized cubic-bezier(.2, 0, 0, 1) 16-motion.css:21
--ease-decelerate cubic-bezier(0, 0, .2, 1) 16-motion.css:21
--ease-accelerate cubic-bezier(.4, 0, 1, 1) 16-motion.css:21
--ease-bounce linear(0, .004 2%, .016 4%, .062 8%, .137 12%, .5 24%, .68 28%, .824 32%, .93 36%, .995 40%, 1.02 44%, 1.01 52%, 1 60%) 16-motion.css:21
--ease-overshoot linear(0, .22 8%, .58 16%, .87 24%, 1.06 32%, 1.11 38%, 1.08 46%, 1.02 58%, 1) 16-motion.css:21
--ease-snap linear(0, .48 12%, .82 22%, .97 32%, 1.02 42%, 1) 16-motion.css:21
--dur-0 0ms 16-motion.css:21
--dur-4 420ms 16-motion.css:21
--dur-5 620ms 16-motion.css:21
--dur-slow 900ms 16-motion.css:21
--stagger-step 45ms 16-motion.css:21
--travel 12px 16-motion.css:21

Controls

The three control heights and the minimum tap target. 44px is the floor a finger needs; every interactive thing in Deck is at least that tall on a touch device even where the visible box looks smaller.

Design tokens this component reads
Token Live Declared value Declared in
--tap 44px 01-tokens.css:11
--control-h-sm 34px 01-tokens.css:11
--control-h 42px 01-tokens.css:11
--control-h-lg 50px 01-tokens.css:11

Stacking

Five named layers, a hundred apart. Deck has exactly one z-index utility and five tokens, on the theory that stacking bugs come from competing numbers and the cure is fewer of them, not more.

Design tokens this component reads
Token Live Declared value Declared in
--z-sticky — 100 01-tokens.css:11
--z-nav — 200 01-tokens.css:11
--z-sheet — 300 01-tokens.css:11
--z-modal — 400 01-tokens.css:11
--z-toast — 500 01-tokens.css:11

Ungrouped

Every token above is accounted for

All 144 tokens matched a group. This section is here so that a token added to src/ that matches none of them appears rather than disappearing, which is the only way this page can be trusted to be complete.

Overriding a token

Custom properties inherit, so where you set one decides how far the change reaches. On :root or the <html> element it is the whole document; on a component it is that subtree.

Specificity still applies to the declaration that sets the property, so a token set in your own @layer app beats Deck's :root without !important — the same rule that makes every other override in Deck work. What custom properties do not do is participate in the cascade at the point of use: var(--surface) resolves to whatever --surface is on that element, whichever layer set it.

A token that resolves to nothing makes its declaration invalid at computed-value time, which usually shows up as an inherited or initial value rather than as an error. If a colour comes out black or a size comes out zero, check the token name for a typo first — var() will not tell you.