/* Composición por sección — Tareas 3 a 7 */

/* --- 1 a 3 · El recorrido: hero, problema y proceso en un solo riel (Tareas 3 a 5) --- */
/* La página es un recorrido guiado por el scroll. La secuencia de fotogramas avanza, SE DETIENE
   en once fotogramas medidos, y es ahí —y sólo ahí— donde entra el texto. Eso no es una decisión
   de estilo: con el texto confinado a las paradas, el fondo bajo cada letra es un fotograma
   CONOCIDO y su contraste está medido contra el píxel real. Por eso cada tiempo declara su tinta
   y esta hoja se limita a traducirla: el color del texto sale del atributo `data-tinta`, nunca de
   una decisión tomada aquí. El guion de los dieciocho tiempos está en js/tiempos.js y el porqué
   en las secciones 3 y 4 de docs/superpowers/specs/2026-10-15-storytelling-v2-design.md.

   TODO lo de este bloque cuelga de `.js-recorrido`, la clase que js/lienzo.js pone en <html>
   cuando hay canvas y la red no está activa. Quitada la clase, la página queda igual que sin
   JavaScript: los once `.paso` en flujo normal, en orden de lectura y sin solaparse. La única
   regla que vive FUERA de la clase es la de aquí debajo, la que esconde el canvas. */

/* Sin JavaScript no hay canvas. Un <canvas> sin módulo que lo pinte no es invisible: es una caja
   vacía con el tamaño de mapa de bits por omisión. Medido antes de esta regla: 300x150 px
   empujando los once bloques de texto 150 px hacia abajo en los cinco anchos de prueba. */
.recorrido__lienzo{ display:none }

/* Sin JavaScript, el aire. Son las dos únicas reglas de maqueta que viven fuera de la clase, y
   están aquí porque `base.css` pone `*{margin:0}`: sin ellas los once bloques salen apelmazados
   unos contra otros y contra el borde izquierdo, que es legible a duras penas y desde luego no es
   «completa». Con la clase puesta, el riel se queda sin relleno y los once bloques comparten
   celda, así que ninguna de las dos pinta nada. */
.recorrido{ padding:var(--section-pad) var(--pad) }
.recorrido__textos{ display:grid; gap:var(--gap) }
.recorrido__rotulos{ display:grid; gap:.4rem; margin-bottom:var(--gap) }

/* El riel. Lo que la sección mide de más que la ventana es el recorrido del scroll, y cada tiempo
   se lleva su peso de js/tiempos.js.
   LA REGLA, que hay que aplicar cada vez que se gire un peso: el peso de js/tiempos.js es
   RELATIVO —una fracción del total—, así que subir el de las paradas para que el texto se quede
   más rato ACELERA los avances, que es lo contrario de lo que se pedía. Para que la secuencia
   siga corriendo a la misma velocidad, el riel tiene que crecer en la misma proporción que el
   total. De los 1400vh y PESO_TOTAL 21.4 originales salen 719,6vh de avance, y ese número es el
   que se conserva:
     1400 -> 1725vh con PESO_TOTAL 26.4 (paradas de 1.00/0.80 a 1.50/1.20, que el cliente pidió
             que se quedaran más rato)
     1725 -> 1780vh con PESO_TOTAL 27.2 (los pasos 4 y 5 suben a 1.90, que el cliente pidió que se
             quedaran más rato todavía porque llevan el argumento de máquina y de volumen)
     1780 -> 1720vh con PESO_TOTAL 26.285 (el arranque pierde cinco fotogramas idénticos y el tramo
             quieto del ponchado pasa a ritmo 0.015: ver el tiempo 6 en js/tiempos.js)
     1720 -> 1630vh con PESO_TOTAL 24.885 (se va la parada del problema: su titular se leía como un
             lema y bajó a texto de apoyo del encabezado de los fallos)
     1630 -> 1522vh con PESO_TOTAL 23.235 (el render de octubre de 2026: dura 26,5 s en vez de 30,
             y los dos tramos quietos medidos —f094-f100 y f170-f183— pasan a ritmo 0,015)
     1522 -> 1522vh, el mismo (la toma del equipo se extrae a 20 fps en vez de a 8 para que el
             movimiento de las personas se vea natural, y el texto de dos paradas pasa a durar
             todo el avance siguiente. Son 248 fotogramas y veinte tiempos en vez de 212 y
             dieciocho, pero el peso total sale igual: los 36 fotogramas densos de más van a
             ritmo 0,02 y pesan lo que pesaban los pocos que sustituyen)
   Comprobado: el scroll por unidad de peso se mantiene en 65,4vh en los cinco riales (1400/21.4,
   1725/26.4, 1780/27.2, 1720/26.285 y 1630/24.885), que es lo que hace que un avance de ritmo 0,05
   corra siempre a la misma velocidad. 1522/23.235 da 65,5: el mismo.
     1483 -> 1542vh con PESO_TOTAL 23.535 (los tres fallos suben de 1.20 a 1.50, que es lo que
             pesan las paradas de los pasos: el cliente dijo que «se frunce dura muy poco, debe
             durar igual que los siguientes». 1542/23.535 da 65,5: el mismo)
     1522 -> 1483vh con PESO_TOTAL 22.635 (el hero baja de 1.40 a 0.80: el cliente dijo que el
             arranque duraba demasiado antes de que entraran los problemas, y el hero es la
             parada que menos necesita durar, porque es lo que ya está mirando cuando decide
             bajar. 1483/22.635 da 65,5: el mismo de siempre)
   Y el reparto de lectura queda en 98vh por parada de paso, 124vh en los pasos 4 y 5, 78vh en
   cada paso, 124vh en los pasos 4 y 5, 98vh en cada fallo y 52vh en el hero. */
.js-recorrido .recorrido{ min-height:1542vh; padding:0 }

