/* global React, Icon, BrandMark, Placeholder, Reveal, Counter */ const { useState: useStateS, useEffect: useEffectS, useRef: useRefS, useMemo: useMemoS } = React; /* ============================================================ SOCIAL BAR (reemplaza UtilityBar) Desktop: barra delgada superior · Móvil: pill flotante inferior ============================================================ */ function SocialBar({ lang, setLang }) { const WA_URL = "https://wa.me/525537175828?text=" + encodeURIComponent( lang === "es" ? "Hola, me gustaría solicitar una cotización." : "Hi, I'd like to request a quote." ); const IG_URL = "https://www.instagram.com/grupooverklin/"; const FB_URL = "https://www.facebook.com/GOKMX/"; const PHONE = "tel:+525537175828"; return ( <> {/* ── DESKTOP: barra superior delgada ── */}
{lang === "es" ? "Lun–Dom · 24/7" : "Mon–Sun · 24/7"}
55 3717 5828
{/* ── MÓVIL: pill flotante inferior ── */}
{lang === "es" ? "Cotizar" : "Quote"}
); } function Header({ active, lang, setLang }) { const [scrolled, setScrolled] = useStateS(false); const [menuOpen, setMenuOpen] = useStateS(false); useEffectS(() => { const onScroll = () => setScrolled(window.scrollY > 8); onScroll(); window.addEventListener("scroll", onScroll, { passive: true }); return () => window.removeEventListener("scroll", onScroll); }, []); const nav = lang === "es" ? [["nosotros","Nosotros"],["servicios","Servicios"],["presencia","Clientes"],["faq","FAQ"]] : [["nosotros","About"],["servicios","Services"],["presencia","Clients"],["faq","FAQ"]]; const closeMenu = () => setMenuOpen(false); return ( <>
{lang === "es" ? "Cotizador Express" : "Instant Quote"}
{ if (e.target === e.currentTarget) closeMenu(); }}> {nav.map(([id, label]) => ( {label} ))}
{lang === "es" ? "Cotizador Express" : "Instatant Quote"}
); } /* ============================================================ HERO ============================================================ */ function Hero({ lang, onBookingChange, booking }) { const t = lang === "es" ? { pill: "Cobertura activa en 28 estados", head1: "Limpieza", head1it: "profesional", head2: "para cualquier", head2it: "industria.", sub: "17 años destacando en programas de limpieza, sanitización y mantenimiento para corporaciones mexicanas.", book: "Cotiza con un experto", name: "Nombre completo", company: "Empresa", email: "Correo electrónico", phone: "Teléfono", zip: "Código postal", svc: "Servicio", options: ["Limpieza general", "Limpieza profunda", "Sanitización", "Pulido y abrillantado de pisos", "Suministro insumos de limpieza", "Asesoría", "Recuperación de alfombras"], cta: "Contactar", meta1: "Respuesta rápida", meta2: "Sin compromiso", eName: "Requerido", eCompany: "Requerido", eEmail: "Correo inválido", ePhone: "Mín. 10 dígitos", eZip: "5 dígitos", eSvc: "Selecciona uno", submitError: "Ocurrió un error. Intenta nuevamente.", successTitle: "¡Gracias!", successBody: "Solicitud enviada correctamente", successFolio: "Folio", successSteps: ["Solicitud recibida", "En revisión", "Propuesta lista"], } : { pill: "Active coverage in 28 states", head1: "Professional", head1it: "cleaning", head2: "for all", head2it: "industries.", sub: "17+ years excelling in cleaning, sanitization and maintenance programs for corporate enterprises across Mexico.", book: "Get a quote from an expert", name: "Full Name", company: "Company", email: "Email address", phone: "Phone", zip: "ZIP Code", svc: "Service", options: ["General cleaning", "Deep cleaning", "Sanitization", "Floor polish & brightening", "Cleaning supplies", "Consulting", "Carpet recovery"], cta: "Request quotation", meta1: "Fast Reply", meta2: "No obligation", eName: "Required", eCompany: "Required", eEmail: "Invalid email", ePhone: "Min. 10 digits", eZip: "5 digits", eSvc: "Select one", submitError: "An error occurred. Please try again.", successTitle: "Thanks!", successBody: "Request submitted successfully", successFolio: "Ref", successSteps: ["Request received", "Under review", "Proposal ready"], }; const [errors, setErrors] = useStateS({}); const [sent, setSent] = useStateS(false); const [folio, setFolio] = useStateS(""); const [loading, setLoading] = useStateS(false); const [submitError, setSubmitError] = useStateS(""); const heroCardRef = useRefS(null); const scrollToCard = (selector) => { setTimeout(() => { const el = selector ? heroCardRef.current?.querySelector(selector) : heroCardRef.current; if (!el) return; const top = el.getBoundingClientRect().top + window.scrollY - 100; window.scrollTo({ top, behavior: "smooth" }); }, 50); }; const submit = async (e) => { e.preventDefault(); if (loading) return; const errs = {}; if (!booking.name?.trim()) errs.name = t.eName; if (!booking.company?.trim()) errs.company = t.eCompany; if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(booking.email?.trim() || "")) errs.email = t.eEmail; const digits = (booking.phone || "").replace(/\D/g, ""); if (digits.length < 10) errs.phone = t.ePhone; if (!/^\d{5}$/.test(booking.zip?.trim() || "")) errs.zip = t.eZip; if (!booking.service) errs.service = t.eSvc; setErrors(errs); setSubmitError(""); if (Object.keys(errs).length > 0) { scrollToCard(".field.error, .err"); return; } if (true) { setLoading(true); try { const response = await fetch("https://n8n-acto.matic0.com/webhook/quote-request", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: booking.name, company: booking.company, email: booking.email, phone: booking.phone, postalCode: booking.zip, service: booking.service, language: lang }) }); if (response.ok) { setFolio("OVK-" + Date.now().toString(36).toUpperCase().slice(-6)); setSent(true); onBookingChange({ name:"", company:"", email:"", phone:"+", zip:"", service:"" }); scrollToCard(null); } else { setSubmitError(t.submitError); } } catch (err) { setSubmitError(t.submitError); } finally { setLoading(false); } } }; return (
{t.pill} EST. 2009 · CDMX

{t.head1} {t.head1it}
{t.head2} {t.head2it}

{t.sub}

{!sent ? ( <>

{t.book}

onBookingChange({name:e.target.value})} placeholder={lang === "es" ? "Ej. Juan García" : "e.g. John Smith"} /> {errors.name && {errors.name}}
onBookingChange({company:e.target.value})} placeholder={lang === "es" ? "Ej. ACME Industrial" : "e.g. ACME Corp"} /> {errors.company && {errors.company}}
onBookingChange({email:e.target.value})} placeholder={lang === "es" ? "nombre@empresa.com" : "name@company.com"} /> {errors.email && {errors.email}}
{let v=e.target.value; if(!v.startsWith("+"))v="+"+v.replace(/^\+*/,""); onBookingChange({phone:v});}} placeholder="+52 55 0000 0000" /> {errors.phone && {errors.phone}}
onBookingChange({zip:e.target.value})} placeholder="06600" /> {errors.zip && {errors.zip}}
{errors.service && {errors.service}}
{submitError && (
{submitError}
)}
↳ {t.meta1} {t.meta2}
) : (

{t.successTitle}

{t.successBody}

{t.successFolio} {folio}
{t.successSteps.map((s, i) => (
{s}
))}
)}
{[ ["17", lang==="es"?"AÑOS DE EXPERIENCIA":"YEARS OF EXPERIENCE"], ["+500", lang==="es"?"COLABORADORES":"COLLABORATORS"], ["+50", lang==="es"?"CLIENTES ACTIVOS":"ACTIVE CLIENTS"], ["24/7", lang==="es"?"DISPONIBILIDAD":"AVAILABILITY"], ].map(([v,k]) => (
{v}
{k}
))}
); } /* ============================================================ MARQUEE (clients) ============================================================ */ function Marquee({ lang }) { const items = lang === "es" ? [ "Cines y Entretenimiento", "Gimnasios y Wellness", "Plantas Industriales", "Automotriz y Manufactura", "Química y Farmacéutica", "Centros Comerciales", "Oficinas y Corporativos", "Hospitales y Clínicas", "Servicios de Empaque", "Logística y Almacenes", "Hoteles", "Universidades", "Retail y Tiendas", "Restaurantes y Franquicias", "Banca y Finanzas", ] : [ "Cinema & Entertainment", "Gyms & Wellness", "Industrial Plants", "Automotive & Manufacturing", "Chemical & Pharmaceutical", "Shopping Malls", "Offices & Corporates", "Hospitals & Clinics", "Packaging Services", "Logistics & Warehouses", "Hotels", "Universities", "Retail & Stores", "Restaurants & Franchises", "Banking & Finance", ]; return (
{[...items, ...items].map((s, i) => ( {s} ))}
); } /* ============================================================ ABOUT ============================================================ */ function About({ lang }) { const t = lang === "es" ? { eye: "SOBRE NOSOTROS — Grupo Over Klin", h: ["17 años","limpiando", "los espacios que","mueven a México."], p1: "Operamos programas de limpieza, sanitización y mantenimiento para corporativos, plantas industriales, cines y centros comerciales o cualquier otra industria. Cada cliente recibe un plan a medida, un supervisor dedicado y reportería de cumplimiento.", p2: "Trabajamos con insumos certificados, protocolos auditables y plantilla 100% propia. Todo nuestro personal cuenta con Constancia de Competencias Laborales DC-3 emitida por la STPS.", cta: "Conoce al equipo", stat1: ["Opinión de Cumplimiento IMSS", "Cada colaborador asignado a tu operación cuenta con alta patronal vigente, garantizando cobertura de seguridad social sin contingencias para tu empresa."], stat2: ["Cumplimiento SAT", "Personal con situación fiscal en regla. Recibes CFDI válido por cada servicio para deducibilidad total del gasto ante el SAT."], stat3: ["Constancia DC-3 · STPS", "Todo el personal operativo cuenta con certificación de competencias laborales emitida por la Secretaría del Trabajo y Previsión Social (STPS)."], } : { eye: "ABOUT — Grupo Over Klin", h: ["17 years","cleaning","the spaces that","move Mexico."], p1: "We run cleaning, sanitization and maintenance programs for corporate offices, industrial complexes, entretainment facilities, malls or virtually any industry. Every client gets a tailored plan, a dedicated supervisor and compliance reporting.", p2: "Certified consumables, auditable protocols and 100% in-house staff — every operator holds the DC-3 Labor Competency Certificate issued by Mexico's STPS.", cta: "Meet the team", stat1: ["IMSS Compliance", "Every worker deployed to your site is fully registered with Mexico's Social Security Institute — zero liability exposure for your company."], stat2: ["SAT Compliance", "Staff with clean tax standing. Each service is invoiced with a valid CFDI, making the expense fully deductible for your business."], stat3: ["DC-3 Certificate · STPS", "Every field operator holds a labor competency certificate issued by Mexico's Ministry of Labor and Social Welfare (STPS)."], }; return (
{t.eye}

{t.h[0]} {t.h[1]}
{t.h[2]} {t.h[3]}

{t.p1}

{t.p2}

Grupo Over Klin
{[t.stat1, t.stat2, t.stat3].map(([title, desc], i) => (
{title}

{desc}

))}
); } /* ============================================================ PROCESS ============================================================ */ function Process({ lang }) { const t = lang === "es" ? { eye: "PROTOCOLO DE ALTA — GRUPO OVER KLIN", h: ["De la cotización", "al primer", "servicio."], sub: "Al enviar tu cotización completaste el Paso 1. A partir de aquí nuestro equipo toma el control para que arranques sin fricciones.", phases: [ { n: "01", label: "Contacto & Diagnóstico", items: [ { n: "01", text: "Primer contacto y solicitud", done: true }, { n: "02", text: "Visita de inspección al inmueble" }, ], }, { n: "02", label: "Propuesta & Cierre", items: [ { n: "03", text: "Elaboración de presupuesto personalizado" }, { n: "04", text: "Presentación y negociación" }, { n: "05", text: "Firma de contrato" }, ], }, { n: "03", label: "Alta & Preparación", items: [ { n: "06", text: "Alta en sistema y expediente" }, { n: "07", text: "Asignación de equipo" }, { n: "08", text: "Briefing interno al personal" }, { n: "09", text: "Dotación de materiales y equipos" }, ], }, { n: "04", label: "Arranque & Seguimiento", items: [ { n: "10", text: "Primer servicio supervisado" }, { n: "11", text: "Seguimiento post-servicio" }, { n: "12", text: "Revisión periódica de calidad" }, ], }, ], } : { eye: "ONBOARDING PROTOCOL — GRUPO OVER KLIN", h: ["From quote", "to first", "service."], sub: "Submitting your quote completed Step 1. From here our team takes over to get you started without friction.", phases: [ { n: "01", label: "Contact & Diagnosis", items: [ { n: "01", text: "First contact & request", done: true }, { n: "02", text: "On-site inspection visit" }, ], }, { n: "02", label: "Proposal & Close", items: [ { n: "03", text: "Custom proposal preparation" }, { n: "04", text: "Presentation & negotiation" }, { n: "05", text: "Contract signing" }, ], }, { n: "03", label: "Onboarding & Setup", items: [ { n: "06", text: "Client registration & file" }, { n: "07", text: "Team assignment" }, { n: "08", text: "Internal briefing" }, { n: "09", text: "Materials & equipment supply" }, ], }, { n: "04", label: "Launch & Follow-up", items: [ { n: "10", text: "First supervised service" }, { n: "11", text: "Post-service follow-up" }, { n: "12", text: "Periodic quality review" }, ], }, ], }; return (
{t.eye}

{t.h[0]}
{t.h[1]} {t.h[2]}

{t.sub}

{t.phases.map((phase) => (
{lang==="es"?"FASE":"PHASE"} {phase.n} / 04

{phase.label}

    {phase.items.map((item) => (
  • {item.n}. {item.text}
  • ))}
))}
); } Object.assign(window, { SocialBar, Header, Hero, Marquee, About, Process });