feat: add theme system, fonts, graph styling, rename Overview→Tasks
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled
Desktop App / Build Linux (amd64) (push) Has been cancelled
Desktop App / Attach to Release (push) Has been cancelled

- Terracotta (light) and Carbon (dark) themes with toggle
- Inknut Antiqua headings, DM Sans body
- Dot grid background on EntityGraph and GraphBackground
- Theme-adaptive graph colors on EntityGraph
- Art Nouveau chat styling (borders, underlines, blockquote quotes)
- Bullet point styles in chat prose
- Task goal in header, rename Overview→Tasks, New Task labels
- Logo uses var(--primary) for theme awareness
This commit is contained in:
2026-07-15 00:14:31 +02:00
parent 49dfaa77e6
commit e8b30cddcf
12 changed files with 422 additions and 105 deletions

View File

@@ -0,0 +1,46 @@
export type Theme = 'light' | 'dark'
const STORAGE_KEY = 'oikos-theme'
function applyClass(theme: Theme): void {
const root = document.documentElement
if (theme === 'dark') {
root.classList.add('dark')
} else {
root.classList.remove('dark')
}
}
function storedTheme(): Theme {
if (typeof localStorage === 'undefined') return 'dark'
const v = localStorage.getItem(STORAGE_KEY)
if (v === 'light' || v === 'dark') return v
return window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'
}
let current: Theme = $state(storedTheme())
applyClass(current)
export function setTheme(t: Theme): void {
current = t
applyClass(t)
if (typeof localStorage !== 'undefined') {
localStorage.setItem(STORAGE_KEY, t)
}
}
export function getTheme(): Theme {
return current
}
export function toggleTheme(): Theme {
const next = current === 'dark' ? 'light' : 'dark'
setTheme(next)
return next
}
export const THEME_LABELS: Record<Theme, string> = {
light: 'Terracotta',
dark: 'Carbon'
}