/* eslint-disable */
/* global React */
const { useState, useEffect, useRef, useCallback } = React;
const WA = "https://wa.me/541126285230";
const waLink = (t) => `${WA}?text=${encodeURIComponent(t)}`;
/* ---------- hooks ---------- */
function useScrolled(threshold){
const [s, setS] = useState(false);
useEffect(() => {
const on = () => setS(window.scrollY > (threshold||20));
on(); window.addEventListener('scroll', on, { passive:true });
return () => window.removeEventListener('scroll', on);
}, []);
return s;
}
function useInView(opts){
const ref = useRef(null);
const [seen, setSeen] = useState(false);
useEffect(() => {
const el = ref.current; if(!el) return;
if(!('IntersectionObserver' in window)){ setSeen(true); return; }
const io = new IntersectionObserver(([e]) => {
if(e.isIntersecting){ setSeen(true); io.disconnect(); }
}, { threshold: 0.18, rootMargin: '0px 0px -8% 0px', ...(opts||{}) });
io.observe(el);
// Fallback: never leave content hidden if IO doesn't fire (bg tab / print / capture).
// Only force-reveal elements that are already at/above the viewport, or when the page
// isn't visible (print/capture/background) — so below-the-fold sections keep waiting
// for the observer and animate when the user actually scrolls to them.
const fb = setTimeout(() => {
const r = el.getBoundingClientRect();
if(r.top < window.innerHeight || document.visibilityState === 'hidden'){ setSeen(true); }
}, 1400);
return () => { io.disconnect(); clearTimeout(fb); };
}, []);
return [ref, seen];
}
function Reveal({ children, className, delay, as, ...rest }){
const [ref, seen] = useInView();
const Tag = as || 'div';
const style = delay ? { transitionDelay: delay+'ms', ...(rest.style||{}) } : rest.style;
return {children};
}
function useCycle(list, ms){
const [i, setI] = useState(0);
useEffect(() => { const t = setInterval(() => setI(p => (p+1)%list.length), ms); return () => clearInterval(t); }, []);
return i;
}
function CountUp({ to, suffix, prefix, dur }){
const [ref, seen] = useInView();
const [v, setV] = useState(0);
useEffect(() => {
if(!seen) return;
let raf, start; const D = dur||1500;
const tick = (t) => { if(!start) start = t; const p = Math.min((t-start)/D, 1);
setV(Math.floor((1-Math.pow(1-p,3))*to)); if(p<1) raf = requestAnimationFrame(tick); };
raf = requestAnimationFrame(tick);
return () => cancelAnimationFrame(raf);
}, [seen, to]);
return {prefix||''}{v.toLocaleString('es-AR')}{suffix||''};
}
/* ---------- icons ---------- */
const IgIcon = () => ();
const InIcon = () => ();
const WaIcon = () => ();
const Arrow = () => ();
const Check = () => ();
/* nav links for inner pages — anchors resolve back to the home page */
const SUB_LINKS = [
['Servicios', '/#servicios'], ['Auditoría', '/auditoria'], ['Asesoría', '/asesoria'],
['Sobre mí', '/#sobremi'], ['Proceso', '/#proceso'],
['Recursos', '/recursos'], ['FAQ', '/#faq'],
];
/* ---------- Nav ---------- */
const NAV_LINKS = [
['Servicios', '#servicios'], ['Auditoría', '/auditoria'], ['Asesoría', '/asesoria'],
['Sobre mí', '#sobremi'], ['Proceso', '#proceso'],
['Recursos', '/recursos'], ['FAQ', '#faq'],
];
function Nav({ links }){
const scrolled = useScrolled();
const [open, setOpen] = React.useState(false);
const items = links || NAV_LINKS;
React.useEffect(() => {
document.body.style.overflow = open ? 'hidden' : '';
return () => { document.body.style.overflow = ''; };
}, [open]);
return (
<>
>
);
}
/* ---------- Footer ---------- */
function Footer(){
return (
);
}
/* ---------- SectionHead ---------- */
function SectionHead({ idx, title, lead, id }){
return (
{idx}
{title}
{lead ? {lead}
: null}
);
}
Object.assign(window, {
useScrolled, useInView, Reveal, useCycle, CountUp,
IgIcon, InIcon, WaIcon, Arrow, Check, Nav, Footer, SectionHead,
WA, waLink, NAV_LINKS, SUB_LINKS,
});