/* ==========================================================================
   layko.com.ar — landing de marca
   Sistema visual del README §3 · Movimiento del README §2 · Estructura del §4

   Direccion: 21 TSI traducida a Layko. Cuatro reglas que no se negocian:

   1. El estado base es VISIBLE. Ninguna animacion de entrada arranca en
      opacity 0 "a la espera" de que algo la encienda. Si el JS falla o el
      navegador no soporta la tecnica, la pagina se ve entera y quieta.
   2. Solo se animan transform, opacity y filter. Nada de width, height, top
      ni margin: obligan a recalcular el layout en cada cuadro.
   3. Sin sombras. La profundidad se hace con hairlines, contraste y —solo
      sobre foto de fondo— filter: blur().
   4. Una sola cosa se mueve por vez. El impacto viene del contraste entre lo
      quieto y lo que se mueve, no de que todo se mueva siempre.

   El contraste de cada par se calcula con scripts/contraste.py. Nada se estima.
   ========================================================================== */

@import url('fuentes.css?v=b4ec2d19');

/* ------------------------------------------------------------- 1. Tokens */

:root {
  /* Base del manual de marca */
  --azul:      #19263C;
  --azul-600:  #3A4A66;
  --blanco:    #FFFFFF;
  --gris:      #E5EDF2;
  --gris-300:  #C7D5E0;
  --gris-100:  #F2F6F9;

  /* Escala oscura — la traduccion de 21 TSI (README §2.1). Derivada del azul
     de marca, no del negro: por eso todas tienen matiz frio. El negro puro no
     es de Layko. */
  --noche:     #0E1520;
  --sup:       #161F2E;
  --sup-2:     #232E42;
  --linea:     #2A3548;
  --txt:       #E8EEF4;
  --txt-2:     #A9B6C6;

  /* Las cinco unidades. Se parten en dos familias con reglas INVERTIDAS
     (§3.2): lima/aqua/naranja son claras —van como texto sobre oscuro y,
     de relleno, llevan texto azul—. Magenta y lila son oscuras: de relleno
     llevan texto blanco, y como texto solo sirven en mayusculas de 12px/700. */
  --lima:      #CFD729;   /* Deporte    */
  --aqua:      #99C6C1;   /* Urbano     */
  --naranja:   #EF7A28;   /* Accesorios */
  --magenta:   #E71F65;   /* Egresados  */
  --lila:      #5868AE;   /* Uniformes  */
  --magenta-700: #B81450; /* solo relleno y sobre claro: 2.84 sobre --noche */
  --lila-700:    #41508A; /* idem: 2.39 sobre --noche */

  --wa-verde:  #0F7F42;   /* WhatsApp accesible: 5.08 con blanco */

  /* Espaciado */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px; --sp-5: 24px;
  --sp-6: 32px; --sp-7: 48px; --sp-8: 64px; --sp-9: 96px;

  /* Tipografia (§3.3) */
  --fs-xs: 12px;  --fs-sm: 14px;  --fs-base: 16px; --fs-md: 20px;
  --fs-lg: 25px;  --fs-xl: 31px;  --fs-2xl: 39px;  --fs-3xl: 76px;

  /* Layout */
  --ancho-max: 1440px;
  --ancho-texto: 62ch;
  --gutter: var(--sp-5);
  --header-alto: 72px;

  /* Movimiento (§2.5). El rango es el de 21 TSI: 0.2 s a 0.6 s. */
  --t-rapido:  .18s;
  --t-medio:   .32s;
  --t-lento:   .6s;
  --e-salida:  cubic-bezier(.16, 1, .3, 1);   /* la curva de la casa */
  --e-entrada: cubic-bezier(.7, 0, .84, 0);
  --e-suave:   cubic-bezier(.4, 0, .2, 1);
  --d-corto:   16px;
  --d-largo:   24px;

  /* Roles semanticos. Los componentes se escriben una vez contra estos, y
     .claro los da vuelta. Sin esto, cada boton y cada hairline tendria que
     escribirse dos veces, y es asi como una de las dos versiones se olvida. */
  --fondo:        var(--noche);
  --fondo-2:      var(--sup);
  --texto:        var(--txt);
  --texto-2:      var(--txt-2);
  --borde:        var(--linea);
  --pri-fondo:    var(--blanco);
  --pri-texto:    var(--azul);
  --pri-hover:    var(--gris);
  --sec-borde:    var(--blanco);
  --foco:         var(--blanco);

  /* --- LQIP: generado por scripts/inyectar-lqip.py, no editar a mano --- */
  --lqip-ancho: url("data:image/webp;base64,UklGRs4AAABXRUJQVlA4IMIAAADwBQCdASogABIAPrVInUmnJCKhMAgA4BaJYwC1Gs86DBADN2O7NzjzJTkqdAlwudHFMRsawHdCoAD+91mtoqlt4ueWfuAnTOaXVbKmiez6GHRdZwI0xM9JZ5otDZLXglGe7D7vjCcXeZ2J7JYfV+oDplXVRkW6EJbE9tR8lyAERNEdi/5JSB806xcy5uehZ4FqhbU2f1MKqovALTvd8hZQKOTc/l20POztQ8l/bofRaV4wTNAhgCty6GWpqEtWKn4AAA==");
  --lqip-alto: url("data:image/webp;base64,UklGRiABAABXRUJQVlA4IBQBAABQBwCdASoYACQAPrVSoU0nJKMiJWsw4BaJYwCy/47BGuiq4DE4A7uJg4OsU3JX4/Xcd22GntPIzP5xX4oiKbIk9DswAP7oqGAjR7e8OsjbND/WtdqnEgsDULkLQDC9imR4i1e4wwGgNs9tO47OcWufxwufms3zNLKKkkek6WAuWlQuMY++mCaBbstH7H0SHp1tLcx7+jfmNmHeSt7pEl7TeAe8o8ZQsddhXM80MXo9FLggSzilendQUKr5RSBmCnQfiMDcPZSO0NqjrqR4SMy7Hx6PBkLEf5iCXR0HGGyU3z5jxTj+7sz6L3OAe7PXAeuZwKUvG/JagqynpUn78bVyUYENgq6Wt8A3ibdI0V4xwqShAAA=");
  /* --- fin LQIP --- */
}

.claro {
  --fondo:        var(--blanco);
  --fondo-2:      var(--gris-100);
  --texto:        var(--azul);
  --texto-2:      var(--azul-600);
  --borde:        var(--gris-300);
  --pri-fondo:    var(--azul);
  --pri-texto:    var(--blanco);
  --pri-hover:    #0F1A2B;
  --sec-borde:    var(--gris-300);
  --foco:         var(--azul);
}

/* ----------------------------------------------- 1b. Pantalla de carga */

/* Oculta por defecto. La habilita el script en linea de index.html poniendo
   .cargando en <html>, y ese script no corre si hay movimiento reducido, si no
   hay JS o si ya se vio en esta sesion. Escrito al reves —visible por defecto,
   oculta por JS— cualquier falla dejaria la pagina tapada por una pantalla
   negra, que es el peor modo de fallar que tiene una landing. */
.carga { display: none; }

html.cargando { overflow: hidden; }

/* La foto tiene que estar YA desenfocada detras de la cortina.

   El destello que se veia —foto nitida primero, desenfoque casi un segundo
   despues— salia de aca, y la causa tiene dos partes:

   1. `overflow: hidden` deja el documento sin recorrido de scroll. El
      view-timeline del hero queda degenerado y, medido, resuelve al FINAL de su
      rango: la capa borrosa termina en opacidad 0 y se ve la foto nitida. Al
      sacarse .cargando vuelve el scroll, el timeline recalcula a 0, y la foto
      se desenfoca a la vista.

   2. El intento anterior de arreglarlo declaraba `opacity: 1` sin mas, y no
      ganaba: en la cascada **las animaciones pesan mas que las declaraciones
      normales**. Solo `!important` esta por encima de una animacion.

   Es exactamente el caso para el que existe `!important`, y esta acotado a
   mientras dura la cortina. Medido con un muestreador cuadro por cuadro
   arrancando antes de que exista el documento: sin esto, 121 de 122 cuadros
   tenian la capa caida. */
html.cargando .hero__borrosa { opacity: 1 !important; }

html.cargando .carga {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  grid-template-rows: 1fr auto auto;
  align-items: center;
  padding: var(--gutter);
  background: var(--noche);
  /* El barrido de salida. inset() es la tecnica de la referencia; aca sube y
     descubre el hero que ya estaba abajo, en vez de desvanecer un velo. */
  clip-path: inset(0 0 0 0);
  transition: clip-path .9s var(--e-salida);
}
html.cargando .carga[data-sale="si"] { clip-path: inset(0 0 100% 0); }

.carga__marca {
  place-self: center;
  /* Entra y se queda. Antes derivaba de un lado al otro mientras corria el
     contador: con la marca centrada, ese ida y vuelta se leia como un error de
     posicionamiento, no como un gesto. El movimiento de esta pantalla lo lleva
     el contador, que ya es suficiente. */
  animation: asentar .7s var(--e-salida) both;
}
.carga__marca img { width: clamp(160px, 26vw, 240px); height: auto; }

.carga__pie {
  grid-row: 2;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--txt-2);
  opacity: 0;
  animation: aparecer .5s var(--e-suave) .35s both;
}

.carga__contador {
  grid-row: 2;
  justify-self: end;
  line-height: .82;
}

/* El numero es lo mas grande que se ve en todo el sitio, y va en 400 como todo
   lo grande (§3.3). font-variant-numeric: tabular evita que el ancho salte al
   pasar de 9 a 10 y de 99 a 100 — sin eso el contador tiembla. */
.carga__numero {
  display: block;
  font-size: clamp(4.5rem, 17vw, 13rem);
  font-weight: 400;
  letter-spacing: -.04em;
  color: var(--txt);
  font-variant-numeric: tabular-nums;
  animation: enfocar-texto 1.1s var(--e-salida) both;
}

