/* global React, PAOLA_DATA */ // Shared components: Nav, Footer, Hero, Reveal, Marquee, helpers const { useState, useEffect, useRef, useMemo, useCallback } = React; /* --- Reveal on scroll --- */ function Reveal({ children, delay = 0, className = '', as = 'div' }) { const ref = useRef(null); const [shown, setShown] = useState(false); useEffect(() => { const el = ref.current; if (!el) return; const io = new IntersectionObserver(([e]) => { if (e.isIntersecting) { setShown(true); io.disconnect(); } }, { threshold: 0.12 }); io.observe(el); return () => io.disconnect(); }, []); const Tag = as; return {children}; } /* --- Nav --- */ function Nav({ route, go, dark, onOpenMenu }) { const [scrolled, setScrolled] = useState(false); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 60); window.addEventListener('scroll', onScroll, { passive: true }); onScroll(); return () => window.removeEventListener('scroll', onScroll); }, []); const navClass = `nav ${scrolled ? 'scrolled' : ''} ${(!scrolled && !dark) ? 'light' : ''}`; const link = (id, label) => ( {e.preventDefault(); go(id);}} className={route===id?'active':''}>{label} ); return (
{e.preventDefault(); go('home');}} className="brand"> PAOLA GARCÍA FOTÓGRAFA PROFESIONAL {e.preventDefault(); go('contact');}} className="nav-cta">Agenda tu sesión
); } /* --- Fullscreen menu (mobile + accessory) --- */ function FullMenu({ open, onClose, go }) { return (
SABANETA · ANTIOQUIA @{PAOLA_DATA.contact.instagram} {PAOLA_DATA.contact.whatsappPretty}
); } /* --- Marquee --- */ function Marquee({ items }) { const all = [...items, ...items]; return (
{all.map((t, i) => {t})}
); } /* --- Footer --- */ function Footer({ go }) { const c = PAOLA_DATA.contact; return ( ); } /* --- Floating WhatsApp --- */ function WhatsAppFloat() { const c = PAOLA_DATA.contact; const phone = String(c.whatsappPretty || c.whatsapp || '').replace(/\D/g, ''); if (!phone) return null; const message = c.whatsappMessage || 'Hola Paola, quiero recibir información sobre una sesión fotográfica.'; const href = `https://wa.me/${phone}?text=${encodeURIComponent(message)}`; return ( WhatsApp ); } /* --- Hero --- */ function Hero({ go, heroCopy }) { const ref = useRef(null); const [loaded, setLoaded] = useState(false); const slides = Array.isArray(PAOLA_DATA.hero.slides) ? PAOLA_DATA.hero.slides.filter(Boolean) : (PAOLA_DATA.hero.main ? [PAOLA_DATA.hero.main] : []); const hasSlides = slides.length > 0; const [idx, setIdx] = useState(0); useEffect(() => { const t = setTimeout(() => setLoaded(true), 80); return () => clearTimeout(t); }, []); // Auto-advance slides useEffect(() => { if (slides.length <= 1) return; const t = setInterval(() => setIdx(i => (i + 1) % slides.length), 5500); return () => clearInterval(t); }, [slides.length]); // Parallax useEffect(() => { const onScroll = () => { if (!ref.current) return; const y = window.scrollY; ref.current.querySelectorAll('.h-bg').forEach(bg => { bg.style.setProperty('--py', `${y * 0.25}px`); }); }; window.addEventListener('scroll', onScroll, { passive: true }); return () => window.removeEventListener('scroll', onScroll); }, []); return (
{slides.map((src, i) => (
))} {hasSlides &&
N° 0{idx+1} · COLECCIÓN 2026
}
FOTÓGRAFA PROFESIONAL — MEDELLÍN

{heroCopy.line1}
{heroCopy.line2}

{heroCopy.sub}

{hasSlides && (
{slides.map((_, i) => ( ))}
)}
SCROLL
); } /* --- Lightbox --- */ function Lightbox({ items, index, onClose, onPrev, onNext }) { const touchStart = useRef(null); useEffect(() => { const onKey = (e) => { if (e.key === 'Escape') onClose(); if (e.key === 'ArrowLeft') onPrev(); if (e.key === 'ArrowRight') onNext(); }; window.addEventListener('keydown', onKey); document.body.style.overflow = 'hidden'; return () => { window.removeEventListener('keydown', onKey); document.body.style.overflow = ''; }; }, [onClose, onPrev, onNext]); const handleTouchStart = (e) => { touchStart.current = e.touches[0].clientX; }; const handleTouchEnd = (e) => { if (touchStart.current === null) return; const dx = e.changedTouches[0].clientX - touchStart.current; if (Math.abs(dx) > 50) { dx < 0 ? onNext() : onPrev(); } touchStart.current = null; }; const item = items[index]; return (
{item.label}e.stopPropagation()} />
{item.label} — {index+1} / {items.length}
); } Object.assign(window, { Reveal, Nav, FullMenu, Marquee, Footer, WhatsAppFloat, Hero, Lightbox });