/* ══════════════════════════════════════════════════════════════════════════
   puertas.css — «Qué hacemos». Las tres puertas: Construir, Crecer, Operar.

   Se monta ENCIMA de `caliber.css`, de la que hereda todos los tokens
   (--tinta, --osc-1..3, --acento, --t1..--t6, --aire, --borde) y las clases
   base (.seccion, .d1-.d3, .parrafo, .rotulo, .boton, .tenue, .mono).
   Aquí sólo vive lo que es de esta página.

   TRES REGLAS QUE VIENEN MEDIDAS Y NO SE NEGOCIAN
   ───────────────────────────────────────────────
   1. TODO A LA IZQUIERDA. De los seis sitios de servicios medidos en vivo el
      2-sep (Cuberto, Instrument ×2, DEPT, Koto, Swanky) ninguno centra su
      texto. Centrar es la decisión por defecto y por defecto se ve barato.
   2. UN SOLO PESO (400) Y SEIS TAMAÑOS. La jerarquía se hace subiendo de TONO
      (--osc-3 → --osc-2 → --osc-1), nunca engordando la letra.
   3. NADA DE CAJA POR ELEMENTO. Ni tarjeta con borde de 1 px gris, ni tres
      columnas iguales en fila: las dos están en la lista negra del director.
      La densidad se gana con filete, tono y aire.
   ══════════════════════════════════════════════════════════════════════════ */

/* ══ EL SÉPTIMO ESCALÓN ═══════════════════════════════════════════════════
   🔴 LA MARCA TIENE SEIS TAMAÑOS Y EL MÁS GRANDE ES 62 px. Medido en vivo el
   2-sep: el titular de servicios de Cuberto va a 81 y el de DEPT a 112. Esta
   página no se veía menos visual por faltarle imágenes — se veía contenida
   porque **lo más grande que teníamos era pequeño**.

   Se abre UN escalón por encima de `--t1`, y sólo se usa en dos sitios: la
   apertura y el nombre de cada puerta. Vive aquí y no en `caliber.css` a
   propósito: primero se prueba en una página; si se aprueba, gradúa al sistema.
   Un tamaño nuevo suelto por hoja es justo cómo se llegó a tener dieciséis.

   `clamp` de 52 a 104: a 390 px de ancho no puede pasar de 13.4% del ancho, que
   es el techo medido de la marca en móvil. */
:root{
  --t0: clamp(3.25rem, 7.2vw, 6.5rem);   /* 52 en teléfono · 104 arriba */
}

/* ── EL REVELADO ──────────────────────────────────────────────────────────
   Mismo gesto que `/proceso` para que las dos páginas se sientan una sola.
   Se dispara UNA vez con IntersectionObserver desde `puertas.js`: nada de
   listener de scroll, que es trabajo continuo en reposo y calienta el
   teléfono. Con `prefers-reduced-motion` todo nace visible. */
.pu-rev{ opacity: 0; }
.pu-rev[data-visto]{ animation: pu-enfoca .62s var(--curva) forwards; }
@keyframes pu-enfoca{ from{ opacity:0; translate:0 14px } to{ opacity:1; translate:0 0 } }

.pu-asienta{ opacity: 0; }
.pu-asienta[data-visto]{ animation: pu-asienta .74s var(--curva) forwards; }
@keyframes pu-asienta{ from{ opacity:0; translate:0 22px } to{ opacity:1; translate:0 0 } }

@media (prefers-reduced-motion: reduce){
  .pu-rev, .pu-asienta{ opacity:1; animation:none }
}

/* 🔴 EL ANCHO SE TOPA CON `padding-inline`, NUNCA CON `max-width` EN LA
   SECCIÓN. Estas secciones llevan su propio fondo (`data-cuerpo`,
   `data-niebla`): al caparlas con `max-width` dejan de ser página y se
   convierten en un rectángulo con canto visible a los lados. Ya pasó en
   `/proceso` y paco lo cazó: «los textos tienen borde que se ve mal». */
.pu-abre, .pu-recorrido, .pu-respiro, .pu-prueba, .pu-cifras, .pu-faq{
  padding-inline: max(1.5rem, (100% - 80rem) / 2);
}

