/* Keiko Eyewear — main app: language state, GSAP scrollytelling, lightbox, mount. */ const { Header, Hero, About, Collections, WaGlyph } = window.KeikoSections1; const { Kids, Gallery, VideoGallery, Retail, Wholesale, Briventi, Contact, Footer } = window.KeikoSections2; const LINKS = window.KEIKO_LINKS; const prefersReduced = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; function FloatingWhatsApp({ label }) { return ( { e.currentTarget.style.transform = 'scale(1.08)'; e.currentTarget.style.filter = 'brightness(1.06)'; }} onMouseLeave={(e) => { e.currentTarget.style.transform = ''; e.currentTarget.style.filter = ''; }}> ); } function Lightbox({ src, onClose }) { React.useEffect(() => { const onKey = (e) => { if (e.key === 'Escape') onClose(); }; document.addEventListener('keydown', onKey); return () => document.removeEventListener('keydown', onKey); }, [onClose]); if (!src) return null; return (
); } function App() { const [lang, setLangState] = React.useState('es'); const [lightbox, setLightbox] = React.useState(null); const t = window.KEIKO_T[lang]; const rootRef = React.useRef(null); const setLang = React.useCallback((code) => { setLangState(code); }, []); // sync dir + lang React.useEffect(() => { const html = document.documentElement; html.setAttribute('lang', t.lang); html.setAttribute('dir', t.dir); }, [t.lang, t.dir]); // GSAP scrollytelling — set up once after mount React.useEffect(() => { if (prefersReduced || !window.gsap) return; const gsap = window.gsap; gsap.registerPlugin(window.ScrollTrigger); const ctx = gsap.context(() => { // hero entrance gsap.from('[data-hero-anim]', { y: 28, opacity: 0, duration: 0.9, ease: 'power3.out', stagger: 0.12, delay: 0.15, }); // standard reveals gsap.utils.toArray('[data-reveal]').forEach((el) => { gsap.from(el, { scrollTrigger: { trigger: el, start: 'top 86%' }, y: 36, opacity: 0, duration: 0.85, ease: 'power3.out', }); }); // playful bounce reveals (Keiko Kids) gsap.utils.toArray('[data-reveal-bounce]').forEach((el, i) => { gsap.from(el, { scrollTrigger: { trigger: el, start: 'top 88%' }, y: 40, opacity: 0, scale: 0.92, duration: 0.7, ease: 'back.out(1.7)', delay: (i % 4) * 0.05, }); }); gsap.utils.toArray('[data-kids-pop]').forEach((el, i) => { gsap.from(el, { scrollTrigger: { trigger: el, start: 'top 95%' }, y: -20, opacity: 0, duration: 0.5, ease: 'back.out(2)', delay: i * 0.06, }); }); // subtle parallax on hero media const heroMedia = document.querySelector('[data-hero-media]'); if (heroMedia) { gsap.to(heroMedia, { yPercent: 14, ease: 'none', scrollTrigger: { trigger: '#hero', start: 'top top', end: 'bottom top', scrub: true }, }); } }, rootRef); const refresh = () => window.ScrollTrigger && window.ScrollTrigger.refresh(); window.addEventListener('load', refresh); const tId = setTimeout(refresh, 400); return () => { ctx.revert(); window.removeEventListener('load', refresh); clearTimeout(tId); }; }, []); // refresh triggers after a language change (text reflow changes heights) React.useEffect(() => { if (window.ScrollTrigger) { const id = setTimeout(() => window.ScrollTrigger.refresh(), 120); return () => clearTimeout(id); } }, [lang]); return (
setLightbox(src)} />
); } ReactDOM.createRoot(document.getElementById('root')).render();