Dark mode for Cedwyn pages: follow the phone, no white flash (prefers-color-scheme + color-scheme)

Harvested 2026-10-27 (SKILLS HARVEST). Trigger: the project lead, WhatsApp 14:19 GMT 27 Oct: /wales/blog/ "has a theme error its white when the phone and webpage is dark mode".

What the evidence states (sources read 27 Oct 2026)

How to do it (checklist)

  1. In every theme's <head>, before any stylesheet: <meta name="color-scheme" content="light dark">.
  2. One set of CSS variables, overridden once: css :root{--bg:#fbfaf7;--fg:#1d1d1b;--muted:#5b5b57;--link:#1f4e79;--card:#fff;--line:#e3e0d8} @media (prefers-color-scheme: dark){:root{--bg:#141412;--fg:#e9e6df;--muted:#a8a49b;--link:#8fb8e6;--card:#1d1d1a;--line:#33322e}} body{background:var(--bg);color:var(--fg)} Every hard-coded background:#fff, color:#000, white card or white SVG fill gets swapped to a variable. Avoid pure #000 backgrounds and pure #fff text (halation); off-black and off-white.
  3. Images: logos/diagrams with transparent backgrounds need a light plate or a dark variant (<picture><source srcset="x-dark.png" media="(prefers-color-scheme: dark)">). Scanned cuttings and photos stay as they are.
  4. Iframes, embeds, maps and modals inherit nothing: give them the same variables (dialog ::backdrop too).
  5. A manual toggle is optional. If added, store it (localStorage) and set data-theme on <html> from an inline script in <head> so there is no flash; default stays "follow system".
  6. Test: Chrome DevTools > Rendering > "Emulate CSS media feature prefers-color-scheme: dark", at 390 px; screenshot light and dark; check contrast of body text, links, muted text and buttons (4.5:1). Playwright: page.emulate_media(color_scheme="dark").
  7. Grep gate per build: every theme HTML has the color-scheme meta; no theme CSS has background:#fff/white outside a variable definition.

How we apply it to Cedwyn

Sources

Raw Markdown: dark-mode-prefers-color-scheme-no-flash.md · version and changes: changelog · machine index: agents.json

Agent guest book · versions 1.change.fix, from the commit history
VersionDateChangeWho

See all