diff --git a/src/app.html b/src/app.html
index 46b5aa6..6b86afc 100644
--- a/src/app.html
+++ b/src/app.html
@@ -10,9 +10,26 @@
-
+
+
+
+
+
+
diff --git a/src/lib/stores.ts b/src/lib/stores.ts
index fc76261..32acb5d 100644
--- a/src/lib/stores.ts
+++ b/src/lib/stores.ts
@@ -8,13 +8,28 @@ export const colorModeKey = `color-mode`
type ColorMode = `light` | `dark` | `system`
-export const colorMode = writable(
- (has_local_store && localStorage[colorModeKey]) || `system`,
-)
+// Initialize to 'system' for SSR, then hydrate from localStorage on client
+export const colorMode = writable(`system`)
-colorMode.subscribe(
- (val: ColorMode) => has_local_store && (localStorage[colorModeKey] = val),
-)
+// Flag to track if we've hydrated from localStorage
+let colorModeHydrated = false
+
+export function hydrateColorMode() {
+ if (!colorModeHydrated && has_local_store) {
+ const stored = localStorage[colorModeKey] as ColorMode | undefined
+ if (stored) {
+ colorMode.set(stored)
+ }
+ colorModeHydrated = true
+ }
+}
+
+// Only persist to localStorage AFTER hydration (to avoid overwriting stored value)
+colorMode.subscribe((val: ColorMode) => {
+ if (colorModeHydrated && has_local_store) {
+ localStorage[colorModeKey] = val
+ }
+})
// Custom session store implementation to replace svelte-zoo
function createSessionStore(key: string, initialValue: T) {
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 11dada6..348eb8b 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -1,5 +1,6 @@
@@ -33,7 +41,6 @@
-
diff --git a/static/dark-theme.css b/static/dark-theme.css
index 79e3683..abbd0a7 100644
--- a/static/dark-theme.css
+++ b/static/dark-theme.css
@@ -1,4 +1,5 @@
-:root {
+/* Dark theme - applies when data-theme="dark" or system preference is dark */
+[data-theme='dark'] {
--text-color: white;
--link-color: var(--light-blue);
--hover-color: var(--green);
diff --git a/static/light-theme.css b/static/light-theme.css
index 7fa944a..7529fd2 100644
--- a/static/light-theme.css
+++ b/static/light-theme.css
@@ -1,4 +1,6 @@
-:root {
+/* Light theme - applies when data-theme="light" or system preference is light */
+:root,
+[data-theme='light'] {
--text-color: black;
--link-color: var(--blue);
--hover-color: var(--light-blue);
diff --git a/static/system-theme.css b/static/system-theme.css
index 16ef5bf..05beb93 100644
--- a/static/system-theme.css
+++ b/static/system-theme.css
@@ -1,3 +1,22 @@
-@import url('/light-theme.css') (prefers-color-scheme: light);
+/* System theme - uses media queries to follow OS preference */
+/* Light is the default via light-theme.css :root selector */
-@import url('/dark-theme.css') (prefers-color-scheme: dark);
+/* Apply dark theme when system preference is dark AND data-theme is "system" */
+@media (prefers-color-scheme: dark) {
+ [data-theme='system'] {
+ --text-color: white;
+ --link-color: var(--light-blue);
+ --hover-color: var(--green);
+ --body-bg: var(--darker-blue);
+ --accent-bg: var(--alt-gray);
+ --light-bg: var(--dark-gray);
+ --shadow: black;
+ --border-color: var(--dark-green);
+ --heading-color: var(--light-green);
+ --header-bg: var(--darker-blue);
+ --header-color: var(--light-blue);
+ --footer-bg: black;
+ --invert: 1;
+ --transparent: rgba(0, 0, 0, 0.5);
+ }
+}