)
}
/**
* Light-switch tick: left position (unchecked) keeps the dark theme, flipping
* right (checked) switches the page to the white theme. The dark side is
* whichever dark base the visitor picked on the Settings tab (royal purple
* by default); both choices persist per visitor. The useSyncExternalStore
* mount guard returns false on the server / first client render and true
* after hydration, so the checkbox never causes a hydration mismatch.
*/
const emptySubscribe = () => () => {}
function ThemeToggle() {
const { resolvedTheme, setTheme } = useTheme()
const mounted = useSyncExternalStore(emptySubscribe, () => true, () => false)
const isLight = mounted && resolvedTheme === 'light'
return (
setTheme(v ? 'light' : getStoredDarkBase())}
aria-label={isLight ? 'Switch to dark theme' : 'Switch to light theme'}
className="data-[state=checked]:bg-emerald-400 data-[state=unchecked]:bg-zinc-600"
/>
)
}
export function AppHeader() {
return (
{/* logo */}
{APP_SHORT}
{APP_NAME.toUpperCase()}
{/* source controls — full row on mobile, after logo on desktop */}