UMBRA
diff --git a/frontend/src/hooks/useTheme.ts b/frontend/src/hooks/useTheme.ts
index 250075b..e3445ce 100644
--- a/frontend/src/hooks/useTheme.ts
+++ b/frontend/src/hooks/useTheme.ts
@@ -15,10 +15,13 @@ const ACCENT_PRESETS: Record = {
export function useTheme() {
const { settings } = useSettings();
- // Ensure localStorage always has an accent color (even default cyan)
- // so the inline script in index.html can prevent flashes on every load
+ // Only apply accent color once settings have loaded from the API.
+ // The inline script in index.html handles the initial paint from localStorage cache.
+ // Firing this effect with settings=undefined would overwrite the cache with cyan.
useEffect(() => {
- const colorName = settings?.accent_color || 'cyan';
+ if (!settings) return;
+
+ const colorName = settings.accent_color || 'cyan';
const preset = ACCENT_PRESETS[colorName];
if (!preset) return;
@@ -31,7 +34,7 @@ export function useTheme() {
try {
localStorage.setItem('umbra-accent-color', JSON.stringify({ h, s, l }));
} catch {}
- }, [settings?.accent_color]);
+ }, [settings]);
return {
accentColor: settings?.accent_color || 'cyan',
diff --git a/frontend/src/index.css b/frontend/src/index.css
index 83ce23f..6b58c1a 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -26,10 +26,9 @@
--ring: var(--accent-h) var(--accent-s) var(--accent-l);
--radius: 0.5rem;
- /* Default accent: cyan */
- --accent-h: 187;
- --accent-s: 85.7%;
- --accent-l: 53.3%;
+ /* Accent vars are set by the inline script in index.html (from localStorage
+ cache or cyan fallback). No CSS defaults here — they would race with the
+ inline script and cause a flash of wrong color on refresh. */
/* Transitions */
--transition-fast: 150ms;