// ============================================================ // App shell + hash router - FreshWave Digital Studio // ============================================================ function parseHash() { const raw = (window.location.hash || '#/').replace(/^#/, ''); // support "/" "/work" "/sleepers" "/sleepers/catalogue" "/process" "/about" "/commission" "/contact" and "/#process" const [path] = raw.split('#'); const clean = path === '' ? '/' : path; return { route: clean, anchor: raw.includes('#') ? raw.split('#')[1] : null }; } const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "neon": "teal", "glow": 1.15, "showMarquee": true, "marqueeSpeed": 26 }/*EDITMODE-END*/; const NEON_HUES = { teal: '181 96% 44%', magenta: '318 94% 53%', violet: '281 91% 62%', sunset: '18 95% 56%' }; function App() { const [{ route, anchor }, setLoc] = useState(parseHash()); const [activeProject, setActiveProject] = useState(null); const [introKey, setIntroKey] = useState(0); const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); useEffect(() => { document.body.classList.add('lights-off'); return () => document.body.classList.remove('lights-off'); }, []); // apply tweaks to CSS variables useEffect(() => { const root = document.documentElement; const hue = NEON_HUES[t.neon] || NEON_HUES.teal; root.style.setProperty('--cyan', hue); root.style.setProperty('--primary', hue); root.style.setProperty('--ring', hue); root.style.setProperty('--glow', String(t.glow)); root.style.setProperty('--marquee-dur', t.marqueeSpeed + 's'); }, [t.neon, t.glow, t.marqueeSpeed]); const replayIntro = () => { try { sessionStorage.removeItem('fw-intro-seen'); } catch (e) {} setIntroKey((k) => k + 1); }; useEffect(() => { const onHash = () => { const loc = parseHash(); setLoc(loc); setActiveProject(null); if (loc.anchor) { // let the view render, then scroll to the section setTimeout(() => { const el = document.getElementById(loc.anchor); if (el) el.scrollIntoView({ behavior: 'smooth' }); }, 60); } else { window.scrollTo({ top: 0, behavior: 'smooth' }); } }; window.addEventListener('hashchange', onHash); return () => window.removeEventListener('hashchange', onHash); }, []); let page; if (route === '/work') page = ; else if (route === '/sleepers/catalogue') page = ; else if (route === '/sleepers') page = ; else if (route === '/process') page = ; else if (route === '/about') page = ; else if (route === '/commission') page = ; else if (route === '/contact') page = ; else page = ; return (
{t.showMarquee && } {page}