/* ============================================================================
   SPICA STUDIO · css/rest.css · LA CORTINA (r14)
   Descanso visual compartido por el Home (#rest, "Seven Solutions. One
   system.") y por las cuatro hojas estandar (.sol-rest, el h2 de seccion como
   gigante). Un solo modulo, js/rest-curtain.js, y esta unica hoja para las
   cinco cortinas del sitio, asi las cinco se comportan igual.

   CONTRATO DEL MARKUP (se pega igual en el Home y en las hojas; PLAN 1.A2 =
   CROSS-UXUI H1). Se pega tal cual, sin cambiar ni un nombre de clase:
     <section class="rest" id="rest" aria-labelledby="rest-title" data-curtain>
       <div class="rest__pin">
         <div class="rest__stage">
           <div class="rest__photo" aria-hidden="true">
             <picture>
               <source media="(max-width: 1080px)" srcset="/assets/rest/rest-curtain-01-m.webp?v=r14" width="800" height="1000" />
               <img src="/assets/rest/rest-curtain-01.webp?v=r14" alt="" width="1600" height="900" loading="lazy" decoding="async" />
             </picture>
             <span class="rest__scrim"></span>
           </div>
           <h2 class="h2 rest__title" id="rest-title"><span class="rest__line">Seven Solutions.</span><br /><span class="rest__line">One system.</span></h2>
         </div>
       </div>
     </section>
   Reglas del contrato:
   · UN solo h2. El gigante y el titular de seccion son el mismo nodo, escalado.
     Nada de kicker, parrafo ni segundo titulo. Cada linea va en span.rest__line
     (white-space: nowrap; la primera, la mas larga, es la que mide el modulo).
   · La foto es decorativa: alt="" y aria-hidden en .rest__photo. Si Cesar
     prefiere clip, <picture> se sustituye por
     <video class="vid" muted playsinline loop preload="metadata" poster="...webp?v=r14">
     SIN autoplay (lo gobierna js/media-io.js); el modulo solo lo escala.
   · En las hojas: <section class="rest sol-rest" ...> con el h2 de la hoja
     ("Where the lead<br />goes next.") y, dentro de .rest__stage, las tres
     tarjetas de cross-link que solution.css revela con .is-landed. La hoja
     declara en su CSS: .sol-rest { --rest-land-y: 0.36 } (reposo del titular
     al 36 % del stage) y, en 3.1, --rest-giant-color: var(--amber-vivid).

   TRES ESTADOS, y el CSS por defecto ES el fallback (nada depende de JS):
   1. Escritorio con motion (>= 1081, sin ?static ni reduced-motion): el
      modulo pone .rest--pin. Recorrido 180svh, stage sticky de 100svh, foto
      a sangre recortada por clip-path (cintura hacia adentro), titular
      gigante en el vivid dueno que aterriza en tinta. Custom properties que
      escribe el modulo en la seccion: --rest-giant (medido, 3.2 a 6) y
      --rest-mix (0 a 1). Por defecto valen 1 y 0.
   2. ?static, reduced-motion y sin JS (escritorio): la clase nunca se pone.
      Foto abierta, sin clip, titular a tamano normal (--text-h2) en papel
      sobre el velo, ESQUINA INFERIOR IZQUIERDA contenida en el gutter, stage
      de min(100svh, 46rem). Es el MISMO estado que el tactil (PLAN 1.A8,
      SPEC-UXUI 4.6); r14 supervision P1-1: centrado sobre el cielo crema daba
      1,2:1 a 1,5:1, porque el velo empieza abajo y la foto mide 0,78 de
      luminancia hasta el 90 % de su alto.
   3. Tactil y ventanas < 1081: la cortina no corre. Foto 4:5 del ancho (tope
      640px de alto, siempre a todo el ancho) con el titular en --text-display, papel sobre el velo, esquina
      inferior izquierda contenida en el gutter, sin sangrar. El titular NO se
      repite debajo: el bloque siguiente es la seccion que sigue.
   El velo (.rest__scrim) esta medido sobre rest-curtain-01.webp (r14 P1-1 y
   P2-1): la foto es crema (0,78) hasta el 90 % y solo oscurece en el 10 %
   final, asi que un degradado 0,55 desde el 45 % dejaba el papel en 1,7:1 a
   3,4:1. Los stops van anclados en rem desde ABAJO (la caja del titular
   siempre cuelga del borde inferior): a 12rem del borde el velo ya vale 0,66
   y 0,74 en el borde; el max() evita que en un stage corto (375: 469px) el
   velo empiece demasiado arriba. El navegador compone el velo en espacio sRGB
   (no lineal): 0,66 sobre la foto crema (sRGB 229) deja 89 de sRGB, o sea
   0,10 de luminancia, papel encima 6,5:1; 0,55 daria 4,5:1 justo y 0,80
   dejaba el tercio inferior casi negro (11:1, medido).
   Remediacion de r14 (2 de septiembre): las cinco fotos de cortina se
   rehicieron con una persona real grande en cuadro, asi que la de arriba ya no
   es un campo crema plano. El velo NO se toca: remedido en WebKit a 390 sobre
   las cinco fotos nuevas, el papel sobre el velo da de 8,1:1 a 17,6:1 de media
   y 6,6:1 en el peor caso, todos por encima del 4,5:1 que pide AA. Detalle en
   docs-r14/SHOTLIST-CORTINAS-R14.md y en MEDIA-MANIFEST.md.

   Fases del scrub (PLAN 1.A4, progreso p en [0, 1] amortiguado con k = 12):
   HOLD 0,00 a 0,12 · CORTINA, ESCALA y POSICION 0,12 a 0,72 · COLOR 0,52 a
   0,72 (detras de la cortina) · REST 0,72 a 1,00. Zoom de la foto 1,06 a 1,00
   lineal de 0,00 a 0,72. is-landed en la seccion con p >= 0,72 (se quita bajo
   0,60). Todo es posicion en funcion de p: 100 % reversible, nunca reloj.

   LA COLA (r14, pasada de ritmo). El recorrido, el reparto de fases y la
   fisica NO se tocan: el stage sigue midiendo 100svh y el pin 180svh, que es
   lo que lee el modulo. Lo que se corrige es lo que pasa DESPUES de aterrizar:
   con el titular al 50 % de un escenario de una pantalla y nada debajo (el
   Home) sobraban 397px de papel dentro del stage mas el respiro de la seccion
   siguiente, o sea 581px medidos entre el pie del titular y el kicker "09 The
   difference" a 1440x900. Se recorta con --rest-tail-cut: la seccion sigue
   ocupando su caja de 180svh para el scrub, pero cede en el FLUJO ese trozo
   final (margin-bottom negativo, la misma jugada que .ba--pin usa desde r6
   C31), asi que el bloque siguiente sube y entra en cuadro mientras el titular
   descansa. Para que el bloque siguiente se vea a traves de ese solape, ni la
   seccion ni el escenario pintan fondo en modo pin: el papel lo pone el body,
   que es el mismo token. Y el escenario deja de capturar el raton (los hijos
   que si lo necesitan, como .sol-link, lo recuperan con pointer-events: auto).
   El tope del recorte es el 40 % del recorrido: por encima, el bloque
   siguiente asomaria ANTES de que el titular aterrice. Home 30svh (nada vive
   bajo el titular), hojas 20svh (debajo van las tres tarjetas de cross-link).
   ========================================================================== */