.js-recorrido .recorrido__fijo{
  position:sticky; top:0;
  /* ALTURA EN svh Y NO EN dvh, Y ES UNA CORRECCIÓN QUE SALE DE UNA GRABACIÓN DEL CLIENTE.
     `dvh` es el viewport DINÁMICO: en un teléfono crece cuando la barra de direcciones se
     esconde al primer scroll. Con la capa en dvh, ese momento no es un cambio de altura
     cualquiera: la capa ocupa la pantalla entera y lleva dentro un lienzo cuyo mapa de bits se
     redimensiona con ella, así que al primer arrastre la imagen pega un estirón. El cliente lo
     describió como «la pantalla se estira hacia arriba en lugar de hacer el scroll», y siguió
     pasándole después de quitar el rebote del navegador, que era la otra mitad del problema.
     `svh` es el viewport PEQUEÑO —el de la barra desplegada— y NO cambia con el scroll. La capa
     deja de moverse y el lienzo deja de redibujarse a destiempo.
     Lo que cuesta: cuando la barra se esconde, sobra una franja de `lvh - svh` por debajo de la
     capa. Esa franja la tapa el fondo del riel, que en móvil es el mismo navy del campo del
     fotograma (ver el bloque de móvil), así que no se ve.
     En escritorio svh, dvh y lvh valen lo mismo: no hay barra que se mueva. */
  height:100vh;
  height:100svh;  /* con reserva: quien no conozca svh se queda con la línea de arriba */
  /* TRES FILAS, Y ESO ES LO QUE IMPIDE EL SOLAPE. Antes el rótulo y el bloque de texto
     compartían celda: el rótulo pegado arriba, el texto centrado, y lo único que los separaba
     era un margen que yo había calculado. Calculado se queda corto en cuanto cambia el ancho de
     la ventana o el tamaño de letra del navegador, y el cliente lo vio: «PROBLEMAS QUE
     RESOLVEMOS ANTES DE PRODUCIR» se le montó encima de «SE FRUNCE». Con la rejilla el texto NO
     PUEDE subir a la zona del rótulo, venga el cuerpo de donde venga, porque no es un cálculo
     mío: es la rejilla la que lo impide.
     LAS TRES SON SIMÉTRICAS —20 % / resto / 20 %— y la de abajo no es decoración. Con sólo dos
     filas el texto quedaba centrado en el 60 % de la CAPA, y cuando la ventana es mucho más alta
     que 16:9 eso ya no es el 60 % del FOTOGRAMA: a 1024x900 el fotograma ocupa sólo la franja
     central —del 18,5 % al 81,5 % de la capa— porque arriba y abajo se estira su borde, así que
     el 71 % de la capa cae en el 84 % del fotograma. Medido: el texto del paso 5 se salía por
     debajo del cian, que acaba en el 76,3 %, y daba 1,05:1. Con la tercera fila el bloque vuelve
     al centro de la capa, que es exactamente el centro del fotograma.
     El 20 % va fijo y no automático para que el texto quede siempre a la misma altura pase lo
     que pase con el rótulo, y para que dentro de esa franja cada rótulo pueda colocarse donde le
     toque: arriba el del proceso, que tiene que caer en la franja de su fotograma; abajo el de
     los problemas, que es lo que pidió el cliente y ahí se puede porque el f020 es blanco entero.
     El cuadro cruza las tres filas: es el fondo de todas. */
  display:grid;
  grid-template-columns:100%;
  grid-template-rows:20% 1fr 20%;
  /* La tinta la fija el TIEMPO, no esta hoja. El valor de aquí es sólo el de reposo, para que un
     `data-tinta` ausente —el instante entre que entra la clase y js/lienzo.js publica el primer
     tiempo— nunca deje texto sin color. */
  --tinta:var(--ink);
  /* EL CAMPO: el color plano del fotograma de la parada, muestreado del .webp y publicado por
     js/lienzo.js en `data-campo`. Dos cosas cuelgan de él.
     · El fondo de la capa, que es lo que se ve entre que entra la clase y llega el primer
       fotograma. Ya no es --stock ni --panel: el navy de la secuencia es #010040 y el de la marca
       #000C43, y pintar el de la marca junto al fotograma deja ver el corte. Era justo lo que se
       veía en la parada de «Aprobación».
     · El RESALTE, el color con el que se marcan las palabras clave dentro del apoyo. No puede ser
       uno solo: sobre campo claro el rojo se lee y el cian no, y sobre el campo navy al revés.
       Medidos contra el campo real y ya con el 0,85 de opacidad del apoyo encima:
         campo blanco #fdfdfd + #C40000 -> 5,29:1     campo cian #18fff3 + #C40000 -> 5,52:1
         campo navy   #010040 + --cyan  -> 11,18:1
       El rojo del resalte es #C40000 y no --red-ink (#D40000) porque sobre el cian el D4 se queda
       en 4,38:1, por debajo del mínimo; el C4 pasa los dos campos claros con el mismo valor. */
  --campo:var(--stock);
  --resalte:#C40000;
  /* El rótulo lleva TINTA PROPIA porque no cae donde el texto. En el f062 cae sobre la franja
     roja —el 27,4 % de arriba— mientras el texto de esa parada va sobre el blanco de abajo, y de
     las dos tintas de marca sólo una sirve sobre ese rojo: hueso 4,56:1, navy 3,88:1. En el f233
     pasa al revés: el rótulo sobre la franja navy de arriba y el texto sobre el blanco de en
     medio. Y en el f208 el cian llega hasta arriba del todo, así que ahí el rótulo va en navy
     sobre cian, 14,68:1, mientras en las otras cinco paradas del proceso va en hueso. Por eso son
     dos atributos y no uno. */
  --tinta-rotulo:var(--ink);
  background:var(--campo);
}
.js-recorrido .recorrido__fijo[data-campo="blanco"]{ --campo:#fdfdfd }
.js-recorrido .recorrido__fijo[data-campo="navy"]{ --campo:#010040; --resalte:var(--cyan) }
.js-recorrido .recorrido__fijo[data-tinta-rotulo="hueso"]{ --tinta-rotulo:var(--panel-ink) }
.js-recorrido .recorrido__fijo[data-tinta-rotulo="navy"]{ --tinta-rotulo:var(--ink) }
.js-recorrido .recorrido__fijo[data-tinta="hueso"]{
  --tinta:var(--panel-ink);
}

/* El cuadro va A SANGRE, no al 70 %. La especificación pide «al menos el 70 %» y el 100 % lo
   cumple; lo que lo decide es que el texto tiene que caber DENTRO del campo plano del fotograma,
   y ese campo es un porcentaje del cuadro: al 70 % el campo navy del f090/f130 —el más estrecho
   de los siete, 37,6 %— mide 270 px a 1024 y 379 a 1440, y el titular más largo de esas paradas
   pide 310; a sangre pasa a medir 379 a 1024 y 536 a 1440. Al 70 % no alcanzaba por debajo de
   1920 px en ningún ancho. A sangre, además, la franja roja del f233 —el 3,2 % izquierdo— encoge
   a 33 px a 1024, y el texto, que arranca en var(--pad), la libra entera.
   El segundo término del min() impide que la proporción 16:9 saque el cuadro de la ventana en
   pantallas anchas y bajas —a 2560x620 el ancho completo pide 1431 px de alto y sólo hay 620—;
   va expresado en ancho y no con max-height para no pelear con `aspect-ratio`. Cuando ese
   término manda, el cuadro queda centrado y más estrecho, y entonces el campo útil es aún MÁS
   ancho que el 37,6 % de la capa, porque a los lados queda el fondo de la capa, que ya lleva la
   tinta. Por eso los topes de abajo se calculan contra el caso peor, el cuadro a sangre.
   Sin fondo propio a propósito: hasta que llega el primer fotograma se ve el de la capa, que ya
   es el campo que la tinta de ese tiempo necesita. */
.js-recorrido .recorrido__lienzo{
  display:block;
  grid-area:1 / 1 / -1 / -1;   /* cruza las tres filas: es el fondo de todas */
  /* LA CAPA ENTERA, sin proporción propia. Antes el lienzo era 16:9 y dejaba dos franjas de color
     de página arriba y abajo —90 px a 1440x900—; ese corte es lo que se veía como «el fondo no
     acompaña a la secuencia». Ahora el lienzo cubre la capa y el relleno lo pone js/lienzo.js con
     los píxeles del propio fotograma (ver `dibujar`), así que no hay dos planos que casar.
     El mapa de bits sigue siendo de 1280 de ancho: lo que cambia es su alto, que lo pone el JS
     siguiendo la proporción de ESTA caja. */
  width:100%;
  height:100%;
}

/* El texto vive en la mitad izquierda, que es donde los fotogramas de parada dejan campo libre.
   Campos medidos muestreando los .webp del perfil de 1280 (hasta dónde llega el campo plano de
   la izquierda, por filas del 30 % al 70 % del alto):
     f020 blanco hasta el 100 %, con el logotipo entrando en el 56,2 % a media altura
     f045 y f062 blanco hasta el 51,3 %      f090 y f130 navy hasta el 37,6 %
     f178 cian hasta el 62,3 %               f233 franja roja del 0 al 3,2 %, blanco después
   Y por columnas (10 % a 36 % del ancho), la franja vertical de campo plano: f045 y f062 del
   28,3 % al 100 %, f178 del 14,7 % al 89,4 %, f233 del 22,8 % al 76,1 %, f020 f090 y f130
   enteros. La intersección —28,3 % a 76,1 % del alto— es la franja que la especificación
   muestreó como 30-70 %.
   La columna se mete entera en el campo más estrecho de los siete, con dos topes medidos:
   · POR LA IZQUIERDA, `max(var(--pad), 4%)`. El 3,2 % izquierdo del f233 es una franja roja
     —rgb(232,0,2)— sobre la que el navy da 3,91:1, por debajo del mínimo. var(--pad) la libra
     sola hasta 1600 px de ancho, porque va en 5vw; de ahí para arriba se topa en 4rem y la
     franja lo adelanta (a 2560 son 81 px de rojo y 64 de relleno). El 4 % deja siempre al menos
     8 px de holgura sobre el 3,2 %: 10 px a 1280, 13 a 1600, 20 a 2560.
   · POR LA DERECHA, el borde del campo navy del f090/f130, el 37,6 %, menos 8 px de holgura. Va
     calculado contra el ancho de la CAPA y no del cuadro, que es el caso peor: cuando el cuadro
     se estrecha por alto, el campo real crece.
   Esto acota las LÍNEAS, que envuelven. Lo que no envuelve es una palabra suelta, y de ahí sale
   el tercer dial, el término en vw de --t-parada (ver tokens.css): «APROBACIÓN» mide 7,97 veces
   el cuerpo y es el titular que manda en el campo más estrecho.
   Con todo eso el bloque sigue sin cruzar el centro del cuadro, así que sigue sin tocar el
   logotipo del f020, que empieza en el 56,2 %. La tabla de holguras de los once tiempos está en
   el informe de la tarea. */
.js-recorrido .recorrido__textos{
  grid-area:2 / 1;             /* la fila de en medio: nunca puede subir a la del rótulo */
  align-self:center;
  justify-self:start;
  /* LOS TOPES VAN CONTRA EL CUADRO, NO CONTRA LA VENTANA. El campo plano del fotograma es un
     porcentaje DEL FOTOGRAMA, y el fotograma sólo coincide con la ventana cuando esta es más
     alta que 16:9. Cuando es más ancha —2560x620 y parecidas— el fotograma se estrecha y se
     centra, y una columna medida en porcentaje de la ventana se sale de él: así es como el texto
     de «Entrega» acababa cruzando la franja roja del f233, que es su 3,4 % izquierdo.
     --cuadro es el ancho del fotograma y --orilla lo que queda a su izquierda; con los dos, el
     4 % y el 37,6 % vuelven a ser lo que se midió. Cuando la ventana es más alta que 16:9,
     --orilla es 0 y esto es idéntico a lo de antes. */
  --cuadro:min(100%, calc(100vh * 16 / 9));
  --cuadro:min(100%, calc(100dvh * 16 / 9));
  --orilla:max(0px, calc((100% - var(--cuadro)) / 2));
  --sangria:max(var(--pad), calc(var(--cuadro) * 0.04));
  width:min(calc(var(--cuadro) * 0.42), 34rem);
  /* 0.366 y no 0.376: el 37,6 % es el borde del campo navy del f090/f097, pero NO es el campo
     más estrecho de los siete. El del f233 lo es: su banda blanca acaba donde empieza la primera
     persona de la foto, en el 36,9 % a media altura (36,9 / 37,5 / 38,1 % a las alturas 50, 60 y
     70). Medido sobre el canvas ya pintado a 1440x900, con el tope en 0.376 la columna acababa
     en el 37,05 % y pisaba la piel: 3,41:1. Con 0.366 y los 8 px acaba 20 px antes del borde.
     Si cambia el fotograma del paso 6, este número se vuelve a medir. */
  max-width:calc(var(--cuadro) * 0.366 - 8px - var(--sangria));
  /* Y por eso su tope de cuerpo es 2.8cqw y no 2.9: el cqw se mide contra el CONTENEDOR, que es
     el 88 % del cuadro, pero este rótulo sólo puede usar el 36,6 %. En el cuadro más estrecho de
     escritorio —825 px— su hueco son 252 px y el contenedor 684, o sea el 36,8 %: con 12,60 de
     multiplicador, 0,368 x 100 / 12,60 = 2,92cqw como máximo. 2.8 deja 10 px de holgura y nunca
     baja de 19,15 px, que sigue siendo texto grande. Con 2.9 y la interletra vieja de .12em se
     partía en dos líneas a 840, a 1024 y a 1280 con la letra agrandada: medido. */
  margin-left:calc(var(--orilla) + var(--sangria));
  grid-template-columns:100%;
  /* DOS FILAS: el encabezado de los problemas arriba y los once bloques debajo. Con la rejilla, el
     encabezado no puede solaparse con el texto venga el cuerpo de donde venga, que es lo que pasaba
     cuando compartían celda.
     La fila del encabezado se reserva SIEMPRE, también en las siete paradas que no lo llevan, y eso
     es deliberado: si colapsara, el bloque de texto daría un salto vertical justo en el cambio de
     parada, que es cuando además está haciendo un fundido. Reservarla cuesta que el texto quede un
     poco más abajo en todas las paradas, y por eso el contraste se volvió a medir con el bloque en
     su sitio nuevo. */
  grid-template-rows:auto auto 1fr;   /* encabezado · su apoyo · los diez bloques */
  /* EL HUECO ENTRE LAS TRES FILAS BAJA DE --gap (40 px a 1920) A .8rem, Y NO ES ESTÉTICA.
     La fila del encabezado se reserva siempre, también en las siete paradas que no lo llevan,
     para que el bloque no dé un salto vertical al cambiar de parada. El precio es que TODOS los
     bloques bajan lo que mida esa reserva, y con --gap medía 207 px: a 1312x657 —la ventana del
     cliente— los bloques arrancaban en el 51 % del alto y el del hero, que es el más alto con
     321 px, acababa 2 px POR DEBAJO del borde de la ventana. El cliente lo vio cortado.
     Con .8rem la reserva baja a 132 px. Medido después: a 1312x657 el hero va de 234 a 555, con
     102 px de margen; a 1312x610, de 214 a 524; a 1024x700, de 261 a 565; a 1920x1040, de 408 a
     777. Ninguna parada se sale por abajo en ninguna de las cuatro.
     Y de paso centra: a 1920x1040 el centro del hero queda 73 px por debajo del de la ventana,
     contra los 101 de antes. La reserva es asimétrica por naturaleza —va arriba y no abajo— así
     que centrar del todo pediría no reservarla, que es lo que causaba el salto. */
  gap:.8rem;
  align-items:center;
  /* Contenedor para el tope del titular. Ver .paso__titulo. */
  container-type:inline-size;
}

/* Los once bloques ocupan la misma celda y sólo se ve el del tiempo activo. El texto NO se
   recorre con el scroll: se funde. Texto que se mueve con el dedo no se lee, y aquí el texto es
   el argumento. La transición va sobre `opacity` y `transform` ÚNICAMENTE: cualquier otra
   propiedad obligaría a rehacer la maqueta en cada fotograma.
   `pointer-events:none` quitaba el ratón de los diez bloques inactivos pero NO el tabulador: el
   enlace «Solicitar cotización» del hero seguía siendo alcanzable con el teclado cuando el hero
   ya no era el tiempo activo, y el foco saltaba a un botón invisible. Lo cierra `visibility`.
   OJO AL LEERLO: `visibility 0s` NO es una excepción a «sólo opacity y transform». Esa regla
   es sobre lo que se ANIMA, y una duración de cero no anima nada: la propiedad conmuta de golpe
   igual que si no estuviera en la lista. Está escrita en la lista para que se vea que es
   deliberado y no un olvido.
   EL RETARDO ES ASIMÉTRICO Y ESO ES EL TRUCO. Al esconder, `visibility` espera `var(--dur-ui)`,
   lo que tarda el `opacity` en llegar a cero: sin esa espera el bloque que sale desaparecería de
   golpe y el cambio de tiempo se leería como un fallo, no como una sustitución. Al mostrar no
   espera nada (la regla del tiempo activo la redeclara sin retardo), porque un bloque que entra
   tiene que poder verse desde el primer fotograma del fundido. El precio es una ventana de 200 ms
   en la que el bloque saliente sigue siendo enfocable; está aceptado a cambio de no dar un salto
   visible en cada parada. */
/* La clase va DOBLADA en el selector a propósito: las reglas base de .rotulo —cuerpo, interletra,
   align-self— viven más abajo en esta hoja y con la misma especificidad ganaban por orden de
   aparición. Medido: el cuerpo salía en 12,59 px, que es el 2.8cqw de la regla base, en vez de los
   32 de aquí. Doblar la clase es más barato que reordenar media hoja. */
.js-recorrido .rotulo.rotulo--encabeza{
  grid-area:1 / 1;
  /* Pegado abajo de su fila, que es lo que lo deja justo encima de su apoyo. */
  align-self:end;
  margin-bottom:.35rem;
  /* MÁS ANCHO QUE LA COLUMNA, Y SE PUEDE. La columna se topa en el 36,6 % porque el campo plano
     más estrecho de las siete paradas —el blanco del f233— acaba ahí; pero este rótulo SÓLO sale
     en el f020, que es blanco de lado a lado, y lo único que tiene que esquivar es el logotipo,
     que empieza en el 56,3 %. El 150 % de la columna deja el borde derecho en el 48,5 % del cuadro
     a 840 px y en el 47 % a 2560: por debajo del logotipo en todo el rango.
     Y de ese ancho sale el cuerpo. Medido con la fuente real, «PROBLEMAS QUE RESOLVEMOS» —la más
     larga de las dos líneas— mide 19,79 veces el cuerpo, así que en el 150 % de la columna caben
     150/19,79 = 7,58cqw. Con 7.2 queda al 95 % y el techo de 2rem manda en cuanto la columna pasa
     de 445 px, que es desde 1430 de ventana. Por eso a tamaño normal se ve a 2rem enteros, que es
     lo que pidió el cliente: que se notara. */
  width:150%;
  font-size:min(2rem, 7.2cqw);
}
/* El apoyo del encabezado: la frase que antes era titular de su propia parada. Baja a cuerpo de
   texto normal —no de display— porque eso es justo lo que el cliente pidió: que dejara de sonar a
   lema. Comparte fila con el encabezado, debajo de él, y por eso la fila es `auto`: crece con los
   dos. Sin opacidad, al contrario que el apoyo de las paradas: aquí la frase ES el argumento, no
   el acompañamiento de un titular. */
.js-recorrido .rotulo.rotulo--apoyo{
  grid-area:2 / 1;
  align-self:start;
  margin-bottom:.9rem;
  width:150%;
  font-family:var(--body);
  font-size:var(--t-body);
  font-weight:400;
  font-variation-settings:normal;
  letter-spacing:0;
  line-height:1.45;
  text-transform:none;
}
.js-recorrido .paso{
  grid-area:3 / 1;
  /* AL PRINCIPIO DE SU FILA, no centrado. La fila mide lo que el bloque más alto de los once —el
     hero, que lleva titular, apoyo, botón y nota— y con los bloques centrados un fallo corto
     quedaba a 175 px por debajo del encabezado. Medido. Alineados al principio, los once arrancan
     a la misma altura y el encabezado queda justo encima del que toque. */
  align-self:start;
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  gap:.9rem;
  /* LA ENTRADA Y LA SALIDA PESAN MÁS QUE ANTES, y es una petición del cliente con la grabación
     de su teléfono delante: «la animación al aparecer y desaparecer no tiene suficiente peso
     para dar cuenta de que cambió el texto». Con 8 px de recorrido y 200 ms, el cambio entre dos
     paradas se parecía demasiado a no cambiar nada, sobre todo scrolleando deprisa.
     Sube el recorrido de 8 a 16 px y la duración de --dur-ui (200 ms) a --dur-reveal (320).
     No más: por encima de ~350 ms la entrada se queda detrás del scroll y entonces el texto
     parece que llega tarde, que es un defecto peor que el que se está corrigiendo.
     El titular lleva además su propio retardo, abajo: llegar el último es lo que hace que el
     ojo registre el cambio. */
  opacity:0;
  visibility:hidden;
  transform:translateY(16px);
  /* LA SALIDA ES INSTANTÁNEA, Y ESO NO ES PEREZA: ES LA ÚNICA FORMA DE QUE EL SOLAPE SEA
     IMPOSIBLE. Los once bloques comparten celda. Mientras el que se va tenga cualquier opacidad
     por encima de cero al mismo tiempo que el que llega, se leen los dos encima.
     Se intentó primero con una salida corta —130 ms— y la entrada retrasada otros 130, que en
     teoría no solapa. El cliente lo volvió a ver. Y tiene que verlo: basta con que el scroll
     cambie de parada MIENTRAS una salida está a medias para que esa salida se interrumpa a
     media opacidad y la siguiente entrada empiece encima. Con el scroll mandando, eso no es un
     caso raro: es lo normal al arrastrar deprisa.
     Sin duración no hay estado intermedio que interrumpir. El bloque que deja de estar activo
     desaparece en el mismo fotograma, y lo que el visitante ve como animación es la ENTRADA del
     que llega, que sí dura 320 ms y sube 16 px. */
  transition:opacity 0s, transform 0s, visibility 0s;
  pointer-events:none;
}
/* Las diez claves son las de js/tiempos.js. Si una no coincide, ese bloque no aparece nunca:
   no hay forma en CSS de comparar el atributo del padre con el del hijo, así que la lista se
   enumera y tiene que mantenerse a mano. */
.js-recorrido .recorrido__fijo[data-clave="hero"] .paso[data-clave="hero"],
.js-recorrido .recorrido__fijo[data-clave="falla-1"] .paso[data-clave="falla-1"],
.js-recorrido .recorrido__fijo[data-clave="falla-2"] .paso[data-clave="falla-2"],
.js-recorrido .recorrido__fijo[data-clave="falla-3"] .paso[data-clave="falla-3"],
.js-recorrido .recorrido__fijo[data-clave="paso-1"] .paso[data-clave="paso-1"],
.js-recorrido .recorrido__fijo[data-clave="paso-2"] .paso[data-clave="paso-2"],
.js-recorrido .recorrido__fijo[data-clave="paso-3"] .paso[data-clave="paso-3"],
.js-recorrido .recorrido__fijo[data-clave="paso-4"] .paso[data-clave="paso-4"],
.js-recorrido .recorrido__fijo[data-clave="paso-5"] .paso[data-clave="paso-5"],
.js-recorrido .recorrido__fijo[data-clave="paso-6"] .paso[data-clave="paso-6"]{
  opacity:1;
  visibility:visible;
  transform:none;
  /* mismo relevo que los bloques de texto: salida instantánea, entrada animada */
  transition:opacity var(--dur-reveal) var(--ease-out),
             transform var(--dur-reveal) var(--ease-out),
             visibility 0s;
  /* LA ENTRADA ES LO ÚNICO QUE SE ANIMA, y no lleva retardo porque ya no hay nada que esperar:
     el bloque anterior desapareció en el mismo fotograma en que dejó de estar activo. Ver el
     comentario de la salida, arriba. */
  transition:opacity var(--dur-reveal) var(--ease-out),
             transform var(--dur-reveal) var(--ease-out),
             visibility 0s;
  pointer-events:auto;
}


/* El rótulo: el letrero fijo de arriba que dice de qué van las paradas que vienen. Tres textos y
   siete paradas, porque varias paradas seguidas comparten rótulo; por eso cuelga de `data-rotulo`
   y no de `data-clave`.
   VA FUERA DE .recorrido__textos y no dentro: la columna de texto está centrada a lo alto y su
   borde de arriba cae sobre el 30 % de la capa, por debajo de la franja navy del f233, que acaba
   en el 22,2 %. El rótulo tiene que colocarse contra la CAPA.
   Los topes de la izquierda son los mismos que los de la columna, y por el mismo motivo: el campo
   plano es una fracción del FOTOGRAMA, no de la ventana. */
.js-recorrido .recorrido__rotulos{
  grid-area:1 / 1;
  justify-self:start;
  --cuadro:min(100%, calc(100vh * 16 / 9));
  --cuadro:min(100%, calc(100dvh * 16 / 9));
  --orilla:max(0px, calc((100% - var(--cuadro)) / 2));
  --sangria:max(var(--pad), calc(var(--cuadro) * 0.04));
  margin-left:calc(var(--orilla) + var(--sangria));
  /* EL RÓTULO ES MÁS ANCHO QUE LA COLUMNA DE TEXTO, y puede serlo porque no cae en el mismo sitio.
     La columna se topa en el 36,6 % porque el campo plano más estrecho —el blanco del f233— acaba
     ahí. Pero el rótulo no se apoya en ese campo: se apoya en la FRANJA de arriba, y las franjas
     van de lado a lado del fotograma (la roja del f062, la navy del f190 y la del f233). Por eso
     aquí el tope es el 88 % y no el 36,6 %, que es lo que permite que «El uniforme es lo primero
     que ve su cliente» quepa en una sola línea, como pidió el cliente.
     La excepción es el rótulo del proceso, que pasa por el f090 y el f150, donde NO hay franja
     arriba sino una columna navy que acaba en el 37,7 %. Ese lleva su propio tope más abajo.
     ANCHO EXPLÍCITO Y NO max-width: container-type:inline-size aplica contención en el eje
     en línea, y un elemento que se encoge al contenido —justify-self:start— con contención se
     queda en CERO, porque el contenido deja de contribuir a su tamaño. Medido: con max-width el
     rótulo salía con 0 px de cuerpo y 0 de alto. La contención necesita una medida que venga de
     la maqueta, no del texto. */
  width:calc(var(--cuadro) * 0.88 - var(--sangria));
  container-type:inline-size;
  /* EL 7 % ES LA ALTURA Y ESTÁ MEDIDO. El rótulo tiene que caer dentro de la franja de arriba de
     su fotograma, y la más corta de las siete es la del f190: navy del 0 al 14,3 % del alto del
     cuadro. Como el cuadro va CONTENIDO —nunca recortado—, esa franja es siempre el 14,3 % del
     alto de la capa, en cualquier ventana. Con el relleno en 7vh y un cuerpo de .95rem, el rótulo
     ocupa del 7 % al 10,3 % a 810 px de alto: dentro, con holgura por los dos lados. Las otras
     seis franjas son más altas —f062 27,4 %, f233 22,2 %, y el f020, f090, f150 y f208 no tienen
     borde porque su campo llega hasta arriba—, así que el 7 % también cabe en ellas.
     En vh y no en % porque los porcentajes de relleno se resuelven contra el ANCHO, no el alto. */
  padding-top:7vh;
  padding-top:7dvh;
  display:grid;
  grid-template-columns:100%;
  grid-template-rows:100%;
}
/* Los tres comparten celda y se funden igual que los bloques de texto: mismo retardo asimétrico
   de `visibility`, por el mismo motivo. Aquí no hay nada enfocable, así que lo que arregla es el
   salto visible al sustituirse, no el tabulador. */
.js-recorrido .rotulo{
  grid-area:1 / 1;
  font-family:var(--display);
  font-weight:700;
  font-variation-settings:'wdth' var(--ancho-display),'wght' 700;
  text-transform:uppercase;
  /* EL CUERPO SALE DE LA ANCHURA, PARA QUE QUEPA EN UNA LÍNEA. Medido con la fuente real
     (Archivo 700, eje de anchura 112, versalitas, interletra .06em), el ancho de cada cadena en
     veces el cuerpo:
       «El uniforme es lo primero que ve su cliente»   31,34
       «Problemas que resolvemos antes de producir»    33,32
       «Nuestro proceso»                               12,60
     100cqw es el ancho de .recorrido__rotulos, que es el 88 % del cuadro menos la sangría. Con
     2.9cqw la más larga de las tres ocupa 2,9 x 33,32 = 96,6 % de ese ancho: una línea, siempre,
     en cualquier ventana. Comprobado en el cuadro más estrecho que puede haber en escritorio,
     840 px: el contenedor mide 697 px, 2.9cqw son 20,2 px y la cadena 673 px.
     EL SUELO DE 1,2rem NO ES COSMÉTICO tampoco: son 19,2 px y con el peso en 700 eso es texto
     grande para la norma, que pide 3:1 en vez de 4,5:1. Hace falta en el paso 1, el único sobre
     la franja roja, donde el hueso da 4,56:1: pasa el 4,5 del texto normal por 0,06, y esa
     holgura se la come cualquier códec. El tope en cqw nunca lo baja de 19,95 px, que sigue
     siendo texto grande, así que las dos reglas conviven.
     En móvil se desactiva: allí el rótulo va en su fila, sobre el hueso de la página. */
  font-size:min(1.2rem, 2.8cqw);
  letter-spacing:.06em;   /* la misma en los tres: de ella sale el multiplicador de ancho */
  line-height:1.2;
  /* Sin opacidad, al contrario que el apoyo: sobre la franja roja del f062 el hueso da 4,56:1, y
     un 0,85 encima lo bajaría de los 4,5 que exige el texto normal. */
  color:var(--tinta-rotulo);
  opacity:0;
  visibility:hidden;
  transform:translateY(6px);
  transition:opacity var(--dur-ui) var(--ease-out), transform var(--dur-ui) var(--ease-out),
             visibility 0s linear var(--dur-ui);
}
/* Las tres claves son las de js/tiempos.js, enumeradas a mano por lo mismo que las once de los
   bloques: en CSS no hay forma de comparar el atributo del padre con el del hijo. */
.js-recorrido .recorrido__fijo[data-rotulo="problemas"] .rotulo[data-clave="problemas"],
.js-recorrido .recorrido__fijo[data-rotulo="proceso"] .rotulo[data-clave="proceso"],
.js-recorrido .recorrido__fijo[data-rotulo="equipo"] .rotulo[data-clave="equipo"]{
  opacity:1;
  visibility:visible;
  transform:none;
  transition:opacity var(--dur-ui) var(--ease-out), transform var(--dur-ui) var(--ease-out),
             visibility 0s;
}

/* DOS RÓTULOS SALEN DE LA MEDIDA COMÚN, y los dos porque el cliente los quiere más grandes.
   Se puede, y por motivos distintos en cada uno:
   · El de los problemas sólo sale en el f020, que es blanco de arriba abajo y de lado a lado
     —el campo llega al 56,2 % y la columna entera es blanca—, así que no hay franja que respetar
     ni por alto ni por ancho. Por eso además puede BAJAR: el cliente lo pidió y aquí no cuesta
     contraste. Baja hasta quedar justo encima del bloque del fallo, que es lo que lo convierte en
     el encabezado de los tres y no en un letrero suelto arriba del todo.
   · El de la entrega sale en el f233, que sí tiene franja: navy del 0 al 22,2 % del alto del
     cuadro. A 2rem y dos líneas ocupa del 7 % al 16,5 %, así que sigue dentro con holgura. NO
     puede bajar: debajo del 22,2 % empieza el blanco y la tinta hueso se volvería invisible.
   El tercero, «NUESTRO PROCESO», se queda en 1,2rem: ese sí pasa por las seis paradas del proceso
   y una de ellas es la franja roja del f062, donde el cuerpo es lo que lo mantiene en texto
   grande (ver el bloque de .rotulo). */
/* Sólo el de la entrega: el de los problemas se mudó a la columna de texto y tiene su propia regla
   —.rotulo--encabeza—, con su propio ancho y su propio cuerpo. Mientras esta regla lo nombraba,
   ganaba por especificidad y le dejaba el cuerpo en 13 px, porque su 2.9cqw se medía contra una
   columna que ya no es la suya. */
.js-recorrido .recorrido__rotulos .rotulo[data-clave="equipo"]{
  /* Los dos suben a 2rem porque el cliente los quiere más grandes, con el MISMO tope en cqw que
     el otro: el cuerpo es el menor de los dos, así que siguen cabiendo en una línea. A 2rem la
     cadena más larga pide 1066 px, que entran en el contenedor desde un cuadro de 1211 px; por
     debajo manda el tope y el cuerpo baja hasta que quepa. */
  font-size:min(2rem, 2.9cqw);
  line-height:1.15;
}
/* El del proceso lleva un tope de ANCHO propio, y es el único que lo necesita: pasa por el f090
   y el f150, donde arriba no hay franja de lado a lado sino la columna navy, que acaba en el
   37,7 %. Los otros dos sólo salen sobre franjas que cruzan el fotograma entero. */
.js-recorrido .rotulo[data-clave="proceso"]{
  /* EN PORCENTAJE DEL CONTENEDOR, NO EN var(--cuadro). Ese token lleva dentro un `100%`, y un
     porcentaje se resuelve contra el elemento QUE LO USA: en .recorrido__rotulos `100%` es la
     capa, pero aquí dentro es el contenedor, que ya es el 88 % de la capa. Usándolo aquí el tope
     salía mucho más estrecho de lo debido y «NUESTRO PROCESO» se partía en dos líneas a 840, a
     1024 y a 1280 con la letra agrandada. Medido, no deducido.
     El 36 % es la cuenta hecha a mano: el hueco real es 0,366 x cuadro - 8 - sangría y el
     contenedor 0,88 x cuadro - sangría, así que la razón entre los dos va del 36,1 % —cuadro
     estrecho, sangría grande— al 39,8 %. El 36 % es conservador en todo el rango, y de él sale
     el 2.8cqw de arriba: 0,36 / 12,60 = 2,857 %. */
  max-width:36%;
}
/* Dentro del 20 % de la primera fila, cada rótulo a su altura. El del proceso arriba, que es
   donde están las franjas de sus seis fotogramas; el de los problemas ABAJO, pegado al borde de
   la fila, que es lo que pidió el cliente: así encabeza los tres fallos en vez de quedar suelto
   arriba del todo. Ahí se puede porque el f020 es blanco de arriba abajo. El de la entrega va
   arriba: su franja navy acaba en el 22,2 % y por debajo empieza el blanco. */
.js-recorrido .rotulo{ align-self:start }
/* EL ENCABEZADO DE LOS PROBLEMAS VA EN TRES LÍNEAS Y ENTRA UNA A UNA, que es como lo pidió el
   cliente: «Problemas que» pequeño, y debajo «resolvemos» y «antes de producir» al tamaño del
   titular de la parada y en el cian de la marca. Son tres <span> y no tres <br> porque cada uno
   necesita su propio retardo.
   EL COLOR VA EN --resalte Y NO EN UN CIAN FIJO porque esa variable ya sabe sobre qué campo
   está: cian sobre el navy del móvil (15,4:1) y rojo #C40000 sobre el hueso del escritorio
   (5,29:1). Un cian fijo habría sido invisible en escritorio, donde este encabezado cae sobre
   la placa hueso del f030: cian sobre #fdfdfd da 1,24:1.
   EL TOPE DEL CUERPO VA CONTRA EL ANCHO DEL PROPIO ENCABEZADO, y por eso éste declara
   `container-type:inline-size`. «ANTES DE PRODUCIR» es la cadena más larga de las tres y tiene
   que caber en UNA línea, que es como lo pidió el cliente. Medida con la fuente real —Archivo
   800, eje de anchura 112, versalitas— mide 12,80 veces el cuerpo, así que el máximo que cabe
   es 100/12,80 = 7,81cqw. Se deja en 7.4 para que el redondeo no la parta.
   Contra el encabezado y no contra la columna porque los dos no miden lo mismo: en escritorio
   este rótulo es más ancho que la columna de texto (ver `width:150%` más abajo) y en móvil es
   igual de ancho. Con el tope atado a sí mismo, el número vale en las dos sin dos reglas.
   LO QUE ESTO IMPLICA EN ESCRITORIO: el cuerpo sale menor que el del titular de la parada
   —unos 34 px contra 55 a 1440— porque el rótulo tiene menos ancho que la columna. El cliente
   pidió «al mismo tamaño de se frunce» mirando el teléfono, donde sí coinciden (26 contra 32).
   Igualarlos en escritorio pediría ensanchar el rótulo por encima del campo plano medido, y eso
   no se toca sin volver a medir. */
.js-recorrido .rotulo.rotulo--encabeza{
  container-type:inline-size;
}
.js-recorrido .rotulo__linea{
  display:block;
}

/* EL CIAN DE «ES LO PRIMERO» SÍ VA FIJO, y es la excepción a lo que hace la línea de arriba.
   El encabezado de los problemas usa --resalte porque cae sobre campo hueso en escritorio y
   sobre navy en móvil, y el cian sobre hueso da 1,23:1. Este rótulo no: cae sobre la FRANJA
   NAVY del f202 en escritorio —medida, plana hasta el 21,4 % del alto, y por eso su parada
   declara `tintaRotulo: 'hueso'`— y sobre el navy del cuadro vertical en móvil. Navy en los dos
   casos, así que el color puede ser el que el cliente pidió sin condiciones.
   Medido: cian sobre ese navy da 15,42:1. Con --resalte habría salido rojo #C40000 en
   escritorio —porque el campo de esa parada es `blanco`, aunque el rótulo no caiga en él— y el
   rojo sobre ese navy da 3,05:1, que para texto grande pasa raspando y se ve apagado. */
.js-recorrido .rotulo__linea--cian{
  color:var(--cyan);
  font-style:normal;
}

/* Y LAS TRES LÍNEAS DE ESE RÓTULO SE TOPAN CONTRA SU PROPIO ANCHO, igual que las del
   encabezado de los problemas y por el mismo motivo: el cliente las quiere en tres líneas, una
   cada una, y la más larga —«que ve su cliente»— mide 11,73 veces el cuerpo medida con la
   fuente real. El máximo que cabe es 100/11,73 = 8,53cqw; se deja en 8.2.
   `1em` es el cuerpo que ya trae el rótulo —el de escritorio o el de móvil, cada uno el suyo— y
   el min sólo lo recorta cuando no cabe, así que una sola regla vale en las dos plataformas. */
.js-recorrido .rotulo[data-clave="equipo"]{
  container-type:inline-size;
}
.js-recorrido .rotulo[data-clave="equipo"] .rotulo__linea{
  font-size:min(1em, 8.2cqw);
}
.js-recorrido .rotulo__linea--grande{
  color:var(--resalte);
  font-style:normal;
  font-size:min(var(--t-parada), 7.4cqw);
  line-height:.95;
}

/* LAS TRES LÍNEAS ENTRAN ESCALONADAS, y el bloque del primer fallo espera a que terminen. El
   cliente lo pidió así: «después de la animación de estos textos ya puede aparecer se frunce».
   El padre no se funde —`transition:none`— para que no haya dos opacidades encadenadas: lo que
   se anima son las líneas, y la visibilidad del padre cambia de golpe. */
.js-recorrido .rotulo.rotulo--encabeza{
  transition:none;
}
.js-recorrido .rotulo--encabeza .rotulo__linea{
  opacity:0;
  transform:translateY(14px);
  transition:opacity var(--dur-reveal) var(--ease-out), transform var(--dur-reveal) var(--ease-out);
}
.js-recorrido .recorrido__fijo[data-rotulo="problemas"] .rotulo--encabeza .rotulo__linea{
  opacity:1;
  transform:none;
}
.js-recorrido .recorrido__fijo[data-rotulo="problemas"] .rotulo--encabeza .rotulo__linea:nth-child(2){
  transition-delay:150ms;
}
.js-recorrido .recorrido__fijo[data-rotulo="problemas"] .rotulo--encabeza .rotulo__linea:nth-child(3){
  transition-delay:300ms;
}
/* Y «SE FRUNCE» espera a las tres. Sólo el primer fallo: al segundo y al tercero el encabezado
   ya está puesto —`data-rotulo` no cambia entre ellos, así que no se reanima— y hacerles esperar
   medio segundo sería castigar al visitante por seguir bajando.
   450 ms = 300 de la última línea + 150 de margen para que se lea antes de que entre otra cosa. */
.js-recorrido .recorrido__fijo[data-clave="falla-1"] .paso[data-clave="falla-1"]{
  transition-delay:450ms;
}

/* El titular de la parada: Archivo en mayúsculas, con el eje de anchura de la marca. El tamaño
   sale de --t-parada, cuyo término en vw se fijó midiendo este campo; ver tokens.css.

   PARA LA TAREA 10, PASO 3 — MEDIDO, NO ARREGLADO AQUÍ. Con el ajuste de tamaño de letra del
   navegador en 20 o en 24 px, y SÓLO entre 840 y ~1100 px de ancho, el titular se sale del campo
   plano de su fotograma. Medido, holgura de la tinta real contra el borde del campo:
     840x1000 con la letra en 20 → paso-4 se pasa 54 px;  con 24 → 119 px
     1024x900 con la letra en 20 → +6 px, por debajo de los 8 de holgura exigidos
     1024x1000 con la letra en 24 → se pasa 59 px
     1440x900 con 20 y con 24 → +14 px, no pasa: ahí ya manda el término en vw
   La causa es que el suelo del token es `2rem` y crece con la letra, mientras que el campo es una
   fracción del ancho de la ventana y no crece. Y la red no lo atrapa: a 840x1000 con la letra en
   20, `40rem` son 800 px y la ventana mide 1000.
   Tres salidas posibles, ninguna aplicada:
     1) topar el titular por su columna en vez de por la ventana —`.recorrido__textos` como
        contenedor y `font-size:min(var(--t-parada), 12cqw)`—: la columna ya está topada contra el
        campo, así que el titular no podría salirse; el precio es que entre 840 y ~1100 deja de
        crecer con el ajuste del usuario;
     2) subir el corte de móvil a ~1100, donde el texto pasa a ir debajo del cuadro y el campo es
        la página, y la cuenta se arregla sola con cualquier letra;
     3) una placa opaca de respaldo bajo el texto, sólo en esa banda de anchos.
   Se decide en la Tarea 10, que tendrá la página montada y podrá medir contra el canvas pintado
   de verdad. No hace falta volver a medir lo de arriba. */
.js-recorrido .paso__titulo{
  font-family:var(--display);
  font-weight:800;   /* respaldo: lo que se ve mientras Archivo carga o si Google falla */
  font-variation-settings:'wdth' var(--ancho-display),'wght' 800;
  text-transform:uppercase;
  /* EL TOPE EN cqw ES LA SALIDA 1 DE LAS TRES ANOTADAS ARRIBA, y cierra la trampa de la letra
     agrandada. 100cqw es el ancho de .recorrido__textos, o sea de la columna, que ya está topada
     contra el campo del fotograma, así que un titular que quepa en 100cqw no se puede salir del
     campo venga el cuerpo de donde venga.
     EL NÚMERO LO PONE LA PALABRA MÁS LARGA, y hay que recalcularlo si cambia un titular. Medidas
     reales, con Archivo en 800 y el eje de anchura en 112, en veces el cuerpo:
       DIGITALIZACION 9,53   PRODUCCION 8,06   APROBACION 7,97   ASEGURADA 7,50
       DENSIDAD 6,12   VOLUMEN 5,90   ENTREGA 5,78   PRECIOS 5,27
     Manda DIGITALIZACION: 100 / 9,53 = 10,49cqw como maximo. Se deja en 10cqw, con lo que esa
     palabra ocupa el 95,3 % de la columna.
     BAJO DE 12 A 10 Y ESO ENCOGE TODOS LOS TITULARES: a 1440 el cuerpo pasa de 54,7 a 46,4 px,
     porque el tope lo pone la palabra mas larga de todas y DIGITALIZACION tiene catorce letras.
     El dial para recuperar el tamano no esta aqui, esta en esa palabra: un titular mas corto en
     el paso 1 sube los seis de golpe.
     En movil el tope no actua: a 390 px la columna es la pagina y 10cqw son 39 px, por encima del
     suelo de 2rem del token. */
  font-size:min(var(--t-parada), 10cqw);
  line-height:.95;
  color:var(--tinta);
}
.js-recorrido .paso__num{
  font-family:var(--display);
  font-weight:800;
  font-variation-settings:'wdth' var(--ancho-display),'wght' 800;
  font-variant-numeric:tabular-nums;
  font-size:1.1rem;
  letter-spacing:.14em;
  line-height:1;
  color:var(--tinta);
}
/* El apoyo baja un punto sin cambiar de tinta: un token más claro rompería el par medido. Al
   85 % sobre el campo de su parada sigue muy por encima del mínimo —navy sobre el blanco del
   fotograma 20: 12,47:1; hueso sobre el navy del 90: 13,31:1; navy sobre el cian del 178:
   10,48:1—. */
.js-recorrido .paso__apoyo{
  max-width:var(--measure);
  color:var(--tinta);
  opacity:.85;
}
/* Las palabras clave del apoyo, en el color de resalte del campo. El <strong> ya estaba en el
   HTML donde el argumento lo pedía: esto le da color, no lo inventa. Los tres pares están
   medidos con el 0,85 de opacidad del padre ya aplicado —5,29, 5,52 y 11,18:1—, ver el bloque
   de --resalte. */
.js-recorrido .paso__apoyo strong{
  color:var(--resalte);
  font-weight:700;
}

/* EL APOYO DE LOS PASOS 4 Y 5 VA EN NEGRITA Y A OPACIDAD PLENA, que es lo que pidió el cliente:
   dijo que ahí el texto secundario se leía flojo y tenía razón.
   ANTES COLGABA DEL CAMPO —era data-campo="cian"— con el argumento de que lo que decide es el
   color de debajo y no cómo se llame el paso. El argumento sigue valiendo pero el campo cian ya
   no existe: el render de octubre de 2026 no trae el bloque turquesa, y los pasos 4 y 5 están
   ahora sobre el hueso de la toma de la máquina, donde el navy a 0,85 de opacidad da 12,65:1 y a
   opacidad plena 17,14. El número pasaba ya a 0,85; lo que se arregla es lo que el cliente ve.
   Cuelga de la clave porque es una petición sobre ESAS DOS PARADAS, no sobre un color. */
.js-recorrido .recorrido__fijo[data-clave="paso-4"] .paso__apoyo,
.js-recorrido .recorrido__fijo[data-clave="paso-5"] .paso__apoyo{
  opacity:1;
  font-weight:700;
}

/* VENTANA BAJA PERO NO TANTO COMO PARA APAGAR EL RECORRIDO. La red lo apaga por debajo de
   37.5rem de alto; entre eso y 46rem el recorrido sigue, pero la capa mide poco y hay que
   apretar. Son las ventanas de portátil con la barra de tareas y la del navegador comidas: la
   del cliente, 1312x657, cae justo aquí.
   Tres aprietes, los tres medidos contra el bloque más alto, que es el del hero:
    · las bandas de arriba y abajo de la capa bajan del 20 % al 14 %, que a 657 px son 39 px más
      de alto útil por banda;
    · el hueco entre filas baja a .6rem;
    · el encabezado de los problemas baja de 2rem a 1.5rem de cuerpo.
   El rótulo sigue cabiendo en su franja: va `align-self:start` y mide unos 30 px, contra los
   92 px que mide la fila del 14 % a 657 de alto y los 131 px de franja roja del f055 —el 19,9 %
   del alto del fotograma, que en una ventana más ancha que 16:9 es el 19,9 % de la capa—. */
@media (min-height:37.5625rem) and (max-height:46rem){
  .js-recorrido .recorrido__fijo{ grid-template-rows:14% 1fr 14% }
  .js-recorrido .recorrido__textos{ gap:.6rem }
  .js-recorrido .rotulo.rotulo--encabeza{ font-size:min(1.5rem, 5.4cqw) }
}

/* MÓVIL: EL CUADRO ES VERTICAL Y EL TEXTO VA ENCIMA, como en escritorio. Hasta octubre de 2026
   era al revés —el cuadro 16:9 arriba y el texto debajo sobre el hueso de la página— y el motivo
   era real: sobre un fotograma 16:9 a 390 px de ancho no hay franja utilizable, porque el campo
   plano de los pasos acaba en el 38 % del ancho, o sea 148 px, y ahí no cabe un titular.
   Lo que cambió no es el CSS, es el FOTOGRAMA: el perfil móvil ahora es 720x1280 vertical, con
   el montaje de 720x406 abajo y navy de marca por encima. El campo plano ya no es una franja
   estrecha al lado de la imagen: es el 56,6 % DE ARRIBA, a todo el ancho.
   Y arriba, no abajo, por una razón que no es de composición: el cliente grabó la pantalla de
   su teléfono con la primera versión —imagen arriba, texto debajo— y el texto caía entre el
   45 % y el 65 % del alto, que es por donde barre el pulgar al hacer scroll. «Los textos quedan
   un poco escondidos». Con la imagen abajo, el texto sube por encima del pulgar y la imagen se
   queda en el tercio inferior, donde que el dedo la cruce da igual: es una foto, no algo que
   haya que leer.
   Y es UN SOLO CAMPO en los 248 fotogramas. Medidos diez repartidos por el recorrido, el navy de
   abajo mide #00003c en todos y empieza en la fila 556 de 1280, el 43,4 %. Por eso este bloque
   puede fijar la tinta y el campo de una vez en lugar de seguir los siete de escritorio.
   DÓNDE EMPIEZA LA IMAGEN EN LA CAPA, que es el tope que el texto no puede cruzar: depende de
   la forma de la ventana, porque el lienzo contiene el fotograma y rellena el resto estirando
   sus bordes. Medido con la aritmética de `dibujar`: en una ventana más ancha que 9:16 —360x640,
   768x1024, 839x841— el fotograma se contiene por el alto y la imagen empieza en el 56,6 %; en
   una más estrecha —todos los teléfonos: 390x844 da 0,462 y 412x915 da 0,450— se contiene por
   el ancho y empieza algo más arriba, en el 55,4 %. El peor caso es ese, así que el texto tiene
   que caber en el 55 % de arriba, y eso es lo que hay que comprobar midiendo.
   El tope de 46dvh del cuadro es lo que deja sitio al texto cuando la ventana es casi cuadrada y
   la letra del navegador está agrandada. El peor caso que no cae en la red es 839x841 en
   vertical: con la letra en 24 px y sin tope, el bloque del hero acaba 35 px POR DEBAJO de la
   capa pegada y aterriza sobre la sección siguiente; con el tope acaba 42 px dentro. Con la
   letra en 16 y en 20 cabría sin tope (sobran 54 y 20 px), así que esto es la red del caso
   grande. En un teléfono el tope no toca nada: sólo actúa cuando el alto baja de 1,22 veces el
   ancho, y a 390x844 o 768x1024 el cuadro sigue yendo a sangre.
   839.98px y no 839px: con 839px, una ventana de 839.5 —que el zoom del navegador produce— no
   entraría ni aquí ni en el `min-width:840px` de ningún otro bloque. El umbral de `perfilPara`
   en js/secuencia.js es `>= 840`, así que a 839.5 los dos coinciden. */
@media (max-width:839.98px){
  /* EL RIEL DE MÓVIL YA NO SE DERIVA DEL DE ESCRITORIO, Y ESE ES EL CAMBIO.
     Hasta aquí salía de multiplicar el de escritorio por 1100/1400, la proporción del diseño
     original, que nadie había comprobado contra un teléfono. El cliente sí: dijo que «hay que
     hacer este gesto muchas veces para avanzar a la siguiente parada» y que al principio parece
     que la página no funciona.
     Tenía razón y el número lo explica. Con 1200vh el recorrido iba a 51,65 vh por unidad de
     peso, así que la parada más larga —los pasos 4 y 5, de 1.90— pedía 101 vh, más de una
     pantalla de arrastre. Y el arranque es el caso peor: las cuatro primeras paradas comparten
     fotograma (el hero y los tres fallos, todas en el f030) y entre las cuatro suman 5.00 de
     peso, o sea 258 vh. Dos pantallas y media de pulgar sin que la imagen se mueva.
     El criterio del número nuevo no es el gusto, es el GESTO: un arrastre controlado recorre
     unos dos tercios de pantalla, así que ninguna parada debería pedir más de ~65 vh. Con
     PESO_TOTAL 23.235, eso da 65 / 1.90 x 23.235 = 795vh, y se redondea a 780.
     Queda: 33,57 vh por unidad y la parada más larga en 65 vh.
     780 -> 760vh al bajar el hero de 1.40 a 0.80, y 760 -> 790 al subir los tres fallos de 1.20
     a 1.50. Los dos conservan los mismos 33,57 vh por unidad (790/23.535). Con eso el arranque —lo que hay que arrastrar antes de que entre el primer
     fallo— pasa de 346 a 227 px en un teléfono de 844, y el recorrido entero queda en 7,6
     pantallas en vez de las 12 del principio.
     Lo que NO cambia es la regla de escritorio: allí se scrollea con rueda y 1522vh está medido.
     La invariante de «mismo scroll por unidad de peso» sigue valiendo dentro de cada plataforma,
     que es donde importa: lo que tiene que ser parejo es la velocidad de la secuencia entre un
     avance y otro, no entre un teléfono y un monitor. */
  /* EL RIEL LLEVA EL NAVY DEL CAMPO DETRÁS, y no es decoración: es lo que tapa la franja que
     aparece cuando la barra de direcciones se esconde. La capa mide 100svh —el viewport con la
     barra desplegada— para no cambiar de altura a media pasada, así que al esconderse la barra
     sobran unos `lvh - svh` por debajo. Sin esto, ahí se veía el hueso de la página: el «cuadro
     blanco por abajo» que reportó el cliente. Con el mismo navy del fotograma, no se ve. */
  .js-recorrido .recorrido{ min-height:790vh; background:#00003c }
  .js-recorrido .recorrido__fijo{
    /* rótulo · texto · el hueco donde cae la imagen. Las dos primeras filas se empaquetan
       arriba, sobre el navy libre del fotograma, y la tercera se queda con lo que sobra.
       EL ORDEN ESTÁ INVERTIDO RESPECTO DE LA PRIMERA VERSIÓN y el motivo está en la cabecera de
       este bloque: con la imagen arriba el texto caía donde barre el pulgar.
       El lienzo cruza las tres filas: es el fondo de todas, igual que en escritorio. */
    /* LA PRIMERA FILA ES EL MARGEN DE ARRIBA, y es una fila y no relleno de un elemento por una
       razón medida: el rótulo no siempre está. En el hero y en los tres fallos no hay rótulo de
       capa —el de los problemas vive dentro de la columna de texto— y su fila colapsa, así que
       un relleno puesto ahí desaparecía con ella y el titular arrancaba pegado al borde de la
       pantalla. El cliente lo vio: «todos los textos empiezan desde muy arriba».
       Como fila propia, el margen está siempre, lleve rótulo la parada o no. 8svh son unos
       68 px en un teléfono de 844, y de paso despegan el texto de la barra de estado.
       Se puede pagar: medido con la imagen ya subida, el bloque más alto acaba en el 43 % y
       la imagen empieza en el 51,5 %, así que sobran ocho puntos. */
    grid-template-rows:8svh auto auto 1fr;
    gap:0;
    padding:0;
  }
  /* EL LIENZO CUBRE LA CAPA ENTERA, como en escritorio. Ya no lleva proporción propia: el
     fotograma es vertical y la capa es la ventana, y de ajustar uno dentro de la otra se encarga
     `dibujar` en js/lienzo.js, conteniendo el fotograma y estirando sus bordes para rellenar.
     Lo que se estira arriba y abajo es el navy del relleno del fotograma —150 px de navy por
     encima de la imagen, puestos a propósito en la extracción—, así que no se ve costura.
     Se va el tope de 46dvh del cuadro: era la red para que al texto le quedara sitio debajo, y
     ya no hay un debajo. */
  .js-recorrido .recorrido__lienzo{
    grid-area:1 / 1 / -1 / -1;
    justify-self:stretch;
    width:100%;
    height:100%;
    aspect-ratio:auto;
  }
  /* El rótulo en móvil: fila propia entre el cuadro y el texto, alineado con el texto y no con el
     cuadro. Aquí no está sobre la imagen, así que su tinta vuelve a la de la página igual que la
     del texto; y pierde el relleno de arriba, que servía para meterlo en la franja del fotograma.
     Cuesta una línea de alto siempre, también en las cuatro paradas sin rótulo, porque
     `visibility:hidden` conserva la caja. Medido a 839x841 con la letra en 24, que es el peor caso
     que la red no atrapa: el bloque acaba 15 px dentro de la capa, antes acababa 42. */
  .js-recorrido .recorrido__rotulos{
    grid-area:2 / 1;
    justify-self:stretch;
    max-width:none;
    margin-left:0;
    /* TODO EL TEXTO EMPIEZA MÁS ABAJO, que es lo que pidió el cliente: «todos los textos
       empiezan desde muy arriba». Como el rótulo es la primera fila de la retícula, bajarlo a
       él baja todo lo que viene detrás. 6svh son unos 50 px en un teléfono de 844, contra los
       20 de --pad, y además lo despega de la barra de estado del sistema.
       En svh y no en px por lo mismo que el resto de este bloque: lo que hay que repartir es el
       alto de la pantalla, no una cantidad fija. */
    padding:0 var(--pad) 0;
  }
  /* El rótulo baja de cuerpo en móvil, y el motivo es que AQUÍ NO HACE FALTA EL SUELO. El 1,2rem
     del bloque de arriba está puesto para que el rótulo sea «texto grande» sobre la franja roja
     del f062, donde el hueso da 4,53:1; en móvil el rótulo no está sobre ninguna franja sino sobre
     el hueso de la página, con la tinta de marca, 17,71:1, y la norma de texto grande no pinta
     nada. Sin esto, medido a 390x844 con la letra del navegador en 24, «PROBLEMAS QUE RESOLVEMOS
     ANTES DE PRODUCIR» ocupaba cuatro líneas —173 px— y la pila se salía 9 px de la capa. Con
     1rem son 115 px y sobran 49. Medido también a 839x841 con 24 (sobran 62) y a 768x1024 con 24
     (sobran 163), que son los otros dos casos que la red no atrapa. */
  .js-recorrido .rotulo{ font-size:1rem }
  /* Y los dos grandes vuelven con ellos: en móvil el rótulo va en su propia fila sobre el hueso
     de la página, donde 2rem no gana nada y sí le cuesta líneas a una pila que ya va justa. El
     margen de arriba también se va, porque aquí no hay franja a la que bajar. */
  /* EL RÓTULO DEL EQUIPO ES EL ÚNICO QUE CRECE, y es una petición del cliente: «es demasiado
     pequeño y muy arriba, no se nota ni se lee, debe tener mucho más peso y protagonismo».
     Puede crecer porque su parada es la que menos texto lleva —«Entrega / Enviamos a todo
     México»— y porque en ella no se muestra el encabezado de los problemas, que es lo que
     aprieta en los fallos. Medido, el bloque del paso 6 acababa en el 25,9 % del alto cuando el
     límite está en el 51,5 %: sobraba media pantalla.
     El tope en svh es el mismo mecanismo que el resto: crece con la pantalla y deja de crecer
     cuando no cabe. A 844 px de alto son 26 px de cuerpo, contra los 16 de antes.
     Se probó con 4.2svh —35 px— y era demasiado: la frase tiene 43 caracteres y a ese cuerpo
     ocupaba CINCO líneas, el 26 % del alto, y el bloque acababa en el 54,2 % cuando el
     límite está en el 51,5. Con 3.1svh son cuatro líneas y el bloque acaba holgado. */
  /* EL SELECTOR LLEVA .recorrido__rotulos A PROPÓSITO, y no es redundante. La regla de
     escritorio es `.js-recorrido .recorrido__rotulos .rotulo[data-clave="equipo"]` y topa el
     cuerpo en 2.9cqw contra el ancho del contenedor; con un selector más corto aquí, aquella
     gana por especificidad y a 390 px de ancho deja este rótulo en 8 px. Medido: salía a
     8,21 px cuando lo que pedía esta regla eran 35.
     Es la tercera vez que este archivo pierde una regla de móvil por especificidad contra una
     de escritorio; cuando una no haga efecto, es lo primero que hay que mirar. */
  .js-recorrido .recorrido__rotulos .rotulo[data-clave="equipo"]{
    font-size:min(1.6rem, 3.1svh);
    letter-spacing:.02em;
    line-height:1.05;
  }
  /* El encabezado de los problemas también vuelve a la medida común en móvil, y pierde el ancho
     extra: aquí la columna es la página y no hay logotipo que esquivar. */
  /* La clase doblada también aquí, por lo mismo que arriba: la regla de escritorio lleva
     .rotulo.rotulo--encabeza y si esta no iguala la especificidad, el 150 % de ancho sobrevive al
     corte de móvil. Medido: a 390 px el rótulo salía hasta 523 y el documento se desplazaba 148 px
     en horizontal. */
  /* EN MÓVIL LAS FILAS DE RÓTULO NO SE RESERVAN: COLAPSAN CUANDO NO TOCAN.
     En escritorio se reservan siempre para que el bloque no dé un salto vertical al cambiar de
     parada, y ahí el precio se paga sin que se note. En una pantalla de teléfono no: medido a
     390x844, entre el rótulo de la capa (72 px) y el encabezado de los problemas con su apoyo
     (152 px) se reservaban 224 px de 844, el 26 % del alto, para etiquetas que SIETE de las diez
     paradas no usan. Con el cuadro ocupando el 46 % de arriba, al bloque del hero —que es el más
     alto— le quedaban 155 px y necesita 277: se salía 45 px por abajo a 390x844, 63 a 375x812 y
     141 a 375x667, que es un iPhone SE y no cae en la red.
     Colapsándolas, el salto vertical vuelve, pero ocurre dos veces en todo el recorrido —al
     entrar en los fallos y al salir de ellos— y durante un fundido. Texto cortado es peor.
     Medido después: ver los números en el comentario de la cabecera de este bloque. */
  .js-recorrido .recorrido__fijo:not([data-rotulo]) .recorrido__rotulos,
  .js-recorrido .recorrido__fijo[data-rotulo=""] .recorrido__rotulos,
  /* y en los fallos también: su rótulo no vive aquí sino dentro de la columna de texto, así
     que esta caja se quedaba reservada y vacía. Medido, 74 px de 844. */
  .js-recorrido .recorrido__fijo[data-rotulo="problemas"] .recorrido__rotulos{ display:none }
  .js-recorrido .recorrido__fijo:not([data-rotulo="problemas"]) .rotulo--encabeza,
  .js-recorrido .recorrido__fijo:not([data-rotulo="problemas"]) .rotulo--apoyo{ display:none }
  .js-recorrido .rotulo.rotulo--encabeza{ font-size:1.15rem; width:100% }
  .js-recorrido .rotulo.rotulo--apoyo{ width:100% }
  .js-recorrido .recorrido__textos{
    grid-area:3 / 1;
    justify-self:stretch;
    align-self:start;
    width:auto;
    /* A todo el ancho de la columna: el campo navy va de borde a borde del fotograma, así que
       aquí no hay que topar nada contra el cuadro como en escritorio. */
    max-width:none;
    margin-left:0;
    padding:.4rem var(--pad) var(--pad);
    gap:.4rem;
  }
  /* AQUÍ LA TINTA Y EL CAMPO NO LOS DECIDE LA PARADA, Y ES LA SIMPLIFICACIÓN QUE TRAE EL CUADRO
     VERTICAL. En escritorio cada parada declara su campo porque el texto cae sobre un sitio
     distinto del fotograma en cada una. En móvil el texto cae SIEMPRE sobre el navy añadido en
     la extracción, que es el mismo en los 248 fotogramas, así que se fija una vez y los
     `data-campo` que publica js/lienzo.js dejan de importar.
     Medido sobre los .webp del perfil vertical, en diez fotogramas repartidos por el recorrido:
     el navy de abajo mide #00003c, el hueso contra él da 18,84:1 y el cian del resalte 15,72:1.
     Antes esto hacía lo contrario —devolvía campo y tinta a los de la página— porque el texto
     estaba debajo del cuadro, sobre el hueso. */
  .js-recorrido .recorrido__fijo,
  .js-recorrido .recorrido__fijo[data-campo="blanco"],
  .js-recorrido .recorrido__fijo[data-campo="navy"]{
    --campo:#00003c;
    --resalte:var(--cyan);
    --tinta-rotulo:var(--panel-ink);
    --tinta:var(--panel-ink);
    background:#00003c;
  }
  /* Y EN MÓVIL EL TEXTO SE MUEVE MÁS TODAVÍA. En escritorio el bloque ocupa un tercio de la
     ventana y 16 px de recorrido bastan para que el cambio se note. En un teléfono el bloque es
     casi toda la columna y el mismo recorrido se diluye, que es de lo que se quejó el cliente
     mirando su propia grabación. 24 px sobre una columna de 390 son el 6 % del ancho: se ve. */
  .js-recorrido .paso{ transform:translateY(24px) }
  .js-recorrido .rotulo{ transform:translateY(24px) }
  /* EL CUERPO DEL TITULAR SE ATA AL ALTO, Y NO AL ANCHO COMO EN ESCRITORIO.
     Allí la restricción es horizontal: el titular tiene que caber en el campo plano del
     fotograma, y por eso el tope va en cqw. Aquí la restricción es VERTICAL: el texto tiene que
     caber por encima de donde empieza la imagen, que es el 55,4 % de la capa en el peor caso.
     Medido sin este tope, el bloque de un fallo —que es el más alto porque además lleva el
     encabezado de los problemas— acababa en el 52,6 % a 375x667 y en el 54,0 % a 390x844 con la
     letra del navegador en 20. Pasaba, pero por 12 px, y 12 px no son una holgura: son suerte.
     Con el tope en 5.4svh el cuerpo deja de crecer cuando la pantalla no da para más, que es
     justo la condición que importa. En un teléfono normal con la letra en 16 no actúa —a 844 px
     de alto son 45 px y el titular pide 40—, así que esto sólo entra en los casos apretados.
     `svh` y no `vh` por lo mismo que la capa: es el viewport con la barra del navegador
     desplegada, que es el que no cambia a media pasada. */
  /* EL TOPE VA EN TODO EL BLOQUE Y NO SÓLO EN EL TITULAR. Con el tope sólo arriba, el bloque de
     un fallo —el más alto, porque además lleva el encabezado de los problemas con su apoyo—
     seguía saliendo del 55,4 % cuando el navegador tenía la letra en 20: acababa en el 56,7 %.
     El titular era lo que más medía pero no lo único: entre el rótulo, el encabezado, su apoyo
     y el texto de la parada hay siete u ocho líneas que crecen con la letra del navegador y
     ninguna miraba el alto de la pantalla. */
  .js-recorrido .paso__titulo{ font-size:min(var(--t-parada), 10cqw, 5svh) }
  .js-recorrido .paso__apoyo{ font-size:min(1rem, 1.9svh) }
  .js-recorrido .rotulo{ font-size:min(1rem, 1.9svh) }
  .js-recorrido .rotulo.rotulo--encabeza{ font-size:min(1.15rem, 2.6svh) }
  .js-recorrido .rotulo.rotulo--apoyo{ font-size:min(1rem, 1.9svh) }
}

/* LA RED — la página vuelve a flujo normal: sin riel, sin capa pegada y sin canvas.
   Cuatro casos:
   1) Movimiento reducido. js/lienzo.js ni pone la clase; esto es la red por si el ajuste del
      sistema cambia con la página ya cargada.
   2) Móvil en horizontal. La capa mide 100vh y apila cuadro y texto: medido desactivando esta
      red, a 740x360 el bloque del hero acaba 90 px por debajo de la capa. Lo que se sale es
      justo el texto, que es el argumento.
   3) Móvil (cualquier orientación) de 46rem de alto o menos — 736 px con la letra en 16.
      ERA 40rem Y SUBIÓ A 46 al pasar el móvil al cuadro vertical. Ahí el texto tiene que caber
      POR ENCIMA de donde empieza la imagen, el 51,5 % de la capa, y por debajo de cierto alto
      no cabe sin encoger la letra por debajo de lo legible. Medido con el bloque más alto —un
      fallo, que además lleva el encabezado de los problemas—: a 375x667 con la letra en 16
      acababa en el 51,3 %, y a 390x844 con la letra en 20, en el 48,9 %; con el texto bajado y
      la imagen subida, los dos se salían.
      Que la cifra vaya en `rem` es lo que hace esto correcto y no un número mágico: 46rem son
      736 px con la letra en 16, 920 con la letra en 20 y 1104 con la letra en 24, o sea que la
      red atrapa exactamente los casos en los que el texto no cabe, cualquiera que sea el ajuste
      del navegador. Se fijó midiendo: con 43rem, un 412x915 con la letra en 20 se quedaba fuera
      de la red y su paso 4 acababa en el 54,8 % cuando el límite es el 51,5.
      Lo que se pierde: los teléfonos de 736 px de alto o menos —un iPhone SE— y cualquiera con
      la letra del navegador agrandada en una pantalla que no dé de sí. A esos les toca la
      retícula estática, que es una página completa y legible, no un recorte.
   4) Ventana de 37.5rem de alto o menos, de cualquier ancho —600 px con la letra en 16—. Aquí no
      se sale nada: a 1440x600 el bloque del hero mide 370 px con la letra en 16 y 487 con la
      letra en 24, y la capa son 600. Lo que se pierde es la franja: a ese alto el cuadro se topa
      en 1067x600 y su campo plano vertical son 287 px —del 28,3 % al 76,1 %—, así que el bloque
      lo desborda ya con la letra normal y el contraste deja de estar garantizado. El corte
      protege la medición, no la maqueta.
   Los dos cortes de altura son distintos —46rem en móvil, 37.5rem en cualquier ancho— porque lo
   que no cabe es distinto: en móvil la pila entera, en escritorio el texto sobre el cuadro.
   POR QUÉ EN `rem` Y NO EN `px`: en una media query, `rem` se resuelve contra el tamaño de letra
   INICIAL del navegador —el ajuste «Grande» = 20 px, «Muy grande» = 24—, no contra el
   `font-size` de la raíz. Así el corte se mueve con la letra, que es justo lo que hacía falta:
   el zoom encoge los `vh` y un corte en px ya lo atrapaba, pero el ajuste de tamaño de letra NO
   toca los `vh`, y con él el bloque de texto crece sin que la ventana encoja. Con la letra en
   16 px estos dos valores son exactamente los 640 y 600 de siempre.

   ESTA LISTA DE CONDICIONES Y LA CONSTANTE `RED` DE js/lienzo.js SON LA MISMA LISTA. Va escrita
   en una sola línea para que se pueda copiar literal: todo lo que hay entre `@media ` y `{` es,
   carácter por carácter, lo que lleva esa constante. Si aquí se toca una condición, allá hay que
   tocarla igual; si no coinciden, el módulo carga 240 imágenes para pintar un canvas que esta
   hoja tiene en `display:none`, o al revés, deja el riel de 1400vh en pie sin nadie que lo
   recorra. Esta regla va la última del bloque a propósito: deshace lo de arriba con la misma
   especificidad y gana por orden. */
@media (prefers-reduced-motion:reduce),(max-width:839.98px) and (orientation:landscape),(max-width:839.98px) and (max-height:46rem),(max-height:37.5rem){
  .js-recorrido .recorrido{ min-height:0; padding:var(--section-pad) var(--pad) }
  /* `height:auto` y `display:block` no son adorno: el bloque de arriba pone `height:100vh/100dvh`
     y `display:grid` con la misma especificidad (0,2,0) que esta regla, y sobreviven a la red si
     no se deshacen aquí. Sin ellos la capa queda como caja de alto fijo con los once bloques
     dentro, desbordando sobre la sección siguiente. */
  .js-recorrido .recorrido__fijo{
    position:static; height:auto; display:block; padding:0;
  }
  /* La tinta vuelve a la de la página: aquí el fondo ya no es un fotograma sino el hueso de
     siempre, y un `data-tinta="hueso"` heredado del último tiempo dejaría el texto invisible.
     Las dos reglas juntas porque la de `[data-tinta="hueso"]` tiene más especificidad que la
     genérica y había que igualarla. */
  .js-recorrido .recorrido__fijo,
  .js-recorrido .recorrido__fijo[data-tinta="hueso"]{ --tinta:var(--ink); background:none }
  .js-recorrido .recorrido__lienzo{ display:none }
  /* Los once bloques, apilados en flujo y no en una celda: `grid-area:auto` los devuelve a once
     filas colocadas automáticamente, cada una con su aire. */
  .js-recorrido .recorrido__textos{
    width:auto;
    max-width:none;
    margin-left:0;
    padding:0;
    align-items:start;
  }
  /* `visibility:visible` es obligatorio aquí: si la red entra con un tiempo activo, los otros
     diez bloques venían de `visibility:hidden` y se quedarían invisibles en una página que la
     red existe precisamente para devolver entera. */
  .js-recorrido .paso{
    grid-area:auto;
    opacity:1;
    visibility:visible;
    transform:none;
    pointer-events:auto;
  }
}

/* La nota bajo el CTA del hero, que vive dentro de la primera parada. */
.hero__cta-note{
  font-size:var(--t-small);
  color:var(--ink-2);
}

/* --- 4 · Sectores (Tarea 6) --- */
/* Sin movimiento propio (docs/motion.md, fila 5): la tira de sectores es evidencia de alcance,
   no una lista de deseos (docs/brand/sectores.md). Los ocho de vitrina, luego la línea de
   afinidad, luego la nota de digitalización sin costo. */
.sectors{
  padding:var(--section-pad) var(--pad);
}
.sectors__title{
  font-family:var(--body);
  font-size:var(--t-h2);
  font-weight:900;
  line-height:.95;
  letter-spacing:-.035em;
  max-width:var(--measure);
  color:var(--ink);
  margin-bottom:var(--gap);
}
.sectors__affinity{
  max-width:var(--measure);
  color:var(--ink-2);
  /* El aire de ARRIBA lo pidió el cliente: sin él, el párrafo se pega a la tira de sectores y los
     dos se leen como un solo bloque. Va en --gap y no en un número suelto para que crezca con el
     ritmo del resto de la página. */
  margin-top:calc(var(--gap) * 1.5);
  margin-bottom:1rem;
}
.sectors__note{
  max-width:var(--measure);
  color:var(--ink);
}

/* --- 5 · Qué bordamos (Tarea 6) --- */
/* Único movimiento: las fotos, opacity + stagger 60ms (docs/motion.md, fila 6). Fotos reales,
   sin recortar sus proporciones — cada figura conserva su relación de aspecto nativa. */
.products{
  padding:var(--section-pad) var(--pad);
}
.products__title{
  font-family:var(--body);
  font-size:var(--t-h2);
  font-weight:900;
  line-height:.95;
  letter-spacing:-.035em;
  max-width:var(--measure);
  color:var(--ink);
  margin-bottom:var(--gap);
}
/* Las ocho prendas: ICONO ARRIBA Y NOMBRE DEBAJO, como pidió el cliente. Antes era una línea de
   nombres separados por puntos medios; los puntos se van con la maqueta, porque entre dos columnas
   con icono no separan nada, estorban.
   Retícula y no flex envolvente: con ocho columnas iguales los iconos quedan alineados entre sí, y
   «auto-fit» con un mínimo deja que bajen a dos filas en un teléfono sin que haya que decidir
   dónde parten. */
.products__list{
  list-style:none;
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(5.5rem, 1fr));
  gap:var(--gap) .5rem;
  font-family:var(--body);
  font-size:var(--t-small);
  font-weight:700;
  color:var(--ink);
  margin-bottom:var(--gap);
}
.products__item{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:.45rem;
  text-align:center;
}
/* El icono de prenda es FOTOGRAFÍA desde el 30 de octubre, no una silueta dibujada. Se sirve a
   400 px y se muestra a 56: a esa medida lo que se reconoce es la silueta y el color, que es
   justo lo que una foto de producto sobre fondo liso da mejor que un dibujo.
   El fondo de los ocho archivos ES el hueso de la página, no transparencia: se compone en
   tools/preparar-prendas.mjs. Si algún día esta sección cambia de color de fondo, hay que
   volver a correr esa herramienta con el color nuevo. */
.products__icono{
  display:block;
  width:3.5rem;
  height:3.5rem;
}
.products__note{
  max-width:var(--measure);
  color:var(--ink-2);
  margin-bottom:var(--gap);
}
/* tela-macro.png trae un margen en blanco bajo la textura; se recorta sin deformar la imagen
   (object-fit:cover conserva la relación de aspecto, solo oculta el excedente). */

@media (min-width:840px){
  .products__grid{
    grid-template-columns:repeat(3, 1fr);
    align-items:start;
  }
  .products__figure--wide{
    grid-column:1 / -1;
  }
}

/* --- 6 · FAQ (Tarea 7) --- */
/* Sin movimiento propio de sección (docs/motion.md, fila 9): lo único que anima es el acordeón,
   al clic — ver css/components.css para la mecánica .faq-i/.faq-a/.faq-plus. */
.faq{
  padding:var(--section-pad) var(--pad);
}
.faq__title{
  font-family:var(--body);
  font-size:var(--t-h2);
  font-weight:900;
  line-height:.95;
  letter-spacing:-.035em;
  max-width:var(--measure);
  color:var(--ink);
  margin-bottom:var(--gap);
}
.faq__list{
  margin-bottom:var(--gap);
}

/* --- Aviso de privacidad --- */
/* Una sola columna de prosa larga, que es lo único que hay en esa página. No reutiliza los
   estilos del recorrido ni los de las secciones del inicio: aquí no hay composición, hay un
   documento que alguien tiene que poder leer entero y, llegado el caso, imprimir.
   El ancho se topa en --measure (64ch) porque es un texto para leer de corrido y una línea más
   larga que eso se pierde al volver al renglón. Los títulos van en la familia de texto y no en
   la de display: la display es una grotesca ancha en mayúsculas, pensada para dos palabras, y
   un «Transferencias y remisiones de datos» en mayúsculas anchas no se lee, se descifra. */
/* EL CUERPO VA EN .8rem Y NO EN EL 1rem DEL RESTO DEL SITIO, y es una peticion del cliente con
   la que estoy de acuerdo. Un aviso de privacidad no es texto de lectura: es un documento al que
   se acude. Al tamano del cuerpo de la pagina ocupaba cinco pantallas y pesaba como si fuera lo
   importante. A .8rem (12,8 px con la letra del navegador en 16) cabe en menos, se ve de un
   vistazo lo que hay, y sigue por encima del tamano al que los navegadores empiezan a estorbar.
   El tope de ancho se baja a 58ch en consecuencia: la medida comoda va en caracteres, no en
   pixeles, y con el cuerpo mas chico --measure (64ch) daria una linea fisicamente mas corta de
   lo que hace falta, pero el texto tiene muchas enumeraciones y 58 se lee mejor.
   NO SE BAJA MAS. Por debajo de .75rem el texto deja de ser legible para quien lo necesita, que
   en un aviso de privacidad es justo la persona que viene a reclamar algo. */
.legal{
  padding:var(--section-pad) var(--pad);
  max-width:calc(58ch + var(--pad) * 2);
  margin-inline:auto;
  font-size:.8rem;
  line-height:1.6;
}
.legal__title{
  font-family:var(--body);
  font-size:1.5rem;
  font-weight:900;
  line-height:1;
  letter-spacing:-.03em;
  color:var(--ink);
  margin-bottom:.6rem;
}
.legal__lede{
  color:var(--ink-2);
  margin-bottom:var(--gap);
}
/* SIN RESALTES EN LA PROSA, que es la otra mitad de la peticion. El texto venia con medias
   frases en negrita —«No recabamos datos personales sensibles», «no se cobra en linea»— y eso
   en un documento legal se lee como si gritara, ademas de dar a entender que lo demas importa
   menos. El enfasis se quita del HTML, no se anula aqui: si manana alguien escribe un <strong>
   en un parrafo, que se vea y se decida, en vez de que una regla lo esconda.
   Los <strong> que quedan son los terminos de las listas —«Fiscales:», «WhatsApp (Meta...)»—,
   que no son enfasis sino la cabeza de una definicion, y por eso van en 700 y no en 900. */
.legal h2{
  font-family:var(--body);
  font-size:.95rem;
  font-weight:800;
  line-height:1.25;
  letter-spacing:-.015em;
  color:var(--ink);
  margin-top:1.8rem;
  margin-bottom:.4rem;
}
.legal p,
.legal ul{
  margin-bottom:.9rem;
}
.legal ul{
  padding-left:1.2rem;
}
.legal li{
  margin-bottom:.35rem;
}
.legal strong{
  font-weight:700;
}
.legal a{
  color:var(--ink);
  text-decoration-thickness:1px;
  text-underline-offset:2px;
}
.legal__fecha{
  margin-top:1.8rem;
  padding-top:.8rem;
  border-top:1px solid var(--grey-2);
  color:var(--ink-2);
  font-size:.75rem;
}

/* --- 404 --- */
/* Página de error mínima (404.html): masthead, regla, mensaje breve y el camino de vuelta.
   Sin movimiento. Las rutas del HTML son absolutas porque se sirve desde cualquier URL. */
.notfound{
  padding:var(--section-pad) var(--pad);
}
.notfound__title{
  font-family:var(--body);
  font-size:var(--t-h2);
  font-weight:900;
  line-height:.95;
  letter-spacing:-.035em;
  max-width:var(--measure);
  color:var(--ink);
  margin-bottom:1rem;
}
.notfound__text{
  max-width:var(--measure);
  color:var(--ink-2);
  margin-bottom:var(--gap);
}
