Files
grabowski 2f55723585 Add a dark/light theme switcher to the navbar
The palette already lived in CSS custom properties, so dark mode is a
token-override block in the new theme.css, applied via data-theme on
the document element. A moon/sun toggle sits top right in the navbar;
an explicit choice persists in localStorage, otherwise the app follows
the OS preference live. An inline head script applies the theme before
first paint so a dark reload never flashes light.

Token hygiene sweep alongside: literal colours that broke under a dark
palette (timeline chip text, color-mix against white, calendar stripes
and bands, warning banners, nav background) moved into ten new tokens
with light-mode values unchanged. The flip clock keeps its fixed dark
look by design; the map keeps standard light tiles in both themes.
2026-08-30 14:07:21 +02:00

76 lines
2.3 KiB
CSS

/* Dark/light theme switcher. See docs/API.md "Theme switcher (dark/light,
frontend-only)". document.documentElement carries data-theme="dark" or
"light" (set by an inline script in index.html's <head>, before first
paint). Token names/values mirror styles.css :root — every light token
defined there (and the hygiene tokens added alongside it, plus --now from
timeline.css) gets a dark counterpart here. Attribute-selector overrides
win on specificity regardless of stylesheet link order. */
:root[data-theme="light"] {
color-scheme: light;
}
:root[data-theme="dark"] {
color-scheme: dark;
--brand: #3b82f6;
--brand-dark: #60a5fa;
--brand-soft: rgba(59, 130, 246, 0.18);
--accent: #38bdf8;
--bg: #0f172a;
--surface: #1e293b;
--surface-2: #253147;
--border: #334155;
--border-strong: #475569;
--text: #e2e8f0;
--text-muted: #94a3b8;
--text-faint: #64748b;
--danger: #f87171;
--danger-soft: rgba(248, 113, 113, 0.16);
--success: #34d399;
--warn: #fbbf24;
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4), 0 1px 3px rgba(0, 0, 0, 0.35);
--shadow-md: 0 4px 14px rgba(0, 0, 0, 0.45);
--shadow-lg: 0 18px 48px rgba(0, 0, 0, 0.55);
/* Theme-hygiene tokens (light values in styles.css) */
--chip-text: #e2e8f0;
--nav-bg: rgba(15, 23, 42, 0.85);
--auth-tint: #1c2b4d;
--stripe-a: #1a2438;
--stripe-b: #17202f;
--warn-soft-bg: rgba(251, 191, 36, 0.14);
--warn-soft-border: rgba(251, 191, 36, 0.35);
--warn-soft-text: #fbbf24;
--role-owner-bg: rgba(251, 191, 36, 0.18);
--chip-price-bg: rgba(255, 255, 255, 0.12);
/* timeline.css defines --now on plain :root; override it here too. */
--now: #f87171;
}
/* ---------- Theme toggle button (top-right of navbar) ---------- */
.theme-toggle {
border: none;
background: var(--surface-2);
color: var(--text-muted);
width: 2.1rem;
height: 2.1rem;
flex-shrink: 0;
border-radius: 50%;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 1.05rem;
line-height: 1;
cursor: pointer;
transition: background 0.15s, color 0.15s, transform 0.1s;
}
.theme-toggle:hover { background: var(--border); color: var(--text); }
.theme-toggle:active { transform: scale(0.94); }
.theme-toggle:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }