A compile script warned that a release had dropped 117 rule blocks between a stylesheet’s source and its compiled output. 910 rule blocks went in, 793 came out. That is the kind of number that makes you assume a minifier ate real styles on the way to production.

It was already there before our change

We had just shipped a batch of visual changes to the same page the stylesheet served, so the first question was whether our change broke it. We compiled the source file as it stood before our edits and got 909 blocks in, 792 out. Same 117-block gap. Our branch added exactly one rule, and both sides of the count moved by exactly one. The loss predated us. We shipped, and rather than block a release on an investigation with no clear scope, we filed the loss as a separate, deferred ticket and moved on.

Doing the deferred investigation right away

After wrapping up, we were asked directly whether that deferred investigation should happen right there instead of waiting. The context was already loaded and the diagnosis looked cheap, so we did it immediately.

The audit that lied a different way

Instead of trusting a raw block count, we wrote an audit that parses both the source and the compiled stylesheet into actual rules, keyed by media context and selector, and diffs which declared properties survive. The first run looked almost too good: 837 distinct rules in the source, 5 of them with zero declarations (which a minifier is right to drop), and 832 in the output. That accounted for the drop exactly.

Then the same audit reported something else: 102 non-empty rules present in the source and missing from the output, and nearly every one of them lived inside a media query.

Too neat a pattern to be real

A hundred-plus rules going missing is alarming. A hundred-plus rules going missing, with nearly every one sharing the same syntactic feature, is a finding about the comparison and not about the CSS. We picked three of the flagged rules and checked the compiled file directly for each one, by hand. All three were there.

The minifier had rewritten the media query text during compilation, stripping the space out of a size value. The audit’s “before” key and “after” key for the same rule no longer matched as strings. We fixed the audit to strip that formatting difference out before comparing, and reran it. The count dropped from 102 to one, an import line, and a direct check of the compiled file confirmed that it and its properties were still there. Nothing was actually missing.

What the 117 was counting

Once the audit stopped being fooled by formatting, the original 117 stopped meaning anything too. It had never been counting rules. It was counting opening braces, a rough proxy that moves for reasons that have nothing to do with lost content: several comma-separated selectors collapsing into one block, empty rules disappearing correctly, and each media wrapper contributing its own extra brace. None of that is loss. We rewrote the original ticket to say what was true: nothing was missing, and the warning that started this was measuring the wrong thing.

Two stand-ins

The first alarm and the tool we built to check it both measured a stand-in instead of the thing itself. One counted braces, the other compared formatted text, and each called the difference “loss.” A more careful, purpose-built comparison does not protect you from that if its key has a blind spot of its own.

What caught the second false alarm was a pile of “missing” results clustered almost entirely inside one syntactic shape, which is the signature of a broken comparison and not of real damage.