.rest {
  position: relative;
  background: var(--paper);
  /* clip y no hidden: hidden convierte a .rest en contenedor de scroll y
     mata el sticky del stage; clip recorta igual sin crear contenedor */
  overflow: clip;
  --rest-giant: 1;
  --rest-mix: 0;
  --rest-land-y: 0.5;
  --rest-giant-color: var(--violet-vivid);
  /* cuanto del final de la seccion se cede al bloque siguiente (ver cabecera).
     Tope duro: 40 % del recorrido, o sea 32svh; el Home usa 30, las hojas 20 */
  --rest-tail-cut: 30svh;
}
.rest__pin { position: relative; height: auto; }
.rest__stage {
  position: relative;
  height: min(100svh, 46rem);
  overflow: hidden;
  display: grid;
  place-items: end start; /* titular abajo a la izquierda en todo estado sin pin */
  background: var(--paper);
}
.rest__photo { position: absolute; inset: 0; z-index: 1; }
.rest__photo picture { display: block; width: 100%; height: 100%; }
.rest__photo img,
.rest__photo video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 40%;
  /* estado quieto: el micro zoom ya aplicado, como el primer frame del scrub */
  transform: scale(1.06);
}
/* el scrim vive DENTRO de la foto para irse con ella al cerrar; solo se ve en
   los estados donde el titular va en papel sobre la foto */
.rest__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    transparent max(28%, 100% - 24rem),
    rgba(17, 17, 16, 0.66) max(56%, 100% - 12rem),
    rgba(17, 17, 16, 0.74) 100%
  );
}
.rest__title {
  position: relative;
  z-index: 3;
  text-align: left;
  padding: 0 var(--gutter) var(--gutter);
  max-width: 100%;
  color: var(--paper);
  font-size: var(--text-h2);
  /* el <br /> fija las dos lineas; el balance de .h2 no manda aqui */
  text-wrap: wrap;
  margin: 0;
}
.rest__line { white-space: nowrap; }

