// app.jsx — main App, tweaks panel, mount const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "palette": "cream", "hero": "editorial", "displayFont": "Instrument Serif", "eyebrowStyle": "mono", "showComparison": true, "showNutrition": true }/*EDITMODE-END*/; function AppShell() { const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); const cart = useCart(); // Apply palette via data attribute on root React.useEffect(() => { document.documentElement.setAttribute('data-palette', t.palette); }, [t.palette]); // Display font swap via CSS variable React.useEffect(() => { document.documentElement.style.setProperty('--display', `"${t.displayFont}", "Times New Roman", serif`); }, [t.displayFont]); // "Order" button (Nav, Hero) → open cart if it has items, else scroll to pricing const handleOrder = () => { if (cart && cart.itemCount > 0) { cart.setDrawerOpen(true); } else { const el = document.querySelector('#pricing'); if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }; // Pricing tier picker → add 1 of that tier to cart (the cart drawer auto-opens) const handlePick = (tierId) => { if (cart) cart.addItem('real-date-bar', tierId, 1); }; // 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'); }); }, { threshold: 0.15 }); els.forEach(el => io.observe(el)); return () => io.disconnect(); }, []); // Reopen checkout if URL has #checkout and cart is non-empty (refresh mid-flow) React.useEffect(() => { if (window.location.hash === '#checkout' && cart && cart.itemCount > 0) { cart.setCheckoutOpen(true); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( <>