Sweep `--el-text-muted` off TINTED surfaces — it clears AA on the white card by 0.04 and fails everywhere else — and turn on the guard's muted arm
Carved out of MOTIR-2459 on 2026-08-08, the second of the two sweeps that card bundled. MOTIR-2455 measured this and called it "the subtler finding, and it catches more code"; it does, and it is a different kind of defect from the faint one, which is why it is a different card.
Repo: motir-core. One PR. Runs after MOTIR-2475 — both edit tests/theme/inkContrastLint.test.ts, and sequencing them keeps that file from being written twice.
The rule, and why this one is about PAIRS rather than about an ink
--el-text-muted is 4.54:1 on the white page/card — safe, by 0.04 — and 4.12–4.34:1 on --el-surface, --el-muted and --el-surface-soft, all of which fail. So unlike --el-text-faint, no site is a defect on its own: the verdict is a property of the ink AND the background under it. That is what makes this the harder sweep and the one with a real blind spot.
What the scanner measured, on origin/main at 0d5279da
130 violations across 75 files — muted TEXT (glyphs and disabled controls already filtered out, since 1.4.3 measures neither) whose nearest background-painting ancestor in the same file is one of the three tinted surfaces. Popovers, menus, sprint headers, soft-tinted cards and the auth shell are where they cluster.
⚠️ This number is a FLOOR, and the card must say so in its PR body rather than report a clean sweep. The scanner resolves an element's surface by walking up the JSX tree within one file. An element whose background is painted by a <Card>, a <Popover.Content> or a layout in ANOTHER module reads as "no surface found here" and the muted rule abstains. So the sites this card fixes are the ones a single file can prove; cross-component surface inheritance is out of the scanner's reach by construction and stays out of it.
The fix
Same substitution as the faint sweep: --el-text-secondary, which clears AA on all four surfaces in both themes, so it is correct without needing to know which surface the element ended up on. The alternative — moving each element onto --el-card — changes layout intent and is not this card's business.
Acceptance criteria
scanSource(from MOTIR-2459) reports zero muted violations across the scanned tree, asserted as a derivation over the scanned file set rather than against a frozen count of 130.tests/theme/inkContrastLint.test.ts— the guard MOTIR-2475 lands — gains its muted arm, failing the build on muted ink overbg-(--el-surface),bg-(--el-surface-soft)orbg-(--el-muted), with the faint arm untouched and still green.- No allowlist, no exclusion. Every violation is fixed by moving the ink.
- The guard's blind spot is stated in the test file itself: surface resolution stops at the file boundary, so a background painted by another module is not seen. A comment, not a silent limit — the card that widens it later needs to know where the edge is.
- The PR body says explicitly which surfaces the guard could NOT rule on (cross-component backgrounds) instead of reporting a clean sweep, and names the a11y-sweep routes that do not cover the files touched.
pnpm lint,pnpm typecheck,pnpm prettierandnext buildpass; component tests asserting on a re-inked class are updated in the same PR.
Context refs
tests/theme/inkContrastScan.ts— the scanner and itsnearestSurfacewalk (MOTIR-2459).tests/theme/inkContrastLint.test.ts— the guard to extend (MOTIR-2475).packages/design-system/theme.css— the two tokens and their comments.motir-core/CLAUDE.md§ The token map — the measured table.