// App entry — orchestrates state, tweaks panel, sections const { useState: useStateA, useEffect: useEffectA } = React; const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "theme": "fire", "language": "de", "heroVariant": "crowd", "grain": 6 }/*EDITMODE-END*/; function App() { const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS); const [activeSection, setActiveSection] = useStateA('top'); // Apply theme useEffectA(() => { document.documentElement.setAttribute('data-theme', tweaks.theme); document.documentElement.style.setProperty('--grain-opacity', (tweaks.grain / 100).toString()); }, [tweaks.theme, tweaks.grain]); // Apply lang attr useEffectA(() => { document.documentElement.setAttribute('lang', tweaks.language); }, [tweaks.language]); // Track active section useEffectA(() => { const ids = ['top', 'info', 'tickets', 'impressions', 'travel', 'faq']; const sections = ids.map(id => document.getElementById(id)).filter(Boolean); const onScroll = () => { const y = window.scrollY + window.innerHeight * 0.35; let curr = ids[0]; for (const s of sections) { if (s.offsetTop <= y) curr = s.id; } setActiveSection(curr); }; window.addEventListener('scroll', onScroll, { passive: true }); onScroll(); return () => window.removeEventListener('scroll', onScroll); }, []); const copy = COPY[tweaks.language] || COPY.de; return ( <>