/* global React */ const { useEffect, useRef, useState } = React; // ============ Constantes de marca ============ const WA_PHONE = '573041170678'; const WA_BASE_MSG = 'Hola Lebike, quiero asesoría'; const WA_URL = `https://wa.me/${WA_PHONE}?text=${encodeURIComponent(WA_BASE_MSG)}`; const WA_URL_UNIFORM = `https://wa.me/${WA_PHONE}?text=${encodeURIComponent('Hola Lebike, quiero asesoría para mi uniforme')}`; // ============ Icon library (minimalist, single-stroke) ============ const I = { arrow: (p={}) => ( ), whatsapp: (p={}) => ( ), wind: (p={}) => ( ), aero: (p={}) => ( ), fabric: (p={}) => ( ), stitch: (p={}) => ( ), drop: (p={}) => ( ), road: (p={}) => ( ), body: (p={}) => ( ), shield: (p={}) => ( ), star: (p={}) => ( ), ig: (p={}) => ( ), fb: (p={}) => ( ), tt: (p={}) => ( ), ruler: (p={}) => (), bike: (p={}) => (), chat: (p={}) => (), }; // ============ Reveal hook ============ function useReveal() { const ref = useRef(null); useEffect(() => { const el = ref.current; if (!el) return; const io = new IntersectionObserver((es) => { es.forEach(e => { if (e.isIntersecting) { el.classList.add('in'); io.unobserve(el); } }); }, { threshold: 0.12 }); io.observe(el); return () => io.disconnect(); }, []); return ref; } // ============ NAV ============ function ThemeToggle() { const getInitial = () => { if (typeof document === 'undefined') return 'dark'; const stored = localStorage.getItem('lebike-theme'); if (stored === 'light' || stored === 'dark') return stored; return document.documentElement.getAttribute('data-theme') || 'dark'; }; const [theme, setTheme] = useState(getInitial); useEffect(() => { document.documentElement.setAttribute('data-theme', theme); try { localStorage.setItem('lebike-theme', theme); } catch (e) {} }, [theme]); const isLight = theme === 'light'; return ( ); } function Nav({ activeCategory }) { const [scrolled, setScrolled] = useState(false); const [menuOpen, setMenuOpen] = useState(false); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 40); window.addEventListener('scroll', onScroll); return () => window.removeEventListener('scroll', onScroll); }, []); useEffect(() => { document.body.style.overflow = menuOpen ? 'hidden' : ''; return () => { document.body.style.overflow = ''; }; }, [menuOpen]); const navItems = [ { key: 'jerseys', label: 'Jerseys', href: '../jerseys/' }, { key: 'licras', label: 'Licras', href: '../licras/' }, { key: 'enterizos', label: 'Enterizos', href: '../enterizos/' }, ]; return ( <>
{headline || defaultHeadline}
{sub || defaultSub}
Las dudas que todo ciclista tiene antes de pedir su uniforme — resueltas. Sin letra pequeña ni promesas vacías.
{b.desc}
{subtitle}
Cada ciclista tiene un cuerpo, un terreno y una meta diferentes. Por eso no usamos calculadoras de talla automáticas: hablamos contigo, entendemos tu ruta y te recomendamos el uniforme que de verdad va a funcionar.
"{t.q}"
Asesoría personalizada para encontrar el uniforme perfecto para ti. Hablamos por WhatsApp y te acompañamos hasta el primer kilómetro.
Personalizamos enterizos para clubes, equipos y academias. Tu logo, tu nombre, tu RH — listos para la línea de salida.
{b.desc}
Si algo no calza o falla por fabricación, lo resolvemos. Estos son los plazos y condiciones que aplican a todos los pedidos Lebike.
Para gestionar un cambio o garantía, escríbenos por WhatsApp con tu nombre completo, número de pedido y fotos de la novedad.