/* global React, Icon, gsap */ const { useState, useEffect, useRef } = React; const NAV = [ { label: 'SERVICIOS', href: '#servicios' }, { label: 'RITUALES', href: '#solucion' }, { label: 'TESTIMONIOS', href: '#testimonios' }, { label: 'CONTACTO', href: '#consulta' }, ]; /* Video presence presets — reshape how alive the background feels */ const MOTION = { intimo: { amp: 6, scale: 1.03 }, equilibrado: { amp: 14, scale: 1.06 }, envolvente: { amp: 26, scale: 1.13 }, }; /* Editorial voice — reshapes the hero message */ const COPY = { sereno: { l1: 'Lo que se fue, también puede trabajarse.', l2: 'Retorno del ser amado, suerte, limpias y protección.', subA: 'Trabajo espiritual guiado, con seriedad y sin promesas vacías.', subB: ' Cada caso se explica antes de empezar.', cta: 'Quiero mi consulta', }, cercano: { l1: 'No tienes que cargar esto en soledad.', l2: 'Retorno del ser amado, suerte, limpias y protección.', subA: 'Estamos aquí para escucharte y acompañarte con calma.', subB: ' Sin juicios, a tu ritmo.', cta: 'Hablemos hoy', }, directo: { l1: 'Recupera lo que perdiste.', l2: 'Amor, suerte, limpias y protección.', subA: 'Resultados con método y seriedad, no promesas vacías.', subB: ' Primera consulta gratis.', cta: 'Empezar ahora', }, }; /* ============================================================ NAVBAR — fixed, glass pill center, collapses <768px ============================================================ */ const Navbar = () => { const [open, setOpen] = useState(false); const [scrolled, setScrolled] = useState(false); useEffect(() => { document.body.style.overflow = open ? 'hidden' : ''; return () => { document.body.style.overflow = ''; }; }, [open]); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 24); window.addEventListener('scroll', onScroll, { passive: true }); onScroll(); return () => window.removeEventListener('scroll', onScroll); }, []); return (
Congregación En La Fe QUIERO MI CONSULTA {open && (
{NAV.map(n => ( setOpen(false)} className="font-fraunces text-2xl text-white/90 hover:text-white"> {n.label.charAt(0) + n.label.slice(1).toLowerCase()} ))} setOpen(false)} className="mt-2 rounded-full px-8 py-3.5 text-[15px] font-medium" style={{ background: '#F4EFE6', color: '#0B1220' }}> Quiero mi consulta
)}
); }; /* ============================================================ VIDEO BACKGROUND — ping-pong + GSAP mouse parallax ============================================================ */ const VideoBackground = ({ motion = 'equilibrado' }) => { const cfg = MOTION[motion] || MOTION.equilibrado; const wrapRef = useRef(null); const videoRef = useRef(null); // Ping-pong playback useEffect(() => { const v = videoRef.current; if (!v) return; let raf, last = 0, dir = 1; const RATE = 1; // reverse scrub speed multiplier const onLoaded = () => { v.playbackRate = 1; v.play().catch(() => {}); }; const onEnded = () => { // switch to reverse scrub from the end dir = -1; v.pause(); last = performance.now(); raf = requestAnimationFrame(scrub); }; const scrub = (now) => { const dt = (now - last) / 1000; last = now; if (dir === -1) { v.currentTime = Math.max(0, v.currentTime - dt * RATE); if (v.currentTime <= 0.02) { dir = 1; v.currentTime = 0; v.play().catch(() => {}); return; // native forward takes over; ended fires again } raf = requestAnimationFrame(scrub); } }; v.addEventListener('loadeddata', onLoaded); v.addEventListener('ended', onEnded); if (v.readyState >= 2) onLoaded(); return () => { cancelAnimationFrame(raf); v.removeEventListener('loadeddata', onLoaded); v.removeEventListener('ended', onEnded); }; }, []); // GSAP mouse parallax with lerp useEffect(() => { const el = wrapRef.current; if (!el || typeof gsap === 'undefined') return; let targetX = 0, targetY = 0, curX = 0, curY = 0, raf; const cx = window.innerWidth / 2, cy = window.innerHeight / 2; const onMove = (e) => { targetX = ((e.clientX - cx) / cx) * cfg.amp; targetY = ((e.clientY - cy) / cy) * cfg.amp; }; const tick = () => { curX += (targetX - curX) * 0.06; curY += (targetY - curY) * 0.06; gsap.set(el, { x: curX, y: curY }); raf = requestAnimationFrame(tick); }; window.addEventListener('mousemove', onMove); raf = requestAnimationFrame(tick); return () => { window.removeEventListener('mousemove', onMove); cancelAnimationFrame(raf); }; }, [cfg.amp]); return (
); }; /* ============================================================ HERO ============================================================ */ const Hero = ({ tone = 'sereno', motion = 'equilibrado' }) => { const c = COPY[tone] || COPY.sereno; const [shown, setShown] = useState(false); useEffect(() => { const t = setTimeout(() => setShown(true), 80); return () => clearTimeout(t); }, []); const base = 'transition-all duration-1000 ease-[cubic-bezier(.2,.8,.2,1)]'; const on = shown ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-6'; return (
{/* Headline */}

{c.l1} {c.l2}

{/* Bottom block */}

{c.subA} {c.subB}

e.currentTarget.style.boxShadow = '0 0 32px 4px rgb(var(--gold) / 0.25)'} onMouseLeave={e => e.currentTarget.style.boxShadow = 'none'}> {c.cta}
100% CONFIDENCIAL.
); }; Object.assign(window, { Navbar, Hero, VideoBackground });