/* global React */ const { useState, useEffect, useRef, useMemo } = React; /* =========================================================== Wordmark — SLF Energía - Full variant: "SLF Energía" with mini solar accent - Compact: "SLF" monogram - Light + dark surfaces =========================================================== */ function Wordmark({ variant = 'full', tone = 'dark', size = 22 }) { // tone = 'dark' => for light backgrounds (text dark) // tone = 'light' => for dark backgrounds (text white) const inkColor = tone === 'dark' ? '#0B2545' : '#FFFFFF'; const accent = '#FFB800'; // Mini mark: an "S" rendered as 3 horizontal solar bars (S = SLF) const Mark = () => ( ); if (variant === 'compact') { return ( SLF ); } return ( SLF Energía ); } /* =========================================================== Reveal-on-scroll wrapper =========================================================== */ function Reveal({ children, delay = 0, as: Tag = 'div', className = '', style }) { const ref = useRef(null); const [shown, setShown] = useState(false); useEffect(() => { const node = ref.current; if (!node) return; const io = new IntersectionObserver( (entries) => entries.forEach((e) => { if (e.isIntersecting) { setTimeout(() => setShown(true), delay); io.disconnect(); } }), { threshold: 0.12 } ); io.observe(node); return () => io.disconnect(); }, [delay]); return ( {children} ); } /* =========================================================== Animated number that counts up when in viewport =========================================================== */ function CountUp({ to, suffix = '', prefix = '', decimals = 0, duration = 1400, format }) { const ref = useRef(null); const [val, setVal] = useState(0); const started = useRef(false); useEffect(() => { const node = ref.current; if (!node) return; const io = new IntersectionObserver( (entries) => entries.forEach((e) => { if (e.isIntersecting && !started.current) { started.current = true; const start = performance.now(); const tick = (now) => { const t = Math.min(1, (now - start) / duration); const eased = 1 - Math.pow(1 - t, 3); setVal(to * eased); if (t < 1) requestAnimationFrame(tick); }; requestAnimationFrame(tick); io.disconnect(); } }), { threshold: 0.3 } ); io.observe(node); return () => io.disconnect(); }, [to, duration]); const display = format ? format(val) : `${prefix}${val.toLocaleString('es-CL', { minimumFractionDigits: decimals, maximumFractionDigits: decimals })}${suffix}`; return {display}; } /* =========================================================== Icons =========================================================== */ const Icon = { Arrow: () => , ArrowSmall: ({ size=14 }) => , Whatsapp: ({ size=20 }) => ( ), Phone: () => , Mail: () => , Map: () => , Clock: () => , Check: () => , Shield: () => , Bolt: () => , Solar: () => , Factory: () => , Mountain: () => , Cart: () => , Leaf: () => , Chart: () => , Doc: () => , Calendar: () => , Download: () => , Play: () => , Wrench: () => , Compass: () => , Eye: () => , X: () => , Linkedin: () => , Facebook: () => , Instagram: () => , Youtube: () => , Menu: () => , }; /* =========================================================== Constants =========================================================== */ const PHONE = '+56953730208'; const PHONE_FMT = '+56 9 5373 0208'; const WA_URL = 'https://api.whatsapp.com/send?phone=56953730208&text=Hola%20SLF%20Energ%C3%ADa%2C%20quiero%20coordinar%20un%20diagn%C3%B3stico%20t%C3%A9cnico'; const EMAIL = 'contacto@slf.cl'; Object.assign(window, { Wordmark, Reveal, CountUp, Icon, PHONE, PHONE_FMT, WA_URL, EMAIL });