Thirteen steps
Each step is a clamp() range, not a value. Across the upper
scale the minimum column advances on ×1.200 — a minor third — and the maximum column on
×1.250 — a major third — so the scale changes proportion as it resizes: tighter on a
phone, where vertical space is the scarce resource, more open on a desk, where it is not.
Three qualifications, because the round numbers are not the whole story.
The bottom two steps are tighter — xs→sm runs ×1.167 and sm→base ×1.205, which is what
rounding to hundredths of a rem does at 11px, so the gauge above samples from 4xl
up where the ratio has settled. The ends are 320px and 1200px, not the edges of the
viewport range: the individual steps bottom out between 296 and 343px and top out between 1029
and 1192px, so above roughly 1200px this scale no longer responds at all. And the readouts
are fractional on purpose — CSS lengths are real numbers, and a browser rasterises
12.34px at a genuinely different advance width from 12px rather than
rounding to an integer, so the decimals below are real rather than decorative.
Ag
Agency
Agency of
A scale that reads
A scale that reads at every width
A scale that reads at every width
A scale that reads at every width
A scale that reads at every width
A scale that reads at every width without a breakpoint
A scale that reads at every width without a breakpoint
A scale that reads at every width without a breakpoint per step
A scale that reads at every width without a breakpoint per step
A scale that reads at every width without a breakpoint per step
Colour, measured
Contrast is not asserted here. The ratios below are computed in your browser from the resolved colours at load — the same method that found the defects in the last section, and the only one that works, because a source review cannot see a cascade. Several of these are light-surface tokens and fail deliberately on this ground; that is the point of measuring rather than declaring.
Motion
Seven durations, running at their real values. Breathing and ambient
are an order of magnitude longer than the interaction tokens on purpose: one set answers a press,
the other is the room being alive. Both stop entirely under
prefers-reduced-motion.
Blur and depth
Six blur steps and three layer transforms. The layer offsets are a token rather than a per-component nudge, which is what keeps a stack of cards in one surface reading as the same stack in another.
What the measurements caught
A token system is worth what it is verified against. These are real defects found in this system, in a browser, by reading computed style on live elements — every one of them invisible to the build, to the type checker, and to a source review.
Seventeen elements of near-black on near-black
The marketing routes strip .dark, so every heading written the app's way — a
neutral-900 paired with a dark: variant — resolved to the light value
on an rgb(14,14,16) ground. Among them: every "how it works" step heading, every
card title, and the entire product column of the comparison table — the column the whole
argument rested on.
It was latent, not new. Those sections sat behind a false feature flag, so
nothing had ever rendered them; flipping that boolean would have shipped all seventeen at once.
Hidden code does not stay correct. It stays unobserved.
An unlayered shorthand outranking every utility on the element
The token stylesheet defined .border { border: 1px solid var(--border-light) }.
Being a shorthand it resets the colour too, and being unlayered it beats every
utility class on the same element — so the paid call to action drew a hairline nobody could see,
whatever colour was asked for.
Two confident diagnoses came first, and both were wrong. "The utility was never
generated" — refuted when the stylesheet scan turned out not to descend into @layer,
and was also reporting a class that demonstrably worked at 17.69:1 as missing. "A bare
var() can't be classified as width or colour" — refuted by giving a probe element a
plain, unambiguous border utility and watching it compute the same invisible grey. A standard
utility failing is not a generation problem; it is an override.
The same root cause, a third time in one day
App-kit ink on a dark marketing surface: first as class names, then as a whole component. A guard was already scanning every class name when this one shipped, and it could not help — a guard on class names cannot see a component. The fix was a second guard banning the component by name in these files, because three prior write-ups had not prevented a fourth occurrence. That is the argument for a test rather than for another comment.
Why no amount of reading would have caught any of it
The correct sibling columns — the ones using the token — measured 7.64:1 on the same ground. So a reviewer reading the source saw two colour utilities side by side with nothing to choose between them. The markup was valid, the classes existed, the build passed, the types passed. Only a computed-style read, on a real element, in the real cascade, is decisive.
Two things this loud is one thing too many
Contrast is a hierarchy, not only a floor. Luminance is pre-attentive — the loudest object on a screen wins wherever it sits — so a second element at 19:1 does not add emphasis, it splits it. The page keeps one primary, and the secondary action became an outline: legible, and quieter.