/* ── P0 · LA APERTURA ─────────────────────────────────────────────────────
   Sin `min-height`. En `/proceso` un 78svh heredado dejó 418 px de vacío sobre
   el rótulo, más que el propio contenido. El alto lo pone el contenido. */
.pu-abre{
  display: flex; flex-direction: column;
  gap: clamp(1rem, 2vw, 1.9rem);
  padding-block: clamp(5rem, 11vh, 8.5rem) clamp(2.5rem, 6vh, 4.5rem);
}
/* 28 caracteres de medida: el titular tiene que romper en tres renglones a
   1440, que es lo que le da su forma de bloque. Más ancho se hace una línea
   larga y pierde el golpe. */
.pu-abre__dice{
  font-size: var(--t0); line-height: .98; letter-spacing: -.032em;
  max-width: 20ch;   /* suelo de medida — ver caliber.css §medida del display */
}
.pu-abre__tesis{ max-width: 46ch; color: var(--osc-2); }

/* ── P1 · EL RECORRIDO ────────────────────────────────────────────────────
   Rejilla de 12: cinco columnas de texto que scrollean, seis de cámara CLAVADA.

   🔴 EL `sticky` VA EN EL ITEM DE LA REJILLA Y EXIGE `align-self:start`. Por
   defecto un item de rejilla se estira a la altura de la fila; estirado, no
   tiene margen para pegarse a nada y el `sticky` no hace absolutamente nada,
   sin un solo error. Es el fallo clásico y es mudo.

   🔴 Y EL `top` TIENE QUE LIBRAR LA CABECERA. La cabecera es fija: pegar la
   pieza a `top:0` la mete debajo del logotipo. */
.pu-recorrido{ padding-block: clamp(2rem, 6vh, 4rem) clamp(4rem, 10vh, 7rem); }
.pu-recorrido__caja{
  display: grid;
  grid-template-columns: repeat(12, minmax(0,1fr));
  column-gap: clamp(1.5rem, 3vw, 3rem);
}
.pu-textos{ grid-column: 1 / -1; }
.pu-camara{
  grid-column: 7 / span 6;
  position: sticky;
  top: clamp(5.5rem, 13vh, 8rem);
  align-self: start;          /* 🔴 sin esto el sticky es decorativo */
}

/* Cada puerta ocupa una pantalla larga: es lo que le da recorrido a la cámara.
   `justify-content:center` reparte el aire arriba y abajo para que el bloque
   quede a la altura de la pieza, no colgando del borde. */
/* 🔴 EL ECLIPSE SE FUE Y LA COLUMNA DE MEDIO NO PODÍA QUEDARSE VACÍA. En vez
   de una pieza a la derecha, la puerta se parte en dos: el NOMBRE se clava a la
   izquierda mientras su propio contenido pasa por la derecha, y se suelta al
   llegar la puerta siguiente. Es el mismo mecanismo de antes sin ningún medio,
   y es lo que hace Koto: el nombre a un lado, las capacidades al otro.
   `min-height` se va: el alto lo pone el contenido, no un número. */
