diff --git a/apps/web/index.html b/apps/web/index.html
index 67efc12ae..bfd00080b 100644
--- a/apps/web/index.html
+++ b/apps/web/index.html
@@ -12,8 +12,9 @@
try {
var t = localStorage.getItem("corbits-theme:last");
var r = document.documentElement;
- if (t === "dark" || t === "canvas") r.setAttribute("data-theme", t);
- if (t === "dark") r.classList.add("dark");
+ if (t !== "dark" && t !== "canvas") t = "light";
+ r.setAttribute("data-theme", t);
+ r.classList.add(t === "dark" ? "dark" : "light");
r.style.colorScheme = t === "dark" ? "dark" : "light";
} catch (e) {}
diff --git a/apps/web/src/theme-store.ts b/apps/web/src/theme-store.ts
index 0bf67a111..b90fc814a 100644
--- a/apps/web/src/theme-store.ts
+++ b/apps/web/src/theme-store.ts
@@ -1,5 +1,6 @@
// The theme lives outside React: `data-theme` on is the one switch,
-// and this store is its only writer. Light is the absence of the attribute.
+// and this store is its only writer. Light is explicit too: react-ui's
+// `prefers-color-scheme: dark` block only skips roots carrying `.light`.
import { reportError } from "@corbits/error-sink";
import { useSyncExternalStore } from "react";
@@ -31,10 +32,10 @@ function readStored(key: string): Theme {
function apply(theme: Theme) {
const root = document.documentElement;
- if (theme === "light") root.removeAttribute("data-theme");
- else root.setAttribute("data-theme", theme);
- // react-ui's `dark:` variant keys off the class.
+ root.setAttribute("data-theme", theme);
+ // react-ui's `dark:` variant keys off `.dark`; its OS-dark block excludes `.light`.
root.classList.toggle("dark", theme === "dark");
+ root.classList.toggle("light", theme !== "dark");
root.style.colorScheme = theme === "dark" ? "dark" : "light";
}