/* 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 });