Dan Mode: pure white backgrounds, electric blue text (#0000ff), nuclear yellow accents (#ffff00), hot magenta borders (#ff00ff), red labels, glowing box-shadows. Maximum saturation. Hostile to human vision by design. Theme toggle now cycles light → dark → dan → light (icons: 🌙 😎 ☀️). PICO_CSS.md: documents [role=button] color clobber, palette scoping rules, and theme toggling pattern for future reference.
58 lines
1.6 KiB
Svelte
58 lines
1.6 KiB
Svelte
<script lang="ts">
|
|
import '@picocss/pico/css/pico.min.css';
|
|
import '../app.css';
|
|
import { browser } from '$app/environment';
|
|
|
|
let { children } = $props();
|
|
|
|
type Theme = 'light' | 'dark' | 'dan';
|
|
const CYCLE: Theme[] = ['light', 'dark', 'dan'];
|
|
const ICONS: Record<Theme, string> = { light: '🌙', dark: '😎', dan: '☀️' };
|
|
|
|
function resolveInitialTheme(): Theme {
|
|
if (!browser) return 'light';
|
|
const stored = localStorage.getItem('theme');
|
|
if (stored === 'light' || stored === 'dark' || stored === 'dan') return stored;
|
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
}
|
|
|
|
let theme = $state<Theme>(resolveInitialTheme());
|
|
|
|
$effect(() => {
|
|
if (!browser) return;
|
|
document.documentElement.setAttribute('data-theme', theme);
|
|
localStorage.setItem('theme', theme);
|
|
});
|
|
|
|
function cycleTheme() {
|
|
const next = CYCLE[(CYCLE.indexOf(theme) + 1) % CYCLE.length];
|
|
theme = next;
|
|
}
|
|
</script>
|
|
|
|
<header>
|
|
<nav class="container">
|
|
<ul>
|
|
<li><strong>Humor Units</strong></li>
|
|
</ul>
|
|
<ul>
|
|
<li><a href="/">Converter</a></li>
|
|
<li><a href="/about">About</a></li>
|
|
<li><a href="/contact">Contact</a></li>
|
|
<li>
|
|
<button class="theme-toggle outline secondary" onclick={cycleTheme} aria-label="Toggle theme">
|
|
{ICONS[theme]}
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
</header>
|
|
|
|
<main class="container">
|
|
{@render children()}
|
|
</main>
|
|
|
|
<footer class="container">
|
|
<small>Humor Units — invented conversions for invented purposes</small>
|
|
</footer>
|