Skip to content
Nasir Nasir-Ameen
Notes

Sellavie AI workspace

A theme repair should remove exceptions, not add more

Replacing 34 hard-coded light surfaces and deleting 131 dark-mode overrides that depended on CSS chunk order.
7 min read

Dark mode in the Sellavie workspace looked finished. In the production build, some panels came out white with light text on them.

Why it only broke in production

The workspace had 34 surfaces with a light background written directly into their styles. Dark mode was achieved by 131 later rules whose only job was to override those backgrounds.

That works as long as the override always arrives after the rule it overrides. The production build splits styles into chunks and loads them as they are needed, and the order of those chunks is not guaranteed to match the order in the source. When an override arrived before the rule it was meant to beat, the surface stayed white while the text colour, which came from a token, had already switched to its dark value.

So the bug was not in any one rule. The design depended on an ordering the build never promised.

The fix I got wrong first

The quick repair is another override with higher priority. That was my first attempt, and it was the wrong fix. It repaired the screens I could see and left the same dependency in place for the next one.

What I did instead

I replaced all 34 hard-coded surfaces with semantic tokens and deleted the 131 overrides. A surface now asks for "panel" or "raised surface" and the theme decides what that means. Nothing has to win a race, because there is only one rule.

The token names describe purpose, not appearance: page, panel, raised surface, border, muted text, interactive state, critical state. The shared buttons, tabs, alerts, dialogs and page headers all use the same set.

Keeping it fixed

I added a check that fails if a hard-coded light surface is introduced again. Without it, the same pattern would come back one convenient shortcut at a time.

What I took from it

A fix that adds an exception has to keep winning. A fix that removes the reason for the exception does not. When a visual bug appears only in production, I now look at ordering and bundling before I look at the component.