/* ServicioPage — shared component rendering one service page from data. */ const { useEffect: useEffectServ, useRef: useRefServ, useState: useStateServ } = React; /* ---------- Logo ---------- */ const LogoServ = ({ size = 32 }) => ( ); /* ---------- Navbar ---------- */ /* ---------- Navbar (mega-menu, sub-page) ---------- */ const NavbarServ = ({ currentService }) => { const ctx = window.useMegaMenuMM(); return ( ); }; /* ---------- FadeUp local ---------- */ const FadeUpServ = window.FadeUp || (({ children, delay = 0, className = '' }) => { const ref = useRefServ(null); const [visible, setVisible] = useStateServ(false); useEffectServ(() => { const el = ref.current; if (!el) return; const io = new IntersectionObserver(([e]) => { if (e.isIntersecting) { setVisible(true); io.disconnect(); } }, { threshold: 0.1 }); io.observe(el); return () => io.disconnect(); }, []); return (
{children}
); }); /* ---------- Breadcrumb ---------- */ const BreadcrumbServ = ({ label }) => ( ); /* ---------- Hero ---------- */ const ServHero = ({ d }) => (
{d.eyebrow}

{d.h1}

{d.sub}

{d.stats}
); /* ---------- Problems ---------- */ const ServProblems = ({ d }) => (
El problema

Lo que está fallando hoy

{d.problems.map((p, i) => { const I = iconFromName(p.icon); return (

{p.title}

{p.body}

); })}
); /* ---------- Proposals ---------- */ const ServProposals = ({ d }) => (
Cómo trabajamos

Dos enfoques, mismo nivel de exigencia.

{d.proposals.map((p, i) => (
0{i+1}

{p.title}

{p.subtitle}

{p.desc}

    {p.bullets.map((b, j) => (
  • {b}
  • ))}
¿Es para vos?

{p.scope}

))}
); /* ---------- Deliverables ---------- */ const ServDeliverables = ({ d }) => (
Qué entregamos

8 cosas que están incluidas siempre.

No hay letra chica ni extras sorpresa. Esto es lo que recibe cada cliente sin importar el tamaño del proyecto.

{d.deliverables.map((item, i) => { const I = iconFromName(item.icon); return (

{item.title}

{item.desc}

); })}
); /* ---------- Process timeline ---------- */ const ServProcess = ({ d }) => { if (!d.process || !d.process.length) return null; return (
Proceso

De primera reunión a deploy en 4 semanas.

{d.process.map((s, i) => (
{s.w}

{s.title}

{s.body}

))}
); }; /* ---------- Final CTA ---------- */ const ServCTA = () => (
¿Empezamos?

Hablemos sin compromiso.

30 minutos para entender tu proyecto, tu objetivo y darte una propuesta concreta. Sin presentaciones genéricas.

); /* ---------- Footer ---------- */ const ServFooter = () => { const [emailValue, setEmailValue] = useStateServ(''); const [newsletterStatus, setNewsletterStatus] = useStateServ('idle'); const currentYear = new Date().getFullYear(); const prefix = '../'; return ( ); }; /* ---------- WhatsApp Floating Button ---------- */ const WhatsAppFloatServ = () => ( ); /* ---------- Page composition ---------- */ const ServicioPage = ({ data }) => ( <> ); /* ---------- Global parallax ---------- */ function useGlobalParallaxServ() { useEffectServ(() => { const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (reduced) return; let raf = 0; function onScroll() { if (raf) return; raf = requestAnimationFrame(() => { const items = document.querySelectorAll('[data-parallax]'); const y = window.scrollY; items.forEach(el => { const speed = parseFloat(el.dataset.parallax) || 0.3; const base = el.dataset.parallaxBase || ''; el.style.transform = `${base} translate3d(0, ${y * speed}px, 0)`; }); raf = 0; }); } window.addEventListener('scroll', onScroll, { passive: true }); onScroll(); return () => window.removeEventListener('scroll', onScroll); }, []); } window.ServicioPage = ServicioPage; window.useGlobalParallaxServ = useGlobalParallaxServ;