The <style id="umbra-accent"> tag injected by index.html gets removed
during page initialization. useTheme now defensively recreates the tag
if it's missing, ensuring color changes from the settings page work.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Inline style attribute on <html> gets stripped during page load.
Switch to injecting a <style id="umbra-accent"> tag with !important
CSS custom properties which persists in the DOM and beats @layer base
defaults. useTheme updates the same style tag when settings load.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both the index.html inline script and useTheme now use setProperty
with 'important' priority flag. This is the highest CSS cascade
priority and cannot be overridden by Vite's stylesheet injection,
@layer rules, or source order. Removes the <style> tag injection
approach which was being overridden.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The inline script's style.setProperty values on <html> were being
stripped during Vite's CSS injection. Switch to injecting a <style>
tag with :root vars which persists in the DOM. Restore CSS defaults
as safety fallback. Update useTheme to sync both the style tag and
inline styles when settings load.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Guard useTheme effect to skip when settings are undefined, preventing
it from overwriting the inline script's cached color with cyan defaults.
Move CSS accent var defaults from index.css :root into the index.html
inline script so they are always set synchronously before paint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Gate dashboard rendering on isLockResolved to prevent content flash
before lock state is known. Remove animate-fade-in from LockOverlay
so it renders instantly. Always write accent color to localStorage
(even default cyan) to prevent theme flash on reload. Resolve lock
state on auth query error to avoid permanent blank screen. Lift
mobileOpen state above lock gate to survive lock/unlock cycles.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Critical: Lock state was purely React useState — refreshing the page reset it.
Now persisted server-side via is_locked/locked_at columns on user_sessions.
POST /auth/lock sets the flag, /auth/verify-password clears it, and
GET /auth/status returns is_locked so the frontend initializes correctly.
UI: Cache accent color in localStorage and apply via inline script in
index.html before React hydrates to eliminate the cyan flash on load.
UI: Increase TanStack Query gcTime from 5min to 30min so page data
survives component unmount/remount across tab switches without skeleton.
UI: Move Projects nav onClick from the icon element to the full-width
container div so the entire row is clickable when the sidebar is collapsed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The swatches were added to SettingsPage but useTheme only had 5 presets,
so selecting the new colors saved to DB but never applied CSS variables.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>