.carga__barra {
  grid-row: 3;
  margin-top: var(--sp-5);
  height: 1px;
  background: var(--linea);
}
.carga__barra span {
  display: block;
  height: 100%;
  background: var(--txt);
  transform: scaleX(0);
  transform-origin: 0 50%;
}

@keyframes asentar {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
@keyframes enfocar-texto {
  from { filter: blur(14px); opacity: 0; }
  to   { filter: blur(0);    opacity: 1; }
}

/* --------------------------------------------------------------- 2. Base */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  /* La cabecera es fija: sin esto un ancla deja el titular tapado */
  scroll-padding-top: calc(var(--header-alto) + var(--sp-4));
}
/* scroll-behavior vive en el bloque 15: tambien es movimiento, y con la
   preferencia reducida activada un salto instantaneo es lo correcto. */

body {
  margin: 0;
  font-family: Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: var(--fs-base);
  font-weight: 400;
  line-height: 1.6;
  letter-spacing: .025em;
  color: var(--texto);
  background: var(--fondo);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg, picture, video { display: block; max-width: 100%; }
img { height: auto; }

/* <picture> es una caja mas entre la seccion y la <img>. Donde la foto va a
   sangre, la caja posicionada es el picture y la img simplemente lo llena: si
   se posiciona la img y se deja el picture en el flujo, queda una caja vacia
   empujando el contenido, y un height en porcentaje de la img no tiene contra
   que resolverse. */
.hero picture,
.division picture {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
.territorio__marco picture { height: 100%; }

h1, h2, h3, p, ul, ol, dl, figure, blockquote { margin: 0; }
ul, ol { padding: 0; list-style: none; }

a { color: inherit; }

:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--foco);
  outline-offset: 3px;
  border-radius: 2px;
}

.saltar {
  position: absolute;
  left: var(--sp-4);
  top: -100px;
  z-index: 100;
  padding: var(--sp-3) var(--sp-5);
  border-radius: 999px;
  background: var(--blanco);
  color: var(--azul);
  font-size: var(--fs-sm);
  font-weight: 700;
  text-decoration: none;
  transition: top var(--t-rapido) var(--e-suave);
}
.saltar:focus { top: var(--sp-4); }

.oculto-visual {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --------------------------------------------------------- 3. Tipografia */

/* La inversion de §3.3: el display va en 400, no en 700. La autoridad viene
   del tamano y del aire, no del grosor. Un --fs-3xl en 700 se ve pesado y
   comercial; en 400 se ve cinematografico. Es lo contrario de la tienda. */
.display {
  font-size: clamp(2.4rem, 7vw, 4.75rem);   /* 38px -> 76px */
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -.025em;                   /* el valor exacto de 21 TSI */
  text-wrap: balance;
}

.display--medio {
  font-size: clamp(1.75rem, 4.4vw, 2.4375rem);  /* 28px -> 39px */
  font-weight: 400;
  line-height: 1.12;
  letter-spacing: -.02em;
  text-wrap: balance;
}

.t-xl {
  font-size: clamp(1.5rem, 3vw, 1.9375rem);   /* 24px -> 31px */
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -.01em;
}

.t-lg {
  font-size: clamp(1.3125rem, 2.2vw, 1.5625rem);  /* 21px -> 25px */
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -.01em;
}

/* El descriptor del manual: mayusculas, 700, tracking amplio. Es el recurso
   que ya usan los sublogos (D E P O R T E) y el que lleva el color de unidad. */
.etiqueta {
  display: block;
  font-size: var(--fs-xs);
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--texto-2);
}

.bajada {
  font-size: var(--fs-md);
  line-height: 1.6;
  color: var(--texto-2);
  max-width: var(--ancho-texto);
}

/* ------------------------------------------------------------- 4. Layout */

.contenedor {
  width: 100%;
  max-width: var(--ancho-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.seccion {
  position: relative;
  padding-block: clamp(4rem, 7vw, 6rem);   /* 64 -> 96, el ritmo del §2.1 */
  background: var(--fondo);
  color: var(--texto);
}

.seccion__cabecera { max-width: var(--ancho-texto); }
.seccion__cabecera .etiqueta { margin-bottom: var(--sp-4); }
.seccion__cabecera .bajada { margin-top: var(--sp-5); }

/* --------------------------------------------------------- 5. Botones */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 48px;
  padding: var(--sp-3) var(--sp-6);
  border: 1px solid transparent;
  border-radius: 999px;
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: .04em;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--t-rapido) var(--e-suave),
              background-color var(--t-rapido) var(--e-suave),
              color var(--t-rapido) var(--e-suave),
              border-color var(--t-rapido) var(--e-suave);
}

.btn--pri { background: var(--pri-fondo); color: var(--pri-texto); }
.btn--pri:hover { background: var(--pri-hover); }

/* El Outline Pill Button de 21 TSI. Es el que va sobre foto: no tapa la
   imagen y se lee igual. */
.btn--sec { background: transparent; color: var(--texto); border-color: var(--sec-borde); }
.btn--sec:hover { background: rgba(255, 255, 255, .12); }
.claro .btn--sec:hover { background: var(--gris-100); }

.btn--wa { background: var(--wa-verde); color: var(--blanco); }
.btn--wa:hover { background: #0C6835; }

.btn:hover { transform: translateY(-2px); }
.btn:active { transform: scale(.985); transition-duration: .08s; }

/* La cruz que crece desde cero al pasar por encima.

   El ancho esta reservado SIEMPRE (1ch) y lo que cambia es la escala. Animar el
   ancho habria empujado la etiqueta en cada cuadro —y habria roto la regla 2 de
   este archivo—; asi el boton mide lo mismo con la cruz visible o invisible, y
   solo se anima transform y opacity. */
.btn--sec::after,
.btn--pri::after {
  content: "+";
  width: 1ch;
  margin-left: calc(var(--sp-1) * -1);
  font-weight: 400;
  transform: scale(0);
  opacity: 0;
  transition: transform var(--t-medio) var(--e-salida),
              opacity var(--t-rapido) var(--e-suave);
}
.btn--sec:hover::after,
.btn--pri:hover::after,
.btn--sec:focus-visible::after,
.btn--pri:focus-visible::after {
  transform: scale(1);
  opacity: 1;
}

/* El enlace terciario: subrayado, sin caja */
.enlace {
  color: var(--texto-2);
  text-decoration: underline;
  text-underline-offset: .25em;
  text-decoration-thickness: 1px;
  transition: color var(--t-rapido) var(--e-suave);
}
.enlace:hover { color: var(--texto); }

/* --------------------------------------------------------- 6. Cabecera */

.cabecera {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  height: var(--header-alto);
  display: flex;
  align-items: center;
  /* Transparente sobre el hero; --noche con hairline a partir del scroll */
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color var(--t-medio) var(--e-suave),
              border-color var(--t-medio) var(--e-suave);
}

.cabecera[data-desplazada="si"] {
  background: var(--noche);
  border-bottom-color: var(--linea);
}

.cabecera__interior {
  width: 100%;
  max-width: var(--ancho-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
}

/* Barra de progreso: se dibuja SOBRE el hairline inferior que la cabecera ya
   tenia, asi que no ocupa alto propio. Con scaleX, no con width. */
.cabecera__progreso {
  position: absolute;
  inset: auto 0 -1px 0;
  height: 1px;
  pointer-events: none;
}
.cabecera__progreso span {
  display: block;
  height: 100%;
  background: var(--txt);
  transform: scaleX(0);
  transform-origin: 0 50%;
}

.cabecera__logo { display: flex; align-items: center; min-height: 44px; }
.cabecera__logo img { width: 62px; height: 38px; }

.cabecera__navs { display: none; }

/* El sprite de iconos: fuera de pantalla sin clip-path, que rompe <use>. */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Un icono de red. El area tactil son 44 px aunque el dibujo mida 21: la
   diferencia es padding, no un icono gigante. */
.red {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 999px;
  color: var(--txt-2);
  transition: color var(--t-rapido) var(--e-suave),
              background-color var(--t-rapido) var(--e-suave);
}
.red svg { width: 21px; height: 21px; }
.red:hover { color: var(--txt); background: rgba(255, 255, 255, .1); }

/* En la cabecera van despues de los destinos, con el hairline separandolos:
   los tres primeros llevan a un sitio de Layko, estos tres llevan afuera. */
.cabecera__redes {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  padding-left: var(--sp-4);
  border-left: 1px solid var(--linea);
}

.menu__redes {
  display: flex;
  gap: var(--sp-2);
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--linea);
}
.menu__redes .red { width: 52px; height: 52px; }
.menu__redes .red svg { width: 25px; height: 25px; }

.cabecera__enlaces { display: flex; align-items: center; gap: var(--sp-2); }

.cabecera__enlace {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: var(--sp-4);
  border-radius: 999px;
  color: var(--txt);
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: .04em;
  text-decoration: none;
  transition: background-color var(--t-rapido) var(--e-suave);
}
.cabecera__enlace:hover { background: rgba(255, 255, 255, .1); }

/* El punto del color de la unidad: el reparto se lee por color antes que por
   texto. Es un grafico, no texto: el umbral es 3.0 y las cinco lo pasan. */
.punto {
  width: 7px; height: 7px;
  margin-right: var(--sp-2);
  border-radius: 999px;
  background: var(--acento, var(--txt-2));
  flex: none;
}

.menu-boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  padding: 0;
  border: 1px solid var(--linea);
  border-radius: 999px;
  background: transparent;
  color: var(--txt);
  cursor: pointer;
}
.menu-boton svg { width: 20px; height: 20px; }
.menu-boton .icono-cerrar { display: none; }
.menu-boton[aria-expanded="true"] .icono-abrir { display: none; }
.menu-boton[aria-expanded="true"] .icono-cerrar { display: block; }