.pu-puerta{
  display: grid;
  grid-template-columns: repeat(12, minmax(0,1fr));
  column-gap: clamp(1.5rem, 3vw, 3rem);
  /* 🔴 SIN ALTO MÍNIMO EL PIN NO SIRVE DE NADA. Medido: la puerta medía 626 px
     y su cabecera 240, así que el nombre se despegaba a los 380 px de scroll —
     un `sticky` correcto que no se nota. Con 72svh hay recorrido de sobra y
     además las tres puertas dejan de ir pegadas una detrás de otra. */
  min-height: 88svh;   /* 648 px daban 0 de recorrido: el relleno se lo comía */
  padding-block: clamp(3.5rem, 10vh, 7rem);
  /* 🔴 NADA DE `align-items:start` AQUÍ. Un item de rejilla alineado a start
     mide lo que su contenido, y un `sticky` dentro de una caja de su misma
     altura NO TIENE POR DÓNDE VIAJAR: se quedaba pegado sólo un momento y
     seguía subiendo. La fila tiene que estirarse (`stretch`, el defecto) y el
     que se alinea a start es el hijo clavado. */
}
.pu-puerta__cab{
  grid-column: 1 / span 5;
  align-self: start;
  position: sticky; top: clamp(7rem, 16vh, 10rem);
  display: grid; gap: clamp(.8rem, 1.6vw, 1.3rem);
}
.pu-puerta__cuerpo{
  grid-column: 7 / span 6;
  display: grid; gap: clamp(1rem, 2vw, 1.6rem);
  align-content: start;
}
.pu-puerta + .pu-puerta{ border-top: 1px solid var(--linea-osc); }
/* 🔴 EL NOMBRE DE LA PUERTA ES EL TITULAR DE SU PANTALLA, NO UN SUBTÍTULO.
   A 48 px competía con la promesa y con la prosa; a 104 manda solo y deja que
   todo lo demás baje de tono en vez de pelear. */
/* El nombre se destapa por debajo de una máscara, como el titular de la
   apertura, y **baja de tono cuando su tramo ya pasó**: mientras lees Crecer,
   Construir sigue clavado arriba pero apagado. Es la jerarquía del sistema
   —tono, nunca peso— usada como movimiento. */
.pu-puerta h2{
  font-size: var(--t0); line-height: .96; letter-spacing: -.032em;
  color: var(--osc-3);
  transition: color var(--lento) var(--curva);
}
.pu-puerta[data-activo] h2{ color: var(--osc-1); }
.pu-puerta[data-activo] .pu-puerta__promesa{ color: var(--osc-1); }
.pu-puerta__promesa{ transition: color var(--lento) var(--curva); }
.pu-puerta__promesa{
  color: var(--osc-1); max-width: 22ch;
  font-size: var(--t3); line-height: 1.18;
}

/* La prosa es la que explica, y por eso baja de tono y sube de medida: se lee
   despacio. Tope de 62 caracteres, dentro del máximo de marca (75). */
.pu-puerta__prosa{
  color: var(--osc-2); max-width: 46ch;
  font-size: var(--t5); line-height: 1.62;
}

/* ── LAS DISCIPLINAS: un renglón corrido, no una pila ────────────────────
   🔴 CUATRO RENGLONES APILADOS SE LEEN COMO FORMULARIO. Pentagram enumera
   dieciséis disciplinas y no se lee a lista porque van EN PROSA, separadas por
   comas. Aquí van corridas y separadas por un punto medio, a tamaño de
   subtítulo: el bloque se lee de un vistazo y ocupa la mitad de alto.
   El separador es un pseudo y no un carácter en el HTML: así el último no lo
   lleva y el texto que copias no arrastra puntos sueltos. */
/* 🔴 NO PUEDE SER FLEX. Un `li` dentro de un contenedor flex se BLOQUEA
   —`display:inline` se ignora— y el separador se va a su propia línea. Esto es
   texto que fluye: contenedor de bloque, hijos en línea. */
.pu-oficios{
  list-style: none; margin: .2rem 0 0; padding: 0;
  display: block;
  /* 🔴 ESTABA EN `--t3`, EL MISMO CUERPO QUE LA PROMESA. Dos papeles distintos
     al mismo tamaño no forman jerarquía: compiten. Medido en /que-hacemos, la
     promesa («Que entre gente, y que compre») y la lista de disciplinas salían
     las dos a 28 px, y la lista, por ser más larga, ganaba la mirada.
     Con `--t4` la escalera queda 28 / 19 / 17: promesa, disciplinas, rasgos. */
  font-size: var(--t4); line-height: 1.34; letter-spacing: -.014em;
  color: var(--osc-2);
}
.pu-oficios li{ display: inline; }
.pu-oficios li:not(:last-child)::after{
  content: '·';
  color: var(--osc-3);
  margin: 0 .5em;
}
/* 🔴 AQUÍ VIVÍA UN HOVER QUE ENCENDÍA LA DISCIPLINA BAJO EL CURSOR Y APAGABA
   las otras tres. Estas `li` NO son enlaces ni llevan a ningún lado: encender
   algo que no se puede pulsar es prometer un clic que no existe, y en una
   captura deja la lista con un elemento «seleccionado» sin motivo. Retirado.
   Si algún día las disciplinas enlazan a su sección, el hover vuelve con
   ellas y entonces sí querrá decir algo. */

/* ── LAS CARACTERÍSTICAS: palomita, porque son una promesa ────────────────
   🔴 LA MISMA PALOMITA DE `/proceso`, dibujada igual: dos filetes de 1 px
   girados 45°, sin pedir una imagen. Repetir la marca a propósito es lo que
   hace que el sitio tenga una gramática. Va en acento: el color se reparte en
   marcas finas en vez de concentrarse en una palabra grande, que competiría
   con el titular.
   `align-items:start` y no `center`: con dos renglones el ancla es la PRIMERA
   línea, no el bulto del texto. */
.pu-marcas{
  list-style: none; margin: .3rem 0 0; padding: 0;
  display: grid; gap: .7rem;
}
.pu-marcas li{
  display: grid; grid-template-columns: 1rem 1fr; gap: .65rem;
  align-items: start;
  color: var(--osc-2);
  font-size: var(--t5);
}
.pu-marcas li::before{
  content: '';
  width: .62rem; height: .34rem;
  border-left: 1px solid var(--acento);
  border-bottom: 1px solid var(--acento);
  rotate: -45deg;
  margin-top: .48em;   /* media línea de cuerpo menos media palomita */
}

.pu-puerta__ruta{ margin: .6rem 0 0; }

/* 🔴 `figure` TRAE `margin: 1em 40px` DEL NAVEGADOR. Sin esta línea la pieza
   se mete 40 px por cada lado y en móvil se ve descuadrada respecto al texto,
   que sí está alineado al borde de la sección. Se perdió una vez al reescribir
   este bloque y el síntoma fue exactamente ese.
   ── LA PIEZA ─────────────────────────────────────────────────────────────
   La definitiva es un vídeo prerenderizado que FLOTA sobre la tinta, sin
   marco. Medido hoy: ninguna de las seis referencias usa 3D en vivo en su
   página de servicios; las dos que sí montan WebGL (Locomotive, Active Theory)
   lo tienen en la PORTADA. Aquí el hero ya carga un lienzo: un segundo motor
   en la misma página es el patrón que calienta el teléfono. */
.pu-pieza{ margin: 0; }
/* ══ LA LÁMINA TIPOGRÁFICA (sustituye al vídeo) ═══════════════════════════
   La pieza clavada ya no enseña un render: enseña el ECLIPSE de la marca con
   tres arcos, uno por puerta, y se enciende el de la que estás leyendo.

   🔴 POR QUÉ ESTO Y NO UNA ILUSTRACIÓN. Dos intentos con imagen generada
   dieron piezas de metal bonitas que no decían «Construir»: el salto entre la
   imagen y la palabra lo tenía que dar el visitante. El eclipse ya ES nuestro
   motivo, pesa dos kilobytes, se anima, y ningún competidor lo puede usar.

   Los arcos se dibujan con `stroke-dasharray` sobre un solo círculo: un arco y
   un hueco, girado para cada puerta. Nada de tres rutas calculadas a mano. */
/* 🔴 EN SVG, `transform-origin: 50% 50%` NO ES EL CENTRO DEL viewBox: es el
   centro de la CAJA DE TRAZO del elemento, que en un arco no está donde crees.
   El grupo giraba alrededor de un punto descentrado y los arcos salían
   despedidos fuera del cuadro. `transform-box: view-box` hace que el 50% sea
   el del lienzo, que es lo que uno da por hecho. */
.pu-orbe{
  display: block; width: 100%; max-width: 26rem; margin-inline: auto;
  height: auto; overflow: visible;
}
.pu-orbe circle{ fill: none; }
/* ⚠️ Y SOLO AL GRUPO. Poner `transform-origin` también en los arcos pisa el
   centro que ya lleva su atributo `rotate(-90 120 120)` y los manda a la
   esquina contraria del lienzo: se veían dos arcos sueltos abajo a la
   izquierda y el aro arriba a la derecha. */
.pu-orbe__gira{ transform-box: view-box; transform-origin: center; }
.pu-orbe .aro{ stroke: var(--linea-osc); stroke-width: 1.25; }
.pu-orbe .arco{
  stroke: var(--osc-3); stroke-width: 2.5; stroke-linecap: round;
  opacity: .3;
  transition: stroke var(--lento) var(--curva), opacity var(--lento) var(--curva),
              stroke-width var(--lento) var(--curva);
}
.pu-orbe .arco[data-vivo]{ stroke: var(--acento); opacity: 1; stroke-width: 4.5; }
/* el disco: un eclipse necesita el cuerpo que TAPA, o es sólo un anillo */
.pu-orbe .disco{ fill: var(--tinta); stroke: none; }

/* gira despacio y no para: es lo único de la página en movimiento continuo y
   por eso funciona como pico. 60 s por vuelta — más rápido se nota y distrae. */
@media (prefers-reduced-motion: no-preference){
  .pu-orbe__gira{ animation: pu-orbita 60s linear infinite; }
}
@keyframes pu-orbita{ to{ rotate: 360deg } }

.pu-pieza__video{
  display: block; width: 100%; height: auto;
  aspect-ratio: 8 / 5;
  background: transparent;
  /* 🔴 SIN MÁSCARA, UN VÍDEO OSCURO SOBRE TINTA ES UNA CAJA NEGRA. El render
     sale a negro casi puro y la sección tiene su propio degradado, así que el
     rectángulo del vídeo se recorta contra el fondo y la pieza deja de flotar:
     pasa a estar PEGADA, que es justo el defecto que la lámina plana vino a
     resolver en la película. La máscara difumina los cuatro cantos y el plató
     del render se funde con el de la página.
     ⚠️ `mask` necesita el prefijo -webkit- para Safari; sin él la caja vuelve. */
  -webkit-mask-image: radial-gradient(115% 115% at 50% 48%, #000 62%, transparent 100%);
          mask-image: radial-gradient(115% 115% at 50% 48%, #000 62%, transparent 100%);
}
/* ── EL PIE QUE CAMBIA ────────────────────────────────────────────────────
   La pieza es una sola y está clavada; lo que cambia es lo que enseña, así que
   su pie también. Los tres viven apilados en la MISMA celda de una rejilla:
   así el bloque mide siempre lo del pie más largo y **el texto de abajo no
   brinca** al cambiar de puerta. Ocultarlos con `display:none` haría justo eso.
   `visibility` además los saca del árbol de accesibilidad, que es lo correcto:
   sólo se anuncia el que se ve. */
.pu-pie{
  margin: .9rem 0 0; font-size: var(--t6);
  color: var(--osc-3); max-width: 42ch;
  display: grid;
}
.pu-pie > [data-pie]{
  grid-area: 1 / 1;
  opacity: 0; visibility: hidden;
  transition: opacity var(--base) var(--curva);
}
.pu-pie > [data-pie][data-vivo]{ opacity: 1; visibility: visible; }

/* 🟡 EL MARCADOR — provisional, se va con el render.
   Punteado a propósito: un filete continuo se leería como el marco que la
   pieza final NO va a tener, y acabaríamos discutiendo un borde que nadie
   pensaba poner. */
.pu-marcador{
  aspect-ratio: 8 / 5;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: .5rem;
  border: 1px dashed rgba(143,181,201,.35);
  border-radius: 18px;
  background:
    radial-gradient(120% 90% at 50% 40%, rgba(143,181,201,.07), transparent 70%),
    var(--sup-1);
}
.pu-marcador{ padding-inline: 1.2rem; text-align: center; }
.pu-marcador__eti{ color: var(--acento); font-size: var(--t6); }
.pu-marcador__dim{ color: var(--osc-3); font-size: var(--t6); }

/* ── P4 · EL RESPIRO ──────────────────────────────────────────────────────
   Una frase sola. El `min-height` aquí SÍ se justifica: el vacío es el
   contenido. Comprimir para poder soltar. */
.pu-respiro{
  min-height: 62svh;
  display: flex; align-items: center;
  padding-block: clamp(4rem, 12vh, 9rem);
}
/* 🔴 A SANGRE Y ROMPIENDO EL MARGEN. La frase que abre el abanico es el
   momento de la página: a tamaño de titular y contenida se leía como un
   párrafo más. Aquí sube al escalón nuevo y se sale por la derecha, que es el
   recurso que ya existe en el cierre de la portada. */
.pu-respiro__frase{
  margin: 0; max-width: none;
  font-size: var(--t0); line-height: 1.0; letter-spacing: -.032em;
  color: var(--osc-1);
}
.pu-respiro__frase .tenue{
  display: block; margin-top: .18em; color: var(--osc-3);
  font-size: .46em; letter-spacing: -.02em; line-height: 1.22; max-width: 26ch;
}

/* ── P4-bis · LAS CIFRAS ──────────────────────────────────────────────────
   Cuatro números al escalón nuevo, en fila, con su glosa debajo en tono bajo.
   La jerarquía la hace el TAMAÑO —doce veces el cuerpo—, no el peso: seguimos
   con un solo 400 en todo el sitio.
   `tabular-nums` para que los dígitos midan igual y la fila no baile. */
.pu-cifras{ padding-block: clamp(3rem, 8vh, 6rem); }
.pu-cifras__lista{
  display: grid; grid-template-columns: repeat(4, minmax(0,1fr));
  gap: clamp(1.5rem, 3vw, 3rem);
  margin: clamp(1.5rem, 4vh, 2.6rem) 0 0;
  border-top: 1px solid var(--linea-osc); padding-top: clamp(1.5rem, 3vh, 2.4rem);
}
.pu-cifras__lista > div{ display: grid; gap: .5rem; align-content: start; }
.pu-cifra{
  font-size: var(--t0); line-height: .9; letter-spacing: -.04em;
  color: var(--osc-1); margin: 0;
  font-variant-numeric: tabular-nums;
}
.pu-cifra__u{ font-size: .42em; letter-spacing: 0; margin-left: .06em; color: var(--osc-3); }
.pu-cifras__lista dd{
  margin: 0; color: var(--osc-2); font-size: var(--t6); max-width: 22ch;
  line-height: 1.45;
}
@media (max-width: 860px){
  .pu-cifras__lista{ grid-template-columns: repeat(2, minmax(0,1fr)); row-gap: 2rem; }
}

/* ── P4-ter · LAS PREGUNTAS ───────────────────────────────────────────────
   Acordeón nativo, mismo patrón que `/proceso`.
   🔴 `allow-discrete` es lo que hace visible la SALIDA: sin él el contenido
   desaparece de golpe al cerrar y sólo se ve la mitad del gesto.
   ⚠️ `interpolate-size` NO es Baseline: va tras `@supports` y donde no exista,
   abre sin transición de altura — degradación aceptable, nunca un salto. */
.pu-faq{ padding-block: clamp(3rem, 8vh, 6rem); }
/* ⚠️ EL ACORDEÓN SE FUE A `caliber.css` COMO `.mas` — era la segunda de
   tres copias que iban a existir. Aquí sólo queda el respiro de la
   sección; las clases del HTML se renombraron a `.mas` / `.mas__cuerpo`. */

/* ── P5 · LOS CASOS ───────────────────────────────────────────────────────
   Índice, no rejilla de tarjetas. Cuatro tarjetas en fila enseñan que son
   cuatro; cuatro renglones se leen como un índice que podría seguir. */
.pu-casos{
  list-style: none; margin: 0; padding: 0;
  border-top: 1px solid var(--linea-osc);
}
.pu-casos a{
  display: grid;
  grid-template-columns: minmax(0,1fr) minmax(0,1fr) auto;
  align-items: baseline; gap: 1rem;
  padding: clamp(1rem, 2.4vh, 1.6rem) 0;
  border-bottom: 1px solid var(--linea-osc);
  text-decoration: none; color: inherit;
  transition: color var(--rapido) var(--curva);
}
.pu-casos__nom{ font-size: var(--t3); color: var(--osc-2); transition: color var(--rapido) var(--curva); }
.pu-casos__que{ font-size: var(--t6); }
.pu-casos__ir{ color: var(--osc-3); transition: translate var(--base) var(--curva); }
.pu-casos a:hover .pu-casos__nom{ color: var(--osc-1); }
.pu-casos a:hover .pu-casos__ir{ translate: 4px -4px; color: var(--acento); }
.pu-casos a:focus-visible{ outline: 2px solid var(--acento); outline-offset: 4px; }

/* ── EL REVELADO DE LOS CASOS ─────────────────────────────────────────────
   La imagen aparece al pasar el cursor, como en el índice de trabajo de la
   portada. Sin esto, el final de la página son cuatro renglones de texto y se
   apaga justo donde tiene que empujar.

   🔴 LA IMAGEN NO PUEDE ROBAR EL CLIC: `pointer-events:none`. Si la lámina
   queda encima del enlace, el ratón entra en ella, sale del enlace, se apaga el
   hover, vuelve a entrar… y parpadea. Ya nos pasó con la tarjeta-enlace.
   🔴 Y NO SE ANIMA `width`/`height`: sólo `opacity` y `scale`, que no tocan
   maquetación. */
.pu-casos{ position: relative; }
.pu-casos__lam{
  position: absolute; right: 0; top: 0;
  width: min(30vw, 22rem); aspect-ratio: 4 / 3;
  object-fit: cover; border-radius: 14px;
  opacity: 0; scale: .96;
  pointer-events: none;
  transition: opacity var(--base) var(--curva), scale var(--base) var(--curva),
              translate var(--lento) var(--curva);
  z-index: 2;
}
.pu-casos__lam[data-vivo]{ opacity: 1; scale: 1; }

@media (hover: none){
  /* En táctil no hay hover: la lámina nunca se enciende y sólo estorbaría. */
  .pu-casos__lam{ display: none; }
}

/* ══ MOVIMIENTO ═══════════════════════════════════════════════════════════
   Cuatro gestos y ninguno decorativo. La regla del sistema: el movimiento
   tiene que EXPLICAR algo, y necesita un pico — si todo se mueve igual, nada
   se mueve. Todo va con `transform`/`opacity`/`clip-path`, que no tocan
   maquetación; nada anima `width`, `height` ni `top`.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1 · EL TITULAR SE DESCUBRE POR DEBAJO DE UNA MÁSCARA ─────────────────
   No aparece: se destapa, como si estuviera escrito y alguien levantara la
   hoja. `clip-path` recorta sin mover al vecino, así que no hay salto de
   maquetación (CLS) por muy grande que sea el bloque. */
.pu-asienta{ opacity: 0; }
.pu-asienta[data-visto]{
  animation: pu-descubre 1s var(--curva) forwards;
}
@keyframes pu-descubre{
  from{ opacity:0; clip-path: inset(0 0 100% 0); translate: 0 18px }
  to  { opacity:1; clip-path: inset(0 0 -12% 0); translate: 0 0 }
}

/* ── 2 · LAS LISTAS ENTRAN EN CASCADA ────────────────────────────────────
   🔴 EL ESCALONADO ES LO QUE CONVIERTE UNA LISTA EN UN GESTO. Los cuatro
   renglones entrando a la vez son un bloque que aparece; entrando a 70 ms de
   distancia se leen en orden, que es como se van a leer de todos modos.
   El retraso va por `nth-child` y no por una variable en el HTML: son cinco
   renglones como mucho y así el marcado se queda limpio. */
.pu-oficios[data-visto] li,
.pu-marcas[data-visto] li{
  animation: pu-enfoca .55s var(--curva) backwards;
}
.pu-oficios[data-visto] li:nth-child(1), .pu-marcas[data-visto] li:nth-child(1){ animation-delay: .04s }
.pu-oficios[data-visto] li:nth-child(2), .pu-marcas[data-visto] li:nth-child(2){ animation-delay: .11s }
.pu-oficios[data-visto] li:nth-child(3), .pu-marcas[data-visto] li:nth-child(3){ animation-delay: .18s }
.pu-oficios[data-visto] li:nth-child(4), .pu-marcas[data-visto] li:nth-child(4){ animation-delay: .25s }
.pu-oficios[data-visto] li:nth-child(5), .pu-marcas[data-visto] li:nth-child(5){ animation-delay: .32s }

/* ⚠️ AQUÍ VIVÍA EL FILETE QUE SE DIBUJABA SOLO. Era de la lista apilada; al
   pasar las disciplinas a renglón corrido se quedó pisando el separador (un
   `::after` no puede ser dos cosas) y las dejaba SUBRAYADAS y pegadas:
   «Dominio, hosting y seguridadSoporte». Retirado a propósito. */

/* ── 3 · EL RIEL: SABER DÓNDE ESTÁS ──────────────────────────────────────
   Tres puntos sobre una línea, uno por puerta, y se enciende el de la que
   estás leyendo. Es el único elemento que da orientación en un recorrido de
   tres pantallas, y además es el que ata la columna de texto con la pieza
   clavada: las dos cosas hablan de la misma puerta al mismo tiempo. */
.pu-textos{ position: relative; padding-left: clamp(1.4rem, 3vw, 2.6rem); }
.pu-textos::before{
  content:''; position:absolute; left:0; top:0; bottom:0; width:1px;
  background: var(--linea-osc);
}
.pu-puerta{ position: relative; }
.pu-puerta::before{
  content:''; position:absolute;
  left: calc(-1 * clamp(1.4rem, 3vw, 2.6rem) - 3.5px); top: 50%;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--tinta);
  box-shadow: inset 0 0 0 1px var(--osc-3);
  transition: background var(--base) var(--curva),
              box-shadow var(--base) var(--curva),
              scale var(--base) var(--curva);
}
.pu-puerta[data-activo]::before{
  background: var(--acento);
  box-shadow: inset 0 0 0 1px var(--acento), 0 0 0 6px rgba(143,181,201,.12);
  scale: 1.15;
}

/* ── 4 · EL PICO: LA PIEZA RESPIRA CON EL SCROLL ─────────────────────────
   El único movimiento continuo de la página, y sólo aquí. Va con líneas de
   tiempo de scroll nativas: cero JavaScript, corre en el hilo del compositor
   y no puede tirar un cuadro.
   ⚠️ `view()` mide EL ELEMENTO, no la sección — por eso el rango se declara
   sobre la propia pieza. Y va dentro de `@supports`: donde no exista, la
   pieza simplemente se queda quieta y no falta nada. */
@supports (animation-timeline: view()){
  @media (prefers-reduced-motion: no-preference){
    .pu-camara{
      animation: pu-respira linear both;
      animation-timeline: view();
      animation-range: entry 10% exit 90%;
    }
    @keyframes pu-respira{
      0%  { scale: .965; opacity: .55 }
      18% { scale: 1;    opacity: 1 }
      82% { scale: 1;    opacity: 1 }
      100%{ scale: .985; opacity: .7 }
    }
  }
}

@media (prefers-reduced-motion: reduce){
  .pu-oficios[data-visto] li, .pu-marcas[data-visto] li{ animation: none }
}

/* ── MÓVIL ────────────────────────────────────────────────────────────────
   La puerta se apila y el nombre deja de clavarse: en 390 px un titular de 52
   px pegado arriba se come el sitio donde hay que leer. */
@media (max-width: 860px){
  .pu-recorrido__caja{ grid-template-columns: 1fr; }
  .pu-textos{ grid-column: 1; }
  .pu-puerta{ grid-template-columns: 1fr; row-gap: clamp(1.2rem, 3vh, 2rem); }
  .pu-puerta__cab{ grid-column: 1; position: static; }
  .pu-puerta__cuerpo{ grid-column: 1; }
  .pu-abre__dice{ max-width: none; }
  .pu-respiro{ min-height: 46svh; }
  .pu-casos a{ grid-template-columns: minmax(0,1fr) auto; }
  .pu-casos__que{ display: none; }   /* el nombre basta; el resto es ruido a 390 */
}
