There is a green on my website. Tailwind’s default green-500, #22c55e, stock pigment from a component library. I never chose it, never saw it rendered, and did not know it existed until Thursday, when the checker I built against my own design contract flagged it seven times. It turns out the largest source of contract violations on my site was code that never ran: a 559-line feedback overlay I experimented with one evening in April, synced to the repo in a catch-all commit, and never imported anywhere. It shipped in no bundle. It carried 97 of my 234 token violations, eleven rounded-corner utilities, and the green. Deleting one dead file fixed forty-one percent of my violation count.

That is the shape of what happened when the contract from last week’s post met the site it was written for. The first run said FAIL 746. By the time the tooling stopped lying, the honest number was 324, and the distance between those two numbers is most of what I learned.

What the first run got wrong

746 was never true. 420 of the token failures were the linter reading build output, minified CSS chunks the framework generates, which nobody authored and no contract governs. A four-digit year in my timeline copy, #1990, matched the hex-color regex. Fifty-two elements “failed” a clipping check that was counting zero-width inline elements as hidden text while the actual zoom measurement passed cleanly. And nine paragraphs failed the body leading band that were not body text at all: they were metadata set at exactly the size and leading my own contract’s type table specifies. The checker sampled every paragraph role-blind and applied the body rule to meta text. The machine flagged, the contract said compliant, the human overruled.

I am keeping that last one as the project’s first formal calibration entry, because it is the whole thesis in one row: an automated judgment, the evidence beside it, and a human verdict that disagreed for a stated reason. The fix is mechanical (the leading check needs role awareness) and the disagreement is now data.

Two more entries joined it. I predicted the lint’s false positives would be borders and hairlines; there were zero border hits, and the actual blind category was authored media, my figure and artifact components, whose single-use palettes are exempt by contract but unmarked in code. My prediction was wrong and the record says so. And the lint that flagged a raw 4px radius could not see rounded-full, rounded-lg, or rounded-md at all, because named utility scales were not in its regex. Eleven of them sailed through invisible, all in the dead file. A checker documenting its own blind spots in its own output is not a failure of the system. It is the system.

What the site actually got wrong

Fourteen focus states were browser-default blue, rgb(0, 95, 204), the exact tool-default my contract’s interaction spec prohibits, fixed with one global :focus-visible rule in ink. My prose measure was a fixed 680 pixels, which renders around 87 characters per line against a contract band of 58 to 70, now a ch value. And the surface story: over the months I had accumulated at least nine slightly different warm off-whites, the same paper re-remembered a shade differently each time I touched the file. The judgment call, and it was the afternoon’s only real one: this site believes in exactly one surface. Everything collapsed to a single ground token. One paper, everything printed on it.

The contract lost one too

My interaction spec said 3px underline offset. The live site uses 6px, a value I had already tuned optically at production sizes and forgotten I had reasoned about. The site’s number won and the contract was amended with the reason recorded. The loop runs in both directions: sometimes the site migrates, sometimes the contract concedes, and a contract that can lose an argument is the only kind worth checking against.

One more thing tried to get in. Mid-sort, I asked a chatbot about rounded corners and got back the case for them: friendlier, more clickable, softer. Generic, plausible, and precisely the reasoning my refusals exist to refuse, an argument for rounding as a policy, everywhere, which is a policy reversal dressed as an exception. The radius on my media corners died under refusal 5, and I looked at the result before letting it stand: square-cornered images on paper read as plates in a book, which is where this site’s language lives anyway. The contract outranks the chatbot. That is what it is for.

After the migration

Pre-migration, corrected: PASS 2, FAIL 324. Post-migration, against the live deploy: PASS 3, FAIL 165. The interaction family went from 14 failures to zero, every browser-default focus ring and chromatic hover replaced by one global rule in ink and one uniform underline geometry. Type failures dropped from 76 to 44, and of the 44 remaining, nine are correctly spec’d captions failing a role-blind band and 35 are layout columns the measure check was never meant to govern, so the residue belongs to the checker’s education, not the site’s. Token violations fell from 234 to 121, and most of what’s left is figure palettes the lint cannot yet recognize as exempt. The site now substantially complies with its own law; the instrument has to catch up to the legislation, which is next week’s work by design.

One artifact of the build pipeline earned its own note: the contract’s new 180ms entrance token was tree-shaken out of the shipped CSS because nothing references it yet. A law that no element invokes does not ship. Declared law and enforced law are different objects, and the bundler knows it before you do.

I went through the live site after the pass. Nothing reached for the exceptions registry. The squared edges sit better in the editorial register than the rounding they replaced, and the link treatment earns its keep: hover changes only the underline’s thickness and offset, geometry doing the communicating where animation would have said nothing. Typography still wants tightening, and that is already a recorded open decision. The level above all of this is delight, the deep kind rather than the bolted-on kind, and a migration pass cannot produce it; it has to be conceived, which makes it the right ambition for the next thing built rather than the next thing fixed.

Next week

The checker learns the things this week taught: role-aware leading bands, named-utility lint, a real clipping check, and a mechanical marker for authored media so figure palettes stop reading as violations. Then the soft clauses start getting scored, which is where the vision model meets the signature rubric and the calibration curve begins in earnest. The contract and checker are public at https://github.com/slow-signal-studio/design-contract. Subscribe at Slow Signal if you want to follow along.