/* global React */ const { useEffect: pUseEffect, useRef: pUseRef, useState: pUseState } = React; /* ---------- Compass dingbat (inspired by the brand mark — original) ---------- */ function Compass({ size = 18, spin = false }) { return ( ); } /* ---------- Arrow ---------- */ function Arrow({ size = 14 }) { return ( ); } /* ---------- Button ---------- */ function Btn({ children, variant = 'primary', onClick, arrow = true, href }) { const Tag = href ? 'a' : 'button'; return ( {children} {arrow && } ); } /* ---------- Scroll reveal ---------- */ function Reveal({ children, delay = 0, as: Tag = 'div', className = '', style = {} }) { const ref = pUseRef(null); const [shown, setShown] = pUseState(false); pUseEffect(() => { const el = ref.current; if (!el) return; const io = new IntersectionObserver((entries) => { entries.forEach(e => { if (e.isIntersecting) { setTimeout(() => setShown(true), delay); io.unobserve(el); } }); }, { threshold: 0.12, rootMargin: '0px 0px -60px' }); io.observe(el); return () => io.disconnect(); }, [delay]); return ( {children} ); } /* ---------- Placeholder image ---------- */ function Placeholder({ label, children, aspect = '16/10', tone = 'default', style = {} }) { const tones = { default: {}, navy: { background: 'linear-gradient(135deg, var(--navy-700), var(--navy-900))', color: 'var(--bg)' }, accent: { background: 'linear-gradient(135deg, var(--accent), var(--navy-800))', color: '#fff' }, cream: { background: 'linear-gradient(135deg, var(--bg-alt), var(--bg))' }, }; return (
{label && {label}} {children || '[ imagen real del cliente ]'}
); } /* ---------- Counter animation ---------- */ function Counter({ to, duration = 1400 }) { const [n, setN] = pUseState(0); const ref = pUseRef(null); pUseEffect(() => { const el = ref.current; if (!el) return; const io = new IntersectionObserver((entries) => { entries.forEach(e => { if (e.isIntersecting) { const start = performance.now(); const step = (t) => { const p = Math.min(1, (t - start) / duration); const eased = 1 - Math.pow(1 - p, 3); setN(Math.round(eased * to)); if (p < 1) requestAnimationFrame(step); }; requestAnimationFrame(step); io.disconnect(); } }); }, { threshold: 0.3 }); io.observe(el); return () => io.disconnect(); }, [to, duration]); return {n}; } Object.assign(window, { Compass, Arrow, Btn, Reveal, Placeholder, Counter });