Diagnose first: why uTune AI can't go dark today

Lesson 1 · utune-ai.vercel.app · Before you can fix low-light readability, you must be able to name exactly what blocks it.

Open utune-ai.vercel.app at night and you get a wall of near-white: a sky-blue illustrated hero, cream card backgrounds, white sections. Turning on OS dark mode changes nothing. This lesson gives you one win: a repeatable, three-step diagnosis — using Chrome DevTools and the page's own CSS — that ends with you naming the three concrete blockers on this specific site.

Step 1 — Emulate dark mode in Chrome DevTools (no OS changes)

You don't need to toggle your Mac's appearance to test. DevTools can lie to the page about the OS setting:

  1. Open the site, then DevTools (Cmd+Option+I).
  2. Open the Command Menu (Cmd+Shift+P) and run “Show Rendering”.
  3. In the Rendering tab, set Emulate CSS media feature prefers-color-scheme to dark.

Observed result on uTune AI: the page does not change at all. That single observation already tells you the site has no meaningful dark theme — the OS signal arrives, and nothing listens to it.

Step 2 — Ask the CSS: is anyone listening for dark mode?

Searching the site's compiled Tailwind CSS for dark-mode rules (run in a terminal).

Listen first: the first command downloads the site's stylesheet with curl. The second uses grep to count rules guarded by the dark-mode media query. On this site the answer is: exactly one media block containing only two utilities, dark:text-orange-400 and dark:text-yellow-400 — leftover accents, not a theme.

Interpretation: this is a Tailwind CSS v4 site, and in v4 the dark: variant compiles to @media (prefers-color-scheme: dark) by default. Only two utilities on the whole page use it. Everything else renders identical colors day and night.

Step 3 — Find why a dark theme would be hard: hardcoded colors

In DevTools, inspect any heading or card (Elements panel), or tally the classes from the served HTML:

The most-used color classes on the homepage, counted from the served HTML.

Listen first: the top classes are Tailwind arbitrary values — raw hex codes wrapped in square brackets. Body headings use text color hex 0f1115 (near-black) 71 times; muted text uses hex 9aa0aa and 6b7180; backgrounds are white, hex f0f0f0, and cream hex fbfaf6. These literals are baked into the markup, so no theme can reinterpret them.

This is the load-bearing insight of the lesson. A class like bg-[#fbfaf6] says “this element is cream, forever, in every context.” A dark theme needs the element to say something semantic instead — “this is a card surface” — so a token like bg-surface can resolve to cream in light mode and deep gray in dark mode. Until the hex literals become semantic tokens, there is nothing for a dark theme to hook into.

The three blockers, named

#BlockerEvidenceFix family (later lessons)
1Colors are hardcoded hex literals in markuptext-[#0f1115] ×71, bg-[#fbfaf6], bg-white ×30…Introduce semantic tokens (CSS custom properties → Tailwind theme)
2Nothing listens to prefers-color-schemeOne media block, two stray dark: utilities; no color-scheme property anywhereDefine dark token values under the dark variant; set color-scheme: light dark so scrollbars/form controls follow
3The hero is an inline SVG with hardcoded gradient stopsstop-color="#6cbfff" sky, #9ad77e hills, white cloudsSwap stops to CSS variables or provide a night-scene variant
“Couldn't we just slap filter: invert(1) on the page?” It's a real technique for quick prototypes, but it inverts brand colors and photos too, wrecks the illustrated hero, and produces off-brand, low-contrast results. It's a diagnosis shortcut, not a shipping fix.
Cold-recall defense (one breath):
uTune AI can't go dark because its colors are hardcoded — text-[#0f1115]-style hex literals in the markup — so the first move is not writing dark: overrides everywhere; it's converting the ~8 recurring hex values into semantic tokens, then flipping the tokens.

Read next

Mission update (2026-07-04): dark mode is deferred — the immediate problem is text contrast in the existing light theme. The diagnosis technique above (DevTools emulation + reading the compiled CSS) still applies.

Primary source

web.dev — “Building a color scheme” by Adam Argyle (~15-min read): the canonical walkthrough of exactly this token-first strategy, from one brand color to paired light/dark themes.

💬 I'm your teacher for this — ask me followups any time.

Lesson 1 · workspace utune-ai · mission: make utune-ai.vercel.app easy to read in low light