diff --git a/frontend/index.html b/frontend/index.html
index 1a51cb8..7d8fbf6 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -20,9 +20,9 @@
var c = localStorage.getItem('umbra-accent-color');
if (c) {
var p = JSON.parse(c);
- if (p.h) h = p.h;
- if (p.s) s = p.s;
- if (p.l) l = p.l;
+ if (p.h && /^\d+$/.test(p.h)) h = p.h;
+ if (p.s && /^\d+\.?\d*%$/.test(p.s)) s = p.s;
+ if (p.l && /^\d+\.?\d*%$/.test(p.l)) l = p.l;
}
} catch(e) {}
document.getElementById('umbra-accent').textContent =
diff --git a/frontend/src/hooks/usePrefetch.ts b/frontend/src/hooks/usePrefetch.ts
index 96dbf60..db78bab 100644
--- a/frontend/src/hooks/usePrefetch.ts
+++ b/frontend/src/hooks/usePrefetch.ts
@@ -12,14 +12,24 @@ export function usePrefetch(enabled: boolean) {
const queryClient = useQueryClient();
const { settings } = useSettings();
const hasPrefetched = useRef(false);
+ const prevEnabled = useRef(false);
+
+ // Reset on re-lock so subsequent unlocks refresh stale data (W-02)
+ useEffect(() => {
+ if (prevEnabled.current && !enabled) {
+ hasPrefetched.current = false;
+ }
+ prevEnabled.current = enabled;
+ }, [enabled]);
useEffect(() => {
- if (!enabled || hasPrefetched.current) return;
+ // Wait for settings to load so upcoming_days is accurate (S-05)
+ if (!enabled || hasPrefetched.current || !settings) return;
hasPrefetched.current = true;
const now = new Date();
const clientDate = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
- const days = settings?.upcoming_days || 7;
+ const days = settings.upcoming_days || 7;
// Prefetch all main page queries (no-op if already cached and fresh)
queryClient.prefetchQuery({
@@ -58,5 +68,5 @@ export function usePrefetch(enabled: boolean) {
queryKey: ['locations'],
queryFn: () => api.get('/locations').then(r => r.data),
});
- }, [enabled, queryClient, settings?.upcoming_days]);
+ }, [enabled, queryClient, settings]);
}