Opacity
The only scale with no appearance of its own — it is a relationship to whatever sits behind it.
base × N like the other scales, with a base of 4%, so --opacity-8 is 32%. Sub-base steps use the same fraction convention as everywhere else: -0-25 and -0-5 are 1% and 2%, and -1-5 is 6%.
The previews below are the token used as a mix rather than as the opacity property, which is what every consumer in this system actually does — and the only preview that stays honest, since a partly transparent thing has no colour until something is behind it.
Levels
Thirteen steps, and the intervals between them are not even.
| Token | Value | Preview |
|---|---|---|
| --opacity-0 | … | |
| --opacity-0-25 | … | |
| --opacity-0-5 | … | |
| --opacity-1 | … | |
| --opacity-1-5 | … | |
| --opacity-2 | … | |
| --opacity-3 | … | |
| --opacity-4 | … | |
| --opacity-6 | … | |
| --opacity-8 | … | |
| --opacity-12 | … | |
| --opacity-16 | … | |
| --opacity-20 | … | |
| --opacity-25 | … |
The steps bunch at the transparent end and thin out toward opaque, which looks arbitrary written down and is obvious on screen: 4% to 8% is a doubling and reads as a clear change, while 80% to 100% is barely a difference at all. Fine control is worth having exactly where small numbers do visible work — tints, overlays, hairline fills — and worth nothing at the top, where the only question left is whether a thing is opaque.
Almost everything this system draws in a tint sits in the bottom third. The guide overlay is --opacity-1, its dashed edge --opacity-8, the content overlay --opacity-1 again — the whole visualisation layer on two steps. The top of the scale is unused so far, and stays for the same reason the unreached breakpoints do: it is deliverable, just not yet needed.
Read the number as a multiplier, not a percentage. --opacity-4 is 16%, and --opacity-25 is 100%. That is the same base × N rule the whole system uses, but this is the one category where it can be misread, because the value happens to be a percentage too — everywhere else the multiplier produces px and no confusion is possible.
Percentages, not decimals
The values are stored as 64% rather than 0.64, and that single choice is what lets one token serve both uses. opacity accepts either — but color-mix() requires a percentage, so a decimal token would work in one place and silently fail in the other. Percentages cost nothing and remove the fork.
It fails silently, which is the part worth knowing: an invalid percentage does not warn, it makes the whole color-mix() invalid, and the declaration is dropped as though it had never been written. --opacity-0 was exactly this until this page was built — it held a bare 0, so any mix using it was discarded. Nothing looked wrong, because a dropped background and a 0% mix are the same nothing. It is 0% now.