/* Menu movil a pantalla completa */
.menu {
  position: fixed;
  inset: var(--header-alto) 0 0 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  justify-content: center;
  overflow-y: auto;
  padding: var(--gutter);
  background: var(--noche);
  /* No se anima el alto: se anima opacity + transform (regla 2) */
  opacity: 0;
  transform: translateY(-8px);
  visibility: hidden;
  transition: opacity var(--t-medio) var(--e-salida),
              transform var(--t-medio) var(--e-salida),
              visibility 0s linear var(--t-medio);
}
.menu[data-abierto="si"] {
  opacity: 1;
  transform: none;
  visibility: visible;
  transition-delay: 0s;
}

.menu__enlace {
  display: flex;
  align-items: center;
  min-height: 64px;
  padding-inline: var(--sp-4);
  border-bottom: 1px solid var(--linea);
  color: var(--txt);
  font-size: var(--fs-lg);
  font-weight: 700;
  letter-spacing: -.01em;
  text-decoration: none;
}
.menu__enlace .punto { width: 9px; height: 9px; margin-right: var(--sp-4); }



/* ------------------------------------------------------------- 7. Hero */

/* El marco le da al sticky un final: el hero queda fijo durante un viewport y
   despues se suelta. Sin marco, el sticky duraria hasta el final de <main> y el
   navegador compondria el hero detras de toda la pagina sin que se vea. */
.hero-marco { position: relative; }

/* Columna, no fila: sin secuencia, el titular y el manifiesto se apilan y el
   hero crece. Con secuencia se superponen en la misma celda (bloque 15). */
.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--sp-8);
  min-height: 100vh;
  min-height: 100svh;   /* en iOS, 100vh incluye la barra y corta el hero */
  padding-top: calc(var(--header-alto) + var(--sp-7));
  padding-bottom: var(--sp-9);
  overflow: hidden;
  background: var(--noche);
}

.hero picture { z-index: 0; }

/* La capa desenfocada NO es una segunda copia de la foto.

   Lo fue, y fallaba de un modo que no se ve en local: una segunda imagen hay que
   bajarla y decodificarla, y hasta que llega no hay nada que dibujar. Se veia la
   foto nitida y recien despues aparecia el desenfoque — casi un segundo de
   destello, justo en la primera impresion de la pagina. No era un problema de
   CSS: la capa dependia de la red.

   Ahora es una miniatura de 32 px incrustada en este mismo archivo como data URI
   (ver scripts/inyectar-lqip.py). El CSS ya es render-blocking, asi que la capa
   esta lista antes del primer pixel. Ampliada a pantalla completa ya se ve
   desenfocada sola; el blur solo termina de suavizarla.

   El blur es fijo: se rasteriza una vez y despues solo se compone, asi que
   cruzarla por opacidad no le cuesta nada al scroll. El scale tapa el borde
   transparente que todo desenfoque deja. */
.hero__borrosa {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--lqip-ancho) center / cover no-repeat;
  filter: blur(22px) saturate(.6);
  transform: scale(1.12);
  /* Sin secuencia —movil, movimiento reducido, sin soporte— la foto se ve
     nitida y esta capa no existe. El estado base es la foto en foco. */
  opacity: 0;
}
@media (max-width: 767px) {
  .hero__borrosa { background-image: var(--lqip-alto); }
}

.hero__foto {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 56% center;
  /* Enfria el beige del edificio hacia la paleta azulada (README §4) */
  filter: saturate(.75);
}

/* El velo va en GRADIENTE, no plano: fuerte donde va el texto, suave sobre la
   figura. Medido con scripts/contraste.py — a .40 sobre el beige el texto cae
   a 3.69 y el descriptor es de 12px, asi que el .68 se sostiene plano hasta el
   42 %, que es donde termina la columna de texto, y recien ahi cae. */
.hero__velo {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: linear-gradient(100deg,
    rgba(14, 21, 32, .72) 0%,
    rgba(14, 21, 32, .68) 42%,
    rgba(14, 21, 32, .40) 68%,
    rgba(14, 21, 32, .18) 100%);
}

/* En movil el recorte es vertical y el velo gira con el: un gradiente
   horizontal sobre una foto alta deja la zona fuerte al costado, no donde esta
   el titular.

   Y va casi parejo, no en degrade fuerte. La medicion que lo fijo asi se hizo
   sobre el hero APILADO —sin secuencia el titular y el manifiesto se suman y el
   hero crece a 1122 px en una pantalla de 844, o sea que el texto ocupa el hero
   ENTERO y no su tercio inferior—. Con las paradas de antes —.72 al 45 %, .30
   arriba— el titular caia en la zona floja y daba 2.81 sobre 3.0 requerido.
   Medido a 390 px con scripts/contraste-sobre-foto.js.

   Desde que el bloque 16f pinea tambien en telefono, ese caso apilado dejo de
   ser el habitual: con JS el hero vuelve a medir 100svh y el texto vuelve al
   tercio de abajo, que es la zona MAS fuerte de este gradiente. Las paradas se
   dejan igual porque el caso apilado sigue existiendo —sin JS, con movimiento
   reducido, o si se cae una CDN— y es el peor de los dos. Un velo medido contra
   el peor caso sirve para los dos; al reves, no. */
@media (max-width: 767px) {
  .hero__velo {
    background: linear-gradient(to top,
      rgba(14, 21, 32, .91) 0%,
      rgba(14, 21, 32, .86) 55%,
      rgba(14, 21, 32, .70) 100%);
  }
}

.hero__contenido {
  position: relative;
  z-index: 3;
  width: 100%;
  max-width: var(--ancho-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.hero h1 { max-width: 18ch; }

/* "Somos Layko." va en 700, por pedido: tenia que resaltar mas.

   Es una excepcion consciente a la inversion del §3.3, que manda el display en
   400. Vale solo para esta linea —la declaracion de marca— y no se propaga: el
   manifiesto y los H2 siguen en 400, que es lo que sostiene el registro
   cinematografico del resto de la pagina.
   700 es lo mas pesado disponible: Roboto se sirve self-hosted en 400 y 700, y
   un extra bold obligaria a bajar un cuarto archivo de fuente. */
.hero__linea-1 { display: block; font-weight: 700; letter-spacing: -.03em; }
.hero__linea-2 {
  display: block;
  margin-top: var(--sp-4);
  font-size: clamp(1.375rem, 3vw, 1.9375rem);   /* 22px -> 31px */
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: -.01em;
  max-width: 24ch;
}

.hero__manifiesto {
  position: relative;
  z-index: 3;
  width: 100%;
  max-width: var(--ancho-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.hero__manifiesto .etiqueta { margin-bottom: var(--sp-5); }

/* El manifiesto necesita MAS velo que el titular, y no es un capricho: sus
   lineas son mucho mas largas —"Instinto para leer el momento." llega al 65 %
   del ancho— y ahi el velo del hero ya bajo a .40, donde el texto cae a 3.69.
   La etiqueta ademas es de 12px, asi que el umbral es 4.5, no 3.0.

   Este velo propio lleva .68 parejo detras de todo el bloque: 7.57 sobre el
   beige del edificio y 6.43 sobre la zona mas clara. Como se suma al velo del
   hero, el valor real es mayor en todos lados — .68 es el piso, no el promedio.

   Se desborda por los cuatro lados. Arriba se desvanece, para no cortar con un
   borde recto en el medio de la foto; abajo y a los costados sobra y lo recorta
   el `overflow: hidden` del hero. Terminandolo en el borde del bloque quedaba
   una franja de foto sin velar debajo —el padding inferior del hero— y se veia
   la linea. */
.hero__manifiesto::before {
  content: "";
  position: absolute;
  inset: -26vh -100vw -40vh -100vw;
  z-index: -1;
  background: linear-gradient(to bottom,
    rgba(14, 21, 32, 0) 0%,
    rgba(14, 21, 32, .68) 34%,
    rgba(14, 21, 32, .68) 100%);
}

.hero .etiqueta { margin-bottom: var(--sp-5); }
.hero__acciones { margin-top: var(--sp-7); display: flex; flex-wrap: wrap; gap: var(--sp-3); }

.hero__bajar {
  position: absolute;
  left: 50%;
  bottom: var(--sp-5);
  z-index: 3;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  border-radius: 999px;
  color: var(--txt-2);
  text-decoration: none;
  transition: color var(--t-rapido) var(--e-suave);
}
.hero__bajar:hover { color: var(--txt); }
.hero__bajar svg { width: 18px; height: 18px; }

/* -------------------------------------------------------- 8. Manifiesto */

/* La seccion mas quieta de la pagina, y por eso funciona el bloque que viene
   despues. Fondo liso, sin foto. */
/* El manifiesto arranca mas chico que el hero y llega al mismo techo. El hero
   tiene una linea de tres palabras; aca hay cuatro frases de hasta treinta
   caracteres, y a 38px en un telefono cada una parte en dos renglones
   desparejos —"Estrategia" sola arriba, "para no errarle." abajo—. A 28px
   entran mejor y la cascada se lee como cascada, no como un texto cortado. */
.manifiesto__lineas {
  /* Techo bajado de 76px a 52px, por pedido: a 76px sobre la foto el bloque
     ocupaba casi toda la pantalla y quedaba pesado. A 52px las cuatro lineas
     entran holgadas, sobra aire abajo, y el cierre puede respirar. */
  font-size: clamp(1.5rem, 3.6vw, 3.25rem);   /* 24px -> 52px */
  max-width: 26ch;
}
.manifiesto__parrafo,
.manifiesto__cierre {
  max-width: var(--ancho-texto);
  color: var(--texto-2);
  font-size: var(--fs-md);
}
.manifiesto__parrafo { margin-top: var(--sp-6); }
.manifiesto__cierre {
  margin-top: var(--sp-6);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--borde);
}

/* -------------------------------------------------------- 9. Divisiones */

/* El corazon funcional: si alguien entra, ve el hero y se va sin saber que
   existen tres destinos, la pagina fallo. Por eso van antes de la mitad.

   El gesto del §2.2 es "el bloque queda fijo mientras las tres unidades pasan
   de a una". Se implementa con la columna izquierda en position: sticky y las
   tres tarjetas pasando al lado. No se oculta ninguna tarjeta ni se secuestra
   el scroll: las tres estan siempre en el DOM y siempre son enfocables.
   Ver docs/registro.md. */
.divisiones { background: var(--sup); }

.divisiones__grilla { display: grid; gap: var(--sp-8); }
.divisiones__fijo { align-self: start; }

.divisiones__indice { display: none; margin-top: var(--sp-7); }

.divisiones__paso {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) 0;
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--txt-2);
  text-decoration: none;
  transition: color var(--t-medio) var(--e-suave);
}
.divisiones__paso::before {
  content: "";
  width: 24px; height: 1px;
  background: var(--linea);
  flex: none;
  /* Excepcion consciente a la regla 2: es una linea de 1px de alto, sin nada
     alrededor que se reacomode. Animar su width no mueve a ningun hermano. */
  transition: width var(--t-medio) var(--e-salida),
              background-color var(--t-medio) var(--e-suave);
}
.divisiones__paso:hover { color: var(--txt); }
.divisiones__paso[data-activo="si"] { color: var(--txt); }
.divisiones__paso[data-activo="si"]::before { width: 44px; background: var(--acento); }

.divisiones__lista { display: grid; gap: var(--sp-6); }

/* La tarjeta de division: el componente propio de esta pagina (§3.5) */
.division {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 420px;
  padding: var(--sp-6);
  border: 1px solid var(--linea);
  overflow: hidden;
  isolation: isolate;
}

.division picture { z-index: -2; }

.division__foto {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--t-lento) var(--e-salida);
}

