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