Found while correcting the ground statistic in the #166 contrast harness (PR #188). Recording, not fixing — none of these is in that card's scope.
What the corrected harness sees that the old one could not
Every contrast sweep this repo has run so far (#140, #167, #166) sampled the ground under a text node as the median of nine samples across its glyph box. A median is a statement about the typical pixel under a string. It is structurally incapable of reporting a string that is mostly on its intended ground and locally on something else — which is exactly what a glyph colliding with a foreground graphic, or a line overflowing the card it was meant to sit inside, looks like.
Scoring the worst ground pixel under the node's own glyph ink instead (same Chromium text{visibility:hidden} raster method, plus a second raster with text visible so the difference gives an ink mask matched to that node's own fill, at raster scales 1x / 0.667x / 2x) surfaces seven nodes in six files below 3:1 that the median reports as comfortably passing — in one case at 12.28:1.
The seven
| File |
class |
size |
fill |
worst ground |
ratio |
ratio the median reports |
what is actually there |
conversational-app-iteration/cover-en.svg |
.label |
18px w740 |
#173a36 |
#163b35 |
1.01 |
12.28 |
the leading C of Change plan is drawn on the dark node marker |
conversational-app-iteration/cover-en.svg |
.tiny |
15px |
#60746e |
#5f7773 |
1.04 |
4.93 |
the dark node marker sits on top of workflows |
conversational-app-iteration/cover.svg |
.tiny |
15px |
#60746e |
#5f7773 |
1.04 |
4.93 |
same node, Simplified sibling |
metadata-not-code-generation/cover-en.svg |
.soft2 |
16px |
#b7d6ce |
#e6e3d5 |
1.21 |
7.90 |
the line runs off the dark card; and audit lands on the cream ground |
ai-wrote-your-app-dare-to-merge/review-loop-en.svg |
.s |
12.5px |
#a9c4ba |
#899a97 |
1.58 |
5.90 |
the line runs off the right edge of its dark card; the final y lands outside |
vibe-coding-technical-debt-2026/debt-curve-en.svg |
(none) |
14px |
#173a36 |
#993a1e |
1.76 |
12.39 |
the debt curve passes through erupts |
self-hosted-ai-app-platform/self-hosted-runtime-en.svg |
(none) |
16px |
#93c5fd |
#2563eb |
2.87 |
8.95 |
the final s of governed tools grazes the blue divider |
The first five are visible losses of text at native size — rendered and looked at, not inferred from the numbers. The last two are a stroke and a rule grazing one or two glyph edges; they are real but cosmetic, and worth triaging separately from the first five.
Why this is a different card from #183 and #181
Suggested handling
Not a mechanical sweep. Each of the first five wants a look at the composition and a one-line geometry change in that file. The last two are arguably fine as authored.
Worth doing at the same time: whatever the repo's next ground-sampling check is, it should score the worst ground under the ink rather than the median, or this class stays invisible. That is the change PR #188 makes to the #166 harness.
Unassigned; recording only.
Generated by Claude Code
Found while correcting the ground statistic in the #166 contrast harness (PR #188). Recording, not fixing — none of these is in that card's scope.
What the corrected harness sees that the old one could not
Every contrast sweep this repo has run so far (#140, #167, #166) sampled the ground under a text node as the median of nine samples across its glyph box. A median is a statement about the typical pixel under a string. It is structurally incapable of reporting a string that is mostly on its intended ground and locally on something else — which is exactly what a glyph colliding with a foreground graphic, or a line overflowing the card it was meant to sit inside, looks like.
Scoring the worst ground pixel under the node's own glyph ink instead (same Chromium
text{visibility:hidden}raster method, plus a second raster with text visible so the difference gives an ink mask matched to that node's own fill, at raster scales 1x / 0.667x / 2x) surfaces seven nodes in six files below 3:1 that the median reports as comfortably passing — in one case at 12.28:1.The seven
conversational-app-iteration/cover-en.svg.label#173a36#163b35CofChange planis drawn on the dark node markerconversational-app-iteration/cover-en.svg.tiny#60746e#5f7773workflowsconversational-app-iteration/cover.svg.tiny#60746e#5f7773metadata-not-code-generation/cover-en.svg.soft2#b7d6ce#e6e3d5and auditlands on the cream groundai-wrote-your-app-dare-to-merge/review-loop-en.svg.s#a9c4ba#899a97ylands outsidevibe-coding-technical-debt-2026/debt-curve-en.svg#173a36#993a1eeruptsself-hosted-ai-app-platform/self-hosted-runtime-en.svg#93c5fd#2563ebsofgoverned toolsgrazes the blue dividerThe first five are visible losses of text at native size — rendered and looked at, not inferred from the numbers. The last two are a stroke and a rule grazing one or two glyph edges; they are real but cosmetic, and worth triaging separately from the first five.
Why this is a different card from #183 and #181
?onenterprise-ontology-race-open-vs-closed/cover{,-en}.svgreads at 1.79:1 — but the mechanical darkening rule cannot be applied to it #181 is the accent-gold?, a single fill that is too light for its (flat) ground..tinywould not stop the marker from coveringworkflows.Suggested handling
Not a mechanical sweep. Each of the first five wants a look at the composition and a one-line geometry change in that file. The last two are arguably fine as authored.
Worth doing at the same time: whatever the repo's next ground-sampling check is, it should score the worst ground under the ink rather than the median, or this class stays invisible. That is the change PR #188 makes to the #166 harness.
Unassigned; recording only.
Generated by Claude Code