I prefixed all the CSS classes for the new chatbot widget with 3mn-. As in Three Moons Network. As in branded. As in “this is going to be embedded on client sites and I want every selector to namespace cleanly so nothing collides with the host page’s CSS.”
Then I spent an hour wondering why none of the styling was applying.
Open dev tools. The classes are there in the HTML. The CSS rules are there in the stylesheet. The selectors look right. The specificity isn’t being overridden. Nothing in the console. Nothing in the network tab. The classes match. The rules match. The browser renders the elements with no styling whatsoever.
I stared at this for a full forty minutes before remembering: CSS class names cannot start with a digit.
.3mn-button is, technically, an invalid selector. The browser doesn’t throw. It doesn’t warn. It just silently ignores the rule and moves on with its day.
There it is. Section 4.1.3 of the CSS Syntax spec, which I haven’t looked at in maybe a decade and which my brain decided to dredge up only after I had personally accused dev tools of being broken. A class name has to start with a letter, an underscore, a hyphen, or an escaped/non-ASCII character. .3mn-button is, technically, an invalid selector. The browser doesn’t throw an error. It doesn’t warn you. It just silently treats the entire rule as malformed and moves on with its day.
I changed the prefix to tmn-. Same brand. One letter different. Every style snapped into place instantly. Twelve hundred lines of CSS suddenly knew what they were for.
Now here’s the part that gets me. Claude was sitting right there the entire time. I had the chatbot widget open in one pane and Claude in the other. We had been working on the file together for the better part of the morning. I asked Claude to “add a hover state to the primary button.” Claude wrote .3mn-button-primary:hover { ... }. I asked Claude to “make sure the modal has a backdrop blur.” Claude wrote .3mn-modal-backdrop { backdrop-filter: blur(...); }. Beautiful, idiomatic, modern CSS. Every selector starts with a digit. Every rule, silently invalid.
When I finally figured out the bug and asked Claude what was going on, Claude said, more or less: “Oh, right — CSS class names can’t start with a digit. The selectors you wrote are ignored by the browser.” Like it had known the whole time. Like it would have told me if I had asked. Like the failure was in my question, not in its answer.
This is the thing about working with an AI pair programmer that you have to keep relearning. The model is not a senior engineer looking over your shoulder, catching the mistakes you would have caught if you were paying attention. The model is a very fast version of you. It has the same blind spots you have, in the same places, for the same reasons. Worse: it has more blind spots, because it’s been trained on a corpus that includes thousands of CSS examples that all start with letters, and it has never personally been bitten by a class name starting with 3 in a way that left a mark.
The corollary, which is the part I think about a lot now, is that the things AI is best at are the things where being fast and confident is mostly correct. The things where AI disappoints you are the things where being a little slower and a little more skeptical would have caught the bug. AI doesn’t slow down. AI doesn’t get suspicious. AI does not have, as far as I can tell, the part of an engineer’s brain that says “wait, that’s weird, let me check the spec.” It just writes the next plausible line of code.
In SRE we have a name for the things that go wrong because nobody bothered to check them. We call them boring. The whole craft of operational engineering is, mostly, building the discipline to check the boring stuff before it bites you. Linters, validators, pre-flight checks, schema enforcement, integration tests. Every one of those tools exists because some human, sometime, in some otherwise-quiet conference room, said “this kept happening, let’s automate the part of our brain that doesn’t fire when we’re tired.”
Working with AI does not change any of this. If anything, it raises the stakes. If you are shipping more code per hour, you are also shipping more boring-mistakes per hour. Your linter and your validator and your pre-flight check are not optional anymore. They are the fence between you and a Friday afternoon of staring at correctly-named classes that the browser silently ignored.
I now have, in my CSS pipeline, a tiny pre-build script that greps for any selector starting with a digit and refuses to ship if it finds one. It exists because of forty minutes of my life I am never getting back. Tomorrow it’ll catch something else, and I’ll add another line. The pipeline gets longer. The Claude pair-programming sessions get faster. The total time to ship stays roughly the same. We have just moved the bottleneck.
To be fair — and I want to be fair, because I use Claude every single day and I am not interested in writing the easy “AI bad” essay — Claude was helpful when I finally turned around and asked. Claude found the bug from the symptoms in about thirty seconds. Claude wrote the pre-flight checker for me, in one shot, the way I wanted it. Claude was a great debugger. The failure mode wasn’t “Claude can’t help with CSS.” The failure mode was “Claude won’t catch the weird stuff while you’re typing, even when it’s right there, even when it’s section 4.1.3 of a spec older than Claude itself.” That is a real, narrow, specific limitation worth knowing.
So here is the partnership, the actual partnership, after a year of doing this every day. Claude writes the next plausible line of code, fast. I bring the slow brain that asks “wait, is this plausible or correct?” Claude writes the validator I describe, fast. I bring the half-remembered spec footnote that tells me which validator to ask for. Claude executes. I supervise. Together, we are roughly as good as one really attentive engineer with infinite patience, except the engineer is fast, and I am the patient one. That is a real, useful trade. It is not magic.
Anyway. CSS class names can’t start with a digit. Now you know. I expect you to forget by Tuesday. Claude will too.