/* global React, ReactDOM */ /* shared.jsx — componentes y utilidades comunes a todas las páginas */ const { useState, useEffect, useRef } = React; /* Base de assets resuelta desde la URL de ESTE script (shared.jsx, siempre en la raíz del sitio). Hace que las imágenes locales carguen igual en la home y en subpáginas como /tu-evento/ (subcarpeta), tanto en local (file://) como en el servidor — sin depender de rutas relativas ni de un prefijo fijo. */ const ASSET_BASE = (function () { try { var s = document.querySelector('script[src*="shared.jsx"]'); if (s && s.src) return s.src.replace(/[^/]*shared\.jsx.*$/, ''); } catch (e) {} return ''; })(); /* ────────── STOCK IMAGES (Unsplash) ────────── */ const IMG = { hero: 'https://images.unsplash.com/photo-1519741497674-611481863552?auto=format&fit=crop&w=2000&q=80', hero2: 'https://images.unsplash.com/photo-1464366400600-7168b8af9bc3?auto=format&fit=crop&w=2000&q=80', hero3: 'https://images.unsplash.com/photo-1465495976277-4387d4b0b4c6?auto=format&fit=crop&w=2000&q=80', sobre: ASSET_BASE + 'uploads/sesion/mom.webp', expBoda: 'https://images.unsplash.com/photo-1511795409834-ef04bbd61622?auto=format&fit=crop&w=1400&q=80', expRet: 'https://images.unsplash.com/photo-1517457373958-b7bdd4587205?auto=format&fit=crop&w=1400&q=80', expInt: 'https://images.unsplash.com/photo-1530023367847-a683933f4172?auto=format&fit=crop&w=1400&q=80', espExpl: ASSET_BASE + 'uploads/explanada.webp', espJard: ASSET_BASE + 'uploads/jardin.webp', espCasa: ASSET_BASE + 'uploads/santuario.webp', espAmen: ASSET_BASE + 'uploads/caminos.webp', bodas: 'https://images.unsplash.com/photo-1519741497674-611481863552?auto=format&fit=crop&w=2000&q=80', intimas: 'https://images.unsplash.com/photo-1530023367847-a683933f4172?auto=format&fit=crop&w=2000&q=80', parallax1: 'https://images.unsplash.com/photo-1505373877841-8d25f7d46678?auto=format&fit=crop&w=2400&q=85', parallax2: 'https://images.unsplash.com/photo-1465495976277-4387d4b0b4c6?auto=format&fit=crop&w=2400&q=85', gal: [], blog: [ 'https://images.unsplash.com/photo-1469371670807-013ccf25f16a?auto=format&fit=crop&w=1000&q=80', 'https://images.unsplash.com/photo-1465495976277-4387d4b0b4c6?auto=format&fit=crop&w=1000&q=80', 'https://images.unsplash.com/photo-1517457373958-b7bdd4587205?auto=format&fit=crop&w=1000&q=80'] }; /* ────────── CUSTOM CURSOR ────────── */ function CustomCursor() { const dotRef = useRef(null); const ringRef = useRef(null); useEffect(() => { let dx = 0,dy = 0,rx = 0,ry = 0,mx = 0,my = 0; const move = (e) => {mx = e.clientX;my = e.clientY;}; window.addEventListener('mousemove', move); let raf; const loop = () => { dx += (mx - dx) * 0.85; dy += (my - dy) * 0.85; rx += (mx - rx) * 0.18; ry += (my - ry) * 0.18; if (dotRef.current) dotRef.current.style.transform = `translate(${dx}px, ${dy}px) translate(-50%, -50%)`; if (ringRef.current) ringRef.current.style.transform = `translate(${rx}px, ${ry}px) translate(-50%, -50%)`; raf = requestAnimationFrame(loop); }; raf = requestAnimationFrame(loop); const hover = (e) => { const t = e.target; if (t.closest && t.closest('.wa-float')) { dotRef.current?.classList.remove('hover'); ringRef.current?.classList.remove('hover'); dotRef.current?.classList.add('neutral'); ringRef.current?.classList.add('neutral'); } else if (t.closest && t.closest('a, button, .btn, .exp-card, .gal-item, .blog-card, input, textarea, select')) { dotRef.current?.classList.remove('neutral'); ringRef.current?.classList.remove('neutral'); dotRef.current?.classList.add('hover'); ringRef.current?.classList.add('hover'); } else { dotRef.current?.classList.remove('neutral'); ringRef.current?.classList.remove('neutral'); dotRef.current?.classList.remove('hover'); ringRef.current?.classList.remove('hover'); } }; window.addEventListener('mouseover', hover); return () => { cancelAnimationFrame(raf); window.removeEventListener('mousemove', move); window.removeEventListener('mouseover', hover); }; }, []); return ( <>
>); } /* ────────── REVEAL OBSERVER ────────── */ function useReveal() { useEffect(() => { const els = document.querySelectorAll('.reveal, .reveal-stagger, .split-line, .manifiesto, .curtain, .ornament, .draw-underline, .mask-reveal'); const io = new IntersectionObserver((entries) => { entries.forEach((e) => {if (e.isIntersecting) e.target.classList.add('in');}); }, { threshold: 0.15 }); els.forEach((el) => io.observe(el)); return () => io.disconnect(); }, []); } /* ────────── PARALLAX ────────── */ function useParallax() { useEffect(() => { const els = document.querySelectorAll('[data-parallax]'); const onScroll = () => { els.forEach((el) => { const speed = parseFloat(el.dataset.parallax) || 0.3; const rect = el.getBoundingClientRect(); const center = rect.top + rect.height / 2 - window.innerHeight / 2; el.style.transform = `translateY(${center * -speed}px)`; }); }; onScroll(); window.addEventListener('scroll', onScroll, { passive: true }); return () => window.removeEventListener('scroll', onScroll); }, []); } /* ────────── BG PARALLAX (background-image style) ────────── */ function useBgParallax() { useEffect(() => { const els = document.querySelectorAll('[data-bg-parallax]'); const onScroll = () => { els.forEach((el) => { const speed = parseFloat(el.dataset.bgParallax) || 0.2; const rect = el.getBoundingClientRect(); const center = rect.top + rect.height / 2 - window.innerHeight / 2; el.style.backgroundPosition = `center calc(50% + ${center * speed}px)`; }); }; onScroll(); window.addEventListener('scroll', onScroll, { passive: true }); return () => window.removeEventListener('scroll', onScroll); }, []); } /* ────────── SOCIAL LINKS (reutilizable en nav y overlay móvil) ────────── */ function SocialLinks({ className = 'nav-socials' }) { return ( ); } /* ────────── NAV ────────── */ function Nav({ home = '/' }) { const [scrolled, setScrolled] = useState(false); const [menuOpen, setMenuOpen] = useState(false); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 80); window.addEventListener('scroll', onScroll, { passive: true }); return () => window.removeEventListener('scroll', onScroll); }, []); useEffect(() => { document.body.style.overflow = menuOpen ? 'hidden' : ''; return () => { document.body.style.overflow = ''; }; }, [menuOpen]); const close = () => setMenuOpen(false); const links = [ ['/', 'Inicio'], ['/tu-evento', 'Tu evento'], ['/#galeria', 'Galería'], ['/blog', 'Blog'], ['/#contacto', 'Contacto']]; return ( <> >); } /* ────────── HELPERS ────────── */ function splitWords(text) { return text.split(' ').map((w, i) => {w} ); } function Particles({ count = 14 }) { const arr = Array.from({ length: count }); return ({lead}
{cta &&Platicar con nosotros es fácil. Nuestro asistente virtual está disponible 24/7 para darte respuestas al instante sobre fechas y paquetes. Si detecta que estás listo, te canalizará con un anfitrión humano de inmediato.
Hablemos. Respuestas al instante.