Utility CSS frameworks now use @layer internally, which quietly changed how they interact with hand-written styles. I kept writing with a fuzzy mental model and got stuck twice in the same spot, so this is the note I should have written the first time.
The rule I had backwards
The cause was embarrassingly simple: styles that belong to no layer beat styles in any layer, and I had memorized it the other way around. Framework utilities live inside a layer, so a sloppy unlayered override wins regardless of specificity. When a rule seems to apply too well, this is the first thing to suspect.
Read the layer declaration
The second lesson was to read the framework’s layer order once instead of guessing:
@layer theme, base, components, utilities;
That single line is the whole precedence picture — later layers are stronger. Putting my component styles into components means utility classes can still fine-tune them, exactly as intended.
Takeaway
Cascade layers replace specificity tug-of-war with explicit design, and the rule set is small. Unlayered styles are strongest; declaration order decides the rest. Once those two facts sank in, the stuck feeling went away.