/* Mismo recurso que los tiles de la tienda, ya probado ahi: velo desde
   --noche al 88 % abajo hasta transparente arriba. */
.division::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to top,
    rgba(14, 21, 32, .88) 0%,
    rgba(14, 21, 32, .74) 45%,
    rgba(14, 21, 32, .10) 100%);
}

/* En movil el velo tiene que subir mucho mas.

   Sus paradas son porcentajes del alto de la tarjeta, y en un telefono el
   bloque de contenido —tres sublogos en dos filas, titulo, bajada y boton—
   ocupa casi toda la tarjeta. El texto trepa mas alla del 45 % y termina sobre
   la parte sin velar. Medido: los sublogos caian sobre la cara de la foto y
   sobre la ventana clara del gimnasio, ilegibles.

   Se ve menos foto, y esta bien: una foto que no se puede leer encima no esta
   cumpliendo su trabajo. */
@media (max-width: 767px) {
  .division::after {
    background: linear-gradient(to top,
      rgba(14, 21, 32, .93) 0%,
      rgba(14, 21, 32, .88) 60%,
      rgba(14, 21, 32, .62) 100%);
  }
}

/* La barra del color de la unidad, arriba de la tarjeta */
.division__barra {
  position: absolute;
  inset: 0 0 auto 0;
  z-index: 1;
  height: 3px;
  background: var(--acento);
}

/* Solo la foto escala, dentro de su recorte. La tarjeta no se mueve ni se
   ilumina: si se moviera, tres tarjetas juntas serian tres cosas moviendose. */
.division:hover .division__foto,
.division:focus-within .division__foto { transform: scale(1.04); }

/* El color de la unidad NO va en el texto de la etiqueta, va en el punto y en
   la barra. Motivo, medido: la etiqueta es de 12px/700, y para WCAG eso es
   texto normal —"grande" arranca en 24px, o 18.66px en negrita—, asi que pide
   4.5. Magenta da 4.17 y lila 3.49 sobre --noche; sus derivados oscuros dan
   2.84 y 2.39, peor. No hay forma de escribir esa etiqueta en su color.

   Como punto es otra cosa: es un grafico, el umbral es 3.0 y las cinco pasan.
   Asi la lectura por color se conserva entera y el texto se lee siempre. Se
   aplica a las tres tarjetas por igual: lima llega a 11.69 y podria ir en
   color, pero una etiqueta verde y dos blancas se leen como un error. */
/* Numero de orden. Marcador editorial, no dato: por eso es aria-hidden en el
   HTML —el lector de pantalla ya sabe que va tercero, se lo dice la lista— y
   por eso va en tabular, para que 01 y 02 ocupen exactamente lo mismo. */
.indice {
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: .1em;
  color: var(--texto-2);
  font-variant-numeric: tabular-nums;
}

.division .indice {
  position: absolute;
  top: var(--sp-6);
  right: var(--sp-6);
  z-index: 1;
  color: var(--txt-2);
}

.fabricacion__item .indice { display: block; margin-bottom: var(--sp-4); }

.division__etiqueta {
  display: flex;
  align-items: center;
  color: var(--txt);
  margin-bottom: var(--sp-4);
}
.division__etiqueta::before {
  content: "";
  width: 7px; height: 7px;
  margin-right: var(--sp-2);
  border-radius: 999px;
  background: var(--acento);
  flex: none;
}
.division__nombre { margin-bottom: var(--sp-3); color: var(--txt); }
.division__bajada { color: var(--txt-2); margin-bottom: var(--sp-6); max-width: 54ch; }
.division__acciones { display: flex; flex-wrap: wrap; gap: var(--sp-3); }

/* El sublogo de cada unidad: logotipo en blanco, isologo en el color de la
   unidad. Es la version para fondo oscuro que genera scripts/sublogos-blancos.py.

   Reemplaza a la etiqueta de texto que estaba antes y resuelve de paso el
   problema del §3.2 —la etiqueta no podia ir en el color de la unidad porque a
   12 px magenta y lila no llegan a 4.5—: aca el color vive en el isologo, que
   es un grafico, y el nombre se lee en blanco. */
.sublogo {
  width: clamp(112px, 14vw, 150px);
  height: auto;
  margin-bottom: var(--sp-4);
}
.sublogo--grande { width: clamp(150px, 18vw, 205px); }

/* Las tres unidades de la tienda conviven en una sola tarjeta. Es el unico
   lugar de la pagina donde se ven las cinco. */
.division__unidades {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-5);
  margin-bottom: var(--sp-5);
}
.division__unidades .sublogo { margin-bottom: 0; }

.division--tienda    { --acento: var(--lima); }
.division--egresados { --acento: var(--magenta); }
.division--uniformes { --acento: var(--lila); }

/* ------------------------------------------------------ 10. Fabricacion */

/* El respiro de la pagina: la unica seccion clara del tramo alto. Es la que le
   habla a un colegio o a un proveedor.

   Sin cifras y sin contadores, por decision del 2026-08-21: el README prohibe
   inventar numeros y no habia numeros verificados. Se cuenta con hechos, que
   es lo que el propio README llama "contarlo de otra forma". */
/* La seccion pasa a tener cuatro parrafos antes de la lista. El de la bisagra
   —"lo que fabricamos, lo fabricamos"— va mas grande porque es lo que hay que
   retener si se lee en diagonal, y con hairline porque parte la seccion en dos
   ideas: lo propio y lo elegido. */
.fabricacion__parrafo {
  margin-top: var(--sp-5);
  max-width: var(--ancho-texto);
  color: var(--texto-2);
}
.fabricacion__parrafo strong { color: var(--texto); font-weight: 700; }

.fabricacion__bisagra {
  margin-top: var(--sp-7);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--borde);
  max-width: var(--ancho-texto);
  font-size: clamp(1.3125rem, 2.2vw, 1.5625rem);
  font-weight: 400;
  line-height: 1.3;
  letter-spacing: -.01em;
  color: var(--texto);
}

.fabricacion__lista {
  margin-top: var(--sp-8);
  border-top: 1px solid var(--borde);
  display: grid;
}

.fabricacion__item {
  padding-block: var(--sp-6);
  border-bottom: 1px solid var(--borde);
}
.fabricacion__item .etiqueta { color: var(--texto-2); margin-bottom: var(--sp-3); }
.fabricacion__item h3 { margin-bottom: var(--sp-3); }
.fabricacion__item p { color: var(--texto-2); max-width: 48ch; }

/* ------------------------------------------------------- 11. Territorio */

.territorio {
  position: relative;
  overflow: hidden;
  background: var(--noche);
  padding-block: clamp(5rem, 10vw, 8rem);
}

.territorio__marco { position: absolute; inset: 0; z-index: 0; overflow: hidden; }

/* Mas alta que su marco: sin ese excedente el parallax mostraria el fondo */
.territorio__foto {
  width: 100%;
  height: 116%;
  object-fit: cover;
  filter: saturate(.7);
}

.territorio__velo {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(to right,
    rgba(14, 21, 32, .88) 0%,
    rgba(14, 21, 32, .76) 55%,
    rgba(14, 21, 32, .55) 100%);
}

/* En movil el texto usa casi todo el ancho, asi que llega hasta la zona del
   .55 y ahi la bajada caia a 4.20 sobre 4.5. El gradiente se aplana: en una
   pantalla angosta no hay lugar para un lado fuerte y otro flojo. */
@media (max-width: 767px) {
  .territorio__velo {
    background: linear-gradient(to right,
      rgba(14, 21, 32, .90) 0%,
      rgba(14, 21, 32, .86) 55%,
      rgba(14, 21, 32, .80) 100%);
  }
}

.territorio .contenedor { position: relative; z-index: 2; }
.territorio__texto { max-width: 40ch; }
.territorio__texto .bajada { margin-top: var(--sp-5); }

