/* ==========================================================================
   Factoria Argentina — editorial dark
   ========================================================================== */

:root{
  --ink:        #08080A;
  --ink-2:      #0D0D10;
  --ink-3:      #121216;
  --cream:      #F3EFE6;
  --cream-2:    #DCD6C9;
  --muted:      #8E8A80;
  --muted-2:    #6E6A62;
  --accent:     #DA4E76;
  --accent-hi:  #F0708F;
  --accent-ink: #2A0F1B;
  --line:       rgba(243,239,230,0.14);
  --line-soft:  rgba(243,239,230,0.07);
  --panel:      rgba(8,8,10,0.72);
  --panel-2:    rgba(15,15,19,0.80);

  /* Superficies y lavados. Estaban escritos a mano (crema translúcida sobre
     negro); pasan a token porque el tema claro necesita invertirlos: un lavado
     de crema sobre blanco no se ve. */
  --tint:       rgba(243,239,230,0.02);   /* relleno suave de tarjetas */
  --tint-2:     rgba(243,239,230,0.035);  /* hover de tarjetas */
  --tint-3:     rgba(243,239,230,0.05);   /* hover de items de menú */
  --line-2:     rgba(243,239,230,0.16);   /* borde algo más marcado */
  --track:      rgba(243,239,230,0.09);   /* riel de barras y gauge */
  --ghost:      rgba(243,239,230,0.24);   /* numerales grandes de fondo */
  --sheen:      rgba(243,239,230,0.05);   /* brillo superior de paneles */
  --nav-bg:     rgba(8,8,10,0.55);        /* barra superior translúcida */
  --menu-bg:    rgba(8,8,10,0.97);        /* desplegables */
  --menu-solid: #08080A;                  /* mismo, opaco (mobile) */
  --btn-ink:    #180810;                  /* texto sobre el botón de acento */
  --band-line:  rgba(42,15,27,0.2);       /* separadores dentro de la banda */
  /* El acento cuando hace de TEXTO o línea fina. En oscuro es el acento tal
     cual; la hoja clara lo oscurece (sobre blanco, un lima o un verde claro no
     llega ni a 2:1 y es ilegible). Los RELLENOS siguen usando --accent. */
  --accent-text: var(--accent);
  --ease:       cubic-bezier(.22,.61,.36,1);
}

*{box-sizing:border-box; margin:0; padding:0;}
html{scroll-behavior:smooth; background:var(--ink);}
body{
  background:var(--ink);
  color:var(--cream);
  font-family:'Inter', system-ui, -apple-system, sans-serif;
  font-size:16px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  overflow-x:hidden;
}
a{color:inherit; text-decoration:none;}
img{max-width:100%; display:block;}
::selection{background:var(--accent); color:#12060B;}

.serif{
  font-family:'Fraunces', Georgia, serif;
  font-variation-settings:'SOFT' 0, 'WONK' 0, 'opsz' 120;
}

/* --- fluid background canvas ---------------------------------------------- */
#ink{
  position:fixed; inset:0;
  width:100%; height:100%;
  display:block;
  z-index:0;
  pointer-events:none;
}
#ink-scrim{
  position:fixed; inset:0; z-index:1; pointer-events:none;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(8,8,10,0) 30%, rgba(8,8,10,0.55) 100%);
}
/* film grain — keeps the fluid's gradients from banding on the dark ground */
#ink-scrim::after{
  content:''; position:absolute; inset:0; opacity:.035; mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
.page{position:relative; z-index:2;}

/* --- shared -------------------------------------------------------------- */
.wrap{max-width:1180px; margin:0 auto; padding:0 32px; width:100%;}
section{padding:112px 0; position:relative;}

.eyebrow{
  font-size:11.5px; letter-spacing:0.18em; text-transform:uppercase;
  color:var(--accent-text); font-weight:600;
  display:inline-flex; align-items:center; gap:14px; margin-bottom:22px;
}
.eyebrow::before{content:''; width:28px; height:1px; background:var(--accent-text); opacity:.8;}
/* Hero: el eyebrow va en gris neutro, sin color — texto y línea (--muted
   se adapta solo al tema claro). */
.hero .eyebrow{color:var(--muted);}
.hero .eyebrow::before{background:var(--muted);}

h2.head{
  font-family:'Fraunces', Georgia, serif;
  font-variation-settings:'SOFT' 0, 'WONK' 0, 'opsz' 144;
  font-size:clamp(32px, 4.6vw, 52px);
  font-weight:500;
  line-height:1.08;
  letter-spacing:-0.015em;
  max-width:15ch;
  color:var(--cream);
}
h2.head em{font-style:italic; color:var(--cream-2);}
.lede{
  color:var(--muted); max-width:58ch; margin-top:20px; font-size:15.5px;
}

.btn-solid{
  background:var(--accent); color:var(--btn-ink); font-weight:600; font-size:11.5px;
  letter-spacing:0.12em; text-transform:uppercase; padding:17px 30px;
  display:inline-block; transition:background .25s var(--ease), transform .25s var(--ease);
}
.btn-solid:hover{background:var(--accent-hi); transform:translateY(-1px);}
.link-arrow{
  font-size:14px; color:var(--cream); display:inline-flex; align-items:center; gap:9px;
  transition:color .25s var(--ease), gap .25s var(--ease);
}
.link-arrow:hover{color:var(--accent-text); gap:14px;}

/* --- nav: overlay flotante sobre el hero ------------------------------------
   Sin barra sólida: el nav flota transparente sobre el video / la ciudad 3D
   y recién al scrollear toma el fondo translúcido con blur (clase .scrolled
   que pone el JS). Así el hero corre full-bleed por detrás. */
nav{
  position:fixed; top:0; left:0; right:0; z-index:40;
  background:transparent;
  border-bottom:1px solid transparent;
  transition:background .35s var(--ease), border-color .35s var(--ease);
}
/* Con el menú mobile abierto la barra también va con fondo: si no, queda
   transparente arriba de un desplegable opaco. */
nav.scrolled, nav.open{
  background:var(--nav-bg);
  backdrop-filter:blur(14px) saturate(1.2);
  -webkit-backdrop-filter:blur(14px) saturate(1.2);
  border-bottom-color:rgba(243,239,230,0.06);
}
/* Con el nav fuera del flujo, los anclajes y el hero necesitan su alto de
   vuelta. --nav-h = padding del .wrap (20+20) + alto del logo (placa: 55px,
   48 ≤860, 42 ≤400) + 1px de borde. */
:root{--nav-h:96px;}
@media(max-width:860px){ :root{--nav-h:89px;} }
@media(max-width:400px){ :root{--nav-h:83px;} }
section[id], footer[id]{scroll-margin-top:var(--nav-h);}
nav .wrap{display:flex; align-items:center; justify-content:space-between; padding-top:20px; padding-bottom:20px;}
/* Marca: lockup SVG (ícono + FACTORIA) inline en el nav. El `color` es lo que
   pintan las piezas en currentColor, así el logo sigue la paleta del Lab; la
   pieza blanca del ícono lleva su fill fijo en el marcado y no se toca. */
