/* global React */ const { useState, useEffect, useRef } = React; // ============================================================= // STAR PATTERN — Sur Lab brand star scattered as hero background // ============================================================= function StarPattern() { // Pseudo-random but stable star positions const stars = [ { x: 8, y: 22, s: 18, op: 0.20, r: -8 }, { x: 18, y: 78, s: 12, op: 0.14, r: 12 }, { x: 32, y: 16, s: 9, op: 0.12, r: 0 }, { x: 48, y: 64, s: 22, op: 0.16, r: -4 }, { x: 64, y: 28, s: 14, op: 0.18, r: 18 }, { x: 72, y: 70, s: 10, op: 0.15, r: -10 }, { x: 86, y: 18, s: 16, op: 0.20, r: 6 }, { x: 92, y: 56, s: 11, op: 0.13, r: -6 }, { x: 26, y: 44, s: 7, op: 0.10, r: 0 }, { x: 56, y: 12, s: 7, op: 0.10, r: 0 }, { x: 78, y: 90, s: 8, op: 0.12, r: 4 }, { x: 14, y: 56, s: 8, op: 0.10, r: -3 }, { x: 40, y: 88, s: 9, op: 0.12, r: 8 }, { x: 96, y: 80, s: 7, op: 0.10, r: 0 }, { x: 4, y: 88, s: 6, op: 0.10, r: 0 }, ]; return ( ); } // ============================================================= // COUNTER // ============================================================= function Counter({ to, prefix = "", suffix = "", duration = 1600, decimals = 0, accent = false }) { const [n, setN] = useState(0); const ref = useRef(null); useEffect(() => { const el = ref.current; if (!el) return; let raf; const io = new IntersectionObserver((entries) => { entries.forEach((e) => { if (e.isIntersecting) { const start = performance.now(); const tick = (t) => { const p = Math.min(1, (t - start) / duration); const eased = 1 - Math.pow(1 - p, 3); setN(eased * to); if (p < 1) raf = requestAnimationFrame(tick); }; raf = requestAnimationFrame(tick); io.disconnect(); } }); }, { threshold: 0.4 }); io.observe(el); return () => { io.disconnect(); if (raf) cancelAnimationFrame(raf); }; }, [to, duration]); const display = n.toLocaleString("es-AR", { minimumFractionDigits: decimals, maximumFractionDigits: decimals }); return {prefix}{accent ? {display} : display}{suffix}; } // ============================================================= // REVEAL // ============================================================= function Reveal({ children, delay = 0, as: As = "div", ...rest }) { const ref = useRef(null); useEffect(() => { const el = ref.current; if (!el) return; let timer; const reveal = () => { timer = setTimeout(() => el.classList.add("is-in"), delay); }; // If already in viewport on mount (or close to it), reveal immediately. const r = el.getBoundingClientRect(); if (r.top < window.innerHeight && r.bottom > 0) { reveal(); return () => { if (timer) clearTimeout(timer); }; } const io = new IntersectionObserver((entries) => { entries.forEach((e) => { if (e.isIntersecting) { reveal(); io.disconnect(); } }); }, { threshold: 0, rootMargin: "0px 0px -10% 0px" }); io.observe(el); // Hard fallback: never leave anything hidden const fallback = setTimeout(() => el.classList.add("is-in"), 1500); return () => { io.disconnect(); if (timer) clearTimeout(timer); clearTimeout(fallback); }; }, [delay]); return {children}; } // ============================================================= // RINGS VIZ — actor map (Sur Lab palette) // ============================================================= const RINGS_DATA = [ { id: 0, label: "Núcleo decisor", count: "≈ 20 operadoras", desc: <>Operadoras y titulares de áreas. Determinan CapEx, cronogramas, contratación, estándares y velocidad de expansión. YPF, PAE, Chevron, Shell, Vista, Tecpetrol, TotalEnergies, Pampa Energía, Pluspetrol, Equinor, Exxon, entre otras. Su nivel de actividad ordena a toda la red. }, { id: 1, label: "Capacidad técnica", count: "+100 empresas", desc: <>Servicios petroleros y proveedores técnicos críticos. Drilling, completación, fractura, wireline, cementación, ingeniería, automatización. Traducen estrategia en producción efectiva. La legitimidad se construye por performance sostenida, cumplimiento y seguridad — no por visibilidad. }, { id: 2, label: "Derrame y territorio", count: "Red pyme multisectorial", desc: <>Pymes que sostienen la operación. Logística, metalmecánica, construcción, alojamiento, catering, software, telecomunicaciones, salud ocupacional. Es donde el desarrollo energético se convierte en economía real — y donde se sienten con más fuerza las asimetrías del sistema. }, { id: 3, label: "Vida social expandida", count: "Impacto urbano", desc: <>Hotelería, gastronomía, salud, educación, deportes, turismo, comercio, desarrollo urbano. Acá Vaca Muerta deja de ser industria y se vuelve fenómeno urbano, cultural y sociológico. Aparecen housing, arraigo, migración interna, profesionalización acelerada y transformación del tejido social. }, { id: 4, label: "Capa transversal: Gobierno", count: "Nación / Provincia / Municipios", desc: <>Marco que hace viable toda la cadena. Marcos regulatorios, política fiscal, seguridad jurídica, infraestructura pública, concesiones, permisos, ordenamiento territorial. No es un proveedor más: es la capa de gobernanza que habilita —o restringe— la escala del ecosistema. }, ]; function RingsViz({ active, setActive }) { const cx = 50, cy = 50; const radii = [10, 22, 34, 46]; const BLUE = "#1F4F7E"; const TEAL = "#3BAFAA"; const MUTE = "#6E6A60"; return ( {/* outer transversal layer (gobierno) */} setActive(4)} /> {radii.map((r, i) => { const isActive = active === i; const fill = isActive ? `color-mix(in oklab, ${TEAL} 16%, transparent)` : (i === 0 ? `color-mix(in oklab, ${BLUE} 18%, transparent)` : "transparent"); return ( setActive(i)}> ); })} {/* labels */} {RINGS_DATA.slice(0,4).map((d, i) => { const r = radii[i] - 2; return ( {`0${i+1}`} ); })} {/* center star (Sur Lab mark) */} {/* tick marks */} {Array.from({ length: 24 }).map((_, i) => { const angle = (i * 15) * Math.PI / 180; const x1 = cx + Math.cos(angle) * 47; const y1 = cy + Math.sin(angle) * 47; const x2 = cx + Math.cos(angle) * (i % 6 === 0 ? 49 : 48); const y2 = cy + Math.sin(angle) * (i % 6 === 0 ? 49 : 48); return ; })} {/* gov label */} Gobierno · capa transversal ); } // ============================================================= // FORM // ============================================================= function SignupForm() { const [submitted, setSubmitted] = useState(false); const [data, setData] = useState({ nombre: "", empresa: "", cargo: "", email: "", whatsapp: "", ciudad: "", sector: "", intereses: ["Recibir el informe"], idioma: "Español", consent: false, }); const update = (k, v) => setData((d) => ({ ...d, [k]: v })); const toggleInt = (label) => { setData((d) => ({ ...d, intereses: d.intereses.includes(label) ? d.intereses.filter(x => x !== label) : [...d.intereses, label] })); }; const handleSubmit = (e) => { e.preventDefault(); if (!data.consent) return; const subject = `Inscripción al Observatorio — ${data.nombre || "(sin nombre)"} · ${data.empresa || "(sin empresa)"}`; const lines = [ "Nuevo registro al Observatorio Vaca Muerta:", "", `Nombre y apellido: ${data.nombre}`, `Empresa / institución: ${data.empresa}`, `Cargo / rol: ${data.cargo}`, `Email: ${data.email}`, `WhatsApp: ${data.whatsapp}`, `Ciudad / país: ${data.ciudad}`, `Sector: ${data.sector}`, `Intereses: ${data.intereses.join(", ")}`, `Idioma preferido: ${data.idioma}`, "", "— Enviado desde la landing del Observatorio.", ]; const body = lines.join("\n"); const mailto = `mailto:observatorio@surlab.com.ar?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`; // Trigger PDF download immediately so the user gets the informe right away. if (typeof window.__dlInforme === "function") window.__dlInforme(); // Then open the user's mail client with the prefilled lead notification. setTimeout(() => { window.location.href = mailto; }, 350); setSubmitted(true); }; if (submitted) { return (
Confirmación