/* --------------------------------------------------------- 12. Contacto */

/* Es el destino: no se le pone friccion. Sin animacion y sin formulario largo
   —esta pagina deriva, no captura—. Cada unidad ya tiene el suyo. */
/* El canal institucional, arriba de las tres unidades. No va como boton: dos
   botones aca competirian con los tres de abajo y la seccion pasaria a tener
   tres niveles de boton. Va como dato con etiqueta, que es lo que es. */
/* Apilado, no en fila: el mail arriba y el WhatsApp abajo. En fila los dos
   datos competian por la mirada y ninguno era el primero; apilados hay un orden
   y el orden dice algo — el mail es el canal que deja constancia escrita, que
   es lo que un colegio o un proveedor necesita. */
.contacto__directo {
  display: grid;
  justify-items: start;
  gap: var(--sp-5);
  margin-top: var(--sp-6);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--borde);
}

.contacto__canal { display: grid; gap: var(--sp-2); }

/* La aclaracion de que no se atienden llamadas. Va en el tamano chico y en el
   color secundario: es una nota al pie del dato, no un dato. */
.contacto__aclaracion {
  font-size: var(--fs-sm);
  line-height: 1.4;
  color: var(--texto-2);
}
.contacto__directo a {
  display: grid;
  align-content: center;
  gap: var(--sp-2);
  min-height: 44px;
  color: var(--texto);
  text-decoration: none;
}
.contacto__dato {
  font-size: var(--fs-md);
  font-weight: 700;
  letter-spacing: -.01em;
  text-decoration: underline;
  text-underline-offset: .25em;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--borde);
  transition: text-decoration-color var(--t-rapido) var(--e-suave);
}
.contacto__directo a:hover .contacto__dato { text-decoration-color: currentColor; }

.contacto__grilla { display: grid; gap: var(--sp-5); margin-top: var(--sp-8); }

.contacto__bloque {
  display: flex;
  flex-direction: column;
  padding: var(--sp-6);
  border: 1px solid var(--borde);
  background: var(--fondo-2);
}
.contacto__bloque .etiqueta { color: var(--texto-2); margin-bottom: var(--sp-4); }
.contacto__bloque h3 { margin-bottom: var(--sp-2); }
.contacto__bloque p { color: var(--texto-2); margin-bottom: var(--sp-5); flex: 1; }
.contacto__acciones { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); }

/* El mail es un enlace terciario, pero sigue siendo algo que se toca: la altura
   la da el area tactil, no el renglon de texto. Medido: sin esto quedaba en 26. */
.contacto__acciones .enlace { display: inline-flex; align-items: center; min-height: 44px; }

.datos { display: grid; gap: var(--sp-5); margin-top: var(--sp-8); }
.datos > div { display: grid; gap: var(--sp-1); }
.datos dt {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--texto-2);
}
.datos dd { margin: 0; }

/* -------------------------------------------------------------- 13. Pie */

.pie {
  background: var(--noche);
  color: var(--txt);
  padding-block: var(--sp-8) var(--sp-6);
  border-top: 1px solid var(--linea);
}
.pie__grilla { display: grid; gap: var(--sp-7); }
.pie__logo { display: inline-flex; align-items: center; min-height: 44px; }
.pie__logo img { width: 132px; height: 40px; }
.pie__lema { margin-top: var(--sp-4); color: var(--txt-2); font-size: var(--fs-sm); max-width: 34ch; }
.pie h2 {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--txt-2);
  margin-bottom: var(--sp-3);
}
.pie__lista a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--txt);
  text-decoration: none;
  font-size: var(--fs-sm);
}
.pie__lista a:hover { text-decoration: underline; text-underline-offset: .25em; }
.pie__contacto { margin-top: var(--sp-3); }

.pie__redes { display: flex; gap: var(--sp-1); margin-left: calc(var(--sp-3) * -1); }
.pie__arroba { margin-top: var(--sp-2); color: var(--txt-2); font-size: var(--fs-sm); }
.pie__contacto a { color: var(--txt-2); }
.pie__contacto a:hover { color: var(--txt); }
.pie__legal {
  margin-top: var(--sp-8);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--linea);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-5);
  justify-content: space-between;
  color: var(--txt-2);
  font-size: var(--fs-sm);
}

/* La linea fiscal se lleva su propio renglon, arriba de las otras dos.

   `flex-basis: 100%` y no un <div> aparte: .pie__legal ya es el flex con el
   hairline y el espaciado medidos, y meterle un hermano obligaria a repetirlos.
   Con la base al 100 % la linea ocupa la fila entera y las otras dos siguen
   repartiendose la de abajo con el `space-between` de siempre.

   La razon social va en --txt y no en --txt-2: es el dato que alguien puede
   estar VINIENDO a buscar —un verificador de Meta, una institucion que da de
   alta un proveedor— y tiene que separarse del resto del renglon. 700 sobre
   --noche da 15.8 de contraste; el resto de la linea, en --txt-2, da 8.6. */
.pie__fiscal { flex-basis: 100%; margin-bottom: var(--sp-1); }
.pie__fiscal strong { color: var(--txt); font-weight: 700; }
/* El CUIT no se parte. A 390 px la linea entra justo y el numero quedaba
   cortado en "CUIT 30-" y "71935611-3": un identificador fiscal en dos
   renglones se lee mal y se copia peor. Con nowrap baja entero. */
.pie__fiscal span { white-space: nowrap; }

/* -------------------------------------------------------- 14. Responsive */