/* ---- 1 · escritorio con motion: la clase la pone js/rest-curtain.js -------- */
/* la caja del scrub no cambia (180svh de pin, 100svh de stage): lo que cambia
   es cuanto de esa caja ocupa la seccion en el FLUJO. El fondo se apaga aqui
   porque .rest es position: relative y su fondo se pintaria por encima del
   texto del bloque siguiente durante el solape; el papel lo pone el body */
.rest--pin {
  margin-bottom: calc(-1 * var(--rest-tail-cut));
  background: transparent;
  /* durante el solape la caja de la seccion sigue cubriendo la cabecera del
     bloque siguiente: no debe robarle el raton. Lo que dentro si lo necesita
     lo recupera con pointer-events: auto (el titular aqui, .sol-link en la
     hoja) */
  pointer-events: none;
}
.rest--pin .rest__pin { height: 180svh; }
.rest--pin .rest__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  background: transparent;
}
.rest--pin .rest__title { pointer-events: auto; }
.rest--pin .rest__scrim { opacity: 0; } /* cielo limpio bajo el gigante */
.rest--pin .rest__photo { will-change: clip-path; }
.rest--pin .rest__photo img,
.rest--pin .rest__photo video {
  transform: none; /* el zoom lo escribe el modulo por frame */
  will-change: transform;
}
.rest--pin .rest__title {
  /* centrado por posicion absoluta, no por la grilla: un item de grid mas
     ancho que su area (el gigante sangra un 14 % por lado) se alinea al
     inicio en Chromium y en WebKit aunque pida center, y el titular quedaba
     corrido 200px a la derecha. Con left/top al 50 % y width max-content, el
     modulo antepone translate(-50%, -50%) (porcentajes de la propia caja) y
     el centro cae exacto en W/2 y en --rest-land-y * H sea cual sea el ancho */
  position: absolute;
  left: 50%;
  top: 50%;
  width: max-content;
  max-width: none;
  padding: 0;
  transform: translate(-50%, -50%);
  /* compuesto YA gigante y escalado hacia ABAJO (de 1 a 1/giant): un texto
     escalado por encima de 1 sale borroso en Safari durante el HOLD */
  font-size: calc(var(--text-h2) * var(--rest-giant));
  /* respaldo sin color-mix(): el modulo escribe el rgb interpolado inline */
  color: var(--rest-giant-color);
  color: color-mix(in srgb, var(--ink) calc(var(--rest-mix) * 100%), var(--rest-giant-color));
  transform-origin: 50% 50%;
  will-change: transform;
}

/* ---- 2 · reduced-motion: aunque la clase llegara a ponerse, no hay scrub --- */
@media (prefers-reduced-motion: reduce) {
  .rest--pin { margin-bottom: 0; background: var(--paper); pointer-events: auto; }
  .rest--pin .rest__stage { background: var(--paper); }
  .rest--pin .rest__pin { height: auto; }
  .rest--pin .rest__stage { position: relative; height: min(100svh, 46rem); }
  .rest--pin .rest__scrim { opacity: 1; }
  .rest--pin .rest__title {
    position: relative;
    left: auto;
    top: auto;
    width: auto;
    max-width: 100%;
    padding: 0 var(--gutter) var(--gutter);
    text-align: left;
    font-size: var(--text-h2);
    color: var(--paper);
    transform: none !important;
  }
  .rest--pin .rest__photo { clip-path: none !important; visibility: visible !important; }
}

/* ---- 3 · tactil y ventanas medianas: la cortina no corre ------------------- */
@media (max-width: 1080px) {
  .rest__stage {
    /* 4:5 del ancho con tope de 640px, como alto EXPLICITO. Con aspect-ratio +
       max-height el tope se transferia al ancho (regla de transferencia de
       css-sizing) y entre 768 y 1080 el stage media 512px con papel al lado
       (medido en Chromium y WebKit a 834: stage 512 x 640). */
    height: min(125vw, 640px);
    aspect-ratio: auto;
  }
  .rest__title { font-size: var(--text-display); }
  /* seguro: el modulo se apaga por matchMedia, pero si la clase quedara un
     frame, el estado apilado sigue mandando */
  .rest--pin { margin-bottom: 0; background: var(--paper); pointer-events: auto; }
  .rest--pin .rest__stage { background: var(--paper); }
  .rest--pin .rest__pin { height: auto; }
  .rest--pin .rest__stage { position: relative; height: auto; }
  .rest--pin .rest__scrim { opacity: 1; }
  .rest--pin .rest__title {
    position: relative;
    left: auto;
    top: auto;
    width: auto;
    padding: 0 var(--gutter) var(--gutter);
    font-size: var(--text-display);
    color: var(--paper);
    transform: none !important;
  }
  .rest--pin .rest__photo { clip-path: none !important; visibility: visible !important; }
  .rest--pin .rest__photo img,
  .rest--pin .rest__photo video { transform: scale(1.06) !important; }
}