.logo{
  color:var(--accent-text);
  display:flex; align-items:center;
  flex:none;
}
/* Alto explícito y ancho automático: el viewBox es 334x59 (5.66:1), así que
   32px de alto dan ~181px de ancho. Nunca `width:100%` — en flex el SVG se
   estira y arrastra el alto del nav. */
.logo-lockup{
  display:block; height:32px; width:auto;
  overflow:visible;
}
@media(max-width:860px){ .logo-lockup{height:28px;} }
@media(max-width:400px){ .logo-lockup{height:24px;} }

/* Los dos tratamientos de la marca (fila «Cambiar logo» del Lab). El fill vive
   acá y no en el marcado para que el cambio sea un atributo en el <html>.
   La pieza blanca no participa: va siempre en blanco, en los dos. */
.lk-white{fill:#FFFFFF;}
.lk-word, .lk-mark{fill:currentColor;}          /* acento: siguen la paleta */
/* «grad1» es la placa lima: OTRO svg (ver .lk-badge-lime en el marcado),
   marco + palabra + brazo derecho en lima fijo #BEFF00, pieza izquierda en
   blanco. No sigue la paleta. Se conmuta mostrando/ocultando. */
.lk-lime-badge{fill:#BEFF00;}
.lk-lime-white{fill:#FFFFFF;}
.lk-badge-lime{display:none;}
[data-logo="grad1"] .lk-plain{display:none;}
[data-logo="grad1"] .lk-badge{display:none;}
[data-logo="grad1"] .lk-badge-lime{display:block;}
/* «lime»: palabra en blanco + brazo derecho en lima #D8FF2C (el acento del
   tema lime). La pieza izquierda (.lk-white) ya va en blanco. No sigue la
   paleta: es un tratamiento fijo, como grad1/grad2. */
[data-logo="lime"] .lk-word{fill:#FFFFFF;}
[data-logo="lime"] .lk-mark{fill:#D8FF2C;}

/* «grad2» (placa) es OTRO svg, no otro fill: distinto viewBox y distinta
   construcción (marco y lockup en un solo path evenodd). Se conmuta
   mostrando uno y ocultando el otro. */
.lk-badge{display:none;}
[data-logo="grad2"] .lk-plain{display:none;}
[data-logo="grad2"] .lk-badge{display:block;}
/* La placa es mucho más alta en proporción (387x125 = 3,10:1 contra 5,66:1),
   así que al mismo alto la palabra queda diminuta: el marco se lleva casi
   la mitad del alto. Va más grande para que el texto mida parecido a los otros. */
[data-logo="grad2"] .logo-lockup{height:55px;}
[data-logo="grad1"] .logo-lockup{height:55px;}
@media(max-width:860px){ [data-logo="grad2"] .logo-lockup{height:48px;} }
@media(max-width:860px){ [data-logo="grad1"] .logo-lockup{height:48px;} }
@media(max-width:400px){ [data-logo="grad2"] .logo-lockup{height:42px;} }
@media(max-width:400px){ [data-logo="grad1"] .logo-lockup{height:42px;} }

/* Destello de la placa: una banda de luz blanca cruza el badge cada 13s —
   más lento y más suave que el destello del viejo logo de texto (6,5s, barrido
   de ~1,7s casi a color pleno): acá el barrido dura ~2,9s con ease-in-out y la
   banda es ancha y tenue (pico .34 de alfa, ver lkShineGrad). El rect arranca
   y termina fuera de la placa (−300…−40 → +820 = 520…780 contra 0…394), así
   el salto de vuelta del loop no se ve. Sólo grad2: vive dentro del svg de la
   placa, que queda display:none en los otros tratamientos. */
.lk-shine{animation:lkShine 13s infinite;}
@keyframes lkShine{
  0%   {transform:translateX(0);
        animation-timing-function:cubic-bezier(.42,0,.24,1);}
  22%  {transform:translateX(820px);}   /* barrió; el resto del ciclo reposa */
  100% {transform:translateX(820px);}
}
.navlinks{
  display:flex; gap:34px; font-size:11.5px; letter-spacing:0.1em;
  text-transform:uppercase; color:var(--cream-2); font-weight:500;
}
.navlinks a{position:relative; padding-bottom:3px;}
.navlinks a::after{
  content:''; position:absolute; left:0; bottom:0; height:1px; width:0;
  background:var(--accent); transition:width .3s var(--ease);
}
.navlinks a:hover::after{width:100%;}

/* flex, not absolute: Chrome does not treat a positioned <button> as the
   containing block for abspos children, which leaves the bars unpainted. */
.nav-toggle{
  display:none; width:34px; height:30px; border:0; padding:0 3px;
  background:transparent; cursor:pointer;
  flex-direction:column; justify-content:center; align-items:stretch; gap:6px;
}
.nav-toggle span{
  display:block; width:100%; height:1.5px; flex:0 0 1.5px; background:var(--cream);
  transition:transform .3s var(--ease);
}
nav.open .nav-toggle span:nth-child(1){transform:translateY(3.75px) rotate(45deg);}
nav.open .nav-toggle span:nth-child(2){transform:translateY(-3.75px) rotate(-45deg);}

@media(max-width:860px){
  .nav-toggle{display:flex;}
  .navlinks{
    position:absolute; top:100%; left:0; right:0;
    flex-direction:column; gap:0;
    /* Opaco: con 0.96 + blur el hero (titular y botón) se colaba por debajo
       y se superponía a las filas del Lab en mobile. */
    background:var(--menu-solid); backdrop-filter:none; -webkit-backdrop-filter:none;
    border-bottom:1px solid var(--line-soft);
    max-height:0; overflow:hidden; transition:max-height .4s var(--ease);
  }
  .navlinks a{padding:18px 32px; border-bottom:1px solid var(--line-soft);}
  .navlinks a::after{display:none;}
  /* 340 alcanzaba para 5 links; con el item Lab (y su desplegable abierto)
     el menú se cortaba. */
  nav.open .navlinks{max-height:760px;}
}

/* ---- LAB: control de pruebas, NO va a producción -------------------------
   Sólo existe con data-lab en el <html> (lo pone el script del <head> en
   localhost y en la preview del sandbox). En producción, fuera. */
html:not([data-lab]) #lab{display:none !important;}
/*
   Vive dentro de .navlinks para heredar el menú desplegable de mobile. */
.lab{position:relative;}
.lab-btn{
  display:inline-flex; align-items:center; gap:7px;
  background:none; border:0; padding:0; cursor:pointer;
  font-family:inherit; font-size:11.5px; letter-spacing:0.1em;
  text-transform:uppercase; font-weight:500; color:var(--muted);
  transition:color .25s var(--ease);
}
.lab-btn:hover, .lab.open .lab-btn{color:var(--accent-text);}
.lab-btn svg{
  width:11px; height:11px; fill:none; stroke:currentColor; stroke-width:2.4;
  stroke-linecap:round; stroke-linejoin:round;
  transition:transform .25s var(--ease);
}
.lab.open .lab-btn svg{transform:rotate(180deg);}

.lab-menu{
  position:absolute; top:calc(100% + 14px); right:0; z-index:50;
  min-width:308px; padding:6px;
  background:var(--menu-bg);
  backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px);
  border:1px solid var(--line-soft);
  opacity:0; visibility:hidden; transform:translateY(-6px);
  transition:opacity .2s var(--ease), transform .2s var(--ease), visibility .2s;
}
.lab.open .lab-menu{opacity:1; visibility:visible; transform:none;}
.lab-menu button{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  width:100%; background:none; border:0; cursor:pointer; text-align:left;
  padding:11px 12px; font-family:inherit; font-size:12px; letter-spacing:0.02em;
  text-transform:none; font-weight:500; color:var(--cream-2);
  transition:background .2s var(--ease), color .2s var(--ease);
}
.lab-menu button:hover{background:var(--tint-3); color:var(--cream);}
.lab-state{
  font-size:9.5px; letter-spacing:0.14em; text-transform:uppercase;
  font-weight:600; color:var(--accent-text);
}
/* Filas con stepper: ‹ anterior / etiqueta / › siguiente para recorrer las
   variantes en ambas direcciones. */
.lab-row{display:flex; align-items:stretch; gap:2px;}
.lab-menu .lab-main{flex:1 1 auto; width:auto; min-width:0; white-space:nowrap;}
.lab-menu .lab-arrow{
  flex:none; width:30px; padding-left:0; padding-right:0;
  display:flex; align-items:center; justify-content:center;
  font-size:16px; line-height:1; color:var(--muted);
}
.lab-menu .lab-arrow:hover{color:var(--accent-text);}
/* Fila Publicado: enlace del sitio en Cloudflare, click = copiar. */
.lab-pub{width:100%; border-top:1px solid var(--line-soft); margin-top:4px; padding-top:14px;}
.lab-pub .lab-state{text-transform:none; letter-spacing:0.02em; font-size:11px;}


/* Fondo del hero = foto del tablero. Devuelve también los niveles que tenía
   antes del video: el metraje nocturno necesitaba más brillo que la foto. */
[data-bg="chess"] .hero-video{display:none;}
[data-bg="chess"] .hero-media{
  background-image:url('assets/hero-chess.jpg');
  filter:contrast(1.06) brightness(.74);
  opacity:.62;
}
/* Fondo del hero = la multitud analizada. La imagen es MUY brillante y con un
   coral saturado, así que va bastante más apagada que las otras dos: sin eso
   se come el titular y pelea con el magenta de la marca. */
[data-bg="crowd"] .hero-video{display:none;}
[data-bg="crowd"] .hero-media{
  background-image:url('assets/crowd.jpg');
  background-position:center 45%;
  filter:saturate(.8) contrast(1.02) brightness(.7);
  opacity:.85;
}
/* Capa extra de oscurecido: el filtro solo no alcanza porque la imagen tiene
   zonas muy claras (los chorros de partículas). */
[data-bg="crowd"] .hero-media::after{
  background:
    linear-gradient(to bottom, rgba(8,8,10,.30) 0%, rgba(8,8,10,.15) 38%, rgba(8,8,10,.50) 100%);
}
/* Fondo del hero = data-city (siluetas + servidores con red de datos).
   Tratamiento liviano a pedido: que se vea la imagen. Mínima sombra arriba
   para que el titular crema se lea sobre la zona brumosa clara. */
[data-bg="data-city"] .hero-video{display:none;}
[data-bg="data-city"] .hero-media{
  background-image:url('assets/data-city.jpg');
  background-position:center 45%;
  filter:saturate(.85) contrast(1.02) brightness(.72);
  opacity:.88;
}
[data-bg="data-city"] .hero-media::after{
  background:
    linear-gradient(to bottom, rgba(8,8,10,.25) 0%, rgba(8,8,10,.12) 38%, rgba(8,8,10,.45) 100%);
}
/* Fondo 3D City: el canvas vive dentro de .hero-media como un fondo más —
   misma posición (derecha 66%), misma máscara de fundido y mismo overlay.
   Sin imagen de fondo: sólo la ciudad. */
#city3d{
  position:absolute; inset:0; width:100%; height:100%;
  display:none; pointer-events:none;
}
[data-bg="city-3d"] #city3d{display:block;}
[data-bg="city-3d"] .hero-video{display:none;}
[data-bg="city-3d"] .hero-media{
  background-image:none;
  filter:none;
  opacity:1;
  animation:none; /* el drift CSS movería el canvas WebGL: la cámara ya se mueve sola */
}
/* Ocultar el fluido ink cuando city-3d está activo para evitar solapamiento */
[data-bg="city-3d"] #ink,
[data-bg="city-3d"] #ink-scrim{
  display:none !important;
}
/* Variante gris de city-3d: la misma ciudad en tonos grises a tono con el
   telón #161616 (ver GRAY en city-3d.js). El renderer es transparente, así
   que el gris lo pone el fondo del .hero entero (la máscara de fundido no
   corta) y la niebla lo acompaña (ver BG_FOG). Sólo en oscuro: en claro la
   ciudad es diurna sobre página blanca. */
html[data-bg="city-01"]:not([data-mode="claro"]) .hero{background:#161616;}
[data-bg="city-01"] #city3d{display:block;}
[data-bg="city-01"] .hero-video{display:none;}
[data-bg="city-01"] .hero-media{
  background-image:none;
  filter:none;
  opacity:1;
  animation:none;
}
[data-bg="city-01"] #ink,
[data-bg="city-01"] #ink-scrim{
  display:none !important;
}

/* Fondo del hero = data-wave (misma familia que data-city, con ola de
   partículas y paneles a la derecha): mismo tratamiento liviano. */
[data-bg="data-wave"] .hero-video{display:none;}
[data-bg="data-wave"] .hero-media{
  background-image:url('assets/data-wave.jpg');
  background-position:center 45%;
  filter:saturate(1) contrast(1.02) brightness(.85);
  opacity:.93;
}
[data-bg="data-wave"] .hero-media::after{
  background:
    linear-gradient(to bottom, rgba(8,8,10,.18) 0%, rgba(8,8,10,.08) 38%, rgba(8,8,10,.32) 100%);
}
/* Fondo del hero = data-lime (misma familia data, con mapas y red lima):
   mismo tratamiento liviano. */
[data-bg="data-lime"] .hero-video{display:none;}
[data-bg="data-lime"] .hero-media{
  background-image:url('assets/data-lime.jpg');
  background-position:center 45%;
  filter:saturate(.85) contrast(1.02) brightness(.72);
  opacity:.88;
}
[data-bg="data-lime"] .hero-media::after{
  background:
    linear-gradient(to bottom, rgba(8,8,10,.25) 0%, rgba(8,8,10,.12) 38%, rgba(8,8,10,.45) 100%);
}
/* Fondo animado vortex: el video lo carga el JS; el póster queda de base
   para mobile / reduced-motion, con los niveles del video de ciudad. */
[data-bg="vortex"] .hero-media{background-image:url('assets/vortex-poster.jpg');}
/* Fondo animado video-lime: el video lo carga el JS; el póster queda de base
   para mobile / reduced-motion, con los niveles del video de ciudad. */
[data-bg="video-lime"] .hero-media{background-image:url('assets/video-lime-poster.jpg');}

@media(max-width:980px){
  [data-bg="chess"] .hero-media{background-image:url('assets/hero-chess-sm.jpg');}
  [data-bg="crowd"] .hero-media{background-image:url('assets/crowd-sm.jpg');}
  [data-bg="data-city"] .hero-media{background-image:url('assets/data-city-sm.jpg');}
  [data-bg="data-wave"] .hero-media{background-image:url('assets/data-wave-sm.jpg');}
  [data-bg="data-lime"] .hero-media{background-image:url('assets/data-lime-sm.jpg');}
  [data-bg="vortex"] .hero-media{background-image:url('assets/vortex-poster.jpg');}
  [data-bg="video-lime"] .hero-media{background-image:url('assets/video-lime-poster.jpg');}
}
/* En mobile el menú del nav ya es una columna: el desplegable se abre en línea
   en vez de flotar. */
@media(max-width:860px){
  .lab{width:100%; border-bottom:1px solid var(--line-soft);}
  .lab-btn{width:100%; justify-content:space-between; padding:18px 22px;}
  .lab-menu{
    position:static; min-width:0; padding:0; border:0;
    /* Hereda el opaco del navlinks; el background:none dejaba transparente
       el área del desplegable y el hero se veía encima de las opciones. */
    background:var(--menu-solid);
    backdrop-filter:none; -webkit-backdrop-filter:none;
    opacity:1; visibility:visible; transform:none;
    max-height:0; overflow:hidden; transition:max-height .3s var(--ease);
  }
  .lab.open .lab-menu{max-height:520px;}
  .lab-menu .lab-main{padding:12px 22px 12px 34px;}
  .lab-menu .lab-arrow{padding-top:12px; padding-bottom:12px;}
}
/* ---- fin LAB ------------------------------------------------------------- */

/* --- hero ---------------------------------------------------------------- */
.hero{position:relative; overflow:hidden; isolation:isolate;}
/* El hero ocupa la pantalla entera y la banda de vidrio queda al pie, sobre
   la ciudad. Columna flex: el contenido crece y empuja la banda abajo. */
.hero{min-height:100vh; min-height:100svh; display:flex; flex-direction:column;}
.hero > .hero-inner{width:100%; flex:1 0 auto;}
.hero-media{
  position:absolute; inset:0 0 0 auto;
  width:66%; z-index:-1;
  background-image:url('assets/city-poster.jpg');
  background-size:cover;
  background-position:center 42%;
  filter:contrast(1.04) brightness(.92);
  opacity:.82;
  -webkit-mask-image:
    linear-gradient(to right, rgba(0,0,0,0) 0%, rgba(0,0,0,.28) 26%, rgba(0,0,0,.85) 58%, #000 100%),
    linear-gradient(to bottom, rgba(0,0,0,0) 0%, #000 16%, #000 100%);
  -webkit-mask-composite:source-in;
  mask-image:
    linear-gradient(to right, rgba(0,0,0,0) 0%, rgba(0,0,0,.28) 26%, rgba(0,0,0,.85) 58%, #000 100%),
    linear-gradient(to bottom, rgba(0,0,0,0) 0%, #000 16%, #000 100%);
  mask-composite:intersect;
  transform:scale(1.02);
  animation:heroDrift 34s ease-in-out infinite alternate;
}
@keyframes heroDrift{
  from{transform:scale(1.02) translate3d(0,0,0);}
  to{transform:scale(1.08) translate3d(-1.2%,-1%,0);}
}
.hero-video{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; display:block; border:0;
}

.hero-media::after{
  content:''; position:absolute; inset:0;
  /* Abajo casi no oscurece: ahí va la banda de vidrio (dentro del hero) y la
     ciudad tiene que verse a través. Por eso la máscara vertical tampoco
     cierra abajo: el borde inferior de la banda es el final del hero. */
  background:linear-gradient(to bottom, rgba(8,8,10,.35) 0%, rgba(8,8,10,0) 35%, rgba(8,8,10,.2) 100%);
}

/* El barrido de luz quedó desactivado al pasar a video de fondo: .hero-shine
   es una copia estática de la imagen llevada a blanco y negro puro, y sobre
   metraje en movimiento se lee como un fantasma quieto deslizándose por encima.
   Las luces de la ciudad ya aportan el brillo que daba el barrido.
   El bloque completo está en el respaldo si se vuelve a la foto fija. */
.hero-shine{display:none;}

.hero .hero-inner{padding-top:calc(var(--nav-h) + clamp(96px,13vh,150px)); padding-bottom:clamp(90px,12vh,140px); position:relative;}
.hero h1{
  font-family:'Fraunces', Georgia, serif;
  font-variation-settings:'SOFT' 0,'WONK' 0,'opsz' 144;
  font-size:clamp(44px, 6.4vw, 88px);
  font-weight:500;
  line-height:1.02;
  letter-spacing:-0.022em;
  /* 28ch: la segunda línea («datos, inteligencia y lectura humana.») es más
     larga que la primera; con 22ch se partía sola en escritorio. El corte lo
     controlan los bloques .h-line, no este max-width. */
  max-width:28ch;
  color:var(--cream);
  text-wrap:balance;
}
.hero h1 em{font-style:italic; font-weight:400;}
/* Tres líneas fijas: cada .h-line es un bloque. En escritorio quedan las 3
   (“y lectura humana.” va en la tercera); en mobile se optimiza tamaño. */
.hero h1 .h-line{display:block;}
@media(max-width:600px){
  .hero h1{font-size:clamp(36px, 11vw, 44px); line-height:1.06;}
}
.hero p.sub{
  margin-top:30px; max-width:42ch; color:var(--muted);
  font-size:16px; line-height:1.72;
}
.hero-cta{display:flex; align-items:center; gap:28px; margin-top:42px; flex-wrap:wrap;}

.hero-stat{
  position:absolute; right:4%; bottom:12%;
  text-align:left; pointer-events:none;
}
.hero-stat b{
  display:block;
  font-family:'Fraunces', Georgia, serif;
  font-variation-settings:'SOFT' 0,'WONK' 0,'opsz' 144;
  font-size:clamp(34px,4.4vw,58px); font-weight:500; line-height:1;
  color:var(--cream); letter-spacing:-0.02em;
}
.hero-stat span{
  display:block; margin-top:8px;
  font-size:10.5px; letter-spacing:0.24em; text-transform:uppercase;
  color:var(--cream-2); opacity:.75;
}
@media(max-width:980px){
  .hero-media{width:100%; opacity:.34;
    background-image:url('assets/city-poster.jpg');
    -webkit-mask-image:linear-gradient(to bottom, rgba(0,0,0,.2) 0%, #000 45%, #000 100%);
    mask-image:linear-gradient(to bottom, rgba(0,0,0,.2) 0%, #000 45%, #000 100%);
    -webkit-mask-composite:source-over; mask-composite:add;
  }
  .hero-stat{display:none;}
}

/* Banda: vidrio gris, no bloque de acento. Tinte translúcido de --cream (gris
   claro sobre negro en oscuro, gris oscuro sobre blanco en claro: la hoja
   clara redefine --cream como tinta) + blur y filos de luz arriba/abajo.
   `html .band` para ganarle a las paletas (grad3 le pone el degradado a
   .band y carga después). Texto y separadores también salen de los tokens. */
html .band{
  background:color-mix(in srgb, var(--cream) 6%, transparent);
  /* Blur corto a propósito: la ciudad tiene que leerse detrás, no borrarse. */
  backdrop-filter:blur(6px) saturate(1.1);
  -webkit-backdrop-filter:blur(6px) saturate(1.1);
  border-top:1px solid var(--line-soft);
  border-bottom:1px solid var(--line-soft);
  box-shadow:inset 0 1px 0 color-mix(in srgb, var(--cream) 8%, transparent);
  color:var(--cream); position:relative; z-index:3;
  --band-line:var(--line-soft);
}
.band-item{color:var(--cream-2);}
.band-item b{color:var(--cream);}
.band .wrap{display:flex; flex-wrap:wrap;}
.band-item{
  padding:20px 30px; font-size:12px; letter-spacing:0.04em;
  border-right:1px solid var(--band-line);
  display:flex; align-items:center; gap:11px;
}
.band-item:first-child{padding-left:0;}
.band-item:last-child{border-right:none;}
.band-item b{
  font-family:'Fraunces', Georgia, serif;
  font-variation-settings:'SOFT' 0,'WONK' 0,'opsz' 90;
  font-weight:600; font-size:15px;
}
@media(max-width:760px){
  .band-item{border-right:none; border-bottom:1px solid var(--band-line); width:100%; padding-left:0;}
  .band-item:last-child{border-bottom:none;}
}

/* --- grids --------------------------------------------------------------- */
.panel{background:var(--panel); backdrop-filter:blur(3px); -webkit-backdrop-filter:blur(3px);}
.panel-2{background:var(--panel-2); backdrop-filter:blur(3px); -webkit-backdrop-filter:blur(3px);}

.grid{
  display:grid;
  border-top:1px solid var(--line-soft);
  border-left:1px solid var(--line-soft);
  margin-top:56px;
}
.grid > *{
  border-right:1px solid var(--line-soft);
  border-bottom:1px solid var(--line-soft);
  transition:background .4s var(--ease);
}
.grid-3{grid-template-columns:repeat(3,1fr);}
.grid-4{grid-template-columns:repeat(4,1fr);}
@media(max-width:900px){ .grid-3{grid-template-columns:repeat(2,1fr);} .grid-4{grid-template-columns:repeat(2,1fr);} }
@media(max-width:600px){ .grid-3, .grid-4{grid-template-columns:1fr;} }

.cell{padding:40px 32px; position:relative;}
.cell:hover{background:var(--tint-2);}
.cell .n{
  font-family:'Fraunces', Georgia, serif;
  font-variation-settings:'SOFT' 0,'WONK' 0,'opsz' 144;
  font-size:34px; font-weight:400; color:var(--ghost);
  display:block; margin-bottom:24px; line-height:1;
  transition:color .4s var(--ease);
}

/* icon + numeral share the head of a service cell */
.cell-head{
  display:flex; align-items:center; justify-content:space-between;
  margin-bottom:26px;
}
.cell-head .n{font-size:21px; margin-bottom:0;}
.ico{
  width:30px; height:30px; flex:none;
  fill:none; stroke:currentColor; stroke-width:1.25;
  stroke-linecap:round; stroke-linejoin:round;
  color:var(--cream-2); opacity:.6;
  transition:color .4s var(--ease), opacity .4s var(--ease);
}
.cell:hover .ico{color:var(--accent-text); opacity:1;}
.cell:hover .n{color:var(--accent-text);}
.cell h3{font-size:17px; font-weight:600; margin-bottom:11px; letter-spacing:-0.005em;}
.cell p{font-size:13.5px; color:var(--muted); line-height:1.68;}
.cell .cat{
  display:inline-block; margin-top:16px; font-size:9.5px; letter-spacing:0.16em;
  text-transform:uppercase; color:var(--accent-text); font-weight:600; opacity:.85;
}
.cell h4{font-size:14.5px; font-weight:600; margin-bottom:9px;}
/* --- método: órbita ------------------------------------------------------- */
/* El anillo es un SVG de 400x400 sin escalar, para que los hairlines queden
   exactos en 1px. Nada acá usa transform: las tarjetas ya lo usan para el
   reveal, y un transform de posicionamiento lo pisaría. */
.orbit{position:relative; height:560px; margin-top:56px;}
.orbit-ring{
  position:absolute; left:50%; top:50%; margin:-200px 0 0 -200px;
  pointer-events:none;
}
/* Gira el grupo entero (arco + punta), no el dash: quedan pegados por
   construcción y no hay fase que mantener a mano. */
.orbit-sweep{
  transform-box:view-box; transform-origin:200px 200px;
  animation:orbitSweep 16s linear infinite;
  /* El arco y la punta usan currentColor: así siguen la paleta del Lab. */
  color:var(--accent);
}
@keyframes orbitSweep{to{transform:rotate(360deg);}}

.node{
  position:absolute; width:36px; height:36px; margin:-18px 0 0 -18px;
  border:1px solid rgba(218,78,118,0.55); border-radius:50%;
  /* El borde sigue al acento del Lab (la línea anterior queda de fallback). */
  border-color:color-mix(in srgb, var(--accent) 55%, transparent);
  background:var(--ink-2);
  display:flex; align-items:center; justify-content:center;
  font-size:12px; font-weight:600; letter-spacing:0.04em;
  color:var(--accent-text); line-height:1;
}
.n1{left:50%; top:120px;}
.n2{left:calc(50% + 160px); top:280px;}
.n3{left:50%; top:440px;}
.n4{left:calc(50% - 160px); top:280px;}

.phase{position:absolute;}
.phase h4{font-size:14.5px; font-weight:600; margin-bottom:9px; letter-spacing:-0.005em;}
.phase p{font-size:12.5px; color:var(--muted); line-height:1.6;}
.f1{top:0; left:0; right:0; margin:0 auto; max-width:340px; text-align:center;}
.f3{top:478px; left:0; right:0; margin:0 auto; max-width:340px; text-align:center;}
.f2, .f4{
  top:0; bottom:0; width:250px;
  display:flex; flex-direction:column; justify-content:center;
}
.f2{left:calc(50% + 202px);}
.f4{right:calc(50% + 202px); text-align:right;}

.orbit-core{
  position:absolute; left:50%; top:50%; margin:-14px 0 0 -90px;
  width:180px; text-align:center;
  display:flex; align-items:center; justify-content:center; gap:9px;
}
.orbit-core-ico{
  width:15px; height:15px; flex:none;
  fill:none; stroke:var(--muted-2); stroke-width:1.25;
  stroke-linecap:round; stroke-linejoin:round;
}
.orbit-core b{
  font-family:'Fraunces', Georgia, serif;
  font-variation-settings:'SOFT' 0,'WONK' 0,'opsz' 144;
  font-style:italic; font-weight:400; font-size:19px; color:var(--muted-2);
  line-height:1;
}

/* Abajo de 980px el anillo no entra: el mismo marcado pasa a lista vertical. */
@media(max-width:980px){
  .orbit{
    position:static; height:auto; margin-top:44px;
    display:grid; grid-template-columns:auto 1fr; gap:0 20px; align-items:start;
  }
  .orbit-ring{display:none;}
  .node{position:static; margin:0;}
  /* margin:0 es necesario: las tarjetas de arriba y abajo traen `margin:0 auto`
     del anillo, y un margen auto en un grid item lo encoge y lo centra. */
  .phase{position:static; width:auto; max-width:none; margin:0; text-align:left;
         padding-bottom:30px;}
  .f2, .f4{display:block;}
  .orbit-core{
    position:static; margin:0; width:auto; grid-column:1 / -1;
    justify-content:flex-start; padding-top:4px;
  }
}

/* team */
.member .role{
  font-size:10.5px; color:var(--accent-text); margin-top:8px;
  letter-spacing:0.14em; text-transform:uppercase; font-weight:600;
}
.member p.bio{font-size:13px; color:var(--muted); margin-top:14px; line-height:1.68;}

/* a grid cell that closes the last row and carries the invitation */
.cell.cta{
  display:flex; flex-direction:column; justify-content:center;
  background:rgba(218,78,118,0.055);
  /* Sigue al acento del Lab (la línea anterior queda de fallback). */
  background:color-mix(in srgb, var(--accent) 6%, transparent);
}
.cell.cta:hover{
  background:rgba(218,78,118,0.10);
  background:color-mix(in srgb, var(--accent) 11%, transparent);
}
.cell.cta p{color:var(--cream-2); font-size:14px; max-width:24ch;}
.cell.cta .link-arrow{margin-top:18px; font-size:12px; letter-spacing:0.1em;
  text-transform:uppercase; font-weight:600; color:var(--accent-text);}

/* alliances */

/* Placa de marca. Placeholder: el monograma va en la tipografía del sitio,
   no imita la identidad real de cada socio. Para poner el logo verdadero,
   reemplazar el <span class="mark"> por un <img src="assets/logos/…">. */
.alliance-logo{
  position:relative;
  display:flex; align-items:center; justify-content:center;
  height:98px; margin-bottom:26px;
  border:1px solid var(--line-soft);
  background:radial-gradient(130% 150% at 50% 0%,
    var(--sheen) 0%, rgba(243,239,230,0) 68%);
  transition:border-color .4s var(--ease), background .4s var(--ease);
}
.alliance-logo::before,
.alliance-logo::after{
  content:''; position:absolute; width:9px; height:9px;
  border:1px solid rgba(218,78,118,0.45);
  /* Sigue al acento del Lab (la línea anterior queda de fallback). */
  border-color:color-mix(in srgb, var(--accent) 45%, transparent);
  transition:border-color .4s var(--ease);
}
.alliance-logo::before{top:7px; left:7px; border-right:0; border-bottom:0;}
.alliance-logo::after{bottom:7px; right:7px; border-left:0; border-top:0;}
.alliance-logo .mark{
  font-family:'Fraunces', Georgia, serif;
  font-variation-settings:'SOFT' 0,'WONK' 0,'opsz' 144;
  font-size:30px; font-weight:500; letter-spacing:0.04em; line-height:1;
  color:var(--cream-2);
  transition:color .4s var(--ease);
}
.alliance-logo .mark em{font-style:italic; color:var(--accent-text);}
.alliance-logo img{max-height:52px; width:auto; object-fit:contain;}
.alliance:hover .alliance-logo{
  border-color:var(--line-2);
  background:radial-gradient(130% 150% at 50% 0%,
    color-mix(in srgb, var(--accent) 11%, transparent) 0%,
    color-mix(in srgb, var(--accent) 0%, transparent) 70%);
}
.alliance:hover .alliance-logo .mark{color:var(--cream);}
.alliance:hover .alliance-logo::before,
.alliance:hover .alliance-logo::after{border-color:var(--accent);}

.alliance{
  padding:36px 32px; display:flex; flex-direction:column; justify-content:space-between; gap:26px;
  transition:background .4s var(--ease);
}
.alliance:hover{background:var(--tint-2);}
.alliance h3{
  font-family:'Fraunces', Georgia, serif;
  font-variation-settings:'SOFT' 0,'WONK' 0,'opsz' 100;
  font-size:20px; font-weight:500; margin-bottom:12px;
}
.alliance p{font-size:13.5px; color:var(--muted); line-height:1.68;}
.alliance .btn{
  align-self:flex-start; font-size:11px; letter-spacing:0.1em; text-transform:uppercase;
  font-weight:600; color:var(--cream); border-bottom:1px solid var(--accent);
  padding-bottom:5px; transition:color .25s var(--ease);
}
.alliance .btn:hover{color:var(--accent-text);}

/* --- producto: mock del portal ---------------------------------------------
   Maqueta ilustrativa de bordes redondeados — la única del sitio, a
   propósito: es una ventana de app, no una sección editorial. Todo cuelga
   de los tokens, así que las paletas del Lab la tiñen en vivo. */
.mock{
  margin-top:56px;
  border:1px solid var(--line-soft);
  border-radius:18px;
  overflow:hidden;
  background:
    linear-gradient(180deg, var(--sheen) 0%, rgba(243,239,230,0) 42%),
    var(--ink-2);
}
.mock-bar{
  display:flex; align-items:center; gap:14px;
  padding:13px 18px;
  border-bottom:1px solid var(--line-soft);
}
.mock-dots{display:flex; gap:6px;}
.mock-dots i{width:9px; height:9px; border-radius:50%; background:var(--line-2);}
.mock-dots i:first-child{background:var(--accent);}
.mock-url{
  flex:1 1 auto; min-width:0; text-align:center;
  font-size:11.5px; letter-spacing:0.04em; color:var(--muted);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.mock-live{
  display:inline-flex; align-items:center; gap:7px; flex:none;
  font-size:10px; letter-spacing:0.18em; text-transform:uppercase;
  font-weight:600; color:var(--cream-2);
}
.mock-live i{
  width:7px; height:7px; border-radius:50%; background:var(--accent);
  animation:livePulse 2.2s ease-in-out infinite;
}
@keyframes livePulse{0%,100%{opacity:1;} 50%{opacity:.25;}}
.mock-tabs{
  display:flex; gap:2px; padding:0 12px;
  border-bottom:1px solid var(--line-soft);
  overflow-x:auto;
}
.mock-tabs [role="tab"]{
  background:none; border:0; border-bottom:2px solid transparent;
  margin-bottom:-1px; padding:14px 16px; cursor:pointer; flex:none;
  font-family:inherit; font-size:12.5px; font-weight:600;
  letter-spacing:0.02em; color:var(--muted);
  transition:color .25s var(--ease), border-color .25s var(--ease);
}
.mock-tabs [role="tab"]:hover{color:var(--cream);}
.mock-tabs [role="tab"][aria-selected="true"]{color:var(--cream); border-color:var(--accent);}
.mock-body{padding:30px 30px 26px;}
.mock-view[hidden]{display:none;}
.mock-view.is-active{animation:viewIn .45s var(--ease);}
@keyframes viewIn{from{opacity:0; transform:translateY(10px);} to{opacity:1; transform:none;}}
.mock-note{margin-top:16px; font-size:11.5px; letter-spacing:0.06em; color:var(--muted-2);}

.kpis{display:grid; grid-template-columns:repeat(3,1fr); gap:14px;}
.kpi{
  border:1px solid var(--line-soft); border-radius:12px;
  padding:20px 20px 18px; background:var(--tint);
}
.kpi-label{
  display:block; font-size:10px; letter-spacing:0.16em; text-transform:uppercase;
  font-weight:600; color:var(--muted); margin-bottom:10px;
}
.kpi-num{
  display:block;
  font-family:'Fraunces', Georgia, serif;
  font-variation-settings:'SOFT' 0,'WONK' 0,'opsz' 144;
  font-size:36px; font-weight:500; line-height:1; letter-spacing:-0.02em;
  color:var(--cream); font-variant-numeric:tabular-nums;
}
.kpi-delta{display:block; margin-top:8px; font-size:12px; color:var(--accent-text); font-weight:500;}

.mock-chart{margin-top:14px; border:1px solid var(--line-soft); border-radius:12px; padding:18px 18px 10px; background:var(--tint);}
.mock-chart svg{display:block; width:100%; height:120px;}
.spark-fill{fill:var(--accent); opacity:.10; stroke:none;}
.spark-line{
  fill:none; stroke:var(--accent); stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round;
  stroke-dasharray:100; stroke-dashoffset:100;
  transition:stroke-dashoffset 1.4s var(--ease) .1s;
}
.mock.seen .spark-line{stroke-dashoffset:0;}

.redes-grid{display:grid; grid-template-columns:230px 1fr; gap:28px; align-items:center;}
.gauge{text-align:center;}
.gauge svg{display:block; width:100%; max-width:230px; margin:0 auto;}
.gauge-track{fill:none; stroke:var(--track); stroke-width:10; stroke-linecap:round;}
.gauge-val{
  fill:none; stroke:var(--accent); stroke-width:10; stroke-linecap:round;
  stroke-dasharray:0 100; /* la anima el JS por frames, sin transition */
}
.gauge-num{
  display:block; margin-top:-52px;
  font-family:'Fraunces', Georgia, serif;
  font-variation-settings:'SOFT' 0,'WONK' 0,'opsz' 144;
  font-size:40px; font-weight:500; line-height:1; color:var(--cream);
  font-variant-numeric:tabular-nums;
}
.gauge-label{display:block; margin-top:6px; font-size:10px; letter-spacing:0.16em; text-transform:uppercase; font-weight:600; color:var(--muted);}
.net-row + .net-row{margin-top:18px;}
.net-head{
  display:flex; align-items:baseline; justify-content:space-between; gap:12px;
  font-size:13.5px; font-weight:600; margin-bottom:8px;
}
.net-head span:last-child{color:var(--cream-2); font-variant-numeric:tabular-nums;}
.net-sub{display:block; margin-top:6px; font-size:11.5px; color:var(--muted-2);}

.bar{height:6px; border-radius:99px; background:var(--track); overflow:hidden;}
.bar > i{
  display:block; height:100%; width:0; border-radius:inherit;
  background:linear-gradient(90deg, var(--accent), var(--accent-hi));
  transition:width 1s var(--ease);
}

.chip{
  flex:none; font-size:9.5px; letter-spacing:0.14em; text-transform:uppercase;
  font-weight:600; padding:5px 10px; border-radius:99px;
  border:1px solid var(--line-soft); color:var(--muted);
}
.chip-on{border-color:var(--accent-text); color:var(--accent-text);}
.chip-off{color:var(--muted-2);}

.file-row{
  display:flex; align-items:center; gap:14px;
  border:1px solid var(--line-soft); border-radius:12px;
  padding:14px 16px; background:var(--tint);
  transition:border-color .3s var(--ease);
}
.file-row + .file-row{margin-top:10px;}
.file-row:hover{border-color:var(--line-2);}
.file-ico{
  width:26px; height:26px; flex:none;
  fill:none; stroke:var(--accent); stroke-width:1.25;
  stroke-linecap:round; stroke-linejoin:round;
}
.file-meta{display:flex; flex-direction:column; gap:3px; min-width:0; flex:1 1 auto;}
.file-name{
  font-size:13.5px; font-weight:600; letter-spacing:-0.005em;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.file-sub{font-size:11.5px; color:var(--muted-2);}
.file-dl{
  width:18px; height:18px; flex:none;
  fill:none; stroke:var(--muted); stroke-width:1.5;
  stroke-linecap:round; stroke-linejoin:round;
  transition:stroke .3s var(--ease), transform .3s var(--ease);
}
.file-row:hover .file-dl{stroke:var(--accent); transform:translateY(2px);}

.prod-cta{margin-top:52px; text-align:center;}
button.btn-solid{border:0; cursor:pointer; font-family:inherit;}

/* --- modal acceso anticipado ------------------------------------------------
   Diálogo nativo (<dialog>), redondeado como el mock: también es ventana de
   app. Sin backend: los datos quedan en localStorage (ver IIFE «acceso»). */
.access-modal{border:0; padding:0; background:transparent; max-width:min(440px, calc(100vw - 44px)); margin:auto; /* el reset *{margin:0} le saca el centrado nativo */}
.access-modal::backdrop{background:rgba(8,8,10,0.72); backdrop-filter:blur(4px); -webkit-backdrop-filter:blur(4px);}
.access-card{
  position:relative;
  background:var(--ink-2);
  border:1px solid var(--line-soft);
  border-radius:16px;
  padding:34px 32px 30px;
  color:var(--cream);
}
.access-close{
  position:absolute; top:10px; right:12px;
  background:none; border:0; cursor:pointer;
  font-size:15px; line-height:1; color:var(--muted); padding:8px;
  transition:color .25s var(--ease);
}
.access-close:hover{color:var(--accent-text);}
.access-body h3{
  font-family:'Fraunces', Georgia, serif;
  font-variation-settings:'SOFT' 0,'WONK' 0,'opsz' 144;
  font-size:27px; font-weight:500; letter-spacing:-0.015em; line-height:1.1;
  margin-bottom:10px; padding-right:24px;
}
.access-body h3 em{font-style:italic; color:var(--accent-text);}
.access-body p{font-size:13.5px; color:var(--muted); line-height:1.65; margin-bottom:20px;}
.access-body form label{
  display:block; font-size:10px; letter-spacing:0.16em; text-transform:uppercase;
  font-weight:600; color:var(--muted); margin-bottom:14px;
}
.access-body form input{
  display:block; width:100%; margin-top:7px;
  background:var(--tint-3);
  border:1px solid var(--line-soft); border-radius:10px;
  color:var(--cream); font-family:inherit; font-size:14.5px;
  padding:12px 13px;
}
.access-body form input::placeholder{color:var(--muted-2);}
.access-body form input:focus{outline:none; border-color:var(--accent);}
.access-error{font-size:12.5px; color:var(--accent-text); font-weight:500; margin-bottom:14px;}
.access-error[hidden]{display:none;}
.access-body .btn-solid{width:100%;}
#accessDoneText{margin-bottom:22px;}

@media(max-width:900px){
  .redes-grid{grid-template-columns:1fr; gap:8px;}
  .gauge svg{max-width:200px;}
  .gauge-num{margin-top:-46px;}
}
@media(max-width:640px){
  .mock-body{padding:20px 16px 18px;}
  .kpis{grid-template-columns:1fr;}
  .kpi-num{font-size:32px;}
  .mock{border-radius:14px;}
}

@media (prefers-reduced-motion: reduce){
  .mock-live i, .mock-view.is-active{animation:none;}
  .dot-ring{animation:none; transform:none; opacity:.5;}
  .spark-line, .bar > i{transition:none;}
}

/* --- footer -------------------------------------------------------------- */
footer{
  padding:110px 0 0; position:relative;
  border-top:1px solid var(--line-soft);
  background:var(--panel);
  backdrop-filter:blur(3px); -webkit-backdrop-filter:blur(3px);
}
.contact-grid{
  display:grid; grid-template-columns:1.2fr 1fr; gap:64px; align-items:end;
}
footer h2{
  font-family:'Fraunces', Georgia, serif;
  font-variation-settings:'SOFT' 0,'WONK' 0,'opsz' 144;
  font-size:clamp(32px,4.8vw,58px); font-weight:500; line-height:1.06;
  letter-spacing:-0.02em; max-width:13ch;
}
footer h2 em{font-style:italic; color:var(--accent-text);}
.contact-info{display:flex; flex-direction:column; gap:14px; font-size:14.5px; color:var(--cream-2);}
.contact-info a:hover{color:var(--accent-text);}
.contact-info .label{
  font-size:10px; letter-spacing:0.2em; text-transform:uppercase;
  color:var(--muted-2); margin-bottom:2px;
}
.foot-cta{margin-top:48px;}
.foot-bottom{
  margin-top:90px; padding:26px 0; border-top:1px solid var(--line-soft);
  display:flex; justify-content:space-between; flex-wrap:wrap; gap:12px;
  font-size:11.5px; letter-spacing:0.08em; text-transform:uppercase; color:var(--muted-2);
}
@media(max-width:820px){
  .contact-grid{grid-template-columns:1fr; gap:44px; align-items:start;}
  .foot-bottom{margin-top:60px;}
  section{padding:84px 0;}
  .wrap{padding-left:22px; padding-right:22px;}
  .cell{padding:32px 24px;}
}

/* --- datos: mapa del territorio ------------------------------------------ */
/* Mapa a la izquierda (misma ventana .mock que el portal), texto a la
   derecha centrado en vertical. El mapa es un webp con el aspecto exacto del
   viewBox del overlay (2000×1562 = 1000×781), por eso el <svg> lleva
   preserveAspectRatio="none" sin deformar nada: así las coordenadas del IIFE
   «datos» caen donde dicen. Las etiquetas van en HTML (no en el SVG) para que
   no escalen con el mapa. */
.datos{
  display:grid; grid-template-columns:minmax(0,1.5fr) minmax(0,1fr);
  gap:64px; align-items:center;
}
.datos-text .head{margin-bottom:0;}
.datos-text .lede{margin-top:22px;}
.datos-p{margin-top:18px; font-size:15px; line-height:1.7; color:var(--muted); max-width:48ch;}
/* Tarjeta simple: sin barra de app, sólo borde y radio (a diferencia del mock
   del portal, que sí es una ventana). */
.dmock{
  border:1px solid var(--line-soft); border-radius:18px; overflow:hidden;
  background:var(--ink-2);
}
.dmap-body{display:flex; flex-direction:column;}
.dmap{
  position:relative; overflow:hidden; background:var(--ink);
  aspect-ratio:2000/1562;
}
.dmap img{width:100%; height:100%; object-fit:fill; filter:contrast(1.06);}
.dmap-overlay{position:absolute; inset:0; width:100%; height:100%; color:var(--accent-text); overflow:visible;}
.dmap-heat circle{mix-blend-mode:screen;}
.dmap-leaders line{stroke:var(--cream-2); stroke-width:1; opacity:.55; vector-effect:non-scaling-stroke;}
.dot{fill:var(--accent); opacity:.9;}
.dot-far{fill:var(--cream-2); opacity:.55;}
.dot-hot{opacity:1;}
.dot-ring{
  fill:none; stroke:var(--accent); stroke-width:1; opacity:.75;
  vector-effect:non-scaling-stroke;
  transform-box:fill-box; transform-origin:center;
  animation:dotPing 2.6s var(--ease) infinite;
}
.dot-ring:nth-of-type(2n){animation-delay:-.9s;}
@keyframes dotPing{0%{transform:scale(.35); opacity:.9;} 70%{opacity:0;} 100%{transform:scale(1.25); opacity:0;}}
.dmap-callouts{position:absolute; inset:0; pointer-events:none;}
.dmap-co{
  position:absolute; transform:translate(0,-100%);
  padding:0 6px 5px; border-bottom:1px solid rgba(220,214,201,0.55);
  white-space:nowrap; line-height:1.25; min-width:112px;
}
.dmap-co.is-left{transform:translate(-100%,-100%); text-align:right;}
.dmap-co b{display:block; font-size:11px; letter-spacing:0.12em; text-transform:uppercase; font-weight:600; color:var(--cream);}
.dmap-co small{display:block; font-size:11px; color:var(--muted);}
.dmap-side{
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:0 24px;
  align-items:start; padding:6px 24px 20px; border-top:1px solid var(--line-soft);
}
.dkpi{padding:16px 0 0;}
.dkpi .kpi-label{margin-bottom:8px;}
.dkpi .kpi-num{font-size:28px;}
.dkpi-sub{display:block; margin-top:7px; font-size:11.5px; color:var(--muted-2);}
.datos-map .mock-note a{color:var(--muted); text-decoration:underline; text-underline-offset:2px;}
@media(max-width:1100px){
  .datos{gap:44px;}
  .dmap-side{padding:6px 18px 16px;}
}
@media(max-width:980px){
  .datos{grid-template-columns:1fr; gap:44px;}
  .datos-text{order:-1;}
}
@media(max-width:600px){
  .dmap-callouts, .dmap-leaders{display:none;}
  .dkpi .kpi-num{font-size:24px;}
  .dkpi-sub{font-size:11px;}
}

/* --- reveal -------------------------------------------------------------- */
.reveal, .reveal-row{
  opacity:0; transform:translateY(22px);
  transition:opacity .9s var(--ease), transform .9s var(--ease);
}
.reveal.in, .reveal-row.in{opacity:1; transform:none;}

.hero-fade{opacity:0; transform:translateY(26px); animation:heroUp 1.1s var(--ease) forwards;}
.d1{animation-delay:.15s;} .d2{animation-delay:.32s;} .d3{animation-delay:.48s;} .d4{animation-delay:.64s;}
@keyframes heroUp{to{opacity:1; transform:none;}}

@media (prefers-reduced-motion: reduce){
  *{animation:none !important; transition:none !important;}
  .reveal, .reveal-row, .hero-fade{opacity:1; transform:none;}
  .hero-media{animation:none;}
}