@media (min-width: 768px) {
  :root { --gutter: var(--sp-6); }

  .divisiones__lista { gap: var(--sp-7); }
  .division { min-height: 460px; padding: var(--sp-7); }
  .fabricacion__lista { grid-template-columns: repeat(2, 1fr); column-gap: var(--sp-8); }
  .datos { grid-template-columns: repeat(3, 1fr); }

  /* auto-fit y no repeat(3): las columnas 1fr no se achican por debajo del
     contenido, asi que forzar tres a 768 daba tres tarjetas de 253 px en
     tracks de 218 y la tercera se salia 7 px de la pantalla. Ademas se leia
     mal: "Ir a la tienda" partia el boton en dos renglones y la bajada quedaba
     en seis lineas de dos palabras.
     Con auto-fit el numero de columnas lo decide el espacio: dos en tablet
     vertical, tres cuando entran de verdad. */
  .contacto__grilla { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }

  /* El pie a dos columnas en tablet vertical. A cuatro en 768 quedaban de
     176 px: "LOS TRES DESTINOS" partia en dos renglones y el lema en cinco. */
  .pie__grilla { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
  /* Las cuatro columnas del pie recien entran aca */
  .pie__grilla { grid-template-columns: 1.5fr 1fr 1fr 1fr; }

  /* Y la columna fija de divisiones tambien. A 1024 sobra lugar para las dos
     columnas; dejarlo en una hasta 1200 dejaba el titular solo en una fila de
     960 px de ancho, con la tarjeta abajo. El pineado del hero sigue arrancando
     en 768, que es otra decision: esa es una pantalla, esto es una grilla. */
  .divisiones__grilla { grid-template-columns: minmax(240px, 320px) 1fr; gap: var(--sp-8); }
  .divisiones__fijo { position: sticky; top: calc(var(--header-alto) + var(--sp-6)); }
  .divisiones__indice { display: block; }
}

@media (min-width: 1200px) {
  .cabecera__navs { display: flex; align-items: center; gap: var(--sp-5); }
  .menu-boton { display: none; }
  .menu { display: none; }

  /* La grilla de divisiones ya arranca en 1024. Aca solo se ensancha: mas aire
     entre las columnas y tarjetas mas altas. */
  .divisiones__grilla { grid-template-columns: minmax(260px, 340px) 1fr; gap: var(--sp-9); }
  .divisiones__fijo { top: calc(var(--header-alto) + var(--sp-7)); }
  .division { min-height: 540px; }

  .fabricacion__lista { grid-template-columns: repeat(3, 1fr); column-gap: var(--sp-7); }
}

/* ------------------------------------------------------- 15. Movimiento */

/* Todo lo que sigue esta envuelto en no-preference. Con la preferencia de
   movimiento reducido activada, la pagina se ve COMPLETA y quieta: no hay una
   sola regla de animacion fuera de este bloque, asi que no queda nada que
   desactivar despues ni nada que pueda quedarse escondido por accidente. */

@media (prefers-reduced-motion: no-preference) {

  html { scroll-behavior: smooth; }

  /* -- Hero: los unicos gestos que corren al cargar, no al scrollear -- */

  /* Aca vivia el trazo del isologo dibujandose. Se fue con el elemento: el
     isologo del hero repetia el de la cabecera y se veia duplicado.
     pathLength="1" y scripts/inyectar-isologo.py quedan en el repo por si el
     gesto vuelve en otra pieza. */

  /* La foto entra en foco. blur(15px) es literal de 21 TSI y este es el unico
     lugar de la pagina donde se usa; el scale(1.06) tapa el borde transparente
     que deja el desenfoque. La foto tiene bokeh natural, asi que se lee como
     que la imagen enfoca de verdad y no como un efecto agregado. */
  .hero__foto { animation: enfocar 1.2s var(--e-salida) forwards; }

  .hero__bajar svg { animation: latir 2.4s var(--e-suave) 1.4s infinite; }

  /* El hero no se anima detras de la pantalla de carga: cuando esta termina,
     ya se habria perdido. Se pausan y arrancan al sacarse .cargando, asi la
     entrada del hero es la continuacion de la carga y no otra cosa que paso
     mientras nadie miraba. */
  html.cargando:not(.entrada) .hero__foto { animation-play-state: paused; }

  /* -- Barra de progreso de la cabecera --
     Ligada al scroll del documento, sin una linea de JS donde el navegador la
     soporta. Donde no, la actualiza main.js. */
  @supports (animation-timeline: scroll()) {
    .cabecera__progreso span {
      animation: progreso linear both;
      animation-timeline: scroll(root block);
    }
    @keyframes progreso {
      from { transform: scaleX(0); }
      to   { transform: scaleX(1); }
    }
  }

  @keyframes aparecer { to { opacity: 1; } }
  @keyframes enfocar {
    from { filter: saturate(.75) blur(15px); transform: scale(1.06); }
    to   { filter: saturate(.75) blur(0);    transform: none; }
  }
  @keyframes latir {
    0%, 70%, 100% { transform: none; }
    35%           { transform: translateY(4px); }
  }

  /* -- Entradas por scroll --

     El estado base sigue siendo visible: .revelar sin nada encima es opacity 1.
     La animacion se agrega de dos maneras que nunca conviven: el timeline de
     scroll donde existe (corre fuera del hilo principal, sin JS), y una clase
     por IntersectionObserver donde no. Ver js/main.js. */

  .revelar { opacity: 1; }

  @supports (animation-timeline: view()) {
    .revelar {
      animation: entrar linear both;
      animation-timeline: view();
      /* El escalonado de 60 ms del §2.6 no se puede expresar en tiempo sobre un
         timeline de scroll: se expresa en recorrido. 4 % de avance por hermano
         da la misma lectura de cascada. */
      animation-range: entry calc(8% + var(--i, 0) * 4%) cover 32%;
    }
  }

  .sin-timeline .revelar {
    opacity: 0;
    transform: translateY(var(--d-largo));
    clip-path: inset(0 0 100% 0);
    transition: opacity var(--t-medio) var(--e-salida),
                transform var(--t-lento) var(--e-salida),
                clip-path var(--t-lento) var(--e-salida);
    transition-delay: calc(var(--i, 0) * 60ms);
  }
  .sin-timeline .revelar[data-visto="si"] {
    opacity: 1;
    transform: none;
    clip-path: inset(0 0 -20% 0);
  }

  /* El revelado va por clip-path, no solo por opacidad.

     Es la diferencia entre "aparece" y "se descubre": con inset() el bloque se
     destapa de abajo hacia arriba mientras sube, que es lo que hace que una
     linea de titular se lea como si saliera de atras de un borde. La referencia
     lo declara asi —will-change: clip-path— y es la tecnica que le da su
     caracter, mas que las curvas o las duraciones.

     Termina en -20% y no en 0 por una razon concreta: a 0 el recorte cae justo
     sobre el borde de la caja y come las colas de las g, las j y las p. */
  @keyframes entrar {
    from { opacity: 0; transform: translateY(var(--d-largo)); clip-path: inset(0 0 100% 0); }
    to   { opacity: 1; transform: none;                       clip-path: inset(0 0 -20% 0); }
  }

  /* -- LA SECUENCIA DEL HERO --

     El gesto central de la pagina. Con el scroll pasan tres cosas encadenadas,
     todas sobre la misma pantalla fija:

       la foto enfoca  ·  el titular se va  ·  el manifiesto entra linea a linea

     y recien cuando terminan, el pin se suelta y llega la seccion de divisiones.

     Como se mide el avance: .hero-marco publica un view-timeline y el rango
     `contain` de un elemento mas alto que la pantalla es EXACTAMENTE lo que dura
     el pin —de "su borde de arriba toca el borde de arriba de la pantalla" a
     "su borde de abajo toca el de abajo"—. Asi los porcentajes de abajo son
     porcentajes del pin, no de una distancia que haya que calcular a mano.

     Corre en el compositor, fuera del hilo principal: por eso no traba el
     scroll aunque haya ocho cosas atadas al mismo recorrido.

     Solo de 768 para arriba, Y ESO YA NO ES LA REGLA DE LA PAGINA: es el limite
     de ESTE camino, el nativo, que hoy es el respaldo. El camino que ve casi
     todo el mundo es el del bloque 16 —GSAP— y ahi el hero SI se pinea en
     telefono, con la coreografia abaratada. Ver el bloque 16f.

     Aca el limite se queda por lo que este camino no puede hacer: los tiempos
     son porcentajes de un view-timeline y no hay donde abaratar nada. No se
     puede partir por palabras en vez de por caracteres ni sacar un blur solo en
     telefono, porque no hay una sola linea de JS midiendo. Un pin de tres
     pantallas con blur a sangre en un telefono de gama media es exactamente el
     escenario que se queria evitar. Y ademas: si el navegador llego hasta aca es
     porque el otro camino fallo, y un respaldo tiene que ser mas barato que lo
     que respalda, no mas caro. Apilado se lee todo, en orden, sin animacion. */
  @media (min-width: 768px) {
    @supports (animation-timeline: view()) {

      .hero-marco {
        height: 360svh;                 /* 260svh de recorrido con el hero fijo */
        view-timeline: --heroe block;
      }
      .hero { position: sticky; top: 0; height: 100svh; min-height: 0; }

      /* Las secciones que siguen tapan el hero cuando el pin se suelta */
      main > .seccion { position: relative; z-index: 2; }

      /* Titular y manifiesto comparten celda: el segundo ocupa el lugar que
         deja el primero. Por eso el titular se va antes de que el otro entre. */
      .hero {
        display: grid;
        /* 1fr y no auto: con la columna en auto, el ancho lo decide el
           contenido mas ancho de los dos bloques y el `margin-inline: auto` de
           cada uno los centra dentro de ESA columna, no del hero. Medido: el H1
           se iba de 272 px a 935 y dejaba de alinear con el resto de la pagina. */
        grid-template-columns: 1fr;
        grid-template-areas: "escena";
        align-content: end;
        gap: 0;
      }
      /* align-self: end es lo que los apoya abajo de la celda.

         Sin esto los dos se estiran al alto de la fila, y la fila mide lo que
         mide el mas alto de los dos —el manifiesto—. El titular quedaba
         estirado sobre esa altura con su contenido arriba, y por eso se veia
         flotando en el medio del hero con un hueco enorme debajo. */
      .hero__contenido, .hero__manifiesto { grid-area: escena; align-self: end; }

      /* Las seis piezas del manifiesto son la etiqueta, las cuatro lineas del
         titular y el cierre. Se listan asi y no con `> *` porque las lineas son
         <span> dentro del <h2>: con `> *` se animaria el h2 entero de una y se
         perderia el escalonado, que es justo el efecto. */
      .hero__borrosa,
      .hero__contenido,
      .hero__bajar,
      .hero__manifiesto::before,
      .hero__manifiesto .etiqueta,
      .hero__manifiesto .manifiesto__lineas,
      .hero__manifiesto .manifiesto__parrafo,
      .hero__manifiesto .manifiesto__cierre {
        animation: linear both;
        animation-timeline: --heroe;
      }

      /* El velo del manifiesto entra antes que el texto, no con el: si entrara
         a la vez se veria aparecer el rectangulo. Base visible (afuera de este
         bloque), asi que si el timeline fallara el texto queda protegido igual. */
      .hero__manifiesto::before {
        animation-name: entrar-velo;
        animation-range: contain 28% contain 44%;
      }
      @keyframes entrar-velo { from { opacity: 0; } to { opacity: 1; } }

      /* 1. La foto enfoca. Es lo primero y lo mas largo: ocupa mas de la mitad
            del recorrido, asi que se ve enfocar de verdad y no de golpe. */
      /* Ritmo recalibrado el 2026-08-22: con los rangos anteriores el titular se
         iba a los dos golpes de rueda y la pagina parecia haberse comido el
         texto principal. Ahora aguanta el primer 16 % entero —unos 370 px de
         scroll— antes de empezar a irse. */
      .hero__borrosa {
        /* Declarada visible, no heredando el estado del keyframe.
           El timeline tarda un cuadro o dos en resolverse despues del primer
           pintado, y en ese hueco el relleno `both` todavia no aplica: se veia
           la foto nitida un instante antes de que apareciera el desenfoque.
           Ahora arranca puesta y la animacion solo la saca.
           El riesgo del estado base invertido no aplica: si el timeline fallara,
           la foto queda suave — que es cosmetico. Nada de contenido se esconde,
           que es lo que protege la regla 1. */
        opacity: 1;
        animation-name: enfocar-foto;
        animation-range: contain 2% contain 62%;
      }
      /* El estado inicial va en el keyframe, no como declaracion suelta.
         animation-fill-mode: both lo sostiene antes de que empiece el rango; y
         si el timeline no existiera por lo que sea, no hay relleno que aplicar
         y queda el valor base —opacity 0, la foto nitida—. Al reves, con
         `opacity: 1` declarado afuera, la misma falla dejaria la foto borrosa
         para siempre. */
      @keyframes enfocar-foto { to { opacity: 0; } }

      /* 2. El titular se va temprano, para dejar la celda libre. */
      .hero__contenido {
        animation-name: irse;
        animation-range: contain 16% contain 36%;
      }
      @keyframes irse {
        to { opacity: 0; transform: translateY(-28px); filter: blur(5px); }
      }

      .hero__bajar {
        animation-name: irse-flecha;
        animation-range: contain 8% contain 20%;
      }
      /* Solo opacidad: la flecha ya usa translateX(-50%) para centrarse y
         pisarle el transform la mandaria al costado. */
      @keyframes irse-flecha { to { opacity: 0; } }

      /* 3. El manifiesto, pieza por pieza. Cada una arranca un 10 % del
            recorrido despues de la anterior: es el escalonado del §2.6, pero
            medido en scroll en vez de en milisegundos, porque el que marca el
            tiempo aca es quien scrollea. */
      .hero__manifiesto .etiqueta,
      .hero__manifiesto .manifiesto__lineas,
      .hero__manifiesto .manifiesto__parrafo,
      .hero__manifiesto .manifiesto__cierre {
        /* Sin `opacity: 0` suelto, por el mismo motivo que arriba: el estado
           inicial lo pone el keyframe con relleno `both`. Si el timeline
           fallara, el texto se ve — que es la regla 1 de este archivo. */
        animation-name: entrar-linea;
        /* Paso de 12 % y no de 9 %: el manifiesto paso de seis piezas a cuatro,
           y con el paso viejo la cascada terminaba antes de la mitad del
           recorrido y quedaba medio pin sin nada que hacer. */
        animation-range: contain calc(36% + var(--i) * 12%)
                         contain calc(50% + var(--i) * 12%);
      }
      @keyframes entrar-linea {
        from { opacity: 0; transform: translateY(var(--d-largo)); clip-path: inset(0 0 100% 0); }
        to   { opacity: 1; transform: none;                       clip-path: inset(0 0 -20% 0); }
      }

      /* El velo NO se toca. Sus paradas estan medidas contra muestras reales de
         la foto (docs/registro.md) y el manifiesto cae en la misma columna
         izquierda que el titular, asi que hereda los mismos 7.57–8.37. Animarlo
         para "reforzarlo" dejaria todo ese calculo sin valor. */
    }
  }

  /* -- Territorio: parallax --

     El unico gesto continuo de la pagina, y el unico sin equivalente por
     IntersectionObserver: no es una entrada, es una posicion ligada al scroll.
     Donde no hay timeline, la foto simplemente no se mueve. Desactivado abajo
     de 768 por §3.6. */
  @supports (animation-timeline: view()) {
    @media (min-width: 768px) {
      .territorio__foto {
        animation: desplazar linear both;
        animation-timeline: view();
        animation-range: cover 0% cover 100%;
      }
      @keyframes desplazar {
        from { transform: translateY(-8%); }
        to   { transform: translateY(0%); }
      }
    }
  }
}

/* ---------------------------- 16. Hero cinematografico (Lenis + GSAP) */

/* Este bloque es ADITIVO y REVERSIBLE. No modifica una sola linea de los
   bloques 7, 8 ni 15: los desactiva selectivamente, y solo cuando
   js/hero-cine.js confirmo que las librerias estan en memoria y puso `hero-js`
   en <html>.

   Volver atras del todo son tres borrados: este bloque, las cuatro etiquetas
   <script> de CDN y js/hero-cine.js. Nada mas que eso.

   Si las librerias no llegan —CDN caida, JS desactivado, movimiento reducido—
   la clase nunca se pone, nada de aca aplica y el sitio queda exactamente como
   estaba: la secuencia nativa del bloque 15 con `animation-timeline: view()`. */


/* -- 16a. Baseline de Lenis --

   Lenis no trae su hoja de estilos por CDN, asi que van sus cuatro reglas.
   La importante es la segunda: el bloque 15 declara
   `html { scroll-behavior: smooth }` y eso PELEA con el scroll interpolado —
   el navegador anima hacia un destino mientras Lenis anima hacia otro. */
html.lenis,
html.lenis body { height: auto; }

.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }
.lenis.lenis-smooth iframe { pointer-events: none; }


