Never pure black
Pure #000 in dark mode causes halation: text and surfaces bloom against it. Use a near-black with a slight hue: #141414 with a warm or cool tint, depending on the brand. The tint keeps surfaces from looking dead.
The same rule applies to pure white text. #f5f5f6 or similar off-white reads softer and does not bloom on OLED screens.
Stack surfaces with borders, not just color
In light mode, surfaces separate by lightness: white card on gray page. In dark mode, lightness barely moves, so you need borders. Every surface step gets a border alpha bump: 0.09, 0.14, 0.22 across three levels.
The pattern: page background, surface-1 for cards, surface-2 for raised headers, and alpha-based borders between them. Semantics over absolute values, the same token works when the brand hue shifts.
Text hierarchy inverts
In light mode, secondary text is darker gray than the background. In dark mode it is lighter gray, and the levels must stay ordered. A common bug: tertiary text ends up lighter than secondary, breaking the reading order.
Check your token file: text, text-2, text-3, text-4 must monotonically lose contrast in both themes.
The glow trap
Accent glows and shadows tuned for dark mode look muddy in light mode. If a glow exists, give it a per-theme value: a 0.25 alpha in light, 0.5 in dark. Shadows shift too: dark mode wants deeper, tighter shadows; light mode wants softer and wider.