Gracias por sumarte al Observatorio.

Vamos a estar en contacto. Te enviaremos el primer informe completo a la brevedad y los próximos cortes a medida que se publiquen.

Próximos pasos

Tu lugar quedó registrado y la descarga comenzó.

El informe en PDF empezó a descargarse automáticamente. Si tu navegador lo bloqueó, tocá aquí para descargarlo manualmente. También recibirás un mail de bienvenida y la agenda de los próximos cortes bimestrales. Para conversar antes, escribinos a observatorio@surlab.com.ar.

); } return (
Inscripción

Sumate al primer corte y a la serie bimestral del Observatorio.

INFORME 1/5 · 2026
PRÓXIMO NÚMERO · FOCO AOG PATAGONIA
update("nombre", e.target.value)} />
update("empresa", e.target.value)} />
update("cargo", e.target.value)} />
update("email", e.target.value)} />
update("whatsapp", e.target.value)} />
update("ciudad", e.target.value)} />
{[ "Recibir el informe", "Recibir próximos cortes bimestrales", "Sumarme al newsletter quincenal", "Participar de futuras entrevistas o paneles", "Explorar oportunidades de colaboración con Sur Lab", ].map((i) => ( ))}
{["Español", "English", "Ambos"].map((l) => ( ))}
Tus datos no se comparten con terceros. Los usamos solo para enviar las publicaciones del Observatorio.
); } Object.assign(window, { StarPattern, Counter, Reveal, RingsViz, RINGS_DATA, SignupForm });