// App composer for ColaFish — light editorial direction. window.cfScrollTo = function (id) { const el = document.getElementById(id); if (!el) return; const y = el.getBoundingClientRect().top + window.pageYOffset - 60; window.scrollTo({ top: y, behavior: 'smooth' }); }; // Earth-tone phase progression — never falls to black. const PHASE_COLORS = { hero: '#FAF7F1', // cream pilares: '#F4EFE6', // paper marcas: '#E8DFCD', // sand metrics: '#EFE8DA', // mist contact: '#EFE8DA', // mist footer: '#DCD3BF', // stone }; const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "pillarLayout": "editorial", "accent": "#7a8c6f", "showRail": true, "showCue": true, "showTextures": false, "typeSystem": "newsreader" }/*EDITMODE-END*/; const ACCENT_OPTIONS = [ '#a8825a', // bronze '#7a8c6f', // moss '#6e8a96', // ocean '#9c6a55', // clay ]; const TYPE_OPTIONS = [ { value: 'instrument', label: 'Instrument' }, { value: 'bodoni', label: 'Bodoni' }, { value: 'newsreader', label: 'Newsreader' }, { value: 'bricolage', label: 'Bricolage' }, ]; function App() { const [activeSection, setActiveSection] = React.useState('hero'); const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS); // Accent CSS variable React.useEffect(() => { document.documentElement.style.setProperty('--accent', tweaks.accent); }, [tweaks.accent]); // Typography system — toggles via data-type attribute React.useEffect(() => { document.documentElement.setAttribute('data-type', tweaks.typeSystem); }, [tweaks.typeSystem]); // Phase tint driver — drives the underlying #phase-tint background. // Each section has its own surface color too, so this is a fallback for // areas between sections and the canvas blending. React.useEffect(() => { const tint = document.getElementById('phase-tint'); if (!tint) return; tint.style.backgroundColor = PHASE_COLORS[activeSection] || PHASE_COLORS.hero; }, [activeSection]); React.useEffect(() => { document.body.classList.toggle('hide-cue', !tweaks.showCue); }, [tweaks.showCue]); // Observe sections React.useEffect(() => { const ids = ['hero', 'pilares', 'marcas', 'contact']; const map = new Map(); const obs = new IntersectionObserver((entries) => { for (const e of entries) map.set(e.target.id, e.intersectionRatio); let best = 'hero', bestR = 0; for (const [id, r] of map) if (r > bestR) { bestR = r; best = id; } if (bestR > 0.18) setActiveSection(best); }, { threshold: [0, 0.18, 0.35, 0.6, 0.85] }); ids.forEach(id => { const el = document.getElementById(id); if (el) obs.observe(el); }); return () => obs.disconnect(); }, []); return (