/* Bluehaus — App root: routing, Tweaks panel */ const { useState: useStateApp, useEffect: useEffectApp } = React; const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "paperPalette": ["#F2EFE8", "#0E2A47", "#0A0F16"], "density": "regular", "fontSize": 16, "showMarquee": true, "accentTreatment": "navy" }/*EDITMODE-END*/; const PALETTE_OPTIONS = [ ["#F2EFE8", "#0E2A47", "#0A0F16"], // warm cream + brand navy (default) ["#FAFAF7", "#10202F", "#0A0F16"], // cool paper + slate navy ["#EDE7DA", "#1B3A5C", "#1A1410"], // sand + ink blue ["#F4F1EC", "#2B4358", "#0A0F16"], // softer ["#0A0F16", "#F2EFE8", "#F2EFE8"], // INVERTED dark mode ]; function App() { const [route, setRoute] = useStateApp(parseRoute(window.location.hash)); const [t, setTweak] = (window.useTweaks ? window.useTweaks(TWEAK_DEFAULTS) : [TWEAK_DEFAULTS, () => {}]); // Hash routing useEffectApp(() => { const onHash = () => { setRoute(parseRoute(window.location.hash)); // scroll to top on route change unless anchor window.scrollTo({ top: 0, behavior: 'instant' }); }; window.addEventListener('hashchange', onHash); return () => window.removeEventListener('hashchange', onHash); }, []); const navigate = (path) => { window.location.hash = '#' + path; }; // apply palette useEffectApp(() => { const [paper, brand, ink] = t.paperPalette; const r = document.documentElement; const isDark = t.paperPalette === PALETTE_OPTIONS[4]; r.style.setProperty('--paper', paper); r.style.setProperty('--blue', brand); r.style.setProperty('--ink', ink); r.style.setProperty('--paper-soft', isDark ? '#11161F' : shade(paper, -6)); r.style.setProperty('--surface', isDark ? '#171C26' : shade(paper, 4)); r.style.setProperty('--ink-soft', isDark ? '#D8D2C5' : shade(ink, 14)); r.style.setProperty('--muted', isDark ? '#9098A2' : '#5F6770'); r.style.setProperty('--line', isDark ? 'rgba(255,255,255,0.12)' : shade(paper, -16)); r.style.setProperty('--line-soft', isDark ? 'rgba(255,255,255,0.06)' : shade(paper, -10)); r.style.setProperty('--blue-deep', isDark ? '#04080F' : shade(brand, -32)); r.style.setProperty('--azure', isDark ? '#5A8AD8' : shade(brand, 30)); r.style.setProperty('--azure-bright', isDark ? '#7AA8E8' : shade(brand, 50)); document.body.style.background = paper; document.body.style.color = ink; }, [t.paperPalette]); // apply density useEffectApp(() => { const r = document.documentElement; if (t.density === 'compact') { r.style.setProperty('--gutter', 'clamp(16px, 3vw, 40px)'); } if (t.density === 'regular') { r.style.setProperty('--gutter', 'clamp(20px, 4vw, 56px)'); } if (t.density === 'comfy') { r.style.setProperty('--gutter', 'clamp(24px, 5vw, 80px)'); } }, [t.density]); // apply font size useEffectApp(() => { document.body.style.fontSize = t.fontSize + 'px'; }, [t.fontSize]); const page = route.page; const param = route.param; const query = route.query; return ( <>