/* App — router + tweaks */ const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "accent": "#FFC72C", "fontDisplay": "Archivo Black", "fontBody": "Manrope", "heroVariant": "A", "density": "default" }/*EDITMODE-END*/; const FONT_PAIRS = { "Archivo Black": { display: "'Archivo Black', Impact, sans-serif", head: "'Archivo', sans-serif" }, "Anton": { display: "'Anton', Impact, sans-serif", head: "'Archivo', sans-serif" }, "Bebas Neue": { display: "'Bebas Neue', Impact, sans-serif", head: "'Archivo', sans-serif" }, "Space Grotesk": { display: "'Space Grotesk', sans-serif", head: "'Space Grotesk', sans-serif" } }; const BODY_FONTS = { "Manrope": "'Manrope', system-ui, sans-serif", "DM Sans": "'DM Sans', system-ui, sans-serif", "Plus Jakarta": "'Plus Jakarta Sans', system-ui, sans-serif", "IBM Plex Sans": "'IBM Plex Sans', system-ui, sans-serif" }; const ACCENT_PALETTE = [ '#FFC72C', // Sr Banheiro yellow (default) '#FFAB00', // sun '#F4631E', // construction orange '#2A6FDB' // utility blue ]; function useHashRoute() { const parse = () => { const hash = window.location.hash.replace(/^#\/?/, '') || ''; const [path] = hash.split('?'); const seg = path.split('/')[0] || 'home'; return seg; }; const [route, setRoute] = React.useState(parse()); React.useEffect(() => { const onHash = () => { setRoute(parse()); window.scrollTo({ top: 0, behavior: 'auto' }); }; window.addEventListener('hashchange', onHash); return () => window.removeEventListener('hashchange', onHash); }, []); return route; } function App() { const route = useHashRoute(); const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS); const [tweaksMounted, setTweaksMounted] = React.useState(false); React.useEffect(() => { setTweaksMounted(true); }, []); // Apply tweaks → CSS variables / styles React.useEffect(() => { const root = document.documentElement; root.style.setProperty('--yellow', tweaks.accent); // adjust yellow-deep proportionally root.style.setProperty('--yellow-deep', shadeColor(tweaks.accent, -18)); root.style.setProperty('--yellow-soft', shadeColor(tweaks.accent, 35)); const pair = FONT_PAIRS[tweaks.fontDisplay] || FONT_PAIRS["Archivo Black"]; root.style.setProperty('--font-display', pair.display); root.style.setProperty('--font-head', pair.head); root.style.setProperty('--font-body', BODY_FONTS[tweaks.fontBody] || BODY_FONTS["Manrope"]); document.body.style.fontSize = tweaks.density === 'compact' ? '15px' : tweaks.density === 'comfortable' ? '17px' : '16px'; }, [tweaks]); let Page = Home; if (route === 'catalogo') Page = Catalogo; else if (route === 'vip') Page = VIP; return ( {route === 'home' ? : } {tweaksMounted && ( setTweak('accent', v)} /> setTweak('fontDisplay', v)} /> setTweak('fontBody', v)} /> setTweak('heroVariant', v)} /> A: tipografia grande + imagem · B: foto cobrindo + texto sobre · C: split editorial 50/50 setTweak('density', v)} /> {[ ['#/', 'Home'], ['#/catalogo', 'Catálogo'], ['#/vip', 'Banheiro VIP'], ].map(([href, label]) => ( → {label} ))} )} ); } /* small color helper */ function shadeColor(hex, percent) { if (!hex || !hex.startsWith('#')) return hex; let h = hex.replace('#', ''); if (h.length === 3) h = h.split('').map(c => c + c).join(''); const num = parseInt(h, 16); let r = (num >> 16) + Math.round(2.55 * percent); let g = ((num >> 8) & 0xff) + Math.round(2.55 * percent); let b = (num & 0xff) + Math.round(2.55 * percent); r = Math.max(0, Math.min(255, r)); g = Math.max(0, Math.min(255, g)); b = Math.max(0, Math.min(255, b)); return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); } window.App = App; ReactDOM.createRoot(document.getElementById('root')).render();
A: tipografia grande + imagem · B: foto cobrindo + texto sobre · C: split editorial 50/50