mirror of
https://github.com/block/buzz.git
synced 2026-10-29 13:31:44 +00:00
Three fixes, and a guard so they cannot regress silently. `text-on-warning` pointed at `var(--neutral-12)`, which is near-black in light mode and near-white in dark. The warning fill is the same amber in both, so dark mode put #f5f5f5 on #eab308: APCA Lc 34, WCAG 1.76:1. It is a literal now — a paired-text token follows its fill, never the mode. The dark neutral text steps were too dim. `text-secondary` (#8f8f8f) measured Lc 38–41 and `text-tertiary` (#6e6e6e) Lc 23–26 against an Lc 60 body target, while passing WCAG AA at 4.4–5.6:1 — legal, and visibly murky. Raise dark neutral-9 to #a6a6a6 and neutral-10 to #c1c1c1, sized against bg-float (#2a2a2a), the lightest dark surface and so the binding case. Light neutral-9 moves #a3a3a3 -> #909090 for the same reason at the meta target. Both ramps stay monotonic, and bg-inverse-hover (the other consumer of neutral-10) still carries its paired text at Lc 70. This is APCA's polarity asymmetry doing real work: light-on-dark needs more separation than the same WCAG ratio implies, so the dark ramp's text steps sit above where mirroring the light ramp would put them. `text-disabled` stays below target deliberately — low contrast is the signal that a control is unavailable, and WCAG exempts inactive controls for the same reason. Raising it would make disabled read as enabled. Recorded as the one exception, with that reason. The guard is the durable part. `scripts/check-contrast.mjs` measures every text role against every surface it can sit on, in both modes, and fails the build below target. It parses `tokens.css` and resolves each `var()` chain rather than holding a copied list of values, so it cannot drift from the system it audits. `scripts/apca.mjs` is the algorithm, asserted against the published reference values on every run so a bad edit to the maths fails loudly rather than quietly shifting every verdict. Verified by falsification: reverting either fix fails the check, and perturbing one APCA exponent trips the reference assertion. Also corrects an earlier misreading: the two `.dark` blocks are not duplicate declarations. The first holds the dark ramp, the second overrides surface roles so the panel lifts off pure black. That is the intended layering. Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>