/* ============================================================
   VELNET S.A. — Tokens de marca (Breakbook 2026)
   Azul #0d3c95 · Naranja #ff4e3c · Negro · Blanco · Montserrat
   ============================================================ */
/* ---------- Tipografia autoalojada ----------
   Antes venia de Google Fonts: 2 conexiones extra (googleapis -> gstatic) antes
   de la primera letra. En gama baja la fuente llegaba a los 4,8 s y el titulo
   de la home recien ahi. Montserrat es variable: un archivo trae los 5 pesos.
   latin (38 KB) cubre todo el espanol; latin-ext solo baja si aparece un
   caracter de ese rango. */
@font-face{font-family:'Montserrat';font-style:normal;font-weight:100 900;font-display:swap;
  src:url('/assets/fonts/montserrat-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Montserrat';font-style:normal;font-weight:100 900;font-display:swap;
  src:url('/assets/fonts/montserrat-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
/* Fallback con las medidas de Montserrat: mientras la fuente carga, el texto
   ocupa lo mismo y no salta al cambiar (en Nosotros el titulo ganaba una linea
   y empujaba todo 34px: CLS 0,119 en gama baja). size-adjust medido contra
   Arial sobre frases reales del sitio (400: 1,124 / 800: 1,117); ascent y
   descent salen de la tabla OS/2 de la fuente (968/-251 sobre 1000),
   divididos por el size-adjust. Android resuelve Arial a Roboto. */
@font-face{font-family:'Montserrat Fallback';font-weight:100 500;src:local('Arial'),local('ArialMT'),local('Roboto');
  size-adjust:112.4%;ascent-override:86.1%;descent-override:22.3%;line-gap-override:0%}
@font-face{font-family:'Montserrat Fallback';font-weight:600 900;src:local('Arial Bold'),local('Arial-BoldMT'),local('Roboto Bold'),local('Roboto-Bold');
  size-adjust:111.7%;ascent-override:86.7%;descent-override:22.5%;line-gap-override:0%}

:root{
  --azul:#0d3c95;
  --azul-800:#0a2f75;
  --azul-900:#082558;
  --azul-950:#061b41;
  --naranja:#ff4e3c;
  --naranja-hover:#e93c2a;
  /* El naranja de marca da 3.28:1 sobre blanco: falla WCAG AA (4.5) como texto.
     Esta variante da 4.99:1 sobre blanco y 4.57:1 sobre --bg-elev y ya pertenece a la familia (esta en el gradiente de .av.or).
     Sobre fondos oscuros el naranja pleno da 5.16:1, asi que ahi se vuelve a usar. */
  --naranja-texto:#cf3626;
  /* Criterio de marca (definido con el cliente): el naranja PLENO manda en todo lo
     que se lee como color -- botones, barras, badges, iconos, avatares. La variante
     oscura queda solo para naranja usado como TEXTO chico sobre fondo claro
     (--naranja-texto), que es donde 3.28:1 realmente lastima la lectura.
     Nota: el texto blanco sobre el relleno pleno da 3.28:1 y no cumple AA para
     texto; es una decision de marca tomada a conciencia, no un descuido. */
  --naranja-fill:var(--naranja);
  --negro:#000000;
  --blanco:#ffffff;

  --bg:var(--blanco);
  --bg-elev:#f2f5fb;
  --bg-hover:#e9eef8;
  --text:#0b1530;
  --text-muted:#55617a;
  --text-inv:#ffffff;
  --text-inv-muted:rgba(255,255,255,.72);
  --accent:var(--naranja);
  --accent-contrast:#ffffff;
  --border:rgba(13,60,149,.12);
  --border-inv:rgba(255,255,255,.16);

  --font:'Montserrat','Montserrat Fallback',system-ui,-apple-system,sans-serif;

  --ease-out-expo:cubic-bezier(0.16,1,0.3,1);
  /* Escala de motion por ROL, no por tamaño. Antes habia 3 duraciones para 5
     trabajos distintos y el hover heredaba los 350ms del movimiento: se movia
     detras del mouse. Referencia: presion 100-160ms, hover 120-200ms,
     desplegables 150-250ms, paneles 200-500ms, scroll de marketing puede ser
     mas largo. */
  --dur-press:.12s;   /* respuesta al click */
  --dur-hover:.18s;   /* color, borde, sombra al pasar el mouse */
  --dur-move:.35s;    /* algo se desplaza o cambia de tamaño en pantalla */
  --dur-panel:.5s;    /* acordeon, menu, panel que se abre */
  --dur-reveal:.7s;   /* entrada por scroll (marketing, puede ser larga) */
  /* alias heredados para no romper reglas existentes */
  --dur-fast:var(--dur-press); --dur:var(--dur-move); --dur-slow:var(--dur-reveal);

  --radius:20px; --radius-sm:12px; --radius-lg:28px;
  --section-y:clamp(80px,12vw,150px);
  /* Despeje bajo la pastilla fija del nav (18px de inset + 66px de alto = 84px)
     + 64px de aire (con 44 el usuario lo seguia viendo pegado en movil).
     El primer bloque de cada pagina interna lo usa como piso. */
  --nav-clear:148px;
  --container:1240px;

  /* ---------- Escala tipografica ----------
     Antes habia 27 tamanos literales y 23 clamps distintos, muchos separados
     por 0.02rem (.78 / .8 / .82 · .85 / .88 / .9 / .92 · .68 / .7 / .72 / .74
     / .75 / .76). Diferencias invisibles de a una, pero juntas hacen que la
     pagina se lea como si nadie hubiera decidido nada. Diez escalones. */
  --fs-3xs:.72rem;   /* badges, pills, contadores */
  --fs-2xs:.8rem;    /* eyebrows, captions, meta */
  --fs-xs:.88rem;    /* cuerpo chico, items de lista */
  --fs-sm:.95rem;    /* cuerpo, botones */
  --fs-md:1rem;      /* cuerpo base */
  --fs-lg:clamp(1.15rem,1.9vw,1.5rem);   /* titulos de card, cita destacada */
  --fs-xl:clamp(1.3rem,2.2vw,1.8rem);    /* h3 */
  --fs-2xl:clamp(1.65rem,2.8vw,2.4rem);  /* h3 grande, h2 de card */
  --fs-3xl:clamp(2rem,4.2vw,3.4rem);     /* h2 */
  --fs-4xl:clamp(2.4rem,4.6vw,3.8rem);   /* h2 de seccion protagonista */
  --fs-5xl:clamp(2.7rem,6.4vw,5.4rem);   /* h1 */
  --fs-giant:clamp(min(13vw,3rem),8vw,6rem); /* "Servicios." / "FAQ": a 320px 3rem (48px) desbordaba 10px, baja solo donde no entra */
  --fs-num:clamp(2.4rem,4.6vw,4rem);     /* cifras grandes */
  --fs-lead:clamp(1.05rem,1.4vw,1.22rem);/* bajadas */
  --fs-stat:2rem;                        /* cifra mediana en linea */

  /* ---------- Escala de espaciado ----------
     Ritmo de bloque. Los micro-gaps internos de cada componente quedan como
     estan: ahi el valor suele ser una alineacion optica con un icono concreto,
     no una decision de ritmo. */
  --sp-1:4px;  --sp-2:8px;  --sp-3:12px; --sp-4:16px;
  --sp-5:20px; --sp-6:24px; --sp-7:32px; --sp-8:40px;
  --sp-9:48px; --sp-10:56px; --sp-11:64px;
  /* Ritmo: el hueco "encabezado de seccion -> grilla de contenido" estaba
     escrito como 52, 56 y 64px segun la seccion. Es un solo gesto: un token.
     Se comprime en mobile desde aca, en vez de 6 overrides sueltos. */
  --rhythm:64px;
  --rhythm-sm:40px;
  /* Hueco entre cards de una misma grilla. Estaba escrito como 14, 18, 20 y
     22px segun el bloque: cuatro valores para el mismo gesto. */
  --gap-cards:20px;
  /* Ancho REAL del viewport (sin scrollbar). 100vw lo incluye: con scrollbar
     clasica (15px) un sangrado a borde hecho con 50vw se pasa 15px y aparece
     scroll horizontal. app.js lo mantiene con documentElement.clientWidth;
     100vw queda solo como valor de partida antes de que corra el script. */
  --vw:100vw;
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{
  font-family:var(--font);
  color:var(--text);
  background:var(--bg);
  line-height:1.6;
  font-size:16px;
  -webkit-font-smoothing:antialiased;
}
a{text-decoration:none;color:inherit}
img{max-width:100%;display:block}
button{font-family:inherit;cursor:pointer;border:none;background:none}
::selection{background:var(--naranja);color:#fff}

.wrap{width:min(var(--container),92%);margin-inline:auto}
section{padding:var(--section-y) 0}
/* ---------- Ritmo entre secciones ----------
   Antes cada seccion parcheaba su padding con style="padding-top:0" inline. El
   parche codificaba una suposicion sobre QUE venia antes, asi que al mover o
   eliminar una seccion quedaba huerfano: al sacar el statement, "Quienes somos"
   se pego al hero. Y las que no tenian el parche sumaban 150+150=300px.
   Con el selector hermano el ritmo se recalcula solo. Hueco unico: --section-y. */
section + section{padding-top:0}
/* Hay secciones cuyo padding vive en un wrapper interno (.hero -> .hero-bleed,
   .contacto -> .contacto-bleed): la seccion en si tiene padding:0, asi que NO
   aporta el hueco inferior del que depende `section + section`. La siguiente
   tiene que poner el suyo. */
.hero + section,
.contacto + section{padding-top:var(--section-y)}
/* En una banda de color el padding es interno, no separacion entre bloques:
   se mantiene para que el contenido no toque el borde de la banda. */
section + .sec-banda{padding-top:var(--section-y)}
/* ...salvo entre dos bandas del MISMO tono: ahi el borde entre bandas no se ve,
   asi que los dos paddings se suman en un hueco muerto del doble. */
.sec-elev + .sec-elev,
.sec-azul + .sec-azul,
.sec-azul950 + .sec-azul950{padding-top:0}
/* Y al reves: cuando una banda TERMINA, su padding inferior queda dentro del
   color. Pasado el cambio de fondo no hay nada, y la seccion siguiente arranca
   pegada al borde. Necesita su propio padding, igual que al entrar a la banda. */
.sec-banda + section:not(.sec-banda){padding-top:var(--section-y)}
/* Bandas de apertura: Servicios y Nosotros abren con el mismo celeste que
   Casos de exito, para que las paginas interiores se lean como una familia. */
#servicios.sec-elev,#nosotros.sec-elev{background:var(--bg-elev)}
/* Dentro de una banda celeste las cards no pueden ser del mismo celeste o
   desaparecen: van en blanco, igual que .caso-card en la pagina de Casos. */
.sec-elev .qs-card{background:#fff}

/* ---------- Tipografía ---------- */
h1,h2,h3,h4{font-weight:800;line-height:1.08;letter-spacing:-.02em;color:var(--azul-950)}
/* Cada pagina interior abre con su h1. Hereda el tamaño del contexto donde
   antes habia un h2, asi que nada cambia visualmente: es solo semantica. */
h1{font-size:var(--fs-3xl)}
.faq h1.giant,.svc-intro h1.giant{font-size:var(--fs-giant)}
.mapa-copy h1,.contacto h1{font-size:var(--fs-4xl)}
.on-dark h1{color:#fff}
h2{font-size:var(--fs-3xl)}
h3{font-size:var(--fs-lg)}
.lead{font-size:var(--fs-lead);color:var(--text-muted);max-width:640px}
.eyebrow{
  display:inline-flex;align-items:center;gap:8px;
  font-size:var(--fs-3xs);font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  color:var(--naranja-texto);margin-bottom:18px;
}
/* En 2 lineas la raya quedaba centrada entre ambas: se ancla a la mitad de la primera. */
.eyebrow::before{content:"";width:22px;height:2px;background:var(--naranja);border-radius:2px;flex-shrink:0;align-self:flex-start;margin-top:calc(.5lh - 1px)}
.on-dark,.mapa-panel,.roles-panel,.oper-band,.plan.popular,.contacto-bleed,footer,.p-card.active{--naranja-texto:var(--naranja)}
.on-dark h1,.on-dark h2,.on-dark h3{color:#fff}
.on-dark .lead{color:var(--text-inv-muted)}

/* ---------- Logo (asset oficial del breakbook) ---------- */
.logo-img{display:block;width:auto}
/* <picture> solo elige WebP o PNG: no debe participar del layout */
.logo-pic{display:contents}

/* ---------- Botones ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font-weight:700;font-size:var(--fs-sm);line-height:1;
  padding:16px 28px;border-radius:999px;
  transition:transform var(--dur-press) var(--ease-out-expo),
             background var(--dur-hover) ease,
             box-shadow var(--dur-hover) ease;
}
.btn:active{transform:scale(.98)}
.btn-primary{background:var(--naranja-fill);color:var(--accent-contrast);box-shadow:0 12px 30px -12px rgba(255,78,60,.55);border:1px solid transparent}
@media (hover:hover){.btn-primary:hover{background:var(--naranja-hover);box-shadow:0 16px 36px -12px rgba(255,78,60,.65);transform:translateY(-2px)}}
/* va DESPUES del hover: con el mouse encima, el hover (misma especificidad) ganaba y el click no se sentia */
.btn.btn-primary:active{transform:translateY(0) scale(.98);box-shadow:0 8px 20px -10px rgba(255,78,60,.55)}
.btn-ghost{background:transparent;color:#fff;border:1.5px solid rgba(255,255,255,.4)}
@media (hover:hover){.btn-ghost:hover{border-color:#fff;background:rgba(255,255,255,.08)}}
.btn-dark{background:var(--azul-950);color:#fff}
@media (hover:hover){.btn-dark:hover{background:var(--azul)}}
.btn-outline{background:transparent;color:var(--azul);border:1.5px solid var(--border)}
@media (hover:hover){.btn-outline:hover{border-color:var(--azul);background:var(--bg-elev)}}
.btn .arr{transition:transform var(--dur) var(--ease-out-expo)}
@media (hover:hover){.btn:hover .arr{transform:translateX(4px)}}

/* ============================================================
   NAV
   ============================================================ */
.nav{
  position:fixed;inset:18px 0 auto;z-index:100;
  display:flex;justify-content:center;
  pointer-events:none;
}
.nav-inner{
  pointer-events:auto;
  width:min(var(--container),94%);
  display:flex;align-items:center;justify-content:space-between;gap:20px;
  background:rgba(255,255,255,.92);
  border:1px solid transparent;
  border-radius:999px;
  padding:10px 12px 10px 26px;
  transition:background var(--dur-hover) var(--ease-out-expo),box-shadow var(--dur-hover) var(--ease-out-expo),border-color var(--dur-hover);
}
.nav.scrolled .nav-inner{
  background:rgba(255,255,255,.82);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  border-color:var(--border);
  box-shadow:0 12px 40px -18px rgba(6,27,65,.25);
}
.nav-links{display:flex;gap:28px;list-style:none}
.nav-links a{font-size:var(--fs-sm);font-weight:600;color:var(--text);position:relative;padding:6px 0}
.nav-links a::after{
  content:"";position:absolute;left:0;bottom:0;height:2px;width:100%;
  background:var(--naranja);border-radius:2px;
  transform:scaleX(0);transform-origin:left;transition:transform var(--dur) var(--ease-out-expo);
}
@media (hover:hover){.nav-links a:hover::after{transform:scaleX(1)}}
.nav-cta{display:flex;align-items:center;gap:12px}
.nav-cta .btn{padding:14px 22px;min-height:44px}
.hamburger{display:none;flex-direction:column;justify-content:center;gap:5px;padding:0 12px;min-height:44px;min-width:44px;transition:scale var(--dur-press) var(--ease-out-expo)}
.hamburger:active{scale:.9}
.hamburger span{width:22px;height:2px;background:var(--azul-950);border-radius:2px;transition:transform var(--dur),opacity var(--dur-hover)}
.mobile-menu{
  position:fixed;inset:0;z-index:99;background:var(--azul-950);
  display:flex;flex-direction:column;justify-content:flex-start;
  padding:96px 8% 40px;
  /* en pantallas bajas (landscape, SE con teclado) los 5 links + el boton no
     entran: sin esto el CTA quedaba inalcanzable con body.menu-open{overflow:hidden} */
  overflow-y:auto;overscroll-behavior:contain;
  transform:translateX(100%);transition:transform .5s var(--ease-out-expo),visibility .5s;
  /* cerrado no debe existir para el teclado ni para lectores de pantalla:
     sin visibility sus 6 enlaces seguian en el orden de tabulacion en TODOS
     los breakpoints, incluido desktop, donde el menu ni siquiera se usa */
  visibility:hidden;
}
.mobile-menu.open{transform:translateX(0);visibility:visible}
/* :not(.btn): con .mobile-menu a (0,1,1) pisando a .btn (0,1,0), el CTA perdia
   su relleno y heredaba la letra gigante de los enlaces (texto contra el borde). */
.mobile-menu a:not(.btn){color:#fff;font-size:clamp(1.45rem,5.5vw,1.8rem);font-weight:800;padding:14px 0;border-bottom:1px solid var(--border-inv)}
.mobile-menu a:not(.btn){transition:opacity var(--dur-press) ease}
.mobile-menu a:not(.btn):active{opacity:.6}
.mobile-menu .btn{margin-top:28px;align-self:flex-start}
/* Centrado con margenes auto y no con justify-content:center: cuando el contenido
   no entra (landscape, 375px de alto) el centrado real lo reparte arriba Y abajo
   y la parte de arriba queda fuera del scroll, tapada por el nav. Con auto, el
   sobrante se reparte solo si existe; si no, el menu empieza abajo del nav. */
.mobile-menu>:first-child{margin-top:auto}
.mobile-menu>:last-child{margin-bottom:auto}
/* Entrada escalonada de los enlaces al abrir. Es una ANIMACION con fill
   "backwards" (no una transition): asi el retraso no se hereda al :active del
   boton y, al terminar, el elemento vuelve a sus valores normales. */
.mobile-menu.open>a{animation:menuItemIn var(--dur-move) var(--ease-out-expo) backwards}
.mobile-menu.open>a:nth-child(1){animation-delay:.10s}
.mobile-menu.open>a:nth-child(2){animation-delay:.14s}
.mobile-menu.open>a:nth-child(3){animation-delay:.18s}
.mobile-menu.open>a:nth-child(4){animation-delay:.22s}
.mobile-menu.open>a:nth-child(5){animation-delay:.26s}
.mobile-menu.open>a:nth-child(6){animation-delay:.30s}
@keyframes menuItemIn{from{opacity:0;transform:translateY(14px)}}
body.menu-open{overflow:hidden}
body.menu-open .hamburger span:nth-child(1){transform:translateY(7px) rotate(45deg)}
body.menu-open .hamburger span:nth-child(2){opacity:0}
body.menu-open .hamburger span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

/* ============================================================
   1 · HERO
   ============================================================ */
.hero{padding:0;margin:0}
.hero-bleed{
  position:relative;min-height:100vh;min-height:100svh;
  border-radius:0 0 var(--radius-lg) var(--radius-lg);
  overflow:hidden;
  display:flex;flex-direction:column;justify-content:flex-end;
  background:var(--azul-950);
}
/* El poster va de fondo del contenedor y NO en el atributo poster del video:
   asi se ve desde el primer pintado aunque el video todavia este en opacity 0,
   y el video entra encima con un fundido en vez de aparecer de golpe. */
.hero-bleed{background:var(--azul-950) url("/assets/video/hero-poster.jpg") center/cover no-repeat}
.hero-bg{
  position:absolute;inset:-8% 0;width:100%;height:116%;
  object-fit:cover;object-position:center;
  opacity:0;transition:opacity var(--dur-reveal) var(--ease-out-expo);
}
.hero-bg.listo{opacity:1}
/* Velo oscuro para que el texto despegue del video. Mas denso a la izquierda,
   que es donde viven el h1, el lead y los botones, y abajo, donde van los
   logos de clientes. La derecha queda mas clara para que el video se vea. */
.hero-velo{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    linear-gradient(102deg,rgba(6,27,65,.95) 0%,rgba(6,27,65,.90) 30%,rgba(6,27,65,.74) 52%,
                           rgba(6,27,65,.38) 78%,rgba(6,27,65,.50) 100%),
    linear-gradient(to top,rgba(6,27,65,.85) 0%,rgba(6,27,65,0) 46%);
}
/* will-change es una pista puntual para una animacion cara en curso, no un
   ajuste permanente: el JS la enciende mientras corre el parallax y la apaga
   cuando el hero sale de pantalla. */
.hero-bg.moviendose{will-change:transform}
.hero-content{position:relative;z-index:2;width:min(var(--container),92%);margin:0 auto;padding:160px 0 56px}
.hero h1{color:#fff;font-size:var(--fs-5xl);max-width:14ch}
.hero .hero-kicker{color:#fff}
.hero-sub{color:var(--text-inv-muted);font-size:var(--fs-lead);max-width:560px;margin-top:26px}
.hero-ctas{display:flex;gap:14px;margin-top:var(--rhythm-sm);flex-wrap:wrap}
.hero-bottom{display:flex;justify-content:space-between;align-items:flex-end;gap:32px;margin-top:72px;flex-wrap:wrap}
.hero-trust{color:var(--text-inv-muted);font-size:var(--fs-xs)}
.avatars{display:flex;margin-bottom:12px}
.avatars .av{
  width:42px;height:42px;border-radius:50%;border:2px solid rgba(255,255,255,.85);
  background:linear-gradient(135deg,var(--azul),var(--azul-800));
  color:#fff;font-size:var(--fs-2xs);font-weight:800;display:grid;place-items:center;
  margin-left:-10px;
}
.avatars .av:first-child{margin-left:0}
.avatars .av.or{background:linear-gradient(135deg,var(--naranja),var(--naranja-hover))}
.hero-logos{display:flex;gap:clamp(20px,2.4vw,34px);align-items:center;margin-top:18px;flex-wrap:wrap}
/* Antes eran los nombres tipeados a mano ("Cargill LDC Bunge ACA"), redundantes
   con el muro de logos reales que esta 200px mas abajo en la misma pagina.
   Ahora son los logos de verdad, pintados de blanco con la misma tecnica de
   mascara que usa el muro. */
.hero-logos .hl{
  display:block;flex-shrink:0;
  height:var(--h);width:calc(var(--h) * var(--r));
  background:rgba(255,255,255,.88);
  -webkit-mask:var(--m) center/contain no-repeat;
          mask:var(--m) center/contain no-repeat;
}
.hero-card{
  background:rgba(255,255,255,.96);
  border-radius:var(--radius);
  padding:14px;display:flex;gap:16px;align-items:stretch;
  max-width:480px;box-shadow:0 30px 70px -30px rgba(6,27,65,.6);
}
.hero-card .thumb{
  width:132px;border-radius:var(--radius-sm);flex-shrink:0;
  /* miniatura de 132px: bajaba la foto entera de 1004px (159 KB) en la primera
     pantalla de la home. La version thumb es de 320px (23 KB). */
  background:url("/assets/tecnico-torre-thumb.jpg") center/cover;
}
.hero-card .body{padding:6px 8px 4px 0}
.hero-card .badge{
  display:inline-block;background:var(--azul-950);color:#fff;
  font-size:var(--fs-3xs);font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  padding:6px 12px;border-radius:999px;margin-bottom:10px;
}
.hero-card p{font-size:var(--fs-xs);font-weight:600;color:var(--text);line-height:1.45}
.hero-card .metric{display:flex;align-items:baseline;gap:10px;margin-top:12px;border-top:1px solid var(--border);padding-top:10px}
.hero-card .metric b{font-size:var(--fs-stat);font-weight:800;color:var(--azul);letter-spacing:-.03em}
.hero-card .metric b .sym{color:var(--naranja-texto)}
.hero-card .metric span{font-size:var(--fs-2xs);color:var(--text-muted);line-height:1.3}

/* ============================================================
   3 · QUIÉNES SOMOS — atributos propios
   ============================================================ */
.qs-head{max-width:800px}
/* Variante con CTA: la cabecera pasa a ancho completo y el boton se va a la
   derecha. Llena el vacio que quedaba al lado del lead y saca un elemento
   centrado mas de la pagina. La columna derecha lleva un elemento
   interactivo, no texto de relleno: por eso es valida. */
.qs-head.qs-head-cta{
  max-width:none;display:grid;
  grid-template-columns:minmax(0,1fr) auto;
  gap:clamp(28px,5vw,64px);align-items:end;
}
.qs-head.qs-head-cta .qs-head-txt{max-width:800px}
.qs-head.qs-head-cta .home-cta{margin-top:0;padding-bottom:4px;justify-content:flex-end}
.qs-head h2 .hl{color:var(--naranja-texto)}
.qs-head .lead{margin-top:var(--sp-5)}
/* Antes: 3x2 de celdas identicas, el MISMO componente que los pilares de
   Home. Las dos secciones se leian como la misma cosa. Ahora una grilla de
   10 columnas con anchos alternados: la fila 1 pesa a la izquierda y la 2 a
   la derecha. Siguen siendo exactamente 6 celdas para 6 items. */
.qs-grid{
  display:grid;grid-template-columns:repeat(10,minmax(0,1fr));
  gap:var(--gap-cards);margin-top:var(--rhythm);
}
.qs-card:nth-child(1),.qs-card:nth-child(6){grid-column:span 4}
.qs-card:nth-child(2),.qs-card:nth-child(3),
.qs-card:nth-child(4),.qs-card:nth-child(5){grid-column:span 3}
/* Una sola celda oscura: "Gestion" es el paraguas de los otros cinco
   ("un solo equipo responde por toda tu conectividad"), asi que se gana el
   foco. Una celda y no tres: el brief pide bajo ruido visual. */
.sec-elev .qs-card:nth-child(1){background:var(--azul-950);border-color:transparent}
.qs-card:nth-child(1) h2,.qs-card:nth-child(1) h3{color:#fff;font-size:var(--fs-xl)}
.qs-card:nth-child(1) p{color:var(--text-inv-muted);font-size:var(--fs-sm)}
.qs-card:nth-child(1) .ic{background:rgba(255,255,255,.10);border-color:var(--border-inv);color:#fff}
@media (hover:hover){.qs-card:nth-child(1):hover{box-shadow:0 24px 50px -30px rgba(6,27,65,.55)}}
.qs-card{
  background:var(--bg-elev);border:1px solid var(--border);
  border-radius:var(--radius-lg);padding:clamp(24px,2.6vw,34px);
  transition:transform var(--dur) var(--ease-out-expo),box-shadow var(--dur-hover) var(--ease-out-expo);
}
@media (hover:hover){.qs-card:hover{transform:translateY(-4px);box-shadow:0 24px 50px -30px rgba(6,27,65,.32)}}
.qs-card .ic{
  width:46px;height:46px;border-radius:var(--radius-sm);display:grid;place-items:center;
  background:#fff;border:1px solid var(--border);color:var(--azul);margin-bottom:20px;
}
.qs-card h2,.qs-card h3{font-size:var(--fs-lg);letter-spacing:-.01em}
.qs-card p{font-size:var(--fs-xs);color:var(--text-muted);line-height:1.6;margin-top:10px}

/* ============================================================
   4 · SERVICIOS — intro + gráfico
   ============================================================ */
.svc-intro h2.giant{font-size:var(--fs-giant);letter-spacing:-.03em}
.svc-intro .lead{margin-top:18px;max-width:60ch}
.svc-intro .lead .hl{color:var(--naranja-texto)}
.svc-claim{
  font-size:var(--fs-2xl);font-weight:800;letter-spacing:-.02em;line-height:1.15;
  color:var(--azul-950);margin-top:var(--rhythm-sm);max-width:20ch;
}

/* 3 pilares que reemplazan al grafico de barras */
/* Antes: 3 tarjetas identicas de 400px con un parrafo corto adentro. La caja
   no comunicaba ninguna jerarquia, solo agregaba borde y relleno, y "tres
   feature cards iguales" es de los patrones mas gastados que hay.
   Ahora: sin cajas, ancho de cada columna segun el largo real de su texto,
   escalonadas, con un filete arriba. El label sube de 12.8px versalita a
   tamano de titulo: manda la tipografia, no el contenedor.
   Los pilares NO son clickeables: no llevan transicion ni hover. */
.pilares{
  display:grid;grid-template-columns:1.15fr .82fr 1.03fr;
  gap:clamp(30px,4.5vw,68px);margin-top:var(--rhythm);
}
.pilar{border-top:2px solid var(--azul-950);padding-top:26px}
/* Asimetria controlada: cada columna baja un escalon. */
.pilar:nth-child(2){margin-top:32px}
.pilar:nth-child(3){margin-top:64px}
.pilar .ic{
  display:block;width:auto;height:auto;background:none;border:0;border-radius:0;
  color:var(--naranja-texto);margin-bottom:20px;
}
.pilar .ic svg{width:30px;height:30px;display:block}
.pilar .k{
  display:block;font-size:var(--fs-xl);font-weight:800;letter-spacing:-.02em;
  text-transform:none;color:var(--azul-950);margin:0 0 14px;line-height:1.12;
}
.pilar p{font-size:var(--fs-sm);color:var(--text-muted);line-height:1.65}

/* ============================================================
   5 · SERVICIOS — lista 01–06
   ============================================================ */
.service{padding:clamp(48px,6vw,84px) 0;border-top:1px solid var(--border)}
.service-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,5vw,72px);align-items:stretch}
.service:nth-child(even) .service-grid .service-media{order:-1}
.service-copy{display:flex;flex-direction:column}
.service-head{display:flex;justify-content:space-between;align-items:flex-start;gap:20px}
/* Los indices 01..06 llevan aria-hidden="true": son decorativos y quedan
   fuera del requisito de contraste. El tono claro es la intencion. */
.service-num{font-size:var(--fs-num);font-weight:800;color:#cbd5ec;letter-spacing:-.04em;line-height:1}
.service-copy h2,.service-copy h3{font-size:var(--fs-2xl);margin-top:10px;max-width:16ch}
.service-copy .desc{color:var(--text-muted);margin-top:16px;max-width:46ch}
.offer{margin-top:auto;padding-top:36px}
.offer h3,.offer h4{font-size:var(--fs-sm);font-weight:700;color:var(--azul-950);margin-bottom:14px}
.chips{display:flex;flex-wrap:wrap;gap:10px}
.chip{
  background:var(--bg-elev);border:1px solid var(--border);color:var(--text);
  font-size:var(--fs-2xs);font-weight:600;padding:9px 16px;border-radius:999px;
}
.service-copy .btn{margin-top:28px;align-self:flex-start}
.service-media{position:relative;min-height:440px}
.service-img{
  position:absolute;inset:0;border-radius:var(--radius-lg);
  background-size:cover;background-position:center;
  overflow:hidden;
}
.service-img::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 55%,rgba(6,27,65,.55))}
/* ============================================================
   5b · ROL TECNOLÓGICO
   ============================================================ */
.roles-panel{
  background:var(--azul-950);border-radius:var(--radius-lg);
  padding:clamp(36px,5vw,72px);
}
.roles-panel h2{max-width:18ch}
.roles-panel .lead{margin-top:16px;max-width:60ch}
.roles-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--gap-cards);margin-top:var(--rhythm)}
.rol{
  background:rgba(255,255,255,.06);border:1px solid var(--border-inv);
  border-radius:var(--radius);padding:28px 26px;
}
.rol .n{
  display:block;font-size:var(--fs-2xs);font-weight:800;letter-spacing:.14em;
  color:var(--naranja);margin-bottom:16px;
}
.rol h3{font-size:var(--fs-lg);color:#fff;letter-spacing:-.01em}
.rol p{font-size:var(--fs-xs);color:rgba(255,255,255,.72);line-height:1.6;margin-top:10px}

/* ============================================================
   6 · PROCESO — 5 fases (cards expandibles estilo Kora)
   ============================================================ */
.process-head{max-width:840px}
.process-head h2 .muted{color:#7d8ba7}
.process-cards{display:flex;gap:var(--gap-cards);margin-top:var(--rhythm);min-height:520px}
.p-card{
  border-radius:var(--radius-lg);padding:34px 30px;cursor:pointer;
  display:flex;flex-direction:column;position:relative;overflow:hidden;
  flex:1;min-width:0;
  background:var(--bg-elev);border:1px solid var(--border);
}
.p-card .p-top{display:flex;justify-content:space-between;align-items:center;gap:10px}
.p-card .p-label{font-size:var(--fs-2xs);font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted);white-space:nowrap}
.p-card .p-label .lbl{opacity:0;transition:opacity .3s ease}
.p-card .p-num{font-weight:800;font-size:var(--fs-md);color:var(--naranja-texto)}
.p-card .p-body{margin-top:auto;transition:opacity .35s ease,transform .5s var(--ease-out-expo)}
/* Colapsada, la card mostraba solo el numero arriba y ~500px de vacio. El
   titulo en vertical llena ese hueco con informacion util y es lo que invita
   a abrirla: se ve QUE hay detras de cada fase. */
.p-card h3{
  font-size:var(--fs-xl);
  writing-mode:vertical-rl;transform:rotate(180deg);
  white-space:nowrap;color:var(--azul-950);
  transition:color .45s ease;
}
.p-card p{
  font-size:var(--fs-sm);color:var(--text-muted);margin-top:12px;max-width:44ch;
  opacity:0;transform:translateY(14px);
  transition:opacity .3s ease,transform .5s var(--ease-out-expo);
}
/* Colapsado el parrafo es invisible pero SEGUIA ocupando 243-292px segun su
   largo, empujando cada titulo vertical a una altura distinta. Fuera de flujo
   los cinco apoyan en la misma linea. */
.p-card:not(.active) p{position:absolute;visibility:hidden;pointer-events:none}
.p-card.active h3{writing-mode:horizontal-tb;transform:none}
.p-card.active p{opacity:1;transform:none;transition-delay:.3s}
.p-card .p-dots{display:flex;gap:5px;opacity:0;transition:opacity .3s}
.p-card .p-dots i{width:7px;height:7px;border-radius:50%;background:rgba(255,255,255,.25)}
.p-card .p-dots i.on{background:var(--naranja)}
/* Es clickeable (role=button) y no daba ninguna señal: el cursor cambiaba
   pero la superficie no. Feedback de hover + presion, ambos rapidos. */
@media (hover:hover){.p-card:not(.active):hover{background:var(--bg-hover);border-color:rgba(13,60,149,.22)}}
@media (hover:hover){.p-card:not(.active):hover h3{color:var(--azul)}}
.p-card:not(.active):active{transform:scale(.985)}
.p-card{transition:flex .65s var(--ease-out-expo),background var(--dur-hover) ease,
        border-color var(--dur-hover) ease,transform var(--dur-press) var(--ease-out-expo)}
.p-card.active{
  flex:3.2;cursor:default;
  background:var(--azul-950);border-color:var(--azul-950);
}
.p-card.active .p-label{color:rgba(255,255,255,.6)}
.p-card.active .p-label .lbl{opacity:1}
.p-card.active .p-num{color:var(--naranja-texto)}
.p-card.active .p-dots{opacity:1}
.p-card.active h3{color:#fff}
.p-card.active p{color:rgba(255,255,255,.75)}

/* ============================================================
   7 · MAPA — dónde operamos
   ============================================================ */
/* El mapa era una tarjeta oscura dentro de .wrap, con bandas blancas a los
   lados. Ahora la banda es la SECCION (de borde a borde, como Sectores o
   Casos) y el panel es solo la grilla del contenido. */
.mapa{background:var(--azul-950)}
.mapa-panel{
  display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);
  gap:clamp(32px,5vw,80px);align-items:center;
}
.mapa-fig{position:relative;display:flex;justify-content:center}
.mapa-svg{width:100%;max-width:420px;height:auto;overflow:visible}

/* ---------- Mapa: animación ----------
   Tres capas, en este orden:
   1. el contorno del pais se dibuja solo (pathLength="1" normaliza el largo
      del trazo a 1, asi el dibujado se anima en CSS sin medirlo con JS)
   2. los 9 nodos entran en cascada
   3. la malla aparece y las lineas quedan "fluyendo": el guion marcha a lo
      largo de cada linea, que es lo que hace que la red se lea transmitiendo
      y no como un dibujo quieto.
   Todo arranca cuando la seccion entra en pantalla (.reveal -> .in), no antes.
   ------------------------------------- */
.mp-pais{
  fill:rgba(255,255,255,.07);stroke:rgba(255,255,255,.28);
  stroke-width:1.6;stroke-linejoin:round;
  stroke-dasharray:1;stroke-dashoffset:1;fill-opacity:0;
}
.mapa-panel.in .mp-pais{
  animation:mpTrazo 1.9s var(--ease-out-expo) forwards,
            mpRelleno .9s ease .95s forwards;
}
@keyframes mpTrazo{to{stroke-dashoffset:0}}
@keyframes mpRelleno{to{fill-opacity:1}}

.mp-red{opacity:0}
.mapa-panel.in .mp-red{animation:mpAparece .9s ease 1.25s forwards}
@keyframes mpAparece{to{opacity:1}}
.mp-red line{stroke:rgba(46,204,113,.32);stroke-width:1.2;stroke-dasharray:4 5}
/* el guion marcha 9px = el largo del patron (4+5), asi el loop es continuo */
/* Los dos loops infinitos corren SOLO con la seccion en pantalla: stroke-dashoffset
   no se compone en GPU, repinta. 11 lineas + 9 halos animando para siempre en
   segundo plano es bateria regalada. */
.mapa-panel.in.mapa-vivo .mp-red line{animation:mpFlujo 1.6s linear infinite 1.25s}
@keyframes mpFlujo{to{stroke-dashoffset:-9}}

.mp-nodo{
  cursor:pointer;outline:none;
  opacity:0;transform-box:fill-box;transform-origin:center;transform:scale(.3);
}
.mapa-panel.in .mp-nodo{
  animation:mpNodo .55s var(--ease-out-expo) forwards;
  animation-delay:calc(.9s + var(--i,0) * .09s);
}
@keyframes mpNodo{to{opacity:1;transform:scale(1)}}

.mp-nodo .hit{fill:transparent}
.mp-nodo .dot{fill:#2ecc71;transition:r var(--dur) var(--ease-out-expo)}
.mp-nodo .halo{fill:#2ecc71;opacity:0;transform-box:fill-box;transform-origin:center}
.mapa-panel.in .mp-nodo .halo{opacity:.16}
.mapa-panel.in.mapa-vivo .mp-nodo .halo{
  opacity:0;
  animation:mpPulso 3s ease-out infinite;
  animation-delay:calc(1.5s + var(--i,0) * .33s);
}
@keyframes mpPulso{0%{transform:scale(.45);opacity:.32}70%{transform:scale(1);opacity:0}100%{opacity:0}}
.mp-nodo:focus-visible .dot{r:10}
@media (hover:hover){.mp-nodo:hover .dot{r:10}}
.mp-nodo:focus-visible .hit{stroke:var(--naranja);stroke-width:2.5;fill:rgba(255,78,60,.12)}
.mp-nodo.is-on .dot{r:10}

/* Cartel de estado: el cliente pidio que al posicionarse salga "red operativa,
   disponibilidad de red y guardia activa" */
.mapa-tip{
  position:absolute;z-index:3;pointer-events:none;
  background:#fff;color:var(--text);border-radius:var(--radius-sm);
  padding:12px 14px;min-width:186px;
  box-shadow:0 22px 44px -18px rgba(0,0,0,.55);
  transform:translate(-50%,-118%);
  /* El origen abajo al centro apunta al nodo del que sale. */
  transform-origin:50% 100%;
}
/* Aparecia de golpe: usa el atributo [hidden], que es display:none y no se
   puede transicionar. Con una animacion sobre :not([hidden]) entra creciendo
   desde el nodo. 180ms: un tooltip que tarda mas se siente pegajoso. La
   salida es instantanea, que es lo normal en un tooltip de hover. */
.mapa-tip:not([hidden]){animation:tipEntra var(--dur-hover) var(--ease-out-expo)}
@keyframes tipEntra{from{opacity:0;transform:translate(-50%,-108%) scale(.96)}}
.mapa-tip b{display:block;font-size:var(--fs-xs);color:var(--azul-950);margin-bottom:6px}
.mapa-tip span{display:flex;align-items:center;gap:7px;font-size:var(--fs-3xs);color:var(--text-muted);line-height:1.7}
.mapa-tip i.ok{width:6px;height:6px;border-radius:50%;background:#2ecc71;flex-shrink:0}
.mapa-tip::after{
  content:"";position:absolute;left:50%;bottom:-6px;width:12px;height:12px;
  background:#fff;transform:translateX(-50%) rotate(45deg);
}

.mapa-copy h2{max-width:15ch}
.mapa-copy .lead{margin-top:16px;max-width:52ch}
.mapa-legend{list-style:none;display:flex;flex-wrap:wrap;gap:10px 24px;margin-top:26px}
.mapa-legend li{display:flex;align-items:center;gap:9px;font-size:var(--fs-2xs);color:rgba(255,255,255,.75)}
.mapa-legend i{width:9px;height:9px;border-radius:50%;flex-shrink:0}
.mapa-legend i.on{background:#2ecc71;box-shadow:0 0 0 4px rgba(46,204,113,.18)}
.mapa-legend i.off{background:rgba(255,255,255,.28)}

.mapa-datos{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--gap-cards);margin-top:var(--rhythm-sm)}
.mapa-datos b{display:block;font-size:var(--fs-stat);font-weight:800;color:#fff;letter-spacing:-.02em;white-space:nowrap}
.mapa-datos b .sym{color:var(--naranja);font-size:.55em}
.mapa-datos>div>span{display:block;font-size:var(--fs-3xs);color:rgba(255,255,255,.6);margin-top:5px;line-height:1.4}
.mapa-datos b .sym{display:inline}
.mapa-hint{font-size:var(--fs-3xs);color:rgba(255,255,255,.5);margin-top:22px}
.mapa-copy .btn{margin-top:14px}

/* ============================================================
   8 · OPERACIÓN — 3 pilares
   ============================================================ */
.oper h2{max-width:20ch}
.oper h2 .muted{color:#7d8ba7}
.oper-band{
  margin-top:var(--rhythm);background:var(--azul-950);border-radius:var(--radius-lg);
  padding:clamp(36px,5vw,64px);
  display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(28px,4vw,56px);
}
.oper-item .ic{width:44px;height:44px;border-radius:var(--radius-sm);background:rgba(255,255,255,.08);display:grid;place-items:center;color:var(--naranja);margin-bottom:20px}
.oper-item p{font-size:var(--fs-sm);color:rgba(255,255,255,.72);line-height:1.6}
.oper-item p b{color:#fff;display:block;margin-bottom:6px;font-size:var(--fs-md)}

/* ============================================================
   9 · SECTORES (grilla estilo team de Kora)
   ============================================================ */
.sectores{background:var(--azul);margin:0;padding:var(--section-y) 0}
.sectores .logo-chip{margin-bottom:28px}
.sectores h2{color:#fff;max-width:16ch}
.sectores h2 .dim{color:rgba(255,255,255,.55)}

/* Ilustracion "sitios dificiles, conectados" (solo home). El estado POR DEFECTO
   es el dibujo terminado: sin JS o con reduced-motion se ve completo y quieto.
   La coreografia solo corre cuando app.js le pone .armada (y .in al entrar). */
.sect-intro{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:clamp(32px,5vw,72px);align-items:center}
.sect-ilu{width:100%;max-width:520px;justify-self:end}
.sect-ilu svg{display:block;width:100%;height:auto;overflow:visible}
.ilu-pts{opacity:.13}
.ilu-ridge{stroke:rgba(255,255,255,.22);stroke-width:1.4}
.ilu-link{stroke:rgba(255,255,255,.38);stroke-width:1.4}
.ilu-link-sat{stroke-dasharray:.03 .025}
.ilu-sitio{stroke:rgba(255,255,255,.9);stroke-width:1.3;transform-box:fill-box;transform-origin:50% 100%}
.ilu-humo,.ilu-ondas{stroke:rgba(255,255,255,.45)}
.ilu-aspas{transform-box:fill-box;transform-origin:50% 66.7%}
.ilu-dot{fill:var(--naranja);stroke:var(--naranja);stroke-width:1.6;transform-box:fill-box;transform-origin:center}
.ilu-hub-base{fill:var(--azul-950);stroke:#fff;stroke-width:1.6}
.ilu-hub-core{fill:var(--naranja)}
.ilu-hub-onda{fill:none;stroke:var(--naranja);stroke-width:1.4;opacity:0;transform-box:fill-box;transform-origin:center}
.ilu-flujo{stroke:var(--naranja);stroke-width:3;stroke-dasharray:.09 1.2;stroke-dashoffset:.09;opacity:0}

/* Entrada: los sitios aparecen, las lineas salen del nodo y cada sitio se
   "enciende" cuando la linea llega. */
.sect-ilu.armada .ilu-sitio{opacity:0}
.sect-ilu.armada .ilu-link{stroke-dasharray:1;stroke-dashoffset:1}
.sect-ilu.armada .ilu-link-sat{stroke-dasharray:1;stroke-dashoffset:1}
.sect-ilu.armada .ilu-dot{fill:var(--azul);stroke:#fff}
.sect-ilu.armada .ilu-hub{opacity:0}
.sect-ilu.armada.in .ilu-hub{animation:iluFade var(--dur-panel) var(--ease-out-expo) forwards}
.sect-ilu.armada.in .ilu-sitio{animation:iluSitio var(--dur-reveal) var(--ease-out-expo) var(--d) forwards}
.sect-ilu.armada.in .ilu-link{animation:iluTrazo .8s var(--ease-out-expo) var(--d) forwards}
.sect-ilu.armada.in .ilu-link-sat{animation:iluTrazo .7s var(--ease-out-expo) var(--d) forwards,iluSat 0s linear calc(var(--d) + .7s) forwards}
.sect-ilu.armada.in .ilu-dot{animation:iluDot var(--dur-panel) var(--ease-out-expo) var(--d) forwards}
@keyframes iluFade{to{opacity:1}}
@keyframes iluSitio{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@keyframes iluTrazo{to{stroke-dashoffset:0}}
@keyframes iluSat{to{stroke-dasharray:.03 .025;stroke-dashoffset:0}}
@keyframes iluDot{
  0%{fill:var(--azul);stroke:#fff;transform:scale(1)}
  40%{fill:var(--naranja);stroke:var(--naranja);transform:scale(1.7)}
  100%{fill:var(--naranja);stroke:var(--naranja);transform:scale(1)}
}

/* Vida en reposo: datos viajando por las lineas, el nodo latiendo y las aspas
   girando. Solo con .vivo (seccion en pantalla); fuera de pantalla se pausa. */
.sect-ilu.armada.in .ilu-flujo{animation:iluFlujo 2.6s linear var(--f) infinite paused}
.sect-ilu.armada.in .ilu-hub-onda{animation:iluOnda 2.8s var(--ease-out-expo) 2.4s infinite paused}
.sect-ilu.armada.in .ilu-hub-onda2{animation-delay:3.8s}
.sect-ilu.armada.in .ilu-aspas{animation:iluGiro 7s linear 1s infinite paused}
.sect-ilu.armada.in.vivo .ilu-flujo,.sect-ilu.armada.in.vivo .ilu-hub-onda,.sect-ilu.armada.in.vivo .ilu-aspas{animation-play-state:running}
@keyframes iluFlujo{0%{stroke-dashoffset:.09;opacity:1}90%{opacity:1}100%{stroke-dashoffset:-1;opacity:0}}
@keyframes iluOnda{from{opacity:.55;transform:scale(1)}to{opacity:0;transform:scale(2.6)}}
@keyframes iluGiro{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){
  .sect-ilu .ilu-flujo,.sect-ilu .ilu-hub-onda{display:none}
  .sect-ilu .ilu-aspas{animation:none!important}
}
@media (max-width:900px){
  .sect-intro{grid-template-columns:minmax(0,1fr)}
  .sect-ilu{justify-self:start;max-width:440px}
}
.sect-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 56px;margin-top:var(--rhythm)}
.sect-row{
  display:flex;align-items:center;gap:20px;padding:26px 18px;
  border-bottom:1px solid rgba(255,255,255,.18);border-radius:var(--radius-sm);
  transition:background var(--dur-hover) var(--ease-out-expo),transform var(--dur) var(--ease-out-expo);
}
@media (hover:hover){.sect-row:hover{background:rgba(255,255,255,.07);transform:translateY(-4px)}}
.sect-row .ic{
  width:58px;height:58px;border-radius:50%;flex-shrink:0;
  background:rgba(255,255,255,.1);color:#fff;display:grid;place-items:center;
}
.sect-row .tx b{display:block;font-size:var(--fs-lg);font-weight:800;color:#fff;letter-spacing:-.01em}
.sect-row .tx span{font-size:var(--fs-xs);color:rgba(255,255,255,.7);line-height:1.45;display:block;margin-top:4px}
.sect-row .idx{margin-left:auto;color:rgba(255,255,255,.62);font-weight:700;font-size:var(--fs-xs)}
.sect-cta{
  margin-top:var(--rhythm);display:flex;align-items:center;justify-content:space-between;gap:28px;
  background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.15);
  border-radius:var(--radius);padding:clamp(24px,3vw,40px);flex-wrap:wrap;
}
.sect-cta h3{color:#fff;font-size:var(--fs-xl)}
.sect-cta p{color:rgba(255,255,255,.7);font-size:var(--fs-sm);margin-top:6px}

/* ============================================================
   9b · CLIENTES (muro de logos: corporativos + ISP)
   ============================================================ */
.clientes{background:var(--bg-elev)}
.cli-head{display:flex;justify-content:space-between;align-items:flex-end;gap:var(--sp-7);flex-wrap:wrap}
/* Iba con text-align:right: texto corrido en bandera izquierda, mas dificil de
   leer y ademas inconsistente con el bloque equivalente de Novedades, que va
   alineado a la izquierda en la misma posicion. */
.cli-note{font-size:var(--fs-xs);line-height:1.6;color:var(--text-muted);font-weight:600;max-width:34ch;padding-bottom:6px}

.cli-group{margin-top:var(--rhythm)}
.cli-group + .cli-group{
  margin-top:44px;padding-top:44px;border-top:1px solid var(--border);
}
.cli-label{
  display:flex;align-items:center;gap:12px;
  font-size:var(--fs-3xs);font-weight:800;letter-spacing:.16em;text-transform:uppercase;
  color:var(--azul);margin-bottom:30px;
}
.cli-label .n{
  font-size:var(--fs-3xs);font-weight:700;letter-spacing:.06em;
  color:var(--text-muted);background:var(--blanco);
  border:1px solid var(--border);border-radius:999px;padding:4px 10px;
}
.cli-label::after{content:"";flex:1;height:1px;background:var(--border)}
/* El grupo ISP tiene 3 logos: en la grilla de 5 quedaban a la izquierda con
   dos columnas vacias y leia como si faltara algo. Debajo de 400px las 3
   columnas no dan el ancho del logo mas grande, asi que ahi vuelve a 2. */
@media (min-width:401px){
  .cli-group:last-child .cli-row{grid-template-columns:repeat(3,minmax(0,1fr))}
}

.cli-row{
  list-style:none;
  display:grid;grid-template-columns:repeat(5,1fr);
  gap:clamp(30px,3.6vw,52px) clamp(24px,3vw,44px);
  align-items:center;justify-items:center;
}
.cli{
  position:relative;flex:0 0 auto;
  height:calc(var(--h,34px) * var(--k,1));
  width:calc(var(--h,34px) * var(--k,1) * var(--r));
  color:var(--azul-950);
  transition:color var(--dur-hover) var(--ease-out-expo);
}
/* Capa monocroma: usa el canal alfa del logo como máscara y lo pinta con currentColor */
.cli::before{
  content:"";position:absolute;inset:0;
  background:currentColor;opacity:.72;
  -webkit-mask:var(--m) center/contain no-repeat;
          mask:var(--m) center/contain no-repeat;
  transition:opacity var(--dur-hover) var(--ease-out-expo);
}
.cli img{
  width:100%;height:100%;object-fit:contain;
  opacity:0;transition:opacity var(--dur-hover) var(--ease-out-expo);
}
@media (hover:hover){.cli:hover::before{opacity:0}}
@media (hover:hover){.cli:hover img{opacity:1}}
@media (hover:none){
  /* en tactil la capa mono no se ve nunca: sin mask no descarga sus 13 PNG (~260 KB) */
  .cli::before{opacity:0;-webkit-mask:none;mask:none}
  .cli img{opacity:1}
}


/* ============================================================
   10 · TESTIMONIOS
   ============================================================ */
.testi-head{display:flex;justify-content:space-between;align-items:flex-end;gap:28px;flex-wrap:wrap}
.rating{display:flex;align-items:center;gap:12px;font-size:var(--fs-xs);color:var(--text-muted);font-weight:600}
.rating .stars{color:var(--naranja-texto);letter-spacing:.18em}
.testi-grid{display:grid;grid-template-columns:1.6fr 1fr 1fr;gap:var(--gap-cards);margin-top:var(--rhythm)}
.testi-card{
  background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius-lg);
  padding:clamp(24px,3vw,40px);display:flex;flex-direction:column;
  transition:transform var(--dur) var(--ease-out-expo),box-shadow var(--dur-hover) var(--ease-out-expo);
}
@media (hover:hover){.testi-card:hover{transform:translateY(-6px);box-shadow:0 26px 60px -30px rgba(6,27,65,.35)}}
.testi-card .stars{color:var(--naranja-texto);letter-spacing:.2em;font-size:var(--fs-xs);margin-bottom:20px}
.testi-card blockquote{font-size:var(--fs-md);font-weight:600;line-height:1.6;color:var(--text)}
.testi-card.big blockquote{font-size:var(--fs-lg);letter-spacing:-.01em}
.testi-card .who{display:flex;align-items:center;gap:14px;margin-top:auto;padding-top:32px}
.testi-card .who .av{width:44px;height:44px;border-radius:50%;flex-shrink:0;background:var(--azul);color:#fff;font-weight:800;font-size:var(--fs-xs);display:grid;place-items:center}
.testi-card .who .av.or{background:var(--naranja-fill)}
.testi-card .who b{display:block;font-size:var(--fs-xs);color:var(--text)}
.testi-card .who span{font-size:var(--fs-2xs);color:var(--text-muted)}

/* Bloque de comentarios al pie del caso destacado. Sin esto el h3 quedaba
   pegado a las cifras y se leia como parte de esa card. */
.testi-mas{margin-top:var(--rhythm);padding-top:var(--rhythm-sm);border-top:1px solid var(--border)}
.testi-mas>h3{
  font-size:var(--fs-2xs);font-weight:800;letter-spacing:.16em;text-transform:uppercase;
  color:var(--azul);margin-bottom:var(--sp-6);
  display:flex;align-items:center;gap:14px;
}
.testi-mas>h3::after{content:"";flex:1;height:1px;background:var(--border)}
.testi-mas .testi-grid{margin-top:0}

/* ============================================================
   11 · STATS + GRUPO
   ============================================================ */
.stats-grid{display:grid;grid-template-columns:repeat(4,1fr);border-top:1px solid var(--border)}
.stat{padding:clamp(28px,3.6vw,56px) clamp(16px,2vw,32px);border-right:1px solid var(--border)}
.stat:last-child{border-right:none}
.stat .num{font-size:var(--fs-num);font-weight:800;letter-spacing:-.03em;color:var(--azul-950);line-height:1;font-variant-numeric:tabular-nums}
.stat .num .sym{color:var(--naranja-texto);font-size:.6em;font-weight:800;margin-left:2px}
.stat p{font-size:var(--fs-xs);color:var(--text-muted);margin-top:14px;max-width:22ch}
.grupo{
  margin-top:80px;background:var(--bg-elev);border-radius:var(--radius-lg);
  padding:clamp(32px,5vw,64px);
  display:grid;grid-template-columns:1.1fr .9fr;gap:clamp(28px,5vw,64px);align-items:center;
}
.grupo-img{border-radius:var(--radius);aspect-ratio:4/3;background:url("/assets/equipo-oficina.jpg") center/cover}
.grupo h3{font-size:var(--fs-2xl);max-width:16ch}
.grupo p{color:var(--text-muted);margin-top:16px;max-width:46ch}
.grupo-marcas{display:flex;gap:14px;margin-top:26px;flex-wrap:wrap}
.marca-pill{border:1px solid var(--border);border-radius:999px;padding:10px 20px;font-weight:700;font-size:var(--fs-xs);color:var(--azul)}
.marca-pill small{display:block;font-weight:500;color:var(--text-muted);font-size:var(--fs-3xs)}
.marca-pill.is-velnet{border-color:var(--naranja);color:var(--naranja-texto)}
.grupo .btn{margin-top:30px}

/* ============================================================
   12 · CASO DESTACADO
   ============================================================ */
.caso{background:var(--bg-elev);margin:0;padding:var(--section-y) 0}
/* El primer bloque de cada pagina interna usaba --section-y (80-92px en movil)
   y el contenido quedaba pegado o TAPADO (-4 a 3px) bajo la pastilla fija del
   nav, que llega a 84px. La home no entra: su hero tiene layout propio. */
main>.sec-banda:first-child,main>.caso:first-child,main>.err404:first-child{padding-top:max(var(--section-y),var(--nav-clear))}
main>.contacto:first-child .contacto-bleed{padding-top:max(var(--section-y),var(--nav-clear))}
.caso-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:var(--gap-cards);margin-top:var(--rhythm)}
.caso-card{background:#fff;border:1px solid var(--border);border-radius:var(--radius-lg);padding:clamp(26px,3.4vw,48px)}
.caso-date{font-size:var(--fs-2xs);font-weight:700;color:var(--text-muted);letter-spacing:.08em;text-transform:uppercase}
.caso-card h2{font-size:var(--fs-2xl);margin-top:14px;max-width:20ch}
.caso-meta{display:grid;gap:14px;margin-top:var(--rhythm-sm)}
.caso-meta .row{display:flex;justify-content:space-between;gap:18px;font-size:var(--fs-xs);border-bottom:1px dashed var(--border);padding-bottom:12px}
.caso-meta .row .k{display:flex;align-items:center;gap:8px;color:var(--text-muted);font-weight:600}
.caso-meta .row .v{font-weight:700;color:var(--text)}
.caso-nums{display:grid;grid-template-columns:1fr 1fr;gap:var(--gap-cards);margin-top:var(--gap-cards)}
.caso-num{background:#fff;border:1px solid var(--border);border-radius:var(--radius);padding:clamp(22px,2.6vw,36px)}
.caso-num .num{font-size:var(--fs-num);font-weight:800;color:var(--azul-950);letter-spacing:-.03em;line-height:1}
.caso-num .num .sym{color:var(--naranja-texto);font-size:.55em}
.caso-num p{font-size:var(--fs-xs);color:var(--text-muted);margin-top:10px}
.caso-right{display:flex;flex-direction:column;gap:var(--gap-cards)}
/* Tenia una cita que era el MISMO testimonio del "Gerente de Operaciones"
   que aparece completo 700px mas abajo, misma atribucion. Sacada la cita,
   el bloque quedo solo con los chips: tres chips no necesitan una caja con
   borde y 26px de padding. Sin caja, y los chips un punto mas grandes.
   Las reglas de .caso-quote p / .who / .av quedaron muertas y se van. */
.caso-quote{display:flex;flex-wrap:wrap;gap:8px;padding-bottom:2px}
.caso-quote .tags{display:flex;flex-wrap:wrap;gap:8px}
.caso-quote .tags .chip{font-size:var(--fs-2xs);padding:8px 15px}
.caso-img{flex:1;min-height:280px;border-radius:var(--radius);background:linear-gradient(180deg,transparent 40%,rgba(6,27,65,.5)),url("/assets/datacenter.jpg") 78% center/128%}
.caso-btn{width:100%;justify-content:center}

/* ============================================================
   13 · NIVELES DE SERVICIO (pricing)
   ============================================================ */
.planes-head{text-align:center;max-width:720px;margin-inline:auto}
.planes-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--gap-cards);margin-top:var(--rhythm);align-items:stretch}
.plan{
  border:1px solid var(--border);border-radius:var(--radius-lg);padding:clamp(26px,2.8vw,40px);
  display:flex;flex-direction:column;background:#fff;position:relative;
  transition:transform var(--dur) var(--ease-out-expo),box-shadow var(--dur-hover) var(--ease-out-expo);
}
@media (hover:hover){.plan:hover{transform:translateY(-6px);box-shadow:0 30px 60px -32px rgba(6,27,65,.35)}}
.plan .p-name{font-size:var(--fs-lg);font-weight:800;color:var(--azul-950)}
.plan .p-for{font-size:var(--fs-xs);color:var(--text-muted);margin-top:8px;min-height:44px}
.plan .p-price{font-size:var(--fs-md);font-weight:800;color:var(--azul);margin-top:22px}
.plan .p-price small{display:block;font-weight:500;color:var(--text-muted);font-size:var(--fs-2xs);margin-top:2px}
.plan ul{list-style:none;margin-top:26px;display:grid;gap:12px}
.plan li{display:flex;gap:10px;font-size:var(--fs-xs);font-weight:500;color:var(--text)}
.plan li .ck{flex-shrink:0;width:20px;height:20px;border-radius:50%;background:var(--bg-elev);color:var(--azul);display:grid;place-items:center;margin-top:1px}
/* margin-top estaba declarado dos veces: el "auto" que empuja el boton al pie
   de la card lo pisaba un "32px" posterior, y los tres botones quedaban a
   alturas distintas segun cuantos items tuviera cada plan. */
.plan .btn{margin-top:auto;padding-top:16px;justify-content:center}
.plan ul{margin-bottom:32px}
.plan.popular{background:var(--azul-950);border-color:var(--azul-950);transform:scale(1.03)}
@media (hover:hover){.plan.popular:hover{transform:scale(1.03) translateY(-6px)}}
.plan.popular .p-name,.plan.popular li{color:#fff}
.plan.popular .p-for{color:rgba(255,255,255,.7)}
.plan.popular .p-price{color:#fff}
.plan.popular .p-price small{color:rgba(255,255,255,.6)}
.plan.popular li .ck{background:rgba(255,255,255,.12);color:var(--naranja)}
.plan .pop-badge{
  position:absolute;top:-14px;left:50%;transform:translateX(-50%);
  background:var(--naranja-fill);color:#fff;font-size:var(--fs-3xs);font-weight:800;letter-spacing:.08em;
  text-transform:uppercase;padding:7px 16px;border-radius:999px;white-space:nowrap;
}
.planes-foot{display:flex;align-items:center;justify-content:center;gap:14px;margin-top:var(--rhythm-sm);color:var(--text-muted);font-size:var(--fs-xs);flex-wrap:wrap;text-align:center}
.planes-foot .av{width:40px;height:40px;border-radius:50%;background:var(--azul);color:#fff;font-weight:800;font-size:var(--fs-2xs);display:grid;place-items:center}

/* ============================================================
   14 · FAQ
   ============================================================ */
.faq h2.giant{font-size:var(--fs-giant);text-align:center;letter-spacing:-.03em}
.faq-box{max-width:780px;margin:var(--rhythm) auto 0;background:var(--bg-elev);border-radius:var(--radius-lg);padding:clamp(18px,2.6vw,32px)}
.faq-tabs{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin-bottom:22px}
.faq-tab{
  border-radius:999px;padding:0 20px;min-height:44px;display:inline-flex;align-items:center;
  font-size:var(--fs-xs);font-weight:700;color:var(--text-muted);
  transition:background var(--dur-hover),color var(--dur-hover),scale var(--dur-press) var(--ease-out-expo);
}
.faq-tab:active{scale:.96}
.faq-tab.active{background:var(--azul);color:#fff}
@media (hover:hover){.faq-tab:not(.active):hover{background:var(--bg-hover)}}
.faq-list{display:grid;gap:12px}
.faq-item{background:#fff;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
.faq-q{
  width:100%;display:flex;justify-content:space-between;align-items:center;gap:18px;
  padding:20px 24px;font-size:var(--fs-md);font-weight:700;color:var(--azul-950);text-align:left;
  transition:background var(--dur-hover) ease,color var(--dur-hover) ease,transform var(--dur-press) var(--ease-out-expo);
}
/* Es un <button> que abre el acordeon y no respondia al hover. */
@media (hover:hover){.faq-item:not(.open) .faq-q:hover{background:var(--bg-elev);color:var(--azul)}}
@media (hover:hover){.faq-item:not(.open) .faq-q:hover .pm{background:var(--azul);color:#fff}}
.faq-q:active{transform:scale(.995)}
.faq-q .pm{
  flex-shrink:0;width:28px;height:28px;border-radius:50%;background:var(--bg-elev);
  display:grid;place-items:center;color:var(--azul);
  transition:transform var(--dur) var(--ease-out-expo),background var(--dur-hover),color var(--dur-hover);
}
.faq-item.open .pm{transform:rotate(135deg);background:var(--naranja);color:#fff}
.faq-a{display:grid;grid-template-rows:0fr;transition:grid-template-rows .5s var(--ease-out-expo)}
.faq-item.open .faq-a{grid-template-rows:1fr}
.faq-a>div{overflow:hidden}
.faq-a p{padding:0 24px 24px;font-size:var(--fs-sm);color:var(--text-muted);line-height:1.7}
.faq-foot{display:flex;align-items:center;justify-content:center;gap:14px;margin-top:var(--sp-7);flex-wrap:wrap}
.faq-foot-q{font-size:var(--fs-xs);color:var(--text-muted)}
.faq-foot .avatars .av{width:36px;height:36px;border-width:2px}
.copy-mail{
  display:inline-flex;align-items:center;gap:10px;font-weight:700;font-size:var(--fs-sm);color:var(--azul);
  border:1.5px dashed var(--border);border-radius:999px;padding:0 22px;min-height:44px;
  max-width:100%;
  transition:border-color var(--dur-hover),background var(--dur-hover),scale var(--dur-press) var(--ease-out-expo);
}
.copy-mail:active{scale:.97}
/* En 360px el mail + el tag + 44px de padding superaban el ancho del box */
@media (max-width:420px){
  .copy-mail{padding:0 14px;gap:8px;font-size:var(--fs-xs)}
  .faq-foot{gap:10px}
}
@media (hover:hover){.copy-mail:hover{border-color:var(--azul);background:var(--bg-elev)}}

/* ============================================================
   15 · NOVEDADES
   ============================================================ */
.news-head{display:flex;justify-content:space-between;align-items:flex-end;gap:28px;flex-wrap:wrap}
.news-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--gap-cards);margin-top:var(--rhythm)}
.news-card{
  position:relative;border-radius:var(--radius-lg);overflow:hidden;aspect-ratio:4/4.6;
  display:flex;flex-direction:column;justify-content:flex-end;padding:26px;
  background-size:cover;background-position:center;
  transition:transform var(--dur) var(--ease-out-expo),box-shadow var(--dur-hover) var(--ease-out-expo),scale var(--dur-press) var(--ease-out-expo);
}
.news-card:active{scale:.985}
@media (hover:hover){.news-card:hover{transform:translateY(-6px);box-shadow:0 30px 60px -30px rgba(6,27,65,.5)}}
.news-card::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(6,27,65,.06) 30%,rgba(6,27,65,.82))}
.news-card>*{position:relative;z-index:2}
.news-card .cat{
  position:absolute;top:20px;left:20px;
  background:rgba(255,255,255,.92);color:var(--azul-950);
  font-size:var(--fs-3xs);font-weight:700;padding:8px 14px;border-radius:999px;
}
.news-card .date{font-size:var(--fs-2xs);color:rgba(255,255,255,.75);font-weight:600}
.news-card h3{color:#fff;font-size:var(--fs-lg);margin-top:8px;line-height:1.25}

/* ============================================================
   16 · CONTACTO
   ============================================================ */
.contacto{padding:0;margin:0}
.contacto-bleed{
  position:relative;overflow:hidden;
  background:linear-gradient(135deg,rgba(6,27,65,.92),rgba(13,60,149,.72)),url("/assets/red-nodos.jpg") center/cover;
  padding:var(--section-y) 0;
}
.contacto-grid{display:grid;grid-template-columns:1fr 1.05fr;gap:clamp(36px,6vw,80px);align-items:start}
/* h1 ADEMAS de h2: al pasar este titulo de h2 a h1 (arreglo de jerarquia de
   encabezados) el tamano lo seguia la regla de arriba pero el color no, y
   quedaba azul-950 sobre fondo azul oscuro. El .form-card de al lado sigue
   en oscuro porque su regla va despues en el archivo, con igual especificidad. */
.contacto h1,.contacto h2{color:#fff;font-size:var(--fs-4xl)}
.contacto .lead{color:var(--text-inv-muted);margin-top:20px}
.c-checks{list-style:none;margin-top:var(--rhythm-sm);display:grid;gap:18px}
.c-checks li{display:flex;gap:14px;color:#fff;font-weight:600;font-size:var(--fs-sm);align-items:flex-start}
.c-checks li .ic{flex-shrink:0;width:26px;height:26px;border-radius:50%;background:var(--naranja);color:#fff;display:grid;place-items:center;margin-top:1px}
/* El borde grueso de 3px a un costado es el tell mas reconocible de UI
   generada por IA (detector de Impeccable: side-tab). Se reemplaza por la
   comilla tipografica, que es lo que una cita realmente necesita. */
.c-quote{margin-top:var(--rhythm-sm);padding-left:34px;position:relative}
.c-quote::before{
  content:"\201C";position:absolute;left:0;top:-6px;
  font-size:3.2rem;line-height:1;color:var(--naranja);opacity:.85;
}
.c-quote p{color:rgba(255,255,255,.85);font-size:var(--fs-sm);font-weight:500;font-style:italic}
.c-quote span{display:block;margin-top:10px;font-size:var(--fs-2xs);color:rgba(255,255,255,.6)}
.c-stats{display:flex;gap:44px;margin-top:var(--rhythm-sm)}
.c-stats b{font-size:var(--fs-stat);font-weight:800;color:#fff;letter-spacing:-.02em;white-space:nowrap}
.c-stats b .sym{display:inline;color:var(--naranja-texto);font-size:.6em}
.c-stats span{display:block;font-size:var(--fs-2xs);color:rgba(255,255,255,.65);margin-top:4px;max-width:18ch}
.form-card{
  background:#fff;border-radius:var(--radius-lg);padding:clamp(26px,3.4vw,44px);
  box-shadow:0 40px 90px -40px rgba(0,0,0,.5);
}
.form-card .f-head{display:flex;align-items:center;gap:12px;margin-bottom:8px}
.form-card h3{font-size:var(--fs-lg)}
.form-card .f-sub{font-size:var(--fs-sm);color:var(--text-muted);margin-bottom:28px}
.form-card .f-sub b{color:var(--text)}
.f-row{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.f-field{margin-bottom:20px}
.f-field label{display:block;font-size:var(--fs-xs);font-weight:700;color:var(--azul-950);margin-bottom:8px}
.f-field input:not([type=radio]),.f-field textarea{
  width:100%;font-family:inherit;font-size:16px;color:var(--text);
  background:var(--bg-elev);border:1.5px solid transparent;border-radius:var(--radius-sm);
  padding:14px 16px;outline:none;
  transition:border-color var(--dur-hover),background var(--dur-hover),box-shadow var(--dur-hover);
}
.f-field input:not([type=radio]):focus,.f-field textarea:focus{border-color:var(--azul);background:#fff;box-shadow:0 0 0 4px rgba(13,60,149,.12)}
.f-field textarea{min-height:110px;resize:vertical}
/* Estado de error: --naranja-texto (4.99:1 sobre blanco) es de la propia
   paleta, asi que no entra un rojo nuevo. El aviso entra con fade + 4px. */
.f-field input[aria-invalid],.f-field select[aria-invalid],.f-field textarea[aria-invalid]{
  border-color:var(--naranja-texto);background:#fff;
}
.f-field input[aria-invalid]:focus,.f-field select[aria-invalid]:focus{box-shadow:0 0 0 4px rgba(207,54,38,.14)}
.f-error{
  margin-top:8px;font-size:var(--fs-2xs);font-weight:600;line-height:1.4;color:var(--naranja-texto);
  animation:errorEntra var(--dur-move) var(--ease-out-expo) both;
}
.f-error[hidden]{display:none}
@keyframes errorEntra{from{opacity:0;transform:translateY(-4px)}}
.f-chips{display:flex;flex-wrap:wrap;gap:10px}
.f-chip{
  border:1.5px solid var(--border);border-radius:999px;padding:0 18px;
  min-height:44px;display:inline-flex;align-items:center;
  font-size:var(--fs-xs);font-weight:600;color:var(--text);background:#fff;
  transition:border-color var(--dur-hover) var(--ease-out-expo),background var(--dur-hover) var(--ease-out-expo),color var(--dur-hover) var(--ease-out-expo),scale var(--dur-press) var(--ease-out-expo);
}
.f-chip:active{scale:.96}
@media (hover:hover){.f-chip:hover{border-color:var(--azul)}}
.f-chip.selected{background:var(--azul);border-color:var(--azul);color:#fff}
.f-radios{display:flex;flex-wrap:wrap;gap:10px}
label.f-radio{
  position:relative;margin:0;
  border:1.5px solid var(--border);border-radius:999px;padding:10px 18px;
  font-size:var(--fs-xs);font-weight:600;color:var(--text);background:#fff;
  display:inline-flex;align-items:center;gap:8px;cursor:pointer;
  transition:border-color var(--dur-hover) var(--ease-out-expo),background-color var(--dur-hover) var(--ease-out-expo),color var(--dur-hover) var(--ease-out-expo),scale var(--dur-press) var(--ease-out-expo);
}
label.f-radio:active{scale:.96}
.f-radio::before{
  content:"";display:block;width:8px;height:8px;border-radius:50%;flex-shrink:0;
  border:2px solid #c3ccdd;transition:all var(--dur) var(--ease-out-expo);
}
.f-radio input{position:absolute;inset:0;opacity:0;margin:0;cursor:pointer}
@media (hover:hover){.f-radio:hover{border-color:var(--azul)}}
/* .on la pone app.js: :has() no existe antes de Chrome 105 / Safari 15.4 /
   Firefox 121, y ahi la opcion elegida quedaba sin marcar a la vista. */
.f-radio.on,.f-radio:has(input:checked){background:var(--azul);border-color:var(--azul);color:#fff}
.f-radio.on::before,.f-radio:has(input:checked)::before{border-color:#fff;background:var(--naranja)}
.f-radio:has(input:focus-visible){outline:3px solid var(--naranja);outline-offset:2px}
.f-hint{font-weight:500;color:var(--text-muted)}
.f-field select{
  width:100%;font-family:inherit;font-size:16px;color:var(--text);
  background:var(--bg-elev);border:1.5px solid transparent;border-radius:var(--radius-sm);
  padding:14px 40px 14px 16px;outline:none;min-height:52px;
  appearance:none;-webkit-appearance:none;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%2355617a' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 16px center;
  transition:border-color var(--dur-hover),background-color var(--dur-hover),box-shadow var(--dur-hover);
}
.f-field select:focus{border-color:var(--azul);background-color:#fff;box-shadow:0 0 0 4px rgba(13,60,149,.12)}
.f-field select:invalid{color:var(--text-muted)}

.form-card .btn{width:100%;justify-content:center;padding:18px;font-size:var(--fs-md)}
.f-success:focus{outline:none}
.f-success{display:none;text-align:center;padding:48px 12px}
.f-success .ok{width:64px;height:64px;border-radius:50%;background:var(--azul);color:#fff;display:grid;place-items:center;margin:0 auto 20px}
.f-success h2,.f-success h3{font-size:var(--fs-xl)}
.f-success p{color:var(--text-muted);margin-top:10px}
.form-card.sent form{display:none}
.form-card.sent .f-success{display:block;animation:exitoEntra var(--dur-panel) var(--ease-out-expo) both}
/* Alguien acaba de dejar sus datos: es el momento de mayor carga emocional
   de todo el sitio y hasta ahora aparecia de golpe (display:none -> block,
   que no se puede transicionar). Es un momento RARO, una vez por persona,
   asi que aca si vale un tiempo generoso. Arranca en .98 y no en 0: nada
   crece desde la nada. */
@keyframes exitoEntra{from{opacity:0;transform:translateY(10px) scale(.98)}}
.form-card.sent .f-success .ok{animation:okAparece var(--dur-panel) var(--ease-out-expo) .09s both}
@keyframes okAparece{from{opacity:0;transform:scale(.62)}}

/* ============================================================
   WHATSAPP — el cliente pidio un acceso que acompañe todo el scroll, y
   reporto que el avatar "V" con la luz verde confundia: "lo aprete varias
   veces, da como que ahi podes chatear con alguien". Ahora efectivamente
   se puede: ese lugar es el acceso a WhatsApp.
   ============================================================ */

/* El FAB media 148x56 y tapaba entre 68 y 126px de la tarjeta del hero en
   1440, 1366, 1280 y 1024 (medido). Ahora es un circulo fijo de 56px y la
   etiqueta aparece a su izquierda al hover, animando SOLO transform y
   opacity: la huella del boton ya no cambia nunca. El nombre accesible
   viene del aria-label del enlace, asi que ocultar .lbl no quita nada. */
.wa-fab{
  position:fixed;right:20px;bottom:20px;z-index:98;
  display:inline-flex;align-items:center;justify-content:center;
  width:56px;height:56px;padding:0;border-radius:50%;
  background:#25D366;color:#fff;font-weight:700;font-size:var(--fs-xs);
  box-shadow:0 16px 34px -12px rgba(37,211,102,.7),0 3px 10px rgba(0,0,0,.18);
  /* Arranca oculto: en el hero ya hay dos CTA y el FAB solo competia con
     ellos ademas de tapar la tarjeta. visibility (y no solo opacity) para
     que no quede en el orden de tabulacion mientras esta invisible. */
  opacity:0;visibility:hidden;transform:translateY(14px) scale(.92);
  transition:opacity var(--dur-hover) var(--ease-out-expo),
             transform var(--dur-move) var(--ease-out-expo),
             box-shadow var(--dur-hover),
             visibility 0s linear var(--dur-move);
}
.wa-fab.visible{
  opacity:1;visibility:visible;transform:none;
  transition:opacity var(--dur-hover) var(--ease-out-expo),
             transform var(--dur-move) var(--ease-out-expo),
             box-shadow var(--dur-hover),visibility 0s;
}
.wa-fab svg{width:26px;height:26px;flex-shrink:0}
.wa-fab .lbl{
  position:absolute;right:calc(100% + 12px);top:50%;
  background:#25D366;color:#fff;border-radius:999px;padding:11px 18px;
  white-space:nowrap;pointer-events:none;opacity:0;
  transform:translateY(-50%) translateX(10px);
  box-shadow:0 10px 24px -10px rgba(37,211,102,.7);
  transition:opacity var(--dur-hover) var(--ease-out-expo),transform var(--dur-move) var(--ease-out-expo);
}
@media (hover:hover){
  .wa-fab.visible:hover{transform:translateY(-3px);box-shadow:0 22px 44px -14px rgba(37,211,102,.8)}
  .wa-fab.visible:hover .lbl{opacity:1;transform:translateY(-50%) translateX(0)}
}
/* el foco por teclado no depende de que exista mouse */
.wa-fab.visible:focus-visible{transform:translateY(-3px);box-shadow:0 22px 44px -14px rgba(37,211,102,.8)}
.wa-fab.visible:focus-visible .lbl{opacity:1;transform:translateY(-50%) translateX(0)}
/* Faltaba respuesta al click en los dos unicos clickeables que quedaban sin
   ella. Van fuera del @media de hover para que el tacto tambien la reciba. */
.wa-fab.visible:active{transform:scale(.93)}
.mcar-dots button:active::before{transform:scale(.82)}
body.menu-open .wa-fab{opacity:0;pointer-events:none}

.f-wa{
  display:inline-flex;align-items:center;gap:10px;min-height:44px;
  font-weight:600;color:rgba(255,255,255,.85);transition:color var(--dur-fast);
}
@media (hover:hover){.f-wa:hover{color:#25D366}}
.f-wa .tag{
  font-size:var(--fs-3xs);font-weight:700;color:#25D366;
  border:1px solid rgba(37,211,102,.45);border-radius:999px;padding:3px 9px;
}

/* ============================================================
   17 · FOOTER
   ============================================================ */
footer{background:var(--azul-950);color:#fff;padding:clamp(64px,8vw,110px) 0 0;position:relative;overflow:hidden}
.f-top{display:grid;grid-template-columns:1.4fr 1fr 1fr 1.2fr;gap:clamp(28px,4vw,56px)}
.f-brand .claim{margin-top:var(--sp-5);font-size:var(--fs-md);font-weight:600;color:rgba(255,255,255,.85);max-width:26ch;line-height:1.5}
.f-brand .claim .accent{color:var(--naranja-texto)}
footer h2,footer h3{color:rgba(255,255,255,.5);font-size:var(--fs-2xs);font-weight:700;letter-spacing:.14em;text-transform:uppercase;margin-bottom:20px}
footer ul{list-style:none;display:grid;gap:4px}
footer ul a{display:inline-flex;align-items:center;min-height:34px;font-size:var(--fs-sm);font-weight:500;color:rgba(255,255,255,.85);transition:color var(--dur-fast)}
@media (hover:hover){footer ul a:hover{color:var(--naranja)}}
.f-contact li{display:flex;gap:10px;align-items:flex-start;color:rgba(255,255,255,.85);font-size:var(--fs-xs)}
.f-contact .ic{color:var(--naranja);flex-shrink:0;margin-top:2px}
.f-copybtn{display:inline-flex;align-items:center;min-height:34px;gap:8px;font-weight:600;color:rgba(255,255,255,.85);transition:color var(--dur-hover),scale var(--dur-press) var(--ease-out-expo)}
.f-copybtn:active{scale:.96}
@media (hover:hover){.f-copybtn:hover{color:var(--naranja)}}
.f-copybtn .cp{font-size:var(--fs-3xs);color:var(--naranja);opacity:0;transition:opacity var(--dur-hover)}
.f-copybtn.copied .cp{opacity:1}
.f-mega{
  margin-top:clamp(48px,7vw,90px);
  display:flex;justify-content:center;
  padding:0 6%;
  opacity:.07;user-select:none;pointer-events:none;
}
.f-mega img{width:min(880px,88%);height:auto}
.f-bottom{
  border-top:1px solid var(--border-inv);
  display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;
  padding:22px 0 26px;position:relative;background:var(--azul-950);
}
/* El boton flotante de WhatsApp es position:fixed y al llegar al final del
   scroll se para justo encima del pie, tapando "Parte del ecosistema...". */
.f-bottom>*:last-child{padding-right:190px}
.f-bottom p{font-size:var(--fs-2xs);color:rgba(255,255,255,.55)}

/* ============================================================
   Scroll reveal
   ============================================================ */
.reveal{opacity:0;transform:translateY(32px);transition:opacity var(--dur-slow) var(--ease-out-expo),transform var(--dur-slow) var(--ease-out-expo)}
.reveal.in{opacity:1;transform:none}
.reveal-l{opacity:0;transform:translateX(max(-30px,-3.5vw));transition:opacity var(--dur-slow) var(--ease-out-expo),transform var(--dur-slow) var(--ease-out-expo)}
.reveal-r{opacity:0;transform:translateX(min(30px,3.5vw));transition:opacity var(--dur-slow) var(--ease-out-expo),transform var(--dur-slow) var(--ease-out-expo)}
.reveal-l.in,.reveal-r.in{opacity:1;transform:none}
/* 3.5vw <= canal lateral de .wrap (4vw): un reveal sin revelar todavia no puede
   ensanchar el documento (antes, entre 641 y ~750px, +30px de la derecha
   creaban scroll horizontal hasta que el elemento entraba en pantalla). */
[data-stagger]>*{opacity:0;transform:translateY(24px);transition:opacity .65s var(--ease-out-expo),transform .65s var(--ease-out-expo)}
[data-stagger].in>*{opacity:1;transform:none}
/* Primera pantalla de las paginas internas: VISIBLE desde el primer dibujado.
   Arrancar en opacity:0 dejaba la pantalla vacia hasta que llegaba app.js
   (~2 s en gama baja) y Chrome recien contaba el contenido al terminar el
   fundido (~950 ms en gama alta; 220 ms sin el). Queda un deslizamiento corto
   solo de transform, por CSS: no espera al JS ni oculta el texto. */
main>:first-child :is(.reveal,.reveal-l,.reveal-r),main>:first-child [data-stagger]>*{
  opacity:1;transform:none;transition:none;animation:primeraPantalla var(--dur-reveal) var(--ease-out-expo) backwards
}
@keyframes primeraPantalla{from{transform:translateY(14px)}}

/* Hero entrada en cascada */
.hero-anim{opacity:0;transform:translateY(28px);animation:heroIn .9s var(--ease-out-expo) forwards}
@keyframes heroIn{to{opacity:1;transform:none}}
.hero-card.hero-anim{animation-name:heroCard}
@keyframes heroCard{0%{opacity:0;transform:translateY(40px) scale(.96)}70%{transform:translateY(-4px) scale(1.005)}100%{opacity:1;transform:none}}

/* CORTE DE HERENCIA: una seccion .on-dark pinta sus titulos de blanco, pero
   adentro puede haber superficies CLARAS (la tarjeta del formulario, la del
   hero, el cartel del mapa). Ahi el blanco desaparece. Bug real encontrado en
   la pantalla de "¡Gracias!" del formulario, invisible hasta que se envia. */
.form-card h1,.form-card h2,.form-card h3,
.hero-card h1,.hero-card h2,.hero-card h3,
.mapa-tip b,
.caso-card h1,.caso-card h2,.caso-card h3,
.caso-quote h1,.caso-quote h2,.caso-quote h3{color:var(--azul-950)}
/* Va al final a proposito: compite con .contacto h2 / .on-dark h2, que tienen
   la MISMA especificidad. En ese empate gana la ultima regla del archivo. */

/* ---------- Continuidad entre paginas ----------
   El sitio es multipagina: cada navegacion era un parpadeo en blanco. Un fade
   corto de entrada da continuidad sin retrasar nada — 220ms es imperceptible
   como espera y suficiente para que el corte no se lea como salto.
   No hay fade de SALIDA a proposito: retrasar la navegacion tras un click es
   penalizar la accion del usuario. */
@view-transition{navigation:auto}
::view-transition-old(root){animation:none}
::view-transition-new(root){animation:vtEntra .22s var(--ease-out-expo)}
@keyframes vtEntra{from{opacity:0;transform:translateY(6px)}}
/* Respaldo para navegadores sin View Transitions */
html:not(.vt) body{animation:paginaEntra .22s var(--ease-out-expo) both}
@keyframes paginaEntra{from{opacity:0}}

/* ============================================================
   Responsive
   ============================================================ */
@media (min-width:1600px){
  :root{--container:1400px}
}
@media (max-width:1024px){
  .nav-links{display:none}
  .hamburger{display:flex}
  .nav-cta .btn{display:none}
  .caso-grid,.contacto-grid,.grupo{grid-template-columns:1fr}
  .qs-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .qs-card:nth-child(1),.qs-card:nth-child(2),.qs-card:nth-child(3),
  .qs-card:nth-child(4),.qs-card:nth-child(5),.qs-card:nth-child(6){grid-column:span 1}
  .roles-grid{grid-template-columns:1fr}
  /* Sin cajas los pilares necesitan menos ancho: aguantan 3 columnas hasta
     860px. El escalonado se apaga porque en columna angosta desalinea. */
  .pilares{grid-template-columns:1fr 1fr 1fr;gap:clamp(24px,3vw,40px)}
  .pilar:nth-child(2),.pilar:nth-child(3){margin-top:0}
  .qs-head.qs-head-cta{grid-template-columns:1fr;align-items:start}
  .qs-head.qs-head-cta .home-cta{justify-content:flex-start;padding-bottom:0}
  .service-grid{grid-template-columns:1fr}
  .service:nth-child(even) .service-grid .service-media{order:0}
  .service-media{min-height:380px}
  .testi-grid{grid-template-columns:1fr 1fr}
  .testi-card.big{grid-column:1/-1}
  .plan.popular{transform:none}
  @media (hover:hover){.plan.popular:hover{transform:translateY(-6px)}}
  .stats-grid{grid-template-columns:1fr 1fr}
  .stat:nth-child(2){border-right:none}
  .stat:nth-child(1),.stat:nth-child(2){border-bottom:1px solid var(--border)}
  .news-grid{grid-template-columns:1fr 1fr}
  .news-card:last-child{grid-column:1/-1;aspect-ratio:16/9}
  .sect-grid{grid-template-columns:1fr}
  .cli-row{--k:.8}
  .cli-note{text-align:left}
  .mapa-panel{grid-template-columns:1fr;gap:36px}
  .mapa-svg{max-width:320px}
  .oper-band{grid-template-columns:1fr}
  .f-top{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* con 4 hijos en 2 columnas, la marca quedaba al lado de "Navegacion" y dejaba
     ~200px de hueco vacio debajo; marca y contacto ocupan la fila entera */
  .f-brand,.f-col-contacto{grid-column:1/-1}
  .only-wide{display:none}
}
@media (min-width:1025px){
  .only-narrow{display:none}
}
@media (max-width:860px){
  .pilares{grid-template-columns:1fr;gap:34px}
}
@media (max-width:820px){
  .cli-row{grid-template-columns:repeat(2,1fr)}
}

/* ============================================================
   CARRUSEL MOBILE (.mcar / .mcar-sm)
   En pantallas angostas apilar cards verticalmente multiplica el scroll sin
   aportar nada: cada card es una unidad independiente y comparable. Se pasan
   a scroll horizontal con snap, sangrado a los bordes de la pantalla y la
   card siguiente asomando, que es la unica senal de "hay mas" que no miente.
   .mcar  -> desde 1024px (proceso y planes: insostenibles ya en tablet)
   .mcar-sm -> desde 640px (en tablet la grilla de 2 columnas sigue ganando)
   ============================================================ */
@media (max-width:1024px){
  .mcar{
    display:flex!important;flex-wrap:nowrap;align-items:stretch;
    gap:var(--gap-cards);
    overflow-x:auto;overflow-y:hidden;
    scroll-snap-type:x mandatory;
    -webkit-overflow-scrolling:touch;
    scrollbar-width:none;-ms-overflow-style:none;
    /* sangrado a borde de pantalla: .wrap mide 92%, esto devuelve el 4% de cada lado */
    margin-inline:calc(50% - var(--vw)/2);
    padding-inline:calc(var(--vw)/2 - 50%);
    scroll-padding-inline:4vw;   /* el canal de .wrap (width:92%) */
    padding-bottom:4px;
    overscroll-behavior-x:contain;
  }
  .mcar::-webkit-scrollbar{display:none}
  .mcar>*{
    flex:0 0 min(84%,340px);
    scroll-snap-align:start;
    min-width:0;
  }
  /* planes: max-width/margin auto del layout viejo romperian el carrusel */
  .planes-grid.mcar{max-width:none;margin-inline:calc(50% - var(--vw)/2)}
  .plan.popular{transform:none;order:0}
  /* colgado con top:-14px dependia de que nada recortara; dentro de un track
     con overflow-y:hidden es fragil. En carrusel entra en el flujo de la card. */
  .plan .pop-badge{position:static;transform:none;align-self:flex-start;margin-bottom:14px}
  .planes-grid.mcar{margin-top:var(--rhythm)}

  /* proceso: en carrusel cada card es una diapositiva ya abierta */
  .process-cards.mcar{min-height:0;margin-top:var(--rhythm)}
  .process-cards.mcar .p-card{padding:26px;flex:0 0 min(84%,340px)}
  .process-cards.mcar .p-card .p-label{opacity:1}
  .process-cards.mcar .p-card .p-label .lbl{opacity:1}   /* sin esto quedaba un "04" flotando */
  .process-cards.mcar .p-card .p-dots{opacity:1}
  .process-cards.mcar .p-card .p-dots i{background:rgba(13,60,149,.2)}
  .process-cards.mcar .p-card .p-body{margin-top:16px}
  .process-cards.mcar .p-card h3{writing-mode:horizontal-tb;transform:none}
  .process-cards.mcar .p-card p{opacity:1;transform:none}
  .process-cards.mcar .p-card{cursor:default}
  .process-cards.mcar .p-card.active{flex:0 0 min(84%,340px)}

  /* el lift de hover se recorta contra overflow-y:hidden y no aporta nada
     en un track que se desliza con el dedo */
  @media (hover:hover){.mcar>*:hover,.mcar-sm>*:hover{transform:none!important;box-shadow:none}}
}

/* ---------- Puntos indicadores del carrusel ---------- */
.mcar-dots{display:none;justify-content:center;gap:0;margin-top:18px}
.mcar-dots button{
  width:44px;height:44px;padding:0;background:none;border:none;
  display:grid;place-items:center;
}
/* el area tactil es el boton (40px, sin solaparse); el punto es solo el ::before */
.mcar-dots button::before{
  content:"";width:8px;height:8px;border-radius:50%;
  background:var(--border);
  transition:background var(--dur-hover),transform var(--dur);
}
.mcar-dots button[aria-current="true"]::before{background:var(--naranja-fill);transform:scale(1.4)}
@media (max-width:1024px){
  .mcar-dots{display:flex}
  .mcar-dots-sm{display:none}
}
@media (max-width:640px){
  .mcar-dots-sm{display:flex}
}
@media (max-width:640px){
  .mcar-sm{
    display:flex!important;flex-wrap:nowrap;align-items:stretch;
    gap:var(--gap-cards);
    overflow-x:auto;overflow-y:hidden;
    scroll-snap-type:x mandatory;
    -webkit-overflow-scrolling:touch;
    scrollbar-width:none;-ms-overflow-style:none;
    margin-inline:calc(50% - var(--vw)/2);
    padding-inline:calc(var(--vw)/2 - 50%);
    scroll-padding-inline:4vw;
    padding-bottom:4px;
    overscroll-behavior-x:contain;
  }
  .mcar-sm::-webkit-scrollbar{display:none}
  .mcar-sm>*{flex:0 0 min(84%,340px);scroll-snap-align:start;min-width:0}
  .testi-card.big{grid-column:auto}
  .news-card:last-child{aspect-ratio:4/4.6}
  /* La banda oscura tiene padding propio: el sangrado se calcula desde ese
     padding, no desde .wrap. */
  .oper-band.mcar-sm{
    margin-inline:0;
    padding:26px 20px 22px;
    scroll-padding-inline:20px;
    gap:12px;
  }
  /* Sin superficie propia, los items eran bloques de texto sueltos sobre la
     banda: el segundo se cortaba a mitad de palabra y leia como texto roto,
     no como "hay otra card". Cada item pasa a ser una card de verdad. */
  .oper-band.mcar-sm>.oper-item{
    flex:0 0 82%;
    background:rgba(255,255,255,.06);
    border:1px solid rgba(255,255,255,.14);
    border-radius:var(--radius);
    padding:22px 20px 24px;
    display:flex;flex-direction:column;
  }
  .oper-band.mcar-sm .oper-item .ic{
    width:38px;height:38px;border-radius:var(--radius-sm);margin-bottom:14px;
    background:rgba(255,78,60,.14);
  }
  .oper-band.mcar-sm .oper-item .ic svg{width:19px;height:19px}
  .oper-band.mcar-sm .oper-item p{font-size:var(--fs-xs);line-height:1.55}
  .oper-band.mcar-sm .oper-item p b{font-size:var(--fs-sm);margin-bottom:8px}
}

@media (max-width:640px){
  :root{--rhythm:44px; --rhythm-sm:28px}
  .hero-content{padding-top:var(--nav-clear)}
  .hero-bottom{margin-top:52px}
  .hero-card{max-width:100%}
  .hero-card .thumb{width:96px}
  /* la metrica en fila dejaba la leyenda en 4 lineas dentro de ~110px */
  .hero-card .metric{flex-direction:column;align-items:flex-start;gap:2px}
  .hero-card .metric span{line-height:1.35}

  /* Los reveals laterales desplazan 30px en X antes de entrar: en mobile eso
     deja contenido fuera del viewport. Ya no hay overflow-x:hidden que lo
     esconda (era un parche): en pantalla angosta entran desde abajo. */
  .reveal-l,.reveal-r{transform:translateY(28px)}
  .qs-grid{grid-template-columns:1fr;gap:12px}
  .pilares{grid-template-columns:1fr;gap:34px}
  .qs-card{padding:22px 20px 24px}
  .qs-card .ic{width:40px;height:40px;margin-bottom:14px}
  .roles-panel{padding:30px 22px 34px}
  .f-row{grid-template-columns:1fr}
  .c-stats{gap:28px;flex-wrap:wrap}
  .eyebrow{font-size:var(--fs-2xs)}
  .cli-label{font-size:var(--fs-2xs)}
  .cli-row{--k:.74;gap:30px 20px}
  .cli-group + .cli-group{margin-top:34px;padding-top:34px}

  /* 2x2 entra perfecto en 359px: pasar a 1 columna duplicaba el alto por nada */
  .stats-grid{grid-template-columns:1fr 1fr}
  .stat{padding:24px 14px;border-right:1px solid var(--border)}
  .stat:nth-child(2n){border-right:none}
  .stat:nth-child(1),.stat:nth-child(2){border-bottom:1px solid var(--border)}
  .stat:last-child{border-bottom:none}
  .stat p{max-width:none}

  /* mismo criterio en el footer: son listas de 5 links cortos */
  .f-top{grid-template-columns:repeat(2,minmax(0,1fr));gap:32px 20px}
  .f-brand,.f-col-contacto{grid-column:1/-1}
  footer ul a{font-size:var(--fs-xs)}

  /* El mapa es el gancho de esta pagina, pero a 250px de ancho medía 490px
     de alto y empujaba el titular fuera de la primera pantalla. */
  .mapa-panel{gap:26px}
  /* 186px dejaba las areas tactiles de las provincias en 21px: la pagina invita
     a "tocar una provincia" y no se podia. A 300px suben a 34px. Los nodos ya
     se solapan al radio actual (el par Santa Fe / Entre Rios esta a 47 unidades
     de viewBox), asi que agrandar el .hit no es opcion: hay que agrandar el mapa. */
  .mapa-svg{max-width:300px}
  .mapa-datos{grid-template-columns:1fr;gap:12px}
  .mapa-datos>div{display:flex;align-items:baseline;gap:12px}
  .mapa-datos b{font-size:1.6rem}
  .mapa-datos span{margin-top:0}
  .mapa-tip{min-width:168px}
  .wa-fab{right:14px;bottom:14px}
  .f-bottom>*:last-child{padding-right:0}
  footer{padding-bottom:78px}

  /* sectores: el icono centrado + el indice dejaban ~180px de texto */
  .sect-row{align-items:flex-start;gap:14px;padding:22px 0}
  .sect-row .ic{width:44px;height:44px}
  .sect-row .ic svg{width:20px;height:20px}
  .sect-row .idx{position:absolute;opacity:0;pointer-events:none}
  .sect-row{position:relative}

  /* Servicios 01-06 es el 26% del scroll. Dos ajustes sin tocar contenido:
     los chips pasan a fila deslizable (4 lineas -> 1) y la cita sale de encima
     de la foto, que en 390px tapaba el 60% de la imagen. */
  /* min-width:0 en toda la cadena: sin esto la fila nowrap le impone su
     max-content al item de grilla y revienta el ancho de la seccion entera */
  .service-grid>*,.service-copy,.offer{min-width:0}
  .chips{
    min-width:0;flex-wrap:nowrap;overflow-x:auto;
    scrollbar-width:none;-ms-overflow-style:none;
    padding-bottom:2px;overscroll-behavior-x:contain;
  }
  .chips::-webkit-scrollbar{display:none}
  .chips>.chip{flex:0 0 auto}
  .offer{padding-top:28px}
  .service-media{min-height:0}
  .service-img{position:relative;inset:auto;aspect-ratio:4/3}

  .caso-meta .row{flex-direction:column;align-items:flex-start;gap:2px}
  .caso-meta .row .v{text-align:left}
  .caso-nums{gap:12px}
  .caso-num{padding:20px 16px}
  .caso-num p{font-size:var(--fs-2xs)}

  .plan .p-for{min-height:0}
  /* Los 4 tabs necesitan 439px y hay 323: no entran ni achicando el padding.
     En 2x2 quedan los cuatro visibles y balanceados, en vez de "Cobertura"
     sola y centrada en un segundo renglon. */
  .faq-tabs{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .faq-tab{padding:0 12px;justify-content:center}
  /* el avatar caia solo en su propio renglon y leia como un error */
  .planes-foot{flex-wrap:nowrap;align-items:flex-start;text-align:left;gap:12px}
  .planes-foot .av{flex-shrink:0}
}

/* ---------- Footer compacto en movil ----------
   Media 1.300px (1,5 a 2,3 pantallas). Se ocultan SOLO en movil tres bloques
   redundantes: la columna Servicios (sus 5 links van todos a /servicios/, que
   ya esta en Navegacion), Grupo (lo repite la linea "Parte del ecosistema...")
   y la marca de agua. Navegacion pasa a 2 columnas. Ningun destino se pierde. */
@media (max-width:640px){
  footer{padding-top:48px}
  .f-top{gap:28px 20px}
  .f-col-servicios,.f-grupo,.f-mega{display:none}
  .f-col-nav{grid-column:1/-1}
  .f-col-nav ul{grid-template-columns:repeat(2,minmax(0,1fr));gap:0 20px}
  .f-brand .claim{margin-top:var(--sp-3)}
  footer h2,footer h3{margin-bottom:8px}
  .f-contact{gap:0}
  .f-bottom{margin-top:32px;padding:18px 0 20px}
  .f-bottom p+p{margin-top:4px}
}

/* ---------- Fotos: diferidas y livianas en movil ----------
   Los fondos por CSS no tienen loading=lazy: Servicios bajaba 675 KB de fotos
   al entrar, aunque estuvieran 5 pantallas mas abajo. Con JS (html.js) quedan
   en pausa hasta que app.js les pone .bg-in al acercarse; sin JS cargan como
   siempre. Las de atributo data-bg las asigna app.js directamente (sin JS no
   se ven: queda el color de fondo, y son decorativas con aria-label). En movil se
   usan las versiones -m (720px; red-nodos 900px porque va ampliada). */
html.js .grupo-img:not(.bg-in),html.js .caso-img:not(.bg-in){background-image:none}
/* Muro de logos de clientes: 13 mascaras (~260 KB) que se pedian apenas
   cargaba el CSS aunque estuvieran pantallas mas abajo, y en gama baja le
   robaban la red a la tipografia (el titulo de la home esperaba a la fuente
   hasta los 4,4 s). Hay que anular la MASCARA, no solo la capa: con
   content:none Chrome igual descargaba la imagen declarada en mask. */
html.js .cli-row:not(.bg-in) .cli::before{content:none;-webkit-mask:none;mask:none}
@media (max-width:640px){
  .grupo-img{background-image:url("/assets/equipo-oficina-m.jpg")}
  .caso-img{background-image:linear-gradient(180deg,transparent 40%,rgba(6,27,65,.5)),url("/assets/datacenter-m.jpg")}
  .contacto-bleed{background-image:linear-gradient(135deg,rgba(6,27,65,.92),rgba(13,60,149,.72)),url("/assets/red-nodos-m.jpg")}
}

/* ---------- Formulario: envio real ---------- */
/* trampa anti-spam: fuera de pantalla (no display:none, que algunos bots detectan) */
.f-trampa{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.f-envio-error{margin:0 0 14px;padding:12px 14px;border-radius:var(--radius-sm);background:rgba(207,54,38,.08);color:var(--naranja-texto);font-size:var(--fs-xs);font-weight:600;line-height:1.45}
.f-envio-error a{color:inherit;text-decoration:underline}
#contactForm button[type=submit][aria-busy=true]{opacity:.7;cursor:progress}

/* ---------- Home movil: listas largas -> tarjetas deslizables ----------
   La home medía 13,7 pantallas en movil; verbos, operacion, sectores y
   decisores sumaban ~3.250px apilados. Pasan al carrusel .mcar-sm (el mismo
   de Casos y Nosotros). Cada item necesita superficie propia: sin ella, el
   que asoma cortado en el borde se lee como texto roto, no como otra card. */
@media (max-width:640px){
  .verbos.mcar-sm>.verbo{
    background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius);
    padding:22px 20px 24px;
  }
  .verbos.mcar-sm .verbo .ic{margin-bottom:16px;background:#fff}
  .sect-grid.mcar-sm{gap:12px}
  .sect-grid.mcar-sm>.sect-row{
    flex-direction:column;align-items:flex-start;gap:14px;
    background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.16);
    border-radius:var(--radius);padding:22px 20px 24px;
  }
  .sect-grid.mcar-sm .sect-row .tx b{font-size:var(--fs-md)}
  /* puntos sobre la banda azul de sectores: el gris claro de base casi no se
     distingue. (Los de .oper-band NO: quedan debajo de la banda, sobre blanco.) */
  .sectores .mcar-dots button::before{background:rgba(255,255,255,.35)}
  .sectores .mcar-dots button[aria-current="true"]::before{background:var(--naranja-fill)}
  .decisores.mcar-sm>.decisor{display:flex;flex-direction:column}

  /* Las cards no suben al aparecer: en movil entran solo con un fundido.
     El desplazamiento vertical en cada tarjeta, pantalla tras pantalla,
     hacia sentir que el contenido "se movia" mientras se leia. */
  [data-stagger]>*,[data-stagger].in>*{transform:none;transition:opacity .5s var(--ease-out-expo)}
}

/* ---------- Tap targets: minimo 44px en todo lo interactivo ---------- */
footer ul a{min-height:44px}
.f-copybtn{min-height:44px}
/* tambien los <a> de telefono/WhatsApp (min-height 44): sin esto el icono quedaba ~12px arriba del texto */
.f-contact li:has(.f-copybtn,a){align-items:center}
.nav-logo{display:inline-flex;align-items:center;min-height:44px}
label.f-radio{padding:11px 18px;min-height:44px}

/* ---------- Tamaños minimos de texto ---------- */
.hero-card .badge{font-size:var(--fs-3xs)}
.cli-label .n{font-size:var(--fs-3xs)}
.f-copybtn .cp{font-size:var(--fs-3xs)}

/* Modo estático (?static): QA / screenshots sin animaciones */
html.no-anim{scroll-behavior:auto}
html.no-anim .reveal,html.no-anim .reveal-l,html.no-anim .reveal-r,html.no-anim [data-stagger]>*{opacity:1!important;transform:none!important;transition:none!important}
html.no-anim .hero-anim{opacity:1;transform:none;animation:none}
html.no-anim .bar{transform:scaleX(1)}
html.no-anim .bar-label{opacity:1}
html.no-anim .hero-bleed{min-height:900px}
html.no-anim .mp-pais,html.no-anim .mp-red,html.no-anim .mp-nodo{
  animation:none!important;stroke-dashoffset:0!important;fill-opacity:1!important;
  opacity:1!important;transform:none!important;
}
html.no-anim .mp-nodo .halo{opacity:.18!important}

/* ============================================================
   Accesibilidad / movimiento reducido
   ============================================================ */
a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible{outline:3px solid var(--naranja);outline-offset:2px}
/* Salto al contenido: quien navega con teclado no deberia recorrer los 6 items
   de la nav en cada pagina antes de llegar al contenido. */
.skip{
  position:absolute;left:16px;top:-100px;z-index:200;
  background:var(--azul-950);color:#fff;font-weight:700;font-size:var(--fs-sm);
  padding:14px 22px;border-radius:999px;
  transition:top var(--dur-hover) var(--ease-out-expo);
}
.skip:focus{top:16px}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}
  .hero-bg{transform:none!important}
  .reveal,.reveal-l,.reveal-r,[data-stagger]>*{opacity:1!important;transform:none!important}
  .hero-anim{opacity:1;transform:none;animation:none}
  ::view-transition-new(root),html:not(.vt) body{animation:none}
  /* el mapa queda dibujado y quieto: sin trazado, sin cascada, sin flujo */
  .mp-pais,.mp-red,.mp-nodo,.mp-red line,.mp-nodo .halo{
    animation:none!important;stroke-dashoffset:0!important;fill-opacity:1!important;
    opacity:1!important;transform:none!important;
  }
  .mp-nodo .halo{opacity:.18!important}
}

/* ============================================================
   HOME — bloques propios del indice
   ============================================================ */
.home-cta{display:flex;justify-content:center;margin-top:var(--rhythm)}
.home-testi{
  display:grid;grid-template-columns:minmax(0,1fr) auto;gap:clamp(24px,3vw,40px);
  align-items:center;margin-top:var(--rhythm);
}
.home-testi .testi-card.big{margin:0}
.home-testi-cta{display:flex;justify-content:center}
/* .sec-azul solo marca el TONO para las reglas de ritmo; no pinta nada.
   Sin este background el panel quedaba con texto blanco sobre blanco. */
.home-cierre{background:var(--azul-950)}
.cierre-panel{
  display:flex;align-items:center;justify-content:space-between;gap:clamp(24px,4vw,56px);
  flex-wrap:wrap;
}
.cierre-panel h2{max-width:16ch}
.cierre-panel .lead{margin-top:14px;max-width:52ch}
.cierre-panel .btn{flex-shrink:0}

/* Item actual de la navegacion */
.nav-links a.is-actual{color:var(--azul)}
.nav-links a.is-actual::after{transform:scaleX(1)}
.mobile-menu a.is-actual{color:var(--naranja)}

@media (max-width:1024px){
  .home-testi{grid-template-columns:1fr}
  .home-testi-cta{justify-content:flex-start}
}

/* ---------- 404 ---------- */
.err404{min-height:72vh;min-height:72svh;display:grid;place-items:center}
.err-panel{max-width:640px;margin-inline:auto;text-align:center}
.err-panel h1{font-size:var(--fs-4xl);margin-top:8px}
.err-panel .eyebrow{justify-content:center}
.err-panel .eyebrow::before{display:none}
.err-panel .lead{margin:20px auto 0}
.err-links{display:flex;justify-content:center;gap:14px;margin-top:var(--rhythm-sm);flex-wrap:wrap}

/* ============================================================
   REPOSICIONAMIENTO MSP · bloques nuevos
   (problema antes/despues, los 4 verbos, capas del modelo,
    valor por decisor). Ver Copy-Web-Velnet-MSP.md
   ============================================================ */

/* --- Comparativo antes / despues ------------------------------- */
.comparativo{
  display:grid;grid-template-columns:1fr auto 1fr;align-items:stretch;
  gap:clamp(16px,2.4vw,28px);margin-top:var(--rhythm);
}
.comp-col{
  background:var(--bg-elev);border:1px solid var(--border);
  border-radius:var(--radius);padding:clamp(24px,2.6vw,34px);
}
.comp-col-ok{
  background:var(--azul-950);border-color:transparent;
  --naranja-texto:var(--naranja);
}
.comp-tag{
  display:inline-block;font-size:var(--fs-3xs);font-weight:800;
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--text-muted);margin-bottom:20px;
}
.comp-col-ok .comp-tag{color:var(--naranja)}
.comp-list{list-style:none;margin:0;padding:0;display:grid;gap:14px}
.comp-list li{
  font-size:var(--fs-xs);color:var(--text-muted);line-height:1.55;
  padding-left:26px;position:relative;
}
.comp-list li::before{
  content:"";position:absolute;left:0;top:.42em;
  width:12px;height:2px;border-radius:2px;background:var(--text-muted);opacity:.5;
}
.comp-col-ok .comp-list li{color:rgba(255,255,255,.78)}
/* El tilde usa el mismo .ck con SVG que los niveles de servicio, en vez de
   dibujarlo con bordes rotados en un pseudo-elemento. */
.comp-col-ok .comp-list li{padding-left:0;display:flex;gap:10px;align-items:flex-start}
.comp-col-ok .comp-list li::before{content:none}
.comp-col-ok .comp-list .ck{flex:0 0 auto;margin-top:.28em;color:var(--naranja);display:inline-flex}
.comp-arrow{
  align-self:center;display:grid;place-items:center;
  width:46px;height:46px;border-radius:50%;
  background:var(--bg-elev);border:1px solid var(--border);color:var(--azul);
}
.comp-claim{
  margin-top:clamp(28px,3.4vw,44px);text-align:center;
  font-size:var(--fs-xl);font-weight:700;letter-spacing:-.01em;color:var(--azul-950);
}

/* --- Los cuatro verbos ----------------------------------------- */
.verbos{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:clamp(24px,3vw,44px);margin-top:var(--rhythm);
}
.verbo .ic{
  width:46px;height:46px;border-radius:var(--radius-sm);display:grid;place-items:center;
  background:var(--bg-elev);border:1px solid var(--border);color:var(--azul);margin-bottom:20px;
}
.verbo .k{
  font-size:var(--fs-lg);letter-spacing:.02em;text-transform:uppercase;color:var(--azul-950);
}
.verbo p{font-size:var(--fs-xs);color:var(--text-muted);line-height:1.6;margin-top:10px}

/* --- Capas del modelo (servicios) ------------------------------- */
.capas{
  display:grid;grid-template-columns:repeat(5,minmax(0,1fr));
  gap:0;margin-top:var(--rhythm);
  border:1px solid var(--border-inv);border-radius:var(--radius-lg);overflow:hidden;
}
.capa{
  padding:clamp(24px,2.4vw,32px) clamp(18px,1.8vw,26px);
  border-right:1px solid var(--border-inv);
}
.capa:last-child{border-right:none}
.capa .n{
  display:block;font-size:var(--fs-3xs);font-weight:800;letter-spacing:.16em;
  color:var(--naranja);margin-bottom:14px;
}
.capa h3{font-size:var(--fs-md);color:#fff;letter-spacing:-.01em}
.capa p{font-size:var(--fs-xs);color:rgba(255,255,255,.7);line-height:1.6;margin-top:10px}

/* --- Valor por decisor ----------------------------------------- */
.decisores{
  display:grid;grid-template-columns:repeat(5,minmax(0,1fr));
  gap:var(--gap-cards);margin-top:var(--rhythm);
}
.decisor{
  background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius);
  padding:clamp(22px,2.2vw,28px);
  transition:transform var(--dur-hover) var(--ease-out-expo),box-shadow var(--dur-hover) var(--ease-out-expo);
}
@media (hover:hover){.decisor:hover{transform:translateY(-4px);box-shadow:0 24px 50px -30px rgba(6,27,65,.32)}}
.d-area{
  display:block;font-size:var(--fs-2xs);font-weight:800;letter-spacing:.04em;
  color:var(--naranja-texto);margin-bottom:12px;
}
.decisor p{font-size:var(--fs-xs);color:var(--text-muted);line-height:1.6}

@media (max-width:1200px){
  .decisores{grid-template-columns:repeat(3,minmax(0,1fr))}
  .capas{grid-template-columns:repeat(3,minmax(0,1fr))}
  .capa:nth-child(3){border-right:none}
  .capa:nth-child(-n+3){border-bottom:1px solid var(--border-inv)}
}
@media (max-width:1024px){
  .verbos{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:860px){
  .comparativo{grid-template-columns:1fr}
  .comp-arrow{transform:rotate(90deg);justify-self:center}
  .decisores{grid-template-columns:repeat(2,minmax(0,1fr))}
  .capas{grid-template-columns:1fr}
  .capa{border-right:none;border-bottom:1px solid var(--border-inv)}
  .capa:last-child{border-bottom:none}
  .capa:nth-child(3){border-right:none}
}
/* La regla global manda .oper-band a 1 columna en <=1024: correcto para los
   3 items de Nosotros, demasiado largo para los 6 de Managed Services. */
@media (max-width:1024px){
  #gestionado .oper-band{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:640px){
  .verbos{grid-template-columns:1fr;gap:30px}
  .decisores{grid-template-columns:1fr}
  .comp-claim{font-size:var(--fs-lg)}
  #gestionado .oper-band{grid-template-columns:1fr}
}

/* Definicion de "cobertura nacional gestionada" en el panel del mapa.
   Va sobre azul-950, por eso el borde y el color son los invertidos. */
.mapa-def{
  margin-top:18px;padding:16px 18px;
  background:rgba(255,255,255,.07);border-radius:var(--radius-sm);
  font-size:var(--fs-xs);color:rgba(255,255,255,.72);line-height:1.6;max-width:48ch;
}

/* Etiqueta del verbo (Disenamos / Conectamos / Gestionamos / Sostenemos)
   dentro de las tarjetas de Nosotros. La primera tarjeta va sobre azul-950. */
.qs-card .verbo-tag{
  display:block;font-size:var(--fs-3xs);font-weight:800;letter-spacing:.16em;
  text-transform:uppercase;color:var(--naranja-texto);margin-bottom:10px;
}
.qs-card:nth-child(1) .verbo-tag{color:var(--naranja)}
/* "Nacional" no es un numero: no entra en la escala de --fs-num ni lo anima el JS. */
.stat .num-txt{font-size:clamp(1.6rem,2.6vw,2.2rem)}

/* OJO: .sec-azul y .sec-azul950 NO pintan fondo -- .sec-azul ni siquiera existe
   como regla y .sec-azul950 solo hace padding-top:0. En este sistema el fondo
   oscuro SIEMPRE lo pone un contenedor concreto (.sectores, .oper-band,
   .roles-panel, .cierre-panel, .mapa-panel) y .on-dark solo pinta el TEXTO en
   claro. Poner .on-dark sin un contenedor que pinte deja texto blanco sobre
   blanco: invisible, y ningun chequeo de estructura lo marca.
   Por eso la seccion del modelo de capas trae su propio fondo. */
.modelo{background:var(--azul);margin:0;padding:var(--section-y) 0}
/* .dim y .eyebrow solo estaban resueltos dentro de .sectores; se generalizan a
   cualquier seccion oscura para que no vuelva a pasar lo mismo. */
.on-dark h2 .dim{color:rgba(255,255,255,.55)}
.on-dark .eyebrow{color:var(--naranja)}

/* .sect-cta nacio dentro de .sectores (fondo azul): trae velo blanco al 7% y
   texto blanco. Reutilizarlo sobre fondo claro da texto blanco sobre blanco.
   Esta variante lo adapta sin tocar el componente original. */
.sect-cta-claro{background:var(--bg-elev);border-color:var(--border)}
.sect-cta-claro h3{color:var(--azul-950)}
.sect-cta-claro p{color:var(--text-muted)}


/* El uppercase de .verbo .k esta pensado para los cuatro verbos de marca, que
   son palabras sueltas. En Multisede los titulos son frases de tres palabras y
   en versales una de ellas se parte en dos lineas y rompe el ritmo de la fila. */
#multisede .verbo .k{text-transform:none;letter-spacing:-.01em}

/* ============================================================
   AUDITORIA UI — lectura en movil
   ============================================================ */
/* --fs-3xs resuelve a 11.52px. En desktop pasa; en un telefono es el tamano al
   que las etiquetas (CONNECT/NETWORK, las descripciones de las metricas del
   mapa, los badges) dejan de leerse comodas. 0.78rem = 12.5px, el piso
   recomendado para texto de apoyo. */
@media (max-width:640px){
  :root{--fs-3xs:.78rem}
}