/* -- 16b. El relevo --

   GSAP toma opacity, transform y filter de estos nodos. Si las animaciones del
   bloque 15 siguieran corriendo, los dos motores se pisarian el mismo estilo en
   el mismo cuadro y ganaria el ultimo que escribio: el titular parpadearia.

   `animation: none` es la forma corta y correcta: la propiedad taquigrafica
   resetea name, timeline, range y fill de una vez. Apagar solo
   `animation-timeline` dejaria vivo `animation-name: irse` con duracion 0 y
   relleno `both`, o sea el estado final aplicado de golpe — texto invisible.
   La especificidad de `html.hero-js` (0,2,1) alcanza para ganarle a todas. */
html.hero-js .hero__foto,
html.hero-js .hero__borrosa,
html.hero-js .hero__contenido,
html.hero-js .hero__bajar,
html.hero-js .hero__manifiesto::before,
html.hero-js .hero__manifiesto .etiqueta,
html.hero-js .hero__manifiesto .manifiesto__lineas,
html.hero-js .hero__manifiesto .manifiesto__parrafo,
html.hero-js .hero__manifiesto .manifiesto__cierre {
  animation: none;
}

/* El latido de la flecha NO se apaga: es un bucle de reposo de 2.4 s que corre
   en el compositor y que GSAP no toca. Apagarlo seria perder un gesto gratis. */


/* -- 16c. El velo del manifiesto, por variable --

   `.hero__manifiesto::before` es un pseudo-elemento y GSAP no puede tomarlo:
   no existe como nodo. Se anima entonces `--velo` sobre el elemento real, y el
   pseudo la lee. Las propiedades personalizadas heredan por defecto, asi que
   el ::before recibe el valor de su originante sin declarar nada mas.

   El respaldo de var() es 1 —visible—, no 0. Si GSAP no llega a escribirla el
   velo esta puesto y el texto conserva su contraste medido; al reves, el
   manifiesto quedaria sobre la foto pelada. */
html.hero-js .hero__manifiesto::before { opacity: var(--velo, 1); }


/* -- 16d. Las mascaras de SplitType --

   El `overflow: hidden` por linea es lo que hace que el caracter se lea como
   si SALIERA de atras de un borde en vez de aparecer flotando. Es la misma
   idea del `clip-path: inset()` del bloque 15, aplicada por renglon.

   El par padding/margin de .14em existe por una razon concreta: un
   `overflow: hidden` ajustado a la caja de texto corta las colas de las g, las
   j y las p, y las tildes de las mayusculas. El padding le da aire abajo y el
   margen negativo se lo devuelve al interlineado, asi que la mascara respira
   sin mover una sola linea de la composicion. */
html.hero-js .hero .line,
html.hero-js .manifiesto__lineas .line {
  display: block;
  overflow: hidden;
  padding-bottom: .14em;
  margin-bottom: -.14em;
}

html.hero-js .hero .word,
html.hero-js .hero .char,
html.hero-js .manifiesto__lineas .word,
html.hero-js .manifiesto__lineas .char {
  display: inline-block;
  /* Sin esto, Safari redondea el subpixel de cada caracter transformado y el
     titular "vibra" mientras entra. */
  backface-visibility: hidden;
}

/* will-change NO va aca a proposito, y es el punto del brief sobre movil.
   Declarado en la hoja de estilos, el telefono mantiene una capa de GPU por
   cada uno de los 35 caracteres del titular durante TODA la visita, para una
   animacion que dura un segundo. Lo pone y lo saca js/hero-cine.js, bloque 4. */


/* -- 16e. Sobre-alto para el parallax --

   La foto necesita mas alto que su caja para tener a donde moverse. 116 % con
   el borde de arriba en -8 % la deja centrada, y el recorrido de GSAP
   (yPercent de -6 a 6, o sea +-7 % de la caja) entra holgado adentro de ese
   sobrante: nunca se ve el borde. El `overflow: hidden` del <picture> recorta.

   Va dentro de no-preference: con movimiento reducido no hay parallax y la
   foto no tiene por que estar sobredimensionada. */
@media (prefers-reduced-motion: no-preference) {
  html.hero-js .hero__foto {
    position: relative;
    top: -8%;
    height: 116%;
  }
}


/* -- 16f. El pin, ahora en todos los navegadores Y EN TELEFONO --

   Estas reglas son las mismas del bloque 15, pero sin dos cosas: sin el
   `@supports (animation-timeline: view())` que las envuelve alla, y sin el
   `min-width: 768px`.

   Lo primero es la ganancia del cambio de motor: hoy Safari y Firefox no
   soportan view-timeline, el hero no se fija y la secuencia entera no existe
   para ellos. Con GSAP midiendo, el pin lo puede hacer `position: sticky`, que
   soportan todos desde hace anos.

   LO SEGUNDO ES UN CAMBIO DE DECISION, y conviene dejarlo escrito.

   El bloque 15 dice —y sigue diciendo, porque para el camino nativo sigue
   valiendo— que en un telefono clavar el hero tres pantallas se siente como
   que el scroll se rompio. La pagina se entrego asi y el efecto real fue el
   contrario del buscado: en el telefono no habia nada que descubrir. La foto ya
   estaba enfocada al cargar, el titular no se iba nunca y el manifiesto era un
   bloque de texto mas, debajo. Se perdia el gesto entero, que es lo unico que
   esta pagina tiene para decir antes de las divisiones.

   Lo que hacia sospechoso el pin en telefono no era el pin: era el COSTO. Un
   scrub que redibuja 35 caracteres con blur propio en cada cuadro es lo que
   rompe el scroll de un telefono de gama media, no `position: sticky`. Ese
   costo se paga en js/hero-cine.js, no aca: alla el telefono parte por palabras
   en vez de por caracteres, no lleva blur por trozo y el scrub va directo.

   El pin es sticky y no ScrollTrigger `pin: true` a proposito: sticky lo
   resuelve el compositor y no inserta el pin-spacer, que es justo la pieza que
   se pelea con un scroll interpolado. ScrollTrigger aca solo mide el avance. */
@media (prefers-reduced-motion: no-preference) {

  html.hero-js .hero-marco { height: var(--pista-hero, 360svh); }

  html.hero-js .hero {
    position: sticky;
    top: 0;
    height: 100svh;         /* svh y no dvh: dvh cambia de valor cuando la barra
                               de URL entra y sale, y el hero fijo se estiraria
                               en medio del scroll. svh es el valor chico y
                               estable — no hay salto posible. Y en telefono no
                               es un detalle: la barra de URL entra y sale en
                               cada gesto. */
    min-height: 0;

    /* Titular y manifiesto comparten celda: el segundo ocupa el lugar que deja
       el primero, y por eso el titular se va antes de que el otro entre. */
    display: grid;
    grid-template-columns: 1fr;
    grid-template-areas: "escena";
    align-content: end;
    gap: 0;
  }

  html.hero-js .hero__contenido,
  html.hero-js .hero__manifiesto {
    grid-area: escena;
    align-self: end;
  }

  /* Las secciones que siguen tapan el hero cuando el pin se suelta */
  html.hero-js main > .seccion { position: relative; z-index: 2; }
}


