/* 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 (
);
}
// =============================================================
// 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.
Acceso al primer informe completo (35 páginas).
4 cortes adicionales a lo largo de la serie 2026.
Newsletter quincenal con insights del ecosistema.
Invitaciones a presentaciones y mesas de trabajo.
Versión en inglés a pedido.
INFORME 1/5 · 2026
PRÓXIMO NÚMERO · FOCO AOG PATAGONIA