// app.jsx — main App const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "palette": "fire", "fontPair": "bricolage", "darkMode": false, "heroLayout": "stage" }/*EDITMODE-END*/; const PALETTES = { fire: { red: '#ED1B3C', redDark: '#C8112F', redSoft: '#FFE2E6' }, midnight:{ red: '#5B9BFF', redDark: '#3A78E0', redSoft: '#E0EAFF' }, mint: { red: '#1FB58F', redDark: '#178A6E', redSoft: '#DCF6EC' }, plum: { red: '#6B4CE6', redDark: '#5536CF', redSoft: '#EBE3FF' }, }; const FONT_PAIRS = { bricolage: { display: '"Bricolage Grotesque", ui-sans-serif, system-ui, sans-serif', body: '"Plus Jakarta Sans", ui-sans-serif, system-ui, sans-serif' }, serif: { display: '"Instrument Serif", "Bricolage Grotesque", serif', body: '"Plus Jakarta Sans", ui-sans-serif, system-ui, sans-serif' }, mono: { display: '"Space Grotesk", "Bricolage Grotesque", sans-serif', body: '"Space Grotesk", ui-sans-serif, system-ui, sans-serif' }, }; function App() { const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); const [scrollY, setScrollY] = React.useState(0); const [heroParallax, setHeroParallax] = React.useState(0); const heroRef = React.useRef(null); React.useEffect(() => { const onScroll = () => { const y = window.scrollY || 0; setScrollY(y); // hero parallax — clamp so cards don't fly off setHeroParallax(Math.min(y, 1200)); }; onScroll(); window.addEventListener('scroll', onScroll, { passive: true }); return () => window.removeEventListener('scroll', onScroll); }, []); // Apply palette + fonts as CSS variables React.useEffect(() => { const p = PALETTES[t.palette] || PALETTES.fire; const fp = FONT_PAIRS[t.fontPair] || FONT_PAIRS.bricolage; document.documentElement.style.setProperty('--red', p.red); document.documentElement.style.setProperty('--red-dark', p.redDark); document.documentElement.style.setProperty('--red-soft', p.redSoft); document.documentElement.style.setProperty('--display', fp.display); document.documentElement.style.setProperty('--body', fp.body); document.body.style.fontFamily = fp.body; document.body.classList.toggle('dark', !!t.darkMode); }, [t.palette, t.fontPair, t.darkMode]); // Reveal-on-scroll React.useEffect(() => { const els = document.querySelectorAll('.reveal'); const io = new IntersectionObserver((entries) => { entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); } }); }, { threshold: 0.12 }); els.forEach(el => io.observe(el)); return () => io.disconnect(); }, []); const accent = (PALETTES[t.palette] || PALETTES.fire).red; return ( <>