/* -- 16f-bis. El mismo pin, medido para una pantalla de telefono --

   EL PROBLEMA QUE RESUELVE ESTE BLOQUE es de centimetros, no de gusto.

   Con el pin, el manifiesto deja de crecer hacia abajo y pasa a tener que
   ENTRAR en una pantalla, apoyado contra el borde inferior de la celda que
   comparte con el titular (`align-self: end`). Si no entra, el
   `overflow: hidden` del hero le come el principio por arriba: se pierden la
   etiqueta y el titular del manifiesto, que son las dos primeras piezas de la
   cascada. Y no se ve venir en un escritorio angosto, donde el alto sobra.

   Con los valores del bloque 8 —parrafos de 20 px, interlineado 1.6, saltos de
   32 px— el manifiesto mide unos 600 px. En un iPhone SE quedan 420 utiles.
   No entra, y no por poco.

   ASI QUE ACA SE APRIETA, y solo aca: cada valor esta atado a `html.hero-js` y
   a `max-width: 767px`, o sea que sin JS, con movimiento reducido o en
   escritorio el bloque 8 sigue mandando intacto.

   El contraste no se toca. Bajar de 20 px a 17 px no mueve la relacion —es el
   mismo --texto-2 sobre el mismo velo— y 17 px regular esta del mismo lado del
   umbral que 20 px: los dos estan abajo de los 24 px del texto grande, asi que
   los dos piden 4.5 y los dos tienen 6.43 de piso (docs/registro.md). Lo unico
   que habria que volver a medir es la etiqueta de 12 px, y esa no cambia.

   El clamp es contra `svh` y no contra `vw`, que es lo raro y es el punto: lo
   que escasea en un telefono no es el ancho, es el ALTO. Un Pixel alto y
   angosto tiene lugar de sobra; un SE, no. */
@media (prefers-reduced-motion: no-preference) and (max-width: 767px) {

  /* Pista mas corta que en escritorio. 360svh son 2,6 pantallas de recorrido, y
     con el pulgar eso son cinco o seis golpes de dedo antes de llegar a las
     divisiones: el gesto deja de leerse como una secuencia y pasa a leerse como
     una pagina que no termina. 300svh son dos pantallas de recorrido —tres o
     cuatro golpes— y la coreografia entra entera igual, porque los tiempos de
     js/hero-cine.js son PORCENTAJES del pin, no distancias. */
  html.hero-js .hero-marco { --pista-hero: 300svh; }

  /* El aire del hero, ajustado. El de arriba solo tiene que despejar la
     cabecera; el de abajo tiene que dejar pasar la flecha, que vive en
     `bottom: var(--sp-5)`. */
  html.hero-js .hero {
    padding-top: calc(var(--header-alto) + var(--sp-4));
    padding-bottom: var(--sp-7);
  }

  /* EL VELO SE AFLOJA ARRIBA, y esto no es cosmetico: es lo que hace que el
     gesto exista.

     El velo movil del bloque 7 va casi parejo —.91 abajo, .70 arriba— porque
     se midio contra el hero APILADO, donde el texto ocupaba la pantalla entera
     y no habia un solo lugar donde aflojar. Con el pin, el texto se replegó al
     tercio de abajo: de la mitad para arriba no hay una sola letra, y ese .70
     encima de la capa desenfocada dejaba la primera pantalla practicamente
     negra. La foto no se descubria: se aclaraba un poco. El gesto entero de la
     pagina depende de que ahi haya una foto que mirar.

     Cuanto se puede aflojar lo dijo la medicion, no el ojo:
     scripts/contraste-sobre-foto.js daba 14.12 en el peor pixel del descriptor
     de 12 px, contra un umbral de 4.5. Sobraban tres veces.

     Las paradas nuevas dejan el texto donde estaba y aflojan solo arriba:

       - 0-42 % desde abajo (.90 → .86): la franja del titular y del manifiesto.
         Practicamente sin cambio.
       - 42-100 % (.86 → .30): la mitad de arriba, que no lleva texto en ningun
         momento de la secuencia. Aca es donde aparece la foto.

     Y no queda desprotegida cuando el manifiesto sube: su propio velo
     —`.hero__manifiesto::before`, que se desborda 26vh hacia arriba— entra
     justo antes que el texto y vuelve a cerrar la parte de arriba. Los dos se
     suman, asi que en la fase del manifiesto el piso real es mas alto que este.

     Va bajo `html.hero-js` a proposito: sin JS no hay pin, el hero vuelve a
     apilarse, el texto vuelve a ocupar la pantalla entera y tiene que volver a
     mandar el velo parejo del bloque 7. */
  html.hero-js .hero__velo {
    background: linear-gradient(to top,
      rgba(14, 21, 32, .90) 0%,
      rgba(14, 21, 32, .86) 42%,
      rgba(14, 21, 32, .52) 72%,
      rgba(14, 21, 32, .30) 100%);
  }

  html.hero-js .hero__manifiesto .etiqueta { margin-bottom: var(--sp-4); }

  html.hero-js .hero__manifiesto .manifiesto__parrafo,
  html.hero-js .hero__manifiesto .manifiesto__cierre {
    font-size: clamp(0.9375rem, 2.1svh, 1.0625rem);   /* 15px -> 17px */
    line-height: 1.5;
    margin-top: var(--sp-5);
  }
  html.hero-js .hero__manifiesto .manifiesto__cierre { padding-top: var(--sp-5); }
}


/* -- 16g. El boton de bajar, con vidrio y con respaldo --

   El unico retoque estetico que suma este bloque, y va sobre un control de
   icono: no tiene texto, asi que no entra en el calculo de contraste medido de
   docs/registro.md. Los botones CON texto del hero quedan intactos por eso
   mismo — `.btn--sec` esta medido sobre la foto y velarlo un poco mas no es
   una decision para tomar de costado.

   Dos respaldos, no uno:
     - donde no hay backdrop-filter (Firefox viejo), un fondo solido;
     - en telefono se apaga aunque este soportado. Un backdrop-filter sobre una
       foto a sangre QUE ADEMAS SE ESTA MOVIENDO obliga a releer y desenfocar
       el fondo en cada cuadro del parallax. Es de los efectos mas caros que
       existen y esta puesto sobre una flecha de 44 px. */
html.hero-js .hero__bajar {
  background: rgba(255, 255, 255, .06);
  border: 1px solid rgba(255, 255, 255, .18);
  -webkit-backdrop-filter: blur(10px) saturate(1.2);
  backdrop-filter: blur(10px) saturate(1.2);
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  html.hero-js .hero__bajar { background: rgba(14, 21, 32, .55); }
}

@media (max-width: 767px) {
  html.hero-js .hero__bajar {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: rgba(14, 21, 32, .55);
  }
}


/* -------------------------------- 17. Las dos secciones a dos columnas */

/* Fabricacion y Contacto tenian el mismo problema y tienen la misma solucion.

   El problema: `.seccion__cabecera` mide 62ch —el ancho de lectura comodo del
   §3.3, y esta bien que lo mida— pero esas dos secciones no tienen nada a la
   derecha de esa columna. En un monitor de 1440 quedaba media pagina vacia al
   costado de un bloque de texto largo, y la seccion se leia como si le
   faltara algo.

   La solucion NO es ensanchar el texto: a 100 caracteres por renglon el ojo
   pierde el salto de linea y se relee. Es partir en dos columnas y darle a la
   derecha lo que ya existia debajo. El texto conserva su medida, la pagina
   deja de tener un agujero, y de paso la seccion gana la jerarquia que no
   tenia: a la izquierda la afirmacion, a la derecha la explicacion.

   Recien de 1024 para arriba. Abajo de eso las dos secciones quedan
   exactamente como estaban: una sola columna, en el mismo orden. */

@media (min-width: 1024px) {

  .fabricacion__intro,
  .contacto__intro {
    /* Pisa el 62ch de .seccion__cabecera: el limite de medida pasa a estar en
       cada columna, no en el conjunto. */
    max-width: none;
    display: grid;
    gap: var(--sp-9);
    align-items: start;
  }

  /* Reparto distinto en cada una, y no es capricho.

     En Fabricacion la derecha lleva tres parrafos y necesita mas lugar; la
     izquierda es un titular de seis palabras. En Contacto la derecha son dos
     datos cortos, asi que la que manda es la izquierda. */
  .fabricacion__intro { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
  .contacto__intro { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); }

  /* El limite va en el TITULAR, no en la columna. Capando la columna entera a
     34ch la bajada caia en cuatro renglones de treinta caracteres y se leia
     picada; el titular es el unico que necesita una medida corta, porque en
     `display--medio` con `text-wrap: balance` es lo que decide cuantas lineas
     tiene y donde parten. */
  .fabricacion__claim,
  .contacto__claim { max-width: var(--ancho-texto); }

  .fabricacion__claim > h2,
  .contacto__claim > h2 { max-width: 18ch; }

  .fabricacion__cuerpo { max-width: var(--ancho-texto); }

  /* El primer parrafo de la derecha no lleva separacion propia: ya lo separa
     la grilla, y con su margen quedaba desalineado del titular de al lado. */
  .fabricacion__cuerpo > :first-child { margin-top: 0; }

  /* El hairline del bloque de datos pasa de horizontal a vertical: ahi arriba
     ya no separa "lo de abajo" de "lo de arriba", separa las dos columnas. */
  .contacto__intro .contacto__directo {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
    padding-left: var(--sp-7);
    border-left: 1px solid var(--borde);
    align-content: start;
  }
}
