Files
Catubba 5b3da78d20 feat: light theme with header toggle; bump to 0.7.0
The dark/light palettes now live as CSS variables in index.css, switched by a
data-theme attribute on <html>; theme.ts tokens reference the variables so the
whole UI (CodeMirror included) restyles without re-rendering. Scattered hex
literals are folded into shared tokens, and the four hex+alpha concatenations
are replaced with color-mix so they work on variable references.

The header gains a moon/sun toggle between Settings and Logout. The choice is
persisted to app.theme through the config API (the value existed since 0.1.0
but was never read) and mirrored to localStorage, which an inline script in
index.html applies before first paint so there is no flash of the wrong theme.
Switching cross-fades over 300ms, skipped under prefers-reduced-motion.

Also: header action buttons stretch to equal height (Logout was 3px short),
the dev stub persists PUT /config edits instead of silently reverting them,
and a parity test asserts both palettes define the identical token set.
2026-07-23 23:37:24 +02:00

26 lines
952 B
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/assets/joulenap-icon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#0f1216" />
<title>Joulenap</title>
<script>
// Apply the persisted theme before first paint so a light-theme user never sees a
// dark flash (and vice versa). Config is the source of truth once loaded; this
// localStorage mirror only covers boot and the pre-login screen.
try {
if (localStorage.getItem('jnTheme') === 'light') {
document.documentElement.dataset.theme = 'light'
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#f3f4f6')
}
} catch (e) {}
</script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>