diff --git a/web/src/app.css b/web/src/app.css index e342abf..1a2a5f0 100644 --- a/web/src/app.css +++ b/web/src/app.css @@ -37,6 +37,7 @@ /* ---- Light Theme (default) ---- */ :root, [data-theme="light"] { + color-scheme: light; --bg-primary: #fdfbff; --bg-secondary: #f9f4fb; --bg-tertiary: #f2e9f4; @@ -78,6 +79,7 @@ /* ---- Dark Theme ---- */ [data-theme="dark"] { + color-scheme: dark; --bg-primary: #0f1117; --bg-secondary: #151821; --bg-tertiary: #1a1d28; @@ -242,6 +244,26 @@ p { color: white; } +/* ---- Docs syntax highlighting ---- */ +.hl-comment { color: #64748b; } +.hl-command { color: var(--accent); } +.hl-arg, +.hl-flag { color: #15803d; } +.hl-operator { color: #6b7280; } +.hl-value { color: #a16207; } +.hl-keyword { color: #7c3aed; } +.hl-string { color: #c2410c; } +.hl-builtin { color: #0369a1; } + +[data-theme="dark"] .hl-comment { color: #94a3b8; } +[data-theme="dark"] .hl-arg, +[data-theme="dark"] .hl-flag { color: #22c55e; } +[data-theme="dark"] .hl-operator { color: #e5e7eb; } +[data-theme="dark"] .hl-value { color: #eab308; } +[data-theme="dark"] .hl-keyword { color: #a855f7; } +[data-theme="dark"] .hl-string { color: #f97316; } +[data-theme="dark"] .hl-builtin { color: #0ea5e9; } + /* Scrollbar */ ::-webkit-scrollbar { width: 6px; diff --git a/web/src/app.html b/web/src/app.html index 070ae8f..5a48692 100644 --- a/web/src/app.html +++ b/web/src/app.html @@ -13,12 +13,13 @@ /> %sveltekit.head% diff --git a/web/src/lib/theme.svelte.ts b/web/src/lib/theme.svelte.ts index db5ee31..54b5e25 100644 --- a/web/src/lib/theme.svelte.ts +++ b/web/src/lib/theme.svelte.ts @@ -2,6 +2,16 @@ import { browser } from '$app/environment'; type Theme = 'light' | 'dark'; +function safeLocalStorage(action: 'get' | 'set', key: string, value?: string): string | null { + try { + if (action === 'get') return localStorage.getItem(key); + localStorage.setItem(key, value!); + return null; + } catch { + return null; + } +} + function getSystemTheme(): Theme { if (!browser) return 'light'; return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; @@ -9,7 +19,7 @@ function getSystemTheme(): Theme { function getStoredPreference(): 'light' | 'dark' | 'system' { if (!browser) return 'system'; - return (localStorage.getItem('hashprep-theme') as 'light' | 'dark' | 'system') || 'system'; + return (safeLocalStorage('get', 'hashprep-theme') as 'light' | 'dark' | 'system') || 'system'; } let preference = $state<'light' | 'dark' | 'system'>(getStoredPreference()); @@ -18,12 +28,15 @@ let resolved = $derived(preference === 'system' ? getSystemTheme() : pref function apply(t: Theme) { if (!browser) return; document.documentElement.setAttribute('data-theme', t); + // Safari needs color-scheme set explicitly to reliably trigger a full + // style recalculation when the theme attribute changes on . + document.documentElement.style.colorScheme = t; } function setPreference(pref: 'light' | 'dark' | 'system') { preference = pref; if (browser) { - localStorage.setItem('hashprep-theme', pref); + safeLocalStorage('set', 'hashprep-theme', pref); } apply(pref === 'system' ? getSystemTheme() : pref); } diff --git a/web/src/routes/docs/+page.svelte b/web/src/routes/docs/+page.svelte index 13a93a2..72ef1b1 100644 --- a/web/src/routes/docs/+page.svelte +++ b/web/src/routes/docs/+page.svelte @@ -716,10 +716,6 @@ summary = analyzer.analyze() margin-bottom: 20px; } - code { - font-family: var(--font-mono); - } - pre::before { position: absolute; inset-block-start: 6px; @@ -742,49 +738,6 @@ summary = analyzer.analyze() content: 'Python'; } - /* Syntax highlighting — light-mode defaults */ - .hl-comment { - color: #64748b; - } - - .hl-command { - color: var(--accent); - } - - .hl-arg, - .hl-flag { - color: #15803d; - } - - .hl-operator { - color: #6b7280; - } - - .hl-value { - color: #a16207; - } - - .hl-keyword { - color: #7c3aed; - } - - .hl-string { - color: #c2410c; - } - - .hl-builtin { - color: #0369a1; - } - - /* Syntax highlighting — dark-mode overrides */ - :global([data-theme="dark"]) .hl-comment { color: #94a3b8; } - :global([data-theme="dark"]) .hl-arg, - :global([data-theme="dark"]) .hl-flag { color: #22c55e; } - :global([data-theme="dark"]) .hl-operator { color: #e5e7eb; } - :global([data-theme="dark"]) .hl-value { color: #eab308; } - :global([data-theme="dark"]) .hl-keyword { color: #a855f7; } - :global([data-theme="dark"]) .hl-string { color: #f97316; } - :global([data-theme="dark"]) .hl-builtin { color: #0ea5e9; } @media (max-width: 960px) { .docs-layout { diff --git a/web/vercel.json b/web/vercel.json new file mode 100644 index 0000000..bd6fd8f --- /dev/null +++ b/web/vercel.json @@ -0,0 +1,3 @@ +{ + "cleanUrls": true +}