Radius

A corner scale sharing its base with Border, and one rule about corners that no token can hold.

base × N with a base of 2px — the same base as Border, so a 2px rule and a 2px corner are the same number in both scales rather than two coincidences.

The previews are square on purpose. On a rectangle the largest step gives a pill, which reads as a fact about the box; on a square it gives a circle, and every step below shows its arc against equal sides with nothing to misattribute.

Radii

Eight steps that double and then thin out, and one that is off the scale entirely.

TokenValuePreview
--radius-0…
--radius-1…
--radius-2…
--radius-4…
--radius-6…
--radius-8…
--radius-12…
--radius-16…
--radius-full…

The scale starts at 2px, not 1px, because a 1px corner is not perceptible — it is a step you could write and never see. A scale should not offer a choice that resolves to nothing.

2 · 4 · 8 · 12 · 16 · 24 · 32, for the reason every scale in this system does: the difference between a 24px and a 28px corner is not one anyone reaches for a token to make.

--radius-full is the one member with a word instead of a number, and the name is doing real work. 9999px is not a position on the ramp, it is “however much it takes” — the corner clamps to half the shorter side, so the same token gives a circle on a square and a pill on a rectangle. A number would imply it belonged in the sequence and could be interpolated toward, which it cannot.

Concentric corners

A formula rather than a token, because both of its inputs change per use.

24px inside 24px — the same token twice

24px − 12px = 12px — the arcs stay parallel

Put a rounded box inside a rounded box and reuse the radius, and the corners fight: the inner arc is far tighter than the space it sits in, so the gap between the two curves pinches at the corners while staying even along the edges. The eye reads it as a mistake without being able to name it. The inner radius should be the outer radius minus the padding between them — then the two curves stay parallel the whole way round.

max(0px, calc(var(--radius-16) - var(--space-component-6)))

A token is a value; this is a function of two. Every combination of radius and padding gives a different answer, so shipping it as a token would mean shipping a table of them. It stays a formula here and gets built into Card in Phase 4, where a component knows its own padding and can do the subtraction once.

The max() is not defensive tidiness. Padding routinely exceeds the radius, and a negative border-radius is invalid — so without it the declaration is dropped and the corner silently returns to square, which looks like a styling oversight rather than a broken calculation.

One thing the formula will not do for you: it keeps two curves parallel, it does not make a radius and a padding suit each other. Try 32px over 24px and the arithmetic is still right while the result is not — a nearly-square 8px inner sitting inside a very round shell. That is the pairing being reported as bad, not the rule failing. A radius roughly twice its padding, as above, is the shape that tends to hold.