The page ground and all body copy.
Tailwind's rose, adopted whole. The accent.
A custom ramp — not Tailwind. The case-study chrome.
One step, not a scale. The muted panel ground.
Tailwind v4 slate. Borders, muted copy, disabled states.
Tailwind's sky ramp under the name blue. Held in reserve.
Orange. Chosen, never given a job. Held in reserve.
Only meaningful over imagery.
Only meaningful over imagery.
| Token | Chain | Value | Origin | Role |
|---|---|---|---|---|
| --surface-primary | --white | #fcfcfc | inherited | the page ground |
| --surface-secondary | --black | #09090b | inherited | — |
| --surface-tertiary | --gray-500 | #62748E | inherited | — |
| --surface-inverse | --black | #09090b | inherited | — |
| --surface-muted | --sage-50 | #f0f7f0 | inherited | was --surface-green, a raw hex declared in this file · .cs-tradeoff, .cs-reflect, and the editorial page ground |
| --surface-brand | --teal-200 | #a0fadd | brand | the tinted panel ground of the case-study layer · .cs-meta-rail, .cs-glance |
| --text-primary | --black | #09090b | inherited | all body copy |
| --text-secondary | --white | #fcfcfc | inherited | text on a dark or accent-filled ground · the pill CTA label |
| --text-tertiary | --gray-800 | #1D293D | inherited | — |
| --text-inverse | --gray-300 | #CAD5E2 | inherited | repointed from the dead --cool-gray-300 in 9802307 · became unreachable when .design-system was retired |
| --text-strong | --gray-900 | #0F172B | brand | near-black section labels, a step lighter than body copy · .cs-kicker |
| --text-muted | --gray-600 | #45556C | brand | .cs-piece metadata |
| --text-disabled | --gray-500 | #62748E | brand | the non-interactive nav item |
| --accent | --rose-700 | #be123c | brand | — |
| --accent-subtle | --rose-300 | #fda4af | brand | a placeholder marker has to be legible to work as a warning. --rose-300 on --surface-brand measured 1.55:1, so .cs-stat .n was repointed to --accent (5.15:1) in 2026-09 and this went to reserve |
| --accent-strong | --rose-800 | #9f1239 | brand | the accent one step down, for hover · solid and ghost button hover |
| --brand-primary | --accent → --rose-700 | #be123c | brand | reconciled 2026-09. Was --rose-500, which made the focus ring the one place the "brand" colour appeared while --rose-700 carried every visible accent. Also raises the ring against --surface-primary from 3.58:1 to 6.13:1 · the global :focus-visible ring |
| --brand-mark | --teal-500 | #00d2aa | brand | the .cs-kicker dash |
| --text-brand | --teal-800 | #006759 | brand | .cs-eyebrow |
| --text-brand-emphasis | --teal-800 | #006759 | brand | emphasis inside a callout, on --surface-muted. Darkened from --teal-700 in 2026-09: the contrast table on /design-system caught it at 4.30:1, under AA for body copy. Now 6.25:1 · .cs-tradeoff <b> |
| --text-on-brand | --teal-900 | #00554b | brand | meta-rail terms and definitions |
| --text-on-brand-strong | --teal-950 | #00302b | brand | glance and stat labels |
| --text-on-brand-muted | --teal-800 | #006759 | brand | de-emphasised copy on --surface-brand. Darkened from --teal-700 in 2026-09 (3.84:1, under AA). Now 5.58:1, still a visible step lighter than --text-on-brand. Same value as --text-brand-emphasis but a different role; they may diverge · meta-rail placeholders |
| --border | --gray-300 | #CAD5E2 | brand | .cs-piece at rest |
| --border-strong | --gray-500 | #62748E | brand | .cs-piece on hover |
| --border-dashed | --gray-400 | #90A1B9 | brand | the .cs-tradeoff dashed rule |
| --border-rule | --gray-600 | #45556C | brand | the footer's top rule |
| Foreground | Background | Ratio | Grade | Where |
|---|---|---|---|---|
| --text-primary | --surface-primary | 19.39:1 | AAA | Body copy on the page |
| --text-strong | --surface-primary | 17.38:1 | AAA | Section kickers |
| --text-muted | --surface-primary | 7.39:1 | AAA | Card metadata |
| --text-disabled | --surface-primary | 4.64:1 | AA | The inactive nav item |
| --text-brand | --surface-primary | 6.64:1 | AA | The case-study eyebrow |
| --accent | --surface-primary | 6.13:1 | AA | Accent copy and the focus ring |
| --text-secondary | --accent | 6.13:1 | AA | Button label, at rest |
| --text-secondary | --accent-strong | 7.81:1 | AAA | Button label, on hover |
| --text-on-brand | --surface-brand | 7.17:1 | AAA | Meta-rail terms and definitions |
| --text-on-brand-strong | --surface-brand | 11.81:1 | AAA | Glance and stat labels |
| --text-on-brand-muted | --surface-brand | 5.58:1 | AA | Meta-rail placeholders |
| --text-primary | --surface-muted | 18.25:1 | AAA | Copy inside a callout |
| --text-brand-emphasis | --surface-muted | 6.25:1 | AA | Emphasis inside a callout |
| --accent | --surface-brand | 5.15:1 | AA | Placeholder markers on a panel |
Rows graded AA non-text clear 3:1 but not 4.5:1. That is the correct bar for a focus ring, a border or a large figure, and the wrong bar for body copy — check the "where" column before reusing a pairing.
Aa Gg Rr 24
Aa Gg Rr 24
Aa Gg Rr 24
Aa Gg Rr 24
All four faces are by Arillatype.Studio — At Haüss, At Textual and At King by Pedro Arilla, At Gambit by Andy Lethbridge. They are licensed to Kayhan Atamyildiz and are not redistributable: this site serves them, it does not offer them. If you like what they do here, buy them from the people who drew them.
32 → 48px. The pre-2026-09 --h4 curve, renamed for what it actually does. Used by the mobile overlay nav and the glance stats
Every size on this page travels with the viewport. Drag the window and the numbers above stay true, because they describe the token, not the moment.
Every size on this page travels with the viewport. Drag the window and the numbers above stay true, because they describe the token, not the moment.
Every size on this page travels with the viewport. Drag the window and the numbers above stay true, because they describe the token, not the moment.
| Token | Value | Status |
|---|---|---|
| --lh-xs | 1em | reserve |
| --lh-s | 1.1em | active |
| --lh-m | 1.2em | active |
| --lh-l | 1.4em | active |
| --lh-xl | 1.6em | reserve |
| Token | Sample | Status |
|---|---|---|
| --fw-100 | Hauss 100 | reserve |
| --fw-200 | Hauss 200 | reserve |
| --fw-300 | Hauss 300 | reserve |
| --fw-400 | Hauss 400 | active |
| --fw-500 | Hauss 500 | active |
| --fw-600 | Hauss 600 | active |
| --fw-700 | Hauss 700 | active |
| --fw-800 | Hauss 800 | active |
| --fw-900 | Hauss 900 | reserve |
The dark bar is the value at 390px, the light bar at
1920px. --space-72 and --space-64 land
on the same maximum and differ only below it — visible above, and worth
knowing before you reach for one.
| Token | Value | Status | Role |
|---|---|---|---|
| --size-0 | 0 | reserve | — |
| --size-1 | 0.0625rem | active | hairline · meta-rail gutters |
| --size-1half | 0.09375rem | reserve | — |
| --size-2 | 0.125rem | active | meta-rail and .cs-meta gutters |
| --size-4 | 0.25rem | active | the .next link's internal gap |
| --size-8 | 0.5rem | reserve | — |
| --size-12 | 0.75rem | active | added in 9802307 to resolve a gap in the ladder · .cs-piece metadata label |
| --size-14 | 0.875rem | active | .cs-piece link, footer copyright |
| --size-16 | 1rem | active | the fixed-position body span, .cs-tradeoff copy |
| --size-18 | 1.125rem | reserve | — |
| --size-20 | 1.25rem | active | the header logo/title gap |
| --size-24 | 1.5rem | active | header and nav gutters |
| --size-32 | 2rem | active | small button height, mobile overlay nav label |
| --size-40 | 2.5rem | active | medium button height |
| --size-48 | 3rem | active | large button height |
| --size-60 | 3.75rem | active | added in 9802307 to resolve a gap in the ladder · the pill CTA height, the compact header logo |
| --size-64 | 4rem | reserve | — |
| --size-72 | 4.5rem | active | the swatch chip on /design-system |
| --size-80 | 5rem | active | the header logo |
| --size-100 | 6.25rem | reserve | — |
| --size-120 | 7.5rem | reserve | — |
| --size-160 | 10rem | reserve | — |
| Token | Value | Drives |
|---|---|---|
| --duration-fast | 0.2s | .cs-piece border and lift |
| --duration-quick | 0.25s | the "view case study" arrow |
| --duration-base | 0.3s | the next-project link |
| --duration-slow | 0.6s | the project-card image scale |
| --duration-reveal | 0.7s | the scroll-reveal fade and rise |
| --ease | ease-out | the only easing curve in the system |
One easing curve, five durations. Every transition on the site now
sits behind a prefers-reduced-motion guard — the card
scale and the next-project lift were unguarded until 2026-09.
| Token | Value | Role |
|---|---|---|
| --z-content | 10 | lifts copy above a full-bleed figure · .metadata-container |
| --z-header | 30 | the mobile nav overlay, above everything · header.nav-open |
Two stacking contexts on the whole site. A third should be a conversation, not a commit.
<Button href={url} variant="solid" size="xl" pill external>
Read the case study
</Button>
Shape, colour and size are three independent decisions. Heights are
fixed --size-* on purpose — a control whose height
changes with the viewport is a tap target you cannot reason about. The
site's own CTA is xl + pill, 60px tall.
Live, from the CMS — this is “Mobile Streaming in a Multi-Device Ecosystem”. Hovering scales the
image 1.025 and lifts it on --shadow-card-hover, while the
arrow travels 6px. Both are suppressed under reduced motion.
Cut the component library from 240 pieces to 61, and shipped the first release in a quarter.
The hard part was never the components. It was agreeing what a component was.Post-mortem, 2025
The blocks above run on representative props so they render whether or
not the CMS is reachable. QuoteBlock is the one place a
serif earns its keep — the pull-quote is At Gambit.

