@font-face {
    font-family: 'Rubik Dirt';
    src: url('../fonts/RubikDirt-Regular.ttf') format('truetype');
    /* Rubik Dirt es una display de UN solo peso: su grueso "normal" (400).
       Declaramos el rango 100–900 para que cualquier `font-weight` que pidan
       los títulos (700, bold, etc.) se resuelva a esa única cara REAL de 400
       -grueso normal-, en vez de que el navegador sintetice un "faux bold"
       que la deforma. */
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}

:root {
    --color-white: #f4f1ec;
    --color-red: #d8162b;
    --color-red-dark: #b01223;                       /* rojo profundo para hover de botones de acción */
    --color-ink: #0e0e10;
    /* Azul de marca JET (pinturasjet.com): navy primario + cian de acento.
       Se usa en el CTA final (sección 10). El navy es oscuro, así que el
       copy blanco existente conserva buen contraste encima. */
    --color-blue: #203c73;
    --color-blue-accent: #24abe2;
    /* Ancho máximo del CONTENIDO (textos, personajes, paneles, íconos). En
       pantallas más anchas el contenido se centra y solo los backgrounds
       crecen. Por debajo de 1440 no tiene efecto (contenido = viewport). */
    --content-max: 1440px;
    /* Profundidad del desvanecimiento foto→ink en los bordes sup/inf de las
       secciones narrativas (03-06). Punto único de ajuste del efecto. */
    --fade-edge: 14%;
    --font-display: 'Rubik Dirt', 'Impact', sans-serif;
    /* Afacad reemplaza Helvetica (sans) y Cambria (italic). Es una
       sans-serif moderna con buen soporte de italic - usamos el mismo
       family para ambos roles y los diferenciamos con font-style. */
    --font-italic: 'Afacad', 'Cambria', 'Georgia', serif;
    --font-sans: 'Afacad', 'Helvetica Neue', 'Arial', sans-serif;

    /* ----------------------------------------------------------------------
       GLASSMORPHISM-INDUSTRIAL (v2)

       Sistema de "placas de vidrio" translúcidas que envuelven el copy de
       lectura para que se lea limpio sobre la fotografía. Generaliza el
       patrón que ya existía en .stages__frame-label. La sensación buscada
       es "placa industrial / panel de instrumentos", no burbuja: radio
       chico, borde frío sutil, highlight superior fino, sombra profunda y
       un acento rojo de marca en un costado.
       --------------------------------------------------------------------- */
    /* Glass intensificado (frosted): translúcido + blur fuerte, se ve
       la foto desenfocada a través de la placa. La legibilidad la sostiene
       el blur + saturación, no la opacidad. (El blur sólo se aprecia en
       navegadores con soporte de backdrop-filter.) */
    --glass-bg: linear-gradient(150deg, rgba(30, 30, 36, 0.34), rgba(15, 15, 19, 0.22));
    --glass-bg-strong: linear-gradient(150deg, rgba(26, 26, 32, 0.50), rgba(14, 14, 18, 0.36));
    --glass-blur: blur(18px) saturate(150%);
    --glass-blur-strong: blur(30px) saturate(165%);
    --glass-border: 1px solid rgba(244, 241, 236, 0.18);
    --glass-border-strong: 1px solid rgba(244, 241, 236, 0.26);
    --glass-highlight: inset 0 1px 0 rgba(244, 241, 236, 0.22);
    --glass-shadow: 0 26px 50px -20px rgba(0, 0, 0, 0.55);
    --glass-radius: clamp(0.45rem, 0.85cqi, 0.95rem);
    --glass-pad: clamp(0.9rem, 1.6cqi, 1.6rem);
    /* Escala de z-index del sitio. */
    --z-nav: 1000;
}

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html, body {
    background-color: var(--color-ink);
    color: var(--color-white);
    font-family: var(--font-sans);
    /* `clip` en lugar de `hidden` - no crea contexto de scroll, así
       position: sticky sigue funcionando dentro del documento. */
    overflow-x: clip;
}

/* ==========================================================================
   GLASS UTILITY (v2) - placa de vidrio industrial reutilizable

   Cualquier grupo de copy puede envolverse con .glass para leerse limpio
   sobre la foto. El acento rojo (regla industrial) es un pseudo-elemento
   en el borde izquierdo. Fallback sin backdrop-filter más abajo.
   ========================================================================== */

.glass {
    position: relative;
    background: var(--glass-bg);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: var(--glass-border);
    border-radius: var(--glass-radius);
    box-shadow: var(--glass-highlight), var(--glass-shadow);
    padding: var(--glass-pad);
}

/* Regla roja de marca al costado izquierdo - sello "industrial". */
.glass::before {
    content: "";
    position: absolute;
    left: 0;
    top: clamp(0.6rem, 1.2cqi, 1.1rem);
    bottom: clamp(0.6rem, 1.2cqi, 1.1rem);
    width: 2px;
    background: var(--color-red);
    border-radius: 2px;
}

.glass--strong {
    background: var(--glass-bg-strong);
    -webkit-backdrop-filter: var(--glass-blur-strong);
    backdrop-filter: var(--glass-blur-strong);
    border: var(--glass-border-strong);
}

/* Variante sin barra roja (para placas donde el acento estorba). */
.glass--plain::before { display: none; }

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .glass { background: var(--glass-bg-strong); }
    .glass--strong { background: rgba(10, 10, 12, 0.9); }
}

/* ==========================================================================
   SITE NAV (v2) - barra glass scroll-aware, full-width

   Reemplaza el pill blanco flotante que se perdía sobre la fotografía.
   Tres estados que togglea script-v2.js:
     · base (top/hero): casi transparente, sólo logo + CTA con sombra.
     · .is-scrolled:    glass sólido, siempre legible.
     · .is-hidden:      oculto al hacer scroll hacia abajo; reaparece al subir.

   Vive fuera de <section.hero> y es position: fixed para persistir entre
   secciones. El track de scroll lo maneja Lenis en script-v2.js.
   ========================================================================== */

.site-nav {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: var(--z-nav);
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: clamp(0.75rem, 2vw, 2rem);
    padding: clamp(0.7rem, 1.4vw, 1.25rem) clamp(1rem, 3vw, 3rem);

    /* Glass base muy sutil - sobre el hero apenas se insinúa. */
    background: linear-gradient(180deg, rgba(8, 8, 10, 0.42), rgba(8, 8, 10, 0));
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    border-bottom: 1px solid transparent;

    transition:
        transform 420ms cubic-bezier(0.4, 0, 0.2, 1),
        background-color 320ms ease,
        backdrop-filter 320ms ease,
        border-color 320ms ease,
        padding 320ms ease;
    will-change: transform;
}

/* Pasado el hero: glass sólido y siempre legible. */
.site-nav.is-scrolled {
    background: var(--glass-bg-strong);
    -webkit-backdrop-filter: var(--glass-blur-strong);
    backdrop-filter: var(--glass-blur-strong);
    border-bottom: var(--glass-border);
    box-shadow: 0 14px 34px -22px rgba(0, 0, 0, 0.8);
    padding-top: clamp(0.55rem, 1vw, 0.95rem);
    padding-bottom: clamp(0.55rem, 1vw, 0.95rem);
}

/* Oculto al bajar; el toggle de .is-hidden lo hace JS según dirección. */
.site-nav.is-hidden { transform: translateY(-105%); }

.site-nav__brand {
    display: block;
    flex-shrink: 0;
    width: clamp(2.6rem, 5vw, 5rem);
    text-decoration: none;
    line-height: 0;
}

.site-nav__brand img {
    width: 100%;
    height: auto;
    display: block;
    filter:
        drop-shadow(0 0 2px rgba(0, 0, 0, 0.85))
        drop-shadow(0 0 8px rgba(0, 0, 0, 0.55))
        drop-shadow(0 4px 12px rgba(0, 0, 0, 0.45));
}

.site-nav__menu {
    display: flex;
    align-items: center;
    gap: clamp(0.4rem, 1vw, 1.1rem);
}

.site-nav__link {
    text-decoration: none;
    color: var(--color-white);
    font-family: var(--font-sans);
    font-weight: 600;
    font-size: clamp(0.85rem, 1vw, 1.05rem);
    letter-spacing: 0.04em;
    padding: 0.5em 0.9em;
    border-radius: 6px;
    white-space: nowrap;
    text-shadow: 0 1px 8px rgba(0, 0, 0, 0.7);
    transition: color 200ms ease, background-color 200ms ease;
}

.site-nav__link:hover,
.site-nav__link:focus-visible {
    color: var(--color-red);
    background: rgba(244, 241, 236, 0.06);
    outline: none;
}

.site-nav__link:focus-visible {
    outline: 2px solid var(--color-red);
    outline-offset: 2px;
}

.site-nav__cta {
    text-decoration: none;
    color: var(--color-white);
    background: var(--color-red);
    font-family: var(--font-sans);
    font-weight: 800;
    font-size: clamp(0.8rem, 1vw, 1rem);
    letter-spacing: 0.05em;
    text-transform: uppercase;
    padding: 0.7em 1.4em;
    border-radius: 999px;
    white-space: nowrap;
    box-shadow: 0 8px 20px -8px rgba(216, 22, 43, 0.7);
    transition: background-color 200ms ease, transform 200ms ease;
}

.site-nav__cta:hover,
.site-nav__cta:focus-visible {
    background: #b81120;
    transform: translateY(-1px);
    outline: none;
}

.site-nav__cta:focus-visible {
    outline: 2px solid var(--color-white);
    outline-offset: 3px;
}

@media (orientation: portrait) {
    .site-nav__link { display: none; }

    .site-nav__cta {
        padding: 0.75em 1.3em;
        font-size: clamp(0.7rem, 3vw, 1rem);
    }
}

/* ==========================================================================
   SIGNAL CARDS (v2) - tarjetas con ícono para las listas de señales

   Reemplaza los bullets de texto plano (term · gloss) por tarjetas glass
   con ícono outline rojo, término en bold uppercase y glosa corta, según
   la referencia del cliente. Patrón compartido por moment / advance /
   holes / face / recognize. Cada sección sólo define dónde se ancla la
   grilla (grid-area / posición); el look de la tarjeta vive acá.

   Marcado:
     <ul class="signal-cards SECTION__signals">
       <li class="signal-card">
         <svg class="signal-card__icon"><use href="#ico-…"/></svg>
         <span class="signal-card__term">BURBUJAS</span>
         <span class="signal-card__desc">Pérdida de adherencia</span>
       </li>
   ========================================================================== */

.signal-cards {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    /* auto-fit: en una banda ancha reparte las tarjetas en fila; en un
       slot angosto se apilan solas. Sin media queries por sección. */
    grid-template-columns: repeat(auto-fit, minmax(clamp(8.5rem, 13cqi, 12.5rem), 1fr));
    gap: clamp(0.5rem, 1cqi, 1rem);
}

/* Las secciones con 4 cards (advance, holes, face) van en 2x2 fijo
   para mantener la lectura por pares. En portrait colapsan a 1 columna. */
.advance__signals,
.holes__signals,
.face__signals {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 767px), (orientation: portrait) {
    .advance__signals,
    .holes__signals,
    .face__signals {
        grid-template-columns: 1fr;
    }
}

/* Sec 06 (face) - variante "consecuencia": fondo rojo con glassmorphism,
   íconos blancos. El blur se mantiene para conservar la profundidad
   visual; el rojo señala que estas ya NO son señales tempranas sino
   consecuencias finales. */
.face__signals .signal-card {
    background:
        linear-gradient(150deg, rgba(216, 22, 43, 0.72), rgba(168, 16, 32, 0.58));
    border: 1px solid rgba(244, 241, 236, 0.28);
    box-shadow:
        inset 0 1px 0 rgba(244, 241, 236, 0.28),
        0 26px 50px -20px rgba(120, 8, 18, 0.55);
}

.face__signals .signal-card__icon {
    color: var(--color-white);
}

.face__signals .signal-card__desc {
    color: rgba(244, 241, 236, 0.92);
}

.signal-card {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-rows: auto auto;
    align-items: center;
    column-gap: clamp(0.55rem, 1cqi, 0.95rem);
    row-gap: 0.15em;

    background: var(--glass-bg);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: var(--glass-border);
    border-radius: var(--glass-radius);
    box-shadow: var(--glass-highlight), var(--glass-shadow);
    padding: clamp(0.7rem, 1.3cqi, 1.25rem) clamp(0.8rem, 1.4cqi, 1.4rem);
}

.signal-card__icon {
    grid-row: 1 / 3;
    width: clamp(1.6rem, 2.6cqi, 2.4rem);
    height: clamp(1.6rem, 2.6cqi, 2.4rem);
    flex-shrink: 0;
    color: var(--color-red);
    /* stroke = currentColor en los <symbol>; relleno transparente. */
}

.signal-card__term {
    align-self: end;
    font-family: var(--font-sans);
    font-weight: 700;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.72rem, 1.05cqi, 1.15rem);
    letter-spacing: 0.08em;
    line-height: 1.15;
}

.signal-card__desc {
    align-self: start;
    font-family: var(--font-sans);
    font-weight: 400;
    color: rgba(244, 241, 236, 0.78);
    font-size: clamp(0.66rem, 0.92cqi, 1rem);
    letter-spacing: 0.01em;
    line-height: 1.2;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .signal-card { background: var(--glass-bg-strong); }
}

/* ==========================================================================
   HERO

   El hero contiene dos escenas apiladas verticalmente (200svh totales)
   sobre un fondo sticky compartido (cielo + paisaje).

   Sticky bg pattern:
   - .hero__sky y .hero__landscape llevan `position: sticky; top: 0;
     height: 100svh; margin-bottom: -100svh`. El margin negativo cancela
     su altura en el flujo → las escenas arrancan en y=0 del .hero. La
     posición sticky los mantiene en el viewport durante todo el scroll
     dentro del .hero.

   Z-index map en el stacking context de .hero (creado por isolation):
     1  hero__sky        (cielo, fondo absoluto)
     2  hero__title      (queda detrás del paisaje → efecto montañas)
     3  hero__landscape  (paisaje, monte y camino)
        hero__conducto   (tubo de scene 2, mismo nivel pero por source order
                          se pinta encima del paisaje)
     4  hero__pointer    (mano, encima del conducto)
     5  hero__character  (trabajador de scene 1)
     6  todos los textos (eyebrow, subline, stat, intro, cta-title, loss)

   IMPORTANTE: las escenas NO tienen z-index ni isolation propios. Sus
   hijos con z-index participan directo en el stacking context de .hero,
   lo que es necesario para que el truco título-detrás-de-montañas siga
   funcionando con el bg sticky.
   ========================================================================== */

.hero {
    position: relative;
    isolation: isolate;
    container-type: inline-size;
}

/* Sky y landscape como <img> directos para que el block-level sea explícito
   y los width/height/margin del sticky se apliquen sin ambigüedad.
   object-fit + object-position hacen el comportamiento de "cover" que antes
   teníamos en un <img> hijo de <picture>. */
.hero__sky,
.hero__landscape {
    position: sticky;
    top: 0;
    left: 0;
    display: block;
    width: 100%;
    height: 100svh;
    object-fit: cover;
    object-position: center;
    margin-bottom: -100svh;
    pointer-events: none;
    /* Oscurece SOLO el fondo del hero (cielo + paisaje). El título (z-index 2,
       elemento aparte) y el personaje (z-index 5) no son hijos de estas
       imágenes, así que no se ven afectados. */
    filter: brightness(0.8);
}

.hero__sky { z-index: 1; }
.hero__landscape { z-index: 3; }

/* ---------- SCENE base ---------- */
.hero__scene {
    position: relative;
    width: 100%;
    min-height: 100svh;
    display: grid;
    /* Clipea imágenes que se salgan (conducto, character).
       overflow: hidden en .hero__scene NO afecta a las sticky de .hero
       porque son siblings, no descendants. */
    overflow: hidden;
}

/* Wrapper interno del hero: TOPA el TEXTO/personaje a --content-max y lo
   centra; nuevo contexto de container-query. Los backgrounds (sky, landscape)
   y el grupo tubo+pointer (conducto/pointer) quedan FUERA → siguen full-bleed
   y crecen (experiencia fullpage de la parte 02). El grid-template concreto lo
   ponen .hero__scene--intro/--recognize .hero__scene-inner. */
.hero__scene-inner {
    position: relative;
    width: 100%;
    max-width: var(--content-max);
    margin-inline: auto;
    min-height: 100svh;
    height: 100%;
    container-type: inline-size;
    display: grid;
}

/* ==========================================================================
   SCENE 1 - INTRO (trabajador con escudo)
   ========================================================================== */

.hero__scene--intro .hero__scene-inner {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr auto;
    grid-template-areas:
        "headline ."
        "stat     .";
    padding: clamp(5rem, 9cqi, 9rem) clamp(1rem, 3cqi, 3rem) clamp(1.5rem, 4cqi, 4rem);
    gap: clamp(1rem, 2cqi, 3rem);
}

/* Tamaño híbrido con min(): el lado más pequeño manda. En viewports
   anchos el alto (svh) limita; en viewports angostos el ancho del
   contenedor (cqi) limita. Así el personaje no come más espacio
   horizontal del que le corresponde cuando se angosta la ventana, y
   deja de "moverse" hacia la izquierda al reescalar. */
.hero__character {
    position: absolute;
    /* Corrido un poco fuera del borde derecho del inner (~3cqi): en aspect
       ratios anchos despeja la cola del título "…IÓN". */
    right: -3cqi;
    bottom: 0;
    /* Alto bajado de 95svh → 80svh: anclado a bottom:0, el personaje (y el
       marco que sostiene a la altura de la cabeza) baja lo suficiente para
       dejar "CORROSIÓN" legible en viewports anchos, sin dejar de ser la
       figura protagonista. El término 70cqi sigue limitando en angostos. */
    height: min(80svh, 70cqi);
    width: auto;
    z-index: 5;
    pointer-events: none;
    user-select: none;
}

.hero__headline {
    grid-area: headline;
    align-self: start;
    padding-left: clamp(1rem, 4cqi, 5rem);
}

.hero__eyebrow {
    position: relative;
    z-index: 6;
    margin-left: 0.8em;
    margin-bottom: 0.05em;
    line-height: 1;
    font-family: var(--font-italic);
    font-style: italic;
    font-weight: 400;
    color: var(--color-white);
    font-size: clamp(1rem, 2cqi, 2.5rem);
    text-shadow: 0 2px 14px rgba(0, 0, 0, 0.45);
}

.hero__title {
    position: relative;
    z-index: 2;
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-white);
    line-height: 0.95;
    letter-spacing: 0.005em;
    /* Rubik Dirt es bastante más ancha que la Thunderhouse original: 16cqi/28rem
       hacían que "Corrosión" (una sola palabra, no parte) desbordara el viewport
       y se cortara. 13cqi/20rem la deja llenar el ancho quedando completa. */
    font-size: clamp(2.75rem, 13cqi, 20rem);
    text-shadow: 0 6px 30px rgba(0, 0, 0, 0.45);
}

.hero__subline {
    position: relative;
    z-index: 6;
    /* Alineado al borde IZQUIERDO del headline = justo debajo de donde
       empieza "Corrosión" (antes margin-left:50% lo empujaba a la derecha). */
    margin-left: 0;
    margin-top: 0.1em;
    font-family: var(--font-italic);
    font-style: italic;
    font-weight: 400;
    color: var(--color-white);
    font-size: clamp(1rem, 1.9cqi, 2.4rem);
    line-height: 1.15;
    text-shadow: 0 2px 14px rgba(0, 0, 0, 0.45);
}

.hero__stat {
    grid-area: stat;
    align-self: end;
    position: relative;
    z-index: 6;
    display: flex;
    align-items: flex-end;
    gap: clamp(0.6rem, 1cqi, 1.5rem);
    padding-left: clamp(1rem, 4cqi, 5rem);
}

.hero__amount {
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-red);
    font-size: clamp(3rem, 10cqi, 18rem);
    line-height: 0.9;
    letter-spacing: 0.01em;
    white-space: nowrap;
    text-shadow: 0 6px 30px rgba(0, 0, 0, 0.5);
}

.hero__amount-caption {
    font-family: var(--font-sans);
    font-weight: 800;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.7rem, 1.1cqi, 1.4rem);
    letter-spacing: 0.06em;
    line-height: 1.25;
    padding-bottom: 0.6em;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
}

/* ==========================================================================
   SCENE 2 - RECONOCERLA (conducto + mano + cta)
   ========================================================================== */

.hero__scene--recognize .hero__scene-inner {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto 1fr auto;
    grid-template-areas:
        ".   intro"
        ".   cta"
        ".   loss";
    padding: clamp(3.5rem, 6cqi, 6rem) clamp(1rem, 3cqi, 3rem) clamp(1rem, 2.5cqi, 2.5rem);
    gap: clamp(0.5rem, 1.5cqi, 2rem);
}

/* El grupo conducto+pointer se posiciona como una unidad. La altura del
   wrapper la fija el conducto (en flujo, width: 100%), así el pointer
   posicionado por % del wrapper queda anclado al conducto y escala
   con él en cualquier viewport. */
.hero__pipe-group {
    position: absolute;
    top: 18%;
    left: 0;
    right: 0;
    width: 100%;
    z-index: 3;
    pointer-events: none;
}

/* Edge-to-edge: el conducto cruza toda la pantalla horizontalmente.
   Dentro del wrapper queda en flujo (position: relative) para que su
   altura intrínseca defina la altura del wrapper. */
.hero__conducto {
    position: relative;
    display: block;
    width: 100%;
    height: auto;
    user-select: none;
}

/* Anclado por % del wrapper (= % del conducto): el pointer mantiene la
   misma relación vertical con el tubo en cualquier viewport. right: 0
   mantiene la manga pegada al borde derecho. */
.hero__pointer {
    position: absolute;
    top: 15%;
    right: 0;
    width: clamp(22rem, 52cqi, 80rem);
    height: auto;
    z-index: 2;
    user-select: none;
}

.hero__intro {
    grid-area: intro;
    align-self: start;
    position: relative;
    z-index: 6;
    padding-right: clamp(1rem, 2cqi, 3rem);
}

.hero__intro p {
    font-family: var(--font-italic);
    font-style: italic;
    font-weight: 400;
    color: var(--color-white);
    font-size: clamp(1rem, 1.9cqi, 2.4rem);
    line-height: 1.3;
    text-shadow: 0 2px 14px rgba(0, 0, 0, 0.45);
}

.hero__intro-emph {
    color: var(--color-red);
    font-style: italic;
    font-weight: 700;
}

/* grid-column: 1 / -1 ocupa ambas columnas: el título tiene todo el
   ancho del viewport para renderizar sus tres líneas sin envolver,
   pero sigue alineado a la derecha (justify-self: end + text-align)
   manteniendo el carácter dramático del diseño. */
.hero__cta-title {
    grid-area: cta;
    grid-column: 1 / -1;
    align-self: center;
    justify-self: end;
    position: relative;
    z-index: 6;
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-white);
    line-height: 0.92;
    letter-spacing: 0.005em;
    font-size: clamp(2.25rem, 7.5cqi, 13rem);
    text-align: right;
    text-shadow: 0 6px 30px rgba(0, 0, 0, 0.45);
}

/* Cada línea es un span en el HTML para animar el stagger con GSAP.
   display: block las acomoda una encima de otra como un <br> implícito. */
.hero__cta-title__line {
    display: block;
}

.hero__loss {
    grid-area: loss;
    align-self: end;
    justify-self: end;
    position: relative;
    z-index: 6;
    text-align: right;
}

.hero__loss-amount {
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-red);
    font-size: clamp(2.5rem, 7.5cqi, 14rem);
    line-height: 0.9;
    letter-spacing: 0.01em;
    white-space: nowrap;
    text-shadow: 0 6px 30px rgba(0, 0, 0, 0.5);
}

.hero__loss-caption {
    font-family: var(--font-sans);
    font-weight: 800;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.7rem, 1.1cqi, 1.4rem);
    letter-spacing: 0.06em;
    line-height: 1.25;
    margin-top: 0.5em;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
}

.hero__loss-source {
    position: relative;
    display: inline-block;
    font-family: var(--font-sans);
    font-weight: 700;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.55rem, 0.75cqi, 0.95rem);
    letter-spacing: 0.08em;
    margin-top: 1em;
    margin-bottom: clamp(1rem, 2.5cqi, 2.5rem);
    padding-bottom: 0.3em;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
}

.hero__loss-source::after {
    content: "";
    position: absolute;
    left: 0;
    width: 1.6em;
    bottom: 0;
    height: 2px;
    background: var(--color-red);
}

/* ==========================================================================
   ACCENT UNDERLINES (compartidas entre escenas)
   ========================================================================== */

.underline-red,
.underline-white {
    position: relative;
    display: inline-block;
}

.underline-red::after {
    content: "";
    position: absolute;
    left: 5%;
    right: 5%;
    bottom: -0.05em;
    height: 2px;
    background: var(--color-red);
}

.underline-white::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -0.15em;
    height: 2px;
    background: var(--color-white);
}

/* ==========================================================================
   SCENE 2 - INITIAL STATE (gated por .js)

   Los elementos de la escena 2 nacen con opacity 0 cuando JS está activo,
   para que GSAP los anime al "armarse" mediante ScrollTrigger.

   El gate `html.js` lo activa un inline <script> en el <head> antes del
   primer paint del body - así no hay flash de elementos visibles antes de
   que GSAP los oculte.

   Si JS está desactivado o falla, el .js nunca se agrega y los elementos
   se ven en su estado natural (visible). Fallback gracioso.

   Los transforms (offsets de entrada) los setea GSAP en script.js, no acá,
   para mantener la sincronización con su sistema de animación.
   ========================================================================== */

/* opacity:0 + visibility:hidden alinea el estado inicial con autoAlpha
   de GSAP. Cuando la animación llega a autoAlpha:1, GSAP restaura
   visibility:inherit, así los elementos invisibles no bloquean clicks. */
html.js .hero__conducto,
html.js .hero__pointer,
html.js .hero__intro,
html.js .hero__cta-title__line,
html.js .hero__loss {
    opacity: 0;
    visibility: hidden;
}

/* ==========================================================================
   PINNED HERO LAYOUT (gated por .js)

   Con JS activo, el hero se pinea via ScrollTrigger y las dos escenas se
   superponen en el mismo viewport (no apiladas). El scroll dentro del pin
   dispara el fade-out de escena 1 y la entrada por etapas de escena 2.

   Sin JS: el layout original (escenas apiladas a 200svh, bg sticky) sigue
   intacto como fallback gracioso.
   ========================================================================== */

html.js .hero {
    height: 100svh;
}

html.js .hero__sky,
html.js .hero__landscape {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    margin-bottom: 0;
}

html.js .hero__scene {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    min-height: 0;
}

/* ==========================================================================
   STAGES - escenografía de cuadros enmarcados que muestran la progresión
   de la corrosión (de leve a destructiva).

   Layout: grid de tres filas (intro / galería / claim). La galería usa
   flex con align-items: flex-end para que los cuadros, de distinto
   tamaño, queden alineados por la base (más chico a más grande, de
   izquierda a derecha).

   Sección width-driven: todo escala con cqi para que la composición se
   mantenga proporcional en cualquier viewport.
   ========================================================================== */

.stages {
    position: relative;
    isolation: isolate;
    container-type: inline-size;
    min-height: 100svh;
    overflow: hidden;
}
.stages .cap {
    min-height: 100svh;
    display: grid;
    /* Columna ÚNICA topada a minmax(0,1fr): sin esto la columna `auto` crecía
       hasta el max-content de la galería (en pantallas grandes los cuadros de
       ancho fijo suman >1440px) y, al desbordar el cap, quedaba anclada a la
       izquierda → la pared de cuadros se salía por la derecha y el cuadro 04
       se recortaba. Con minmax(0,1fr) la columna nunca supera el ancho del cap;
       el `justify-content:center` de .stages__gallery reparte el sobrante de
       los cuadros a ambos lados y la pared queda centrada en el viewport. */
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto 1fr auto;
    grid-template-areas:
        "intro"
        "gallery"
        "claim";
    padding: clamp(3.5rem, 7cqi, 8rem) clamp(1.25rem, 4cqi, 4rem) clamp(2rem, 4cqi, 5rem);
    gap: clamp(1rem, 2.5cqi, 2.5rem);
}

/* Edge fade SÓLO inferior: el borde de abajo de la foto de `.stages` se
   funde a ink para encontrarse con el tope ya fundido de `.moment` (su
   tope conecta con el hero y no entra en este ajuste).

   z-index 0 (no 1 como en 03-06): `.stages__claim` ocupa el z-index 1 y
   está bottom-anchored - el fade debe quedar DEBAJO del claim. Como el
   `::after` es el último nodo del DOM, en z-index 0 pinta sobre el bg
   (0) pero bajo el claim (1) y el intro (2). El gradiente es transparente
   salvo el 14% inferior, así que no afecta a la galería. */
.stages::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background: linear-gradient(
        to bottom,
        transparent calc(100% - var(--fade-edge)),
        var(--color-ink) 100%
    );
}

/* Estados iniciales para el reveal: los HIJOS del .stages__frame
   (imagen y label) arrancan invisibles, no el <li> contenedor - así
   el grid mantiene sus slots y sólo se animan los contenidos.

   Ya no hay pin del stages - antes el `html.js .stages { height: 100svh }`
   estaba aquí para forzar altura exacta durante el pin. Sin pin, la
   sección crece naturalmente con `min-height: 100svh` desde el base,
   y el contenido nunca se recorta. */
html.js .stages__frame-label,
html.js .stages__claim {
    opacity: 0;
    visibility: hidden;
}

/* La imagen se ocultó con opacity SOLA (sin visibility): en Safari,
   alternar `visibility` sobre una capa con `filter: blur()` la deja
   pintada en blanco. El reveal anima sólo `opacity` (ver script-v2.js).*/
html.js .stages__frame-img {
    opacity: 0;
}

.stages__bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    z-index: 0;
    pointer-events: none;
    user-select: none;
}

/* ---------- intro (italic, top-left) ---------- */

.stages__intro {
    grid-area: intro;
    z-index: 2;
    max-width: clamp(14rem, 24cqi, 28rem);
    padding-left: clamp(0.5rem, 1cqi, 1.5rem);
    padding-top: clamp(0.5rem, 2cqi, 2rem);
}

.stages__intro p {
    font-family: var(--font-italic);
    font-style: italic;
    font-weight: 400;
    color: var(--color-white);
    font-size: clamp(1rem, 1.9cqi, 2.3rem);
    line-height: 1.3;
    text-shadow: 0 2px 12px rgba(0, 0, 0, 0.55);
}

.stages__intro-emph {
    color: var(--color-red);
    font-style: italic;
    font-weight: 600;
}

/* ---------- galería de cuadros ---------- */

/* Grid con columnas de ANCHO FIJO en rem (no 1fr). Esto significa que
   los cuadros mantienen el mismo tamaño cuando se reescala la ventana
   dentro de un breakpoint - sólo cambia el número de columnas al cruzar
   un breakpoint. justify-content: center centra el grid horizontalmente
   en el espacio disponible.

   La galería es SIEMPRE una grilla 2×2 (dos columnas): sólo cambia el
   tamaño del cuadro al cruzar un breakpoint, nunca el número de columnas
   (salvo el colapso a 1 columna en móvil). El base aplica a ≥1680px. */
.stages__gallery {
    grid-area: gallery;
    align-self: end;
    z-index: 2;
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(2, 28rem);
    justify-content: center;
    align-items: end;
    row-gap: 3rem;
    column-gap: 2.5rem;
}

.stages__frame {
    position: relative;
    justify-self: center;
    align-self: end;
    width: 100%;
    text-align: center;
}

/* drop-shadow respeta la transparencia del PNG → la sombra sigue el
   contorno del marco, no del bounding box rectangular. Dos sombras
   superpuestas: una corta y oscura (cuadro pegado a la pared) y otra
   larga y difusa (sombra ambiental), simulando iluminación real de
   galería. */
/* La sombra del cuadro va en `.stages__frame-media` (wrapper estático),
   NO en la imagen: la imagen se anima (transform/opacity/blur) y, en
   Safari, un `filter` sobre el elemento que se anima queda pintado en
   blanco. El wrapper no se anima → su `drop-shadow` es estable, y respeta
   el alpha del PNG (margen transparente alrededor del marco), abrazando el
   contorno del marco en vez de dibujar un rectángulo. */
.stages__frame-media {
    display: block;
    filter:
        drop-shadow(0 0.6rem 0.8rem rgba(0, 0, 0, 0.55))
        drop-shadow(0 2rem 2.5rem rgba(0, 0, 0, 0.45));
}

.stages__frame-img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 3 / 2;

    /* Sin `filter` propio en reposo: la sombra la da el wrapper. El `blur`
       del reveal se aplica sólo durante la animación y se limpia al
       terminar (ver script-v2.js), para que Safari no deje un layer de
       filtro pintado en blanco. */
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
    will-change: transform, opacity;
}

/* Label como "tag" de museo: pequeña placa centrada bajo cada cuadro,
   con fondo translúcido oscuro, borde sutil y leve sombra propia. */
.stages__frame-label {
    display: inline-block;
    margin-top: clamp(1rem, 1.5cqi, 1.5rem);
    padding: clamp(0.4rem, 0.5cqi, 0.6rem) clamp(0.75rem, 1cqi, 1.1rem);
    background: rgba(16, 16, 18, 0.55);
    border: 1px solid rgba(244, 241, 236, 0.2);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);

    font-family: var(--font-sans);
    font-weight: 600;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.6rem, 0.8cqi, 0.9rem);
    letter-spacing: 0.16em;
    line-height: 1.3;
    white-space: nowrap;
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.6);
}

/* ---------- claim final ---------- */

.stages__claim {
    grid-area: claim;
    z-index: 1;
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-white);
    line-height: 0.9;
    letter-spacing: 0.005em;
    /* Bajado de 11cqi/20rem: era desproporcionado para un claim de 2 líneas. */
    font-size: clamp(1.8rem, 6cqi, 5rem);
    text-shadow: 0 4px 30px rgba(0, 0, 0, 0.55);
    padding-bottom: clamp(0.3rem, 0.8cqi, 1rem);
}

.stages__claim-line {
    display: block;
}

/* ==========================================================================
   PORTRAIT (único breakpoint - orientación, no tamaño)
   ========================================================================== */

@media (orientation: portrait) {
    /* ----- SCENE 1 ----- */
    .hero__scene--intro .hero__scene-inner {
        grid-template-columns: 1fr;
        grid-template-rows: auto 1fr auto;
        grid-template-areas:
            "headline"
            "."
            "stat";
        padding: clamp(5rem, 14cqi, 8rem) clamp(1rem, 5cqi, 3rem) clamp(1.5rem, 6cqi, 4rem);
        gap: clamp(0.75rem, 3cqi, 2rem);
    }

    .hero__landscape {
        object-position: center 30%;
    }

    /* El PNG es 3:2 con el operario al ~58% del canvas (no centrado). Con
       width:auto rendía ~2× el viewport y, aun centrando el box, el operario
       salía a la derecha con el escudo cortado. object-fit:cover + object-
       position encuadra al operario centrado, mismo tamaño, recortando el
       canvas vacío en vez del operario. El encuadre vive en object-position
       (no en transform), así que el y:-20 del fade y los cambios de svh
       (barra de URL al scrollear) ya no lo descentran. */
    .hero__character {
        height: min(75svh, 130cqi);
        width: 100%;
        left: 0;
        right: 0;
        bottom: 0;
        object-fit: cover;
        object-position: 67% center;
        margin-inline: 0;
        transform: none;
    }

    .hero__eyebrow {
        font-size: clamp(1rem, 4.5cqi, 1.8rem);
        margin-left: 1em;
        margin-bottom: 0.05em;
    }

    .hero__title {
        /* Portrait: bajado de 26cqi para que "Corrosión" entre completa en
           pantallas angostas con Rubik Dirt (más ancha). */
        font-size: clamp(2.5rem, 13cqi, 11rem);
    }

    .hero__subline {
        font-size: clamp(1rem, 4cqi, 1.7rem);
        margin-left: 0;
        margin-top: 0.1em;
    }

    .hero__stat {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.4em;
    }

    .hero__amount {
        font-size: clamp(3rem, 18cqi, 8rem);
    }

    .hero__amount-caption {
        font-size: clamp(0.7rem, 2.8cqi, 1.1rem);
        padding-bottom: 0;
    }

    /* ----- SCENE 2 ----- */
    .hero__scene--recognize .hero__scene-inner {
        grid-template-columns: 1fr;
        grid-template-rows: auto auto 1fr auto;
        grid-template-areas:
            "intro"
            "cta"
            "."
            "loss";
        padding: clamp(5rem, 14cqi, 8rem) clamp(1rem, 5cqi, 3rem) clamp(1.5rem, 6cqi, 4rem);
        gap: clamp(0.75rem, 3cqi, 2rem);
    }

    .hero__pipe-group {
        top: 32%;
    }

    .hero__pointer {
        width: clamp(20rem, 95cqi, 50rem);
    }

    .hero__intro {
        padding-right: 0;
    }

    .hero__intro p {
        font-size: clamp(1rem, 4cqi, 1.7rem);
    }

    .hero__cta-title {
        font-size: clamp(2.5rem, 10.5cqi, 7.5rem);
        justify-self: end;
    }

    .hero__loss-amount {
        font-size: clamp(2.5rem, 14cqi, 7rem);
    }

    .hero__loss-caption {
        font-size: clamp(0.65rem, 2.5cqi, 1rem);
    }

    .hero__loss-source {
        font-size: clamp(0.55rem, 1.8cqi, 0.85rem);
    }

}

/* ==========================================================================
   STAGES - responsive width-based (no orientation)

   Cada breakpoint define un ancho FIJO de cuadro en rem y la cantidad
   de columnas. Dentro de cada rango, los cuadros no cambian de tamaño
   al reescalar el viewport - sólo al cruzar un breakpoint cambia la
   cantidad de columnas o el tamaño.

   Cascada (orden importa) - SIEMPRE 2 columnas (grilla 2×2):
     base (≥ 1680px)  → 2 columnas × 28rem
     ≥ 1920px         → 2 columnas × 30rem
     ≥ 2400px         → 2 columnas × 34rem (2K+ monitores)
     ≥ 2800px         → 2 columnas × 38rem (4K)
     max-width 1679   → 2 columnas × 26rem (laptops chicos)
     max-width 1279   → 2 columnas × 24rem (tablets)
     max-width 767    → 1 columna × min(20rem, 88vw) (mobile)

   Al ser siempre 2×2, en pantallas grandes la sección crece por encima
   de 100svh (dos filas de cuadros): es esperado, no hay pin ni recorte
   (min-height, no height fija). ========================================= */

@media (min-width: 1920px) {
    .stages__gallery {
        grid-template-columns: repeat(2, 30rem);
        row-gap: 3rem;
        column-gap: 3rem;
    }
}

@media (min-width: 2400px) {
    .stages__gallery {
        grid-template-columns: repeat(2, 34rem);
        row-gap: 3.5rem;
        column-gap: 3.5rem;
    }
}

@media (min-width: 2800px) {
    .stages__gallery {
        grid-template-columns: repeat(2, 38rem);
        row-gap: 4rem;
        column-gap: 4rem;
    }
}

@media (max-width: 1679px) {
    .stages__gallery {
        grid-template-columns: repeat(2, 26rem);
        row-gap: 3rem;
        column-gap: 2.5rem;
    }
}

@media (max-width: 1279px) {
    .stages {
        padding: clamp(2rem, 6cqi, 5rem) clamp(1rem, 4cqi, 3rem) clamp(2rem, 4cqi, 4rem);
    }

    .stages__intro {
        max-width: clamp(14rem, 35cqi, 28rem);
    }

    .stages__gallery {
        grid-template-columns: repeat(2, 24rem);
        row-gap: clamp(2rem, 5cqi, 5rem);
        column-gap: clamp(1.5rem, 3cqi, 3rem);
    }

    .stages__frame-label {
        font-size: clamp(0.65rem, 1.2cqi, 0.95rem);
    }
}

@media (max-width: 767px) {
    .stages {
        padding: clamp(2rem, 8cqi, 4rem)
                 clamp(1rem, 5cqi, 2rem)
                 clamp(3rem, 10cqi, 5rem);
        gap: clamp(1rem, 4cqi, 2.5rem);
    }

    .stages__intro {
        max-width: 100%;
        padding-left: 0;
    }

    .stages__intro p {
        font-size: clamp(1rem, 4.5cqi, 1.5rem);
    }

    /* min(20rem, 88vw) protege contra overflow en phones muy chicos:
       en cualquier device típico (375-414px) el cuadro queda fijo en
       20rem; abajo de eso baja a 88vw para no desbordar. */
    .stages__gallery {
        grid-template-columns: min(20rem, 88vw);
        row-gap: clamp(1.5rem, 5cqi, 3rem);
    }

    .stages__frame-label {
        font-size: clamp(0.7rem, 3cqi, 1rem);
        letter-spacing: 0.14em;
    }

    .stages__claim {
        font-size: clamp(1.8rem, 9cqi, 3.5rem);
    }
}

/* ==========================================================================
   EDGE FADE - desvanecimiento de los bordes de las fotos de fondo (03-06).

   Cada sección narrativa funde su foto a `--color-ink` arriba y abajo, de
   modo que dos fotos contiguas nunca exhiben un corte duro: se encuentran
   en una banda negra compartida.

   z-index 1: por encima del bg (0) y a la par del velo (div en z-index 1) -
   como el `::after` es el último nodo del DOM, pinta después del velo. Queda
   DEBAJO del title (2), tubo (3), personaje (4) y textos (5), así sólo se
   difumina la foto y el velo; el contenido legible queda nítido por encima.

   Un `::after` con `position: absolute` no es grid item - `display: grid` de
   las secciones no se ve afectado. Bloque autocontenido: borrarlo (más la
   línea `--fade-edge` de `:root`) elimina el efecto sin tocar nada más.
   ========================================================================== */

.moment::after,
.advance::after,
.holes::after,
.face::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background: linear-gradient(
        to bottom,
        var(--color-ink) 0%,
        transparent var(--fade-edge),
        transparent calc(100% - var(--fade-edge)),
        var(--color-ink) 100%
    );
}

/* ==========================================================================
   MOMENT - sección 03 - "Comienza a correr el reloj"

   Escena: operario sosteniendo una muestra de pintura agrietada (izquierda)
   + tubería corroída cruzando la zona baja (full-bleed) + columna de textos
   a la derecha que sube desde el tag superior hasta los bullets inferiores.

   Sección width-driven (cqi) - toda la composición escala con el ancho del
   contenedor para mantenerse proporcional en cualquier viewport.

   Z-index map en el stacking context de .moment (creado por isolation):
     0  moment__bg       (fondo full-cover)
     2  moment__title    (display gigante, queda atrás de la tubería)
     3  moment__tubo     (cruza por encima del title como en el diseño)
     4  moment__character (operario, sample en mano, delante de la tubería)
     5  textos secundarios (tag, claim, quote, signals)

   Toda la CSS - base, portrait y reduced-motion gate - vive en este bloque
   para que la sección sea trasplantable sin tocar las demás.
   ========================================================================== */

.moment {
    position: relative;
    isolation: isolate;
    container-type: inline-size;
    min-height: 100svh;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto 1fr auto;
    grid-template-areas:
        "quote  tag"
        ".      claim"
        ".      title"
        ".      signals";
    padding: clamp(5rem, 7cqi, 8rem)
             clamp(1.5rem, 4cqi, 4rem)
             clamp(2rem, 4cqi, 4rem);
    gap: clamp(0.5rem, 1.5cqi, 2rem);
    overflow: hidden;
}

.moment__bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    z-index: 0;
    pointer-events: none;
    user-select: none;
    /* Overscan: el scrub blurrea el fondo a 4.5px; el 6% extra empuja
       el fringe del blur fuera del overflow:hidden de la sección.
       `scale` (propiedad CSS) es independiente del `transform` que usa
       el parallax del mouse - ambos componen sin conflicto. */
    scale: 1.06;
}

/* Velo de oscurecimiento sobre el fondo (z-index 1: encima del bg,
   debajo del tubo/personaje/textos). El scrub anima su opacidad de
   0 a 0.35 en la fase 1. Sin JS queda en 0.35 (fondo ya oscurecido);
   con html.js parte de 0 y GSAP toma el control. */
.moment__veil {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: #000;
    opacity: 0.35;
    pointer-events: none;
}

/* Tubería: bottom-anchored, cruza el ancho completo. El PNG (1536x1024)
   tiene padding transparente arriba y abajo del tubo, así que con
   `bottom: 0` el tubo queda muy arriba. Empujamos hacia abajo con un
   `bottom` muy negativo - el overflow: hidden del .moment recorta la
   franja inferior vacía. Va detrás del personaje pero delante del title
   gigante (replica el corte de "CORRER EL RELOJ" pasando por detrás
   del tubo en el diseño). */
.moment__tubo {
    position: absolute;
    left: 0;
    right: 0;
    bottom: clamp(-32rem, -26cqi, -12rem);
    width: 100%;
    height: auto;
    z-index: 3;
    pointer-events: none;
    user-select: none;
}

/* Personaje: ancla bottom-left, oversized para llenar verticalmente.
   El PNG es 3:2 landscape (brazos abiertos sosteniendo la muestra). Para
   que el personaje llene ~80% del alto del viewport, el canvas debe ser
   muy ancho - sale del borde izquierdo (left negativo) y el overflow
   hidden del .moment recorta el sobrante. Así la muestra metálica queda
   bien en el centro-izquierda del diseño. */
.moment__character {
    position: absolute;
    left: clamp(-22rem, -18cqi, -5rem);
    bottom: 0;
    width: clamp(34rem, 78cqi, 100rem);
    height: auto;
    z-index: 4;
    pointer-events: none;
    user-select: none;
}

/* Quote en la zona alta-izquierda, anclada al personaje. El leader line
   rojo (::after) imita la línea diagonal del diseño que conecta la cita
   con la muestra metálica. */
/* Quote movido a la columna izquierda del grid del dossier (swap visual
   con el tag). Texto descriptivo más largo que la cita original - ya no
   tiene leader-line porque no hay ancla visual al sample desde esta
   posición. */
.moment__quote {
    grid-area: quote;
    justify-self: start;
    align-self: start;
    z-index: 5;
    font-family: var(--font-italic);
    font-style: italic;
    font-weight: 400;
    color: var(--color-white);
    font-size: clamp(0.9rem, 1.4cqi, 1.8rem);
    line-height: 1.3;
    text-shadow: 0 2px 12px rgba(0, 0, 0, 0.75);
    max-width: 28ch;
    pointer-events: none;
    margin: 0;
}

.moment__quote::after { display: none; }

/* ---------- tag (top-right) ---------- */

.moment__tag {
    grid-area: tag;
    z-index: 5;
    justify-self: end;
    text-align: right;
}

.moment__tag-eyebrow {
    font-family: var(--font-sans);
    font-weight: 800;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.8rem, 1.2cqi, 1.55rem);
    letter-spacing: 0.05em;
    line-height: 1.2;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
}

.moment__tag-accent {
    position: relative;
    color: var(--color-red);
}

.moment__tag-accent::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -0.2em;
    height: 2px;
    background: var(--color-red);
}

.moment__tag-sub {
    margin-top: 0.85em;
    font-family: var(--font-sans);
    font-weight: 600;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.65rem, 0.95cqi, 1.2rem);
    letter-spacing: 0.18em;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
}

/* ---------- claim italic (mid-right) ---------- */

.moment__claim {
    grid-area: claim;
    z-index: 5;
    justify-self: end;
    align-self: start;
    text-align: right;
    margin-top: clamp(1rem, 2cqi, 3rem);
}

.moment__claim p {
    font-family: var(--font-italic);
    font-style: italic;
    font-weight: 400;
    color: var(--color-white);
    font-size: clamp(1.1rem, 2.3cqi, 3rem);
    line-height: 1.3;
    text-shadow: 0 2px 14px rgba(0, 0, 0, 0.65);
}

.moment__claim-emph {
    font-style: italic;
    font-weight: 700;
}

/* ---------- big display title (lower-right) ---------- */

.moment__title {
    grid-area: title;
    grid-column: 1 / -1;
    justify-self: end;
    align-self: end;
    z-index: 2;
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-white);
    line-height: 0.92;
    letter-spacing: 0.005em;
    font-size: clamp(3rem, 10.5cqi, 18rem);
    text-align: right;
    text-shadow: 0 6px 30px rgba(0, 0, 0, 0.5);
    margin-bottom: clamp(2rem, 5cqi, 6rem);
    padding-right: clamp(0rem, 1cqi, 1rem);
}

.moment__title-line {
    display: block;
}

/* ---------- signals (bullet list, bottom-right) ---------- */

.moment__signals {
    grid-area: signals;
    z-index: 5;
    justify-self: end;
    list-style: none;
    margin: 0;
    padding: 0;
}

.moment__signal {
    position: relative;
    padding-left: 2.6em;
    margin-top: 0.35em;
    font-family: var(--font-sans);
    font-weight: 700;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.7rem, 1.05cqi, 1.3rem);
    letter-spacing: 0.1em;
    line-height: 1.3;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
    white-space: nowrap;
}

.moment__signal::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.55em;
    width: 1.8em;
    height: 2px;
    background: var(--color-red);
}

/* ---------- MOMENT - initial state gated por .js (para animar con GSAP) -- */

html.js .moment__veil,
html.js .moment__tubo,
html.js .moment__character,
html.js .moment__quote,
html.js .moment__tag,
html.js .moment__claim p,
html.js .moment__title-line,
html.js .moment__signals-heading,
html.js .moment__signal {
    opacity: 0;
    visibility: hidden;
}

/* ---------- MOMENT - portrait (sólo orientación)

   El diseño mobile reorganiza la composición:
   - Tag arriba a la izquierda, con eyebrow COMPLETO en rojo y barra
     horizontal roja debajo (no el split blanco/rojo del desktop).
   - Personaje grande al centro como héroe vertical.
   - Quote pegada a la cabeza del personaje (derecha del helmet).
   - Tubo decorativo entrando desde el borde derecho, detrás del
     personaje, a la altura de la muestra.
   - Italic claim en columna estrecha, alineada a la derecha, entre el
     personaje y el title.
   - Title gigante alineado a la IZQUIERDA, dos líneas a ancho completo.
   - Bullets alineados a la izquierda al final.
   ---------------------------------------------------------------- */

@media (orientation: portrait) {
    /* Composición del diseño mobile:
       - Tag top-left con eyebrow rojo y barra horizontal.
       - Quote en el upper-right con leader-line hacia el operario.
       - Operario GRANDE, anclado a la izquierda, su canvas se apoya
         sobre el TITLE (bottom de la sección).
       - Tubo cruza horizontalmente, edge-to-edge, a la altura del
         sample/manos, pasa por DETRÁS del operario.
       - Italic claim en columna estrecha a la derecha del operario,
         a la altura del sample.
       - Big title GIGANTE al fondo, full-width, left-aligned.
       - Bullets en el extremo inferior, full-width.

       Toda la sección se posiciona ABSOLUTA respecto a .moment.
       La sección tiene min-height alta porque la composición es
       muy vertical (aspect ~1:2 en el diseño). */
    .moment {
        position: relative;
        min-height: 115svh;
        display: block;
        gap: 0;
        padding: 0;
        grid-template-columns: none;
        grid-template-areas: none;
    }

    /* ---- TAG (top-left, eyebrow rojo con barra) ---- */
    .moment__tag {
        position: absolute;
        order: 0;
        top: clamp(5.5rem, 14cqi, 8rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: auto;
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        text-align: left;
        z-index: 5;
    }

    /* Eyebrow completamente rojo + barra horizontal debajo. */
    .moment__tag-eyebrow {
        color: var(--color-red);
        font-size: clamp(1rem, 3.6cqi, 1.5rem);
        line-height: 1.2;
        padding-bottom: 0.45em;
        border-bottom: 2px solid var(--color-red);
        display: inline-block;
    }

    .moment__tag-accent {
        color: var(--color-red);
    }

    .moment__tag-accent::after { display: none; }

    .moment__tag-sub {
        margin-top: 0.85em;
        font-size: clamp(0.65rem, 2.4cqi, 1.05rem);
        letter-spacing: 0.18em;
        color: var(--color-white);
    }

    /* ---- QUOTE (upper-right, con leader-line)
       Usamos svh para que la quote se posicione a la altura del helmet
       del operario (que está bottom-anchored) en lugar de bajar/subir
       con el ancho del viewport. */
    .moment__quote {
        display: block;
        position: absolute;
        top: clamp(8rem, 20svh, 16rem);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        left: auto;
        text-align: left;
        font-size: clamp(0.9rem, 3.2cqi, 1.4rem);
        line-height: 1.3;
        max-width: 50%;
        z-index: 6;
    }

    .moment__quote::after {
        content: "";
        position: absolute;
        left: -0.4em;
        bottom: -1.4em;
        width: 2px;
        height: 1.8em;
        background: var(--color-red);
        transform: rotate(22deg);
        transform-origin: top right;
        display: block;
        right: auto;
    }

    /* ---- CHARACTER - LEFT-anchored, grande, su canvas se posa sobre
       el TITLE.

       Height-driven (svh) → tamaño consistente entre breakpoints,
       no varía con el ancho del viewport.
       Bottom-anchored arriba del title con clamp.
       Left negativo: el canvas 3:2 landscape sale del borde izquierdo
       y el overflow:hidden recorta - el operario queda visualmente
       en la zona LEFT del viewport.

       No usamos translateX para centrar (GSAP escribe `transform`
       durante la animación de entrada y lo pisaría). */
    /* Personaje siempre pegado al borde inferior (bottom: 0). El title
       y bullets viven con z-index más alto y se SUPERPONEN sobre el
       operario en lugar de empujarlo arriba - así el operario domina
       el bottom sin importar el tamaño del viewport.

       left: usamos svh (no cqi) porque el canvas escala con svh (height-
       driven). Si el left usara cqi, viewports anchos/casi-cuadrados
       recortarían el operario por izquierda al crecer la fracción cqi
       más rápido que el canvas. Con -28svh la compensación es
       aspect-independent y mantiene al operario visible. */
    .moment__character {
        position: absolute;
        order: 0;
        left: clamp(-35rem, -28svh, -8rem);
        right: auto;
        top: auto;
        bottom: 0;
        height: clamp(50svh, 62svh, 72svh);
        width: auto;
        max-width: none;
        margin: 0;
        align-self: auto;
        z-index: 4;
    }

    /* ---- TUBO - horizontal, edge-to-edge, detrás del operario, a la
       altura del sample/manos.

       Width 130cqi + left/right negativos lo lleva más ancho que el
       viewport, exponiendo el cilindro a lo ancho del diseño. El bottom
       lo coloca al sample-level del operario (~38svh desde el bottom,
       calculado para alinear con la zona de las manos). */
    /* Tubo a la altura del sample del operario, edge-to-edge.

       width explícito (130cqi) en lugar de `width: auto` con left+right -
       en elementos replaced (<img>) con dimensiones intrínsecas, el
       auto resuelve al tamaño natural del PNG (1536×1024) ignorando los
       offsets de left/right. Con cqi explícito el tubo escala con el
       ancho del contenedor y la altura sigue el aspect ratio del PNG.

       Bottom: con character.bottom 0 y height 62svh, el sample del
       operario queda a ~37svh desde el bottom de la sección. El tubo
       a 130cqi de ancho tiene ~87cqi de alto; la franja visible del
       tubo dentro del canvas ocupa el ~50% central (canvas y=33-83%).
       Para centrar esa franja con el sample del operario, calculamos:
       bottom = 37svh - 0.42 × 87cqi ≈ 37svh - 37cqi. Clamp para no
       irse a valores negativos en viewports muy anchos. */
    .moment__tubo {
        position: absolute;
        order: 0;
        top: auto;
        bottom: clamp(6svh, calc(37svh - 37cqi), 26svh);
        left: -15cqi;
        right: auto;
        width: 130cqi;
        height: auto;
        max-width: none;
        margin: 0;
        z-index: 3;
    }

    /* ---- CLAIM italic - columna estrecha a la derecha del operario,
       a la altura del sample. */
    .moment__claim {
        position: absolute;
        order: 0;
        top: auto;
        bottom: clamp(30svh, 38svh, 46svh);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        left: auto;
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        text-align: right;
        max-width: clamp(10rem, 42cqi, 18rem);
        margin: 0;
        z-index: 5;
    }

    .moment__claim p {
        font-size: clamp(1.05rem, 3.6cqi, 1.7rem);
        line-height: 1.2;
    }

    /* ---- TITLE - BOTTOM, full-width, GIGANTE, left-aligned.
       z-5 → se SUPERPONE sobre el personaje (z-4). En mobile el title
       cubre la cintura/parte baja del operario sin tapar la cara ni el
       sample (que están más arriba), dando presencia a la tipografía
       sin sacrificar al operario al fondo. */
    .moment__title {
        position: absolute;
        order: 0;
        top: auto;
        bottom: clamp(8rem, 20cqi, 13rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        text-align: left;
        font-size: clamp(2.8rem, 15cqi, 8rem);
        line-height: 0.92;
        margin: 0;
        padding: 0;
        z-index: 5;
    }

    /* ---- SIGNALS (left-aligned bullets, full-width, very bottom) ---- */
    .moment__signals-heading {
        position: absolute;
        bottom: calc(clamp(1.5rem, 4cqi, 3rem) + clamp(7rem, 22cqi, 13rem));
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        z-index: 5;
        text-align: left;
        margin: 0;
    }

    .moment__signals {
        position: absolute;
        order: 0;
        top: auto;
        bottom: clamp(1.5rem, 4cqi, 3rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        margin: 0;
        z-index: 5;
    }

    .moment__signal {
        font-size: clamp(0.78rem, 2.7cqi, 1.15rem);
        text-align: left;
        white-space: normal;
        padding-left: 3em;
        margin-top: 0.5em;
        letter-spacing: 0.08em;
    }

    .moment__signal::before {
        width: 2em;
        top: 0.6em;
    }
}

/* ==========================================================================
   ADVANCE - sección 04 - "La corrosión avanza"

   Escena: operario right-anchored (mirror de moment) sosteniendo una
   muestra con corrosión avanzada en soldaduras + columna izquierda con
   tag (red line ARRIBA, todo crema), claim italic, big display title que
   queda DETRÁS del personaje, bullets de señales y cost stat S/ 8M al
   fondo izquierdo.

   Sección width-driven (cqi) en desktop / height-driven (svh) en portrait
   - misma filosofía que moment.

   Z-index map en el stacking context de .advance (creado por isolation):
     0  advance__bg        (fondo full-cover: muelle + barco + atardecer)
     2  advance__title     (display, queda detrás del personaje en desktop)
     4  advance__character (operario right-anchored, bottom)
     5  textos (tag, claim, signals, cost) y title en portrait (overlap)
   ========================================================================== */

.advance {
    position: relative;
    isolation: isolate;
    container-type: inline-size;
    min-height: 100svh;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto auto 1fr auto auto;
    grid-template-areas:
        "tag     ."
        "claim   ."
        "title   ."
        ".       ."
        "signals ."
        "cost    .";
    padding: clamp(5rem, 7cqi, 8rem)
             clamp(1.5rem, 4cqi, 4rem)
             clamp(2rem, 4cqi, 4rem);
    gap: clamp(0.5rem, 1.5cqi, 2rem);
    overflow: hidden;
}

.advance__bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    z-index: 0;
    pointer-events: none;
    user-select: none;
    /* Overscan para el blur del scrub - ver nota en .moment__bg. */
    scale: 1.06;
}

.advance__veil {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: #000;
    opacity: 0.35;
    pointer-events: none;
}

/* Personaje: ancla bottom-RIGHT (mirror de moment, que ancla bottom-LEFT).
   El PNG es 3:2 landscape (1536×1024); para que el operario llene
   verticalmente y quede en la mitad derecha del viewport, el canvas sale
   por el borde derecho (right negativo) y el overflow:hidden recorta el
   sobrante. La muestra metálica queda hacia el centro del diseño. */
.advance__character {
    position: absolute;
    right: clamp(-22rem, -18cqi, -5rem);
    bottom: 0;
    width: clamp(34rem, 78cqi, 100rem);
    height: auto;
    z-index: 4;
    pointer-events: none;
    user-select: none;
}

/* ---------- tag (top-left, eyebrow con red line ARRIBA) ---------- */

.advance__tag {
    grid-area: tag;
    z-index: 5;
    justify-self: start;
    text-align: left;
}

/* Diferencia con moment__tag: en sec 04 la línea roja va ARRIBA del
   eyebrow (no debajo del accent), y TODO el texto va en crema (no hay
   split blanco/rojo). Usamos ::before como accent corto de 4em - no
   border-top porque queremos que la línea NO ocupe todo el ancho del
   texto. */
.advance__tag-eyebrow {
    position: relative;
    font-family: var(--font-sans);
    font-weight: 800;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.8rem, 1.2cqi, 1.55rem);
    letter-spacing: 0.05em;
    line-height: 1.2;
    padding-top: 0.7em;
    display: inline-block;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
}

.advance__tag-eyebrow::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 4em;
    height: 2px;
    background: var(--color-red);
}

.advance__tag-accent {
    color: var(--color-white);
}

.advance__tag-sub {
    margin-top: 0.85em;
    font-family: var(--font-sans);
    font-weight: 600;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.65rem, 0.95cqi, 1.2rem);
    letter-spacing: 0.18em;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
}

/* ---------- claim italic (mid-left) ---------- */

.advance__claim {
    grid-area: claim;
    z-index: 5;
    justify-self: start;
    align-self: start;
    text-align: left;
    margin-top: clamp(1rem, 2cqi, 3rem);
    max-width: clamp(18rem, 42cqi, 36rem);
}

.advance__claim p {
    font-family: var(--font-italic);
    font-style: italic;
    font-weight: 400;
    color: var(--color-white);
    font-size: clamp(1.1rem, 2.3cqi, 3rem);
    line-height: 1.3;
    text-shadow: 0 2px 14px rgba(0, 0, 0, 0.65);
}

.advance__claim p + p {
    margin-top: 0.4em;
}

.advance__claim-emph {
    font-style: italic;
    font-weight: 700;
}

/* ---------- big display title (mid-lower-left)

   grid-column: 1/-1 + justify-self: start - el título ocupa todo el ancho
   del viewport para renderizar sus dos líneas grandes sin envolver, pero
   queda alineado a la izquierda. La parte derecha del título ("AVANZA")
   se SUPERPONE con el personaje (z-2 < personaje z-4 → personaje cubre
   parcialmente la parte derecha). ---------- */

.advance__title {
    grid-area: title;
    grid-column: 1 / -1;
    justify-self: start;
    align-self: end;
    z-index: 2;
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-white);
    line-height: 0.92;
    letter-spacing: 0.005em;
    /* Más grande que moment__title porque el texto es más corto
       ("LA CORROSIÓN" 12ch vs "COMIENZA A CORRER EL RELOJ" 26ch) -
       para que el título ocupe similar share del ancho, sube cqi. El
       "AVANZA" debe extenderse hasta superponerse con el personaje y
       quedar parcialmente cubierto por él (z-2 detrás de z-4 character). */
    font-size: clamp(3rem, 18cqi, 26rem);
    text-align: left;
    text-shadow: 0 6px 30px rgba(0, 0, 0, 0.5);
    /* Respiro grande antes Y DESPUÉS del título: a 18cqi el display
       domina (306px @ 1700) y con grid-gap chico (1.5cqi = 25px) la
       mass del title "abraza" al claim arriba y a los bullets abajo
       en widths medios. Margins simétricas escalan con cqi así que
       siempre hay ~6% del width de separación, proporcional al título. */
    margin-top: clamp(2rem, 6cqi, 7rem);
    margin-bottom: clamp(2rem, 6cqi, 7rem);
    padding-left: clamp(0rem, 0.5cqi, 0.5rem);
}

.advance__title-line {
    display: block;
}

/* ---------- signals (bullet list, lower-left) ---------- */

.advance__signals {
    grid-area: signals;
    z-index: 5;
    justify-self: start;
    list-style: none;
    margin: 0;
    padding: 0;
}

.advance__signal {
    position: relative;
    padding-left: 2.6em;
    margin-top: 0.35em;
    font-family: var(--font-sans);
    font-weight: 700;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.7rem, 1.05cqi, 1.3rem);
    letter-spacing: 0.1em;
    line-height: 1.3;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
    white-space: nowrap;
}

.advance__signal::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.55em;
    width: 1.8em;
    height: 2px;
    background: var(--color-red);
}

/* ---------- cost stat (bottom-left, S/ 8M)

   Mismo molde tipográfico que .hero__loss pero alineado a la izquierda. */

.advance__cost {
    grid-area: cost;
    z-index: 5;
    justify-self: start;
    align-self: end;
    text-align: left;
    margin-top: clamp(1rem, 2cqi, 2rem);
}

.advance__cost-amount {
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-red);
    font-size: clamp(3rem, 9cqi, 16rem);
    line-height: 0.9;
    letter-spacing: 0.01em;
    white-space: nowrap;
    text-shadow: 0 6px 30px rgba(0, 0, 0, 0.5);
}

.advance__cost-caption {
    font-family: var(--font-sans);
    font-weight: 800;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.7rem, 1.1cqi, 1.4rem);
    letter-spacing: 0.06em;
    line-height: 1.25;
    margin-top: 0.5em;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
}

/* ---------- ADVANCE - initial state gated por .js (para animar con GSAP) -- */

html.js .advance__veil,
html.js .advance__character,
html.js .advance__tag,
html.js .advance__claim p,
html.js .advance__title-line,
html.js .advance__signals-heading,
html.js .advance__signal,
html.js .advance__cost {
    opacity: 0;
    visibility: hidden;
}

/* ---------- ADVANCE - portrait (sólo orientación)

   Reorganiza la composición vertical en mobile:
   - Tag top-left con red line arriba.
   - Claim italic debajo del tag (zona libre antes que el personaje).
   - Title GIGANTE, full-width left-aligned, SOBRE el personaje (z-5).
   - Personaje GRANDE center-right, height-driven (svh), bottom-anchored.
   - Bullets + cost stat en el extremo inferior izquierdo (sobre piernas
     del operario porque z-5 > personaje z-4).

   min-height: 115svh - la composición es más vertical que el viewport.
   ---------------------------------------------------------------- */

@media (orientation: portrait) {
    /* min-height: 125svh (no 115) - el contenido vertical (tag, claim,
       title gigante, signals, cost) NO entra cómodo en 115svh cuando el
       aspect ratio se acerca a 1:1 (iPad portrait, navegadores con
       sidebars). 125svh da el respiro necesario sin sacrificar mobile. */
    .advance {
        position: relative;
        min-height: 125svh;
        display: block;
        gap: 0;
        padding: 0;
        grid-template-columns: none;
        grid-template-areas: none;
    }

    /* ---- TAG (top-left, red line ARRIBA) ---- */
    .advance__tag {
        position: absolute;
        top: clamp(5.5rem, 14cqi, 8rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: auto;
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        text-align: left;
        z-index: 5;
    }

    .advance__tag-eyebrow {
        font-size: clamp(1rem, 3.6cqi, 1.5rem);
        line-height: 1.2;
        padding-top: 0.7em;
        display: inline-block;
    }

    .advance__tag-eyebrow::before {
        width: 3em;
    }

    .advance__tag-sub {
        margin-top: 0.85em;
        font-size: clamp(0.65rem, 2.4cqi, 1.05rem);
    }

    /* ---- CLAIM (left, debajo del tag) ---- */
    .advance__claim {
        position: absolute;
        top: clamp(10rem, 26cqi, 16rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        max-width: clamp(16rem, 60cqi, 26rem);
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        margin-top: 0;
        z-index: 5;
    }

    .advance__claim p {
        font-size: clamp(1.05rem, 3.6cqi, 1.7rem);
        line-height: 1.25;
    }

    /* ---- CHARACTER - RIGHT-anchored, height-driven (mirror de moment).

       Right negativo en svh (no cqi) para que el offset sea
       aspect-independent - en viewports anchos/casi-cuadrados la fracción
       cqi crece más rápido que el canvas height-driven y recortaría al
       operario. Con svh la compensación se queda con el canvas. */
    .advance__character {
        position: absolute;
        right: clamp(-35rem, -28svh, -8rem);
        left: auto;
        top: auto;
        bottom: 0;
        height: clamp(50svh, 62svh, 72svh);
        width: auto;
        max-width: none;
        margin: 0;
        align-self: auto;
        z-index: 4;
    }

    /* ---- TITLE - middle, full-width, left-aligned, SOBRE el personaje
       (z-5). El diseño mobile muestra el "AVANZA" cubriendo parte del
       hombro/casco del operario.

       Anclado por TOP en cqi (no bottom en svh) - claim usa top en cqi,
       así ambos están en el mismo eje y no colisionan en aspect ratios
       cuadrados (ej. iPad portrait 834x1112). Bottom-svh causaba que
       title y claim se acercaran cuando la altura del viewport bajaba. */
    .advance__title {
        position: absolute;
        top: clamp(16rem, 48cqi, 32rem);
        bottom: auto;
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        text-align: left;
        font-size: clamp(2.8rem, 15cqi, 8rem);
        line-height: 0.92;
        margin: 0;
        padding: 0;
        z-index: 5;
    }

    /* ---- SIGNALS (bullets, left, sobre piernas del personaje)

       Bottom en CQI (no svh): mismo eje que .advance__title, que está
       anclado por top en cqi. Si mezclamos svh/cqi, en aspect ratios
       casi-cuadrados (≈1:1) signals sube y title baja, y se montan. */
    .advance__signals {
        position: absolute;
        top: auto;
        bottom: clamp(15rem, 25cqi, 22rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        margin: 0;
        z-index: 5;
    }

    .advance__signal {
        font-size: clamp(0.78rem, 2.7cqi, 1.15rem);
        text-align: left;
        white-space: normal;
        padding-left: 3em;
        margin-top: 0.5em;
        letter-spacing: 0.08em;
    }

    .advance__signal::before {
        width: 2em;
        top: 0.6em;
    }

    /* ---- COST (bottom-left, S/ 8M, sobre piernas del personaje) ---- */
    .advance__cost {
        position: absolute;
        top: auto;
        bottom: clamp(1.5rem, 4cqi, 3rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: auto;
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        text-align: left;
        margin: 0;
        z-index: 5;
    }

    .advance__cost-amount {
        font-size: clamp(2.5rem, 13cqi, 5.5rem);
    }

    .advance__cost-caption {
        font-size: clamp(0.65rem, 2.4cqi, 1rem);
    }
}

/* ==========================================================================
   HOLES - sección 05 - "Agujeros visibles"

   Escena: operaria con casco sosteniendo una plancha metálica perforada
   por corrosión (DAÑO ESTRUCTURAL). Personaje CENTRADO (no right como
   sec 04, ni left como sec 03). Cost stat S/ 25M en bottom-RIGHT (sec 04
   tenía cost en bottom-LEFT) - el contraste con la columna izquierda
   (tag/claim/title/signals) crea un eje diagonal de lectura.

   Sección width-driven (cqi) en desktop / height-driven (svh) en portrait.

   Z-index map en el stacking context de .holes (creado por isolation):
     0  holes__bg        (fondo full-cover: factory interior con luz cenital)
     2  holes__title     (display, queda detrás del personaje centrado)
     4  holes__character (operaria centrada, bottom-anchored)
     5  textos (tag, claim, signals, cost)
   ========================================================================== */

.holes {
    position: relative;
    isolation: isolate;
    container-type: inline-size;
    min-height: 100svh;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto auto 1fr auto;
    grid-template-areas:
        "tag     ."
        "claim   ."
        "title   title"
        ".       ."
        "signals cost";
    padding: clamp(5rem, 7cqi, 8rem)
             clamp(1.5rem, 4cqi, 4rem)
             clamp(2rem, 4cqi, 4rem);
    gap: clamp(0.5rem, 1.5cqi, 2rem);
    overflow: hidden;
}

.holes__bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    z-index: 0;
    pointer-events: none;
    user-select: none;
    /* Overscan para el blur del scrub - ver nota en .moment__bg. */
    scale: 1.06;
}

.holes__veil {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: #000;
    opacity: 0.35;
    pointer-events: none;
}

/* Personaje CENTRADO en desktop (mirror de sec 04 + sec 03). El PNG es
   3:2 landscape; con width 64cqi explícito y margin-left = -half_width,
   el centro de la imagen cae sobre 50% del viewport.

   No usamos translateX(-50%) porque GSAP escribe `transform` (parallax +
   reveal) y pisaría el centrado - el margin-left coexiste con transform. */
.holes__character {
    position: absolute;
    bottom: 0;
    left: 50%;
    width: clamp(36rem, 76cqi, 110rem);
    margin-left: clamp(-55rem, -38cqi, -18rem);
    height: auto;
    z-index: 4;
    pointer-events: none;
    user-select: none;
}

/* ---------- tag (top-left, red line ARRIBA) - idéntico a sec 04 ------ */

.holes__tag {
    grid-area: tag;
    z-index: 5;
    justify-self: start;
    text-align: left;
}

.holes__tag-eyebrow {
    position: relative;
    font-family: var(--font-sans);
    font-weight: 800;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.8rem, 1.2cqi, 1.55rem);
    letter-spacing: 0.05em;
    line-height: 1.2;
    padding-top: 0.7em;
    display: inline-block;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
}

.holes__tag-eyebrow::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 4em;
    height: 2px;
    background: var(--color-red);
}

.holes__tag-accent {
    color: var(--color-white);
}

.holes__tag-sub {
    margin-top: 0.85em;
    font-family: var(--font-sans);
    font-weight: 600;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.65rem, 0.95cqi, 1.2rem);
    letter-spacing: 0.18em;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
}

/* ---------- claim italic (mid-left, 3 lines) ---------- */

.holes__claim {
    grid-area: claim;
    z-index: 5;
    justify-self: start;
    align-self: start;
    text-align: left;
    margin-top: clamp(1rem, 2cqi, 3rem);
    max-width: clamp(18rem, 42cqi, 36rem);
}

.holes__claim p {
    font-family: var(--font-italic);
    font-style: italic;
    font-weight: 400;
    color: var(--color-white);
    font-size: clamp(1.1rem, 2.3cqi, 3rem);
    line-height: 1.3;
    text-shadow: 0 2px 14px rgba(0, 0, 0, 0.65);
}

.holes__claim p + p {
    margin-top: 0.3em;
}

.holes__claim-emph {
    font-style: italic;
    font-weight: 700;
}

/* ---------- big display title (mid-lower-left, behind personaje)

   grid-column: 1 / -1 + justify-self: start - el título es full-width
   pero queda alineado a la izquierda. El personaje CENTRADO (z-4) cubre
   parcialmente el "AGUJEROS" y "VISIBLES" en su mitad derecha - overlap
   más fuerte que sec 04 porque el personaje está más al centro.

   margin-top y margin-bottom simétricos en cqi (≈ 1/3 del font-size cqi)
   para que la masa del título no abrace al claim ni a los signals
   (lección de sec 04). ---------- */

.holes__title {
    grid-area: title;
    grid-column: 1 / -1;
    justify-self: start;
    align-self: end;
    z-index: 2;
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-white);
    line-height: 0.92;
    letter-spacing: 0.005em;
    font-size: clamp(3rem, 18cqi, 26rem);
    text-align: left;
    text-shadow: 0 6px 30px rgba(0, 0, 0, 0.5);
    margin-top: clamp(2rem, 6cqi, 7rem);
    margin-bottom: clamp(2rem, 6cqi, 7rem);
    padding-left: clamp(0rem, 0.5cqi, 0.5rem);
}

.holes__title-line {
    display: block;
}

/* ---------- signals (bullet list, lower-left) - idéntico a sec 04 -- */

.holes__signals {
    grid-area: signals;
    z-index: 5;
    justify-self: start;
    list-style: none;
    margin: 0;
    padding: 0;
}

.holes__signal {
    position: relative;
    padding-left: 2.6em;
    margin-top: 0.35em;
    font-family: var(--font-sans);
    font-weight: 700;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.7rem, 1.05cqi, 1.3rem);
    letter-spacing: 0.1em;
    line-height: 1.3;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
    white-space: nowrap;
}

.holes__signal::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.55em;
    width: 1.8em;
    height: 2px;
    background: var(--color-red);
}

/* ---------- cost stat (bottom-RIGHT, S/ 25M)

   Diferencia clave vs sec 04: alineado a la DERECHA. La caption sigue
   debajo del amount, también right-aligned. justify-self: end + text-
   align: right alinean tanto el bloque como el texto interno. */

.holes__cost {
    grid-area: cost;
    z-index: 5;
    justify-self: end;
    align-self: end;
    text-align: right;
    margin-top: clamp(1rem, 2cqi, 2rem);
}

.holes__cost-amount {
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-red);
    font-size: clamp(3rem, 9cqi, 16rem);
    line-height: 0.9;
    letter-spacing: 0.01em;
    white-space: nowrap;
    text-shadow: 0 6px 30px rgba(0, 0, 0, 0.5);
}

.holes__cost-caption {
    font-family: var(--font-sans);
    font-weight: 800;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.7rem, 1.1cqi, 1.4rem);
    letter-spacing: 0.06em;
    line-height: 1.25;
    margin-top: 0.5em;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
}

/* ---------- HOLES - initial state gated por .js (para animar con GSAP) -- */

html.js .holes__veil,
html.js .holes__character,
html.js .holes__tag,
html.js .holes__claim p,
html.js .holes__title-line,
html.js .holes__signals-heading,
html.js .holes__signal,
html.js .holes__cost {
    opacity: 0;
    visibility: hidden;
}

/* ---------- HOLES - portrait (sólo orientación)

   Reorganiza la composición vertical en mobile:
   - Tag top-left con red line arriba.
   - Claim italic (3 lines) debajo del tag.
   - Title GIGANTE, full-width left-aligned, SOBRE el personaje (z-5).
   - Personaje CENTRADO horizontalmente, height-driven (svh), bottom-
     anchored. Width = height × 1.5 (PNG 3:2). Centrado vía left:50% +
     margin-left:-half_width.
   - Bullets + cost stat en el extremo inferior. En mobile el cost va a
     la IZQUIERDA (no derecha como desktop), según el diseño.

   min-height: 125svh: los aspect ratios casi-cuadrados ahogaban el
   contenido a 115svh (visto antes en sec 04).

   Signals y title ambos anclados por CQI (mismo eje) para que no
   colisionen entre posiciones absolutas. --------------------------- */

@media (orientation: portrait) {
    .holes {
        position: relative;
        min-height: 125svh;
        display: block;
        gap: 0;
        padding: 0;
        grid-template-columns: none;
        grid-template-areas: none;
    }

    /* ---- TAG (top-left, red line ARRIBA) ---- */
    .holes__tag {
        position: absolute;
        top: clamp(5.5rem, 14cqi, 8rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: auto;
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        text-align: left;
        z-index: 5;
    }

    .holes__tag-eyebrow {
        font-size: clamp(1rem, 3.6cqi, 1.5rem);
        line-height: 1.2;
        padding-top: 0.7em;
        display: inline-block;
    }

    .holes__tag-eyebrow::before {
        width: 3em;
    }

    .holes__tag-sub {
        margin-top: 0.85em;
        font-size: clamp(0.65rem, 2.4cqi, 1.05rem);
    }

    /* ---- CLAIM (left, debajo del tag) ---- */
    .holes__claim {
        position: absolute;
        top: clamp(10rem, 26cqi, 16rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        max-width: clamp(16rem, 60cqi, 26rem);
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        margin-top: 0;
        z-index: 5;
    }

    .holes__claim p {
        font-size: clamp(1.05rem, 3.6cqi, 1.7rem);
        line-height: 1.25;
    }

    /* ---- CHARACTER - CENTRADO, height-driven (svh).

       PNG 3:2 landscape, height 62svh → width 93svh. Centrado vía
       left:50% + margin-left:-46.5svh (= -half_width). El canvas sale
       de los bordes laterales en mobile angosto y el overflow:hidden
       recorta - el operario queda en la mitad central del viewport. */
    .holes__character {
        position: absolute;
        bottom: 0;
        top: auto;
        left: 50%;
        right: auto;
        height: 62svh;
        width: 93svh;
        margin-left: -46.5svh;
        max-width: none;
        margin-top: 0;
        margin-right: 0;
        margin-bottom: 0;
        align-self: auto;
        z-index: 4;
    }

    /* ---- TITLE - middle, full-width, left-aligned, SOBRE el personaje
       (z-5). Anclado por TOP en cqi (mismo eje que claim arriba y signals
       abajo) para evitar overlap en aspect ratios casi-cuadrados. */
    .holes__title {
        position: absolute;
        top: clamp(16rem, 48cqi, 32rem);
        bottom: auto;
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        text-align: left;
        font-size: clamp(2.8rem, 15cqi, 8rem);
        line-height: 0.92;
        margin: 0;
        padding: 0;
        z-index: 5;
    }

    /* ---- SIGNALS (bullets, left, bottom-anchored cqi) ---- */
    .holes__signals {
        position: absolute;
        top: auto;
        bottom: clamp(15rem, 25cqi, 22rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        margin: 0;
        z-index: 5;
    }

    .holes__signal {
        font-size: clamp(0.78rem, 2.7cqi, 1.15rem);
        text-align: left;
        white-space: normal;
        padding-left: 3em;
        margin-top: 0.5em;
        letter-spacing: 0.08em;
    }

    .holes__signal::before {
        width: 2em;
        top: 0.6em;
    }

    /* ---- COST (bottom-LEFT en mobile, no right como desktop) ---- */
    .holes__cost {
        position: absolute;
        top: auto;
        bottom: clamp(1.5rem, 4cqi, 3rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: auto;
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        text-align: left;
        margin: 0;
        z-index: 5;
    }

    .holes__cost-amount {
        font-size: clamp(2.5rem, 13cqi, 5.5rem);
    }

    .holes__cost-caption {
        font-size: clamp(0.65rem, 2.4cqi, 1rem);
    }
}

/* ==========================================================================
   FACE - sección 06 - "La corrosión se volvió la cara de tu operación"

   Sección clímax de la narrativa: NO hay cost stat (las consecuencias ya
   no se miden en plata). El personaje es un ejecutivo en TRAJE sosteniendo
   una plancha destruida por corrosión a la altura de su cara - metáfora
   visual de "la corrosión se volvió tu cara".

   Composición invertida respecto a sec 04/05:
   - Tag y claim → TOP-RIGHT (no left)
   - Personaje → CENTER-LEFT (no center, no right)
   - Title (3 líneas) → BOTTOM-RIGHT right-aligned
   - Bullets → BOTTOM-RIGHT debajo del title
   - Red line BAJO el eyebrow (no arriba como sec 04/05)
   - Punto separador "·" en ROJO en sub + bullets (no blanco)

   Z-index map en el stacking context de .face (creado por isolation):
     0  face__bg        (fondo: paisaje minero arrasado, atardecer)
     2  face__title     (display 3 líneas, queda detrás del personaje)
     4  face__character (ejecutivo center-left, bottom-anchored)
     5  textos (tag, claim, signals)
   ========================================================================== */

.face {
    position: relative;
    isolation: isolate;
    container-type: inline-size;
    min-height: 100svh;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto 1fr auto auto;
    grid-template-areas:
        ".  tag"
        ".  claim"
        ".  ."
        ".  title"
        ".  signals";
    padding: clamp(5rem, 7cqi, 8rem)
             clamp(1.5rem, 4cqi, 4rem)
             clamp(2rem, 4cqi, 4rem);
    gap: clamp(0.5rem, 1.5cqi, 2rem);
    overflow: hidden;
}

.face__bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    z-index: 0;
    pointer-events: none;
    user-select: none;
    /* Overscan para el blur del scrub - ver nota en .moment__bg. */
    scale: 1.06;
}

.face__veil {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: #000;
    opacity: 0.35;
    pointer-events: none;
}

/* Personaje CENTER-LEFT: anclado por left con leve offset negativo. El
   canvas 3:2 con el ejecutivo centrado → con left:-10cqi y width 60cqi,
   el centro del PNG cae sobre ~20% del viewport. La plancha corroída
   queda a la altura facial del ejecutivo, en la mitad izquierda. */
.face__character {
    position: absolute;
    bottom: 0;
    /* Personaje visible al ~30% del canvas (verificado con análisis de
       alpha del PNG, ver shots/_cdp-shot.mjs). Con width 80cqi y left
       -7cqi, el centro de la imagen cae sobre ~30% del viewport, dejando
       espacio para que el title gigante a la derecha se superponga. */
    left: clamp(-12rem, -7cqi, -1rem);
    width: clamp(40rem, 80cqi, 105rem);
    height: auto;
    z-index: 4;
    pointer-events: none;
    user-select: none;
}

/* ---------- tag (TOP-RIGHT en desktop, red line ABAJO del eyebrow) ----

   Diferencias vs sec 04/05:
   - Posicionado a la derecha (justify-self: end)
   - Red line va DEBAJO de la eyebrow (no arriba). Usamos ::after en
     lugar de ::before.
   - El separador "·" en .face__tag-sub va en rojo (face__dot). */

.face__tag {
    grid-area: tag;
    z-index: 5;
    justify-self: end;
    text-align: right;
}

.face__tag-eyebrow {
    position: relative;
    font-family: var(--font-sans);
    font-weight: 800;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.8rem, 1.2cqi, 1.55rem);
    letter-spacing: 0.05em;
    line-height: 1.2;
    padding-bottom: 0.7em;
    display: inline-block;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
}

/* Red line ABAJO del eyebrow, alineada a la DERECHA del inline-block
   (el right:0 del elemento inline-block = right edge del texto). En
   portrait se override a left:0 para alinearse con el texto left-align. */
.face__tag-eyebrow::after {
    content: "";
    position: absolute;
    bottom: 0;
    right: 0;
    width: 4em;
    height: 2px;
    background: var(--color-red);
}

.face__tag-accent {
    color: var(--color-white);
}

.face__tag-sub {
    margin-top: 0.4em;
    font-family: var(--font-sans);
    font-weight: 600;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.65rem, 0.95cqi, 1.2rem);
    letter-spacing: 0.18em;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
}

/* Punto separador rojo (· entre INTEGRIDAD COMPROMETIDA y OPERACIÓN
   PARALIZADA, y entre cada par de bullets). Margen lateral mínimo para
   que el dot tenga aire sin separar las dos partes del texto. */
.face__dot {
    color: var(--color-red);
    margin: 0 0.15em;
    font-weight: 900;
}

/* ---------- claim italic (UPPER-RIGHT, right-aligned, 2 lines) ------ */

.face__claim {
    grid-area: claim;
    z-index: 5;
    justify-self: end;
    align-self: start;
    text-align: right;
    margin-top: clamp(1rem, 2cqi, 3rem);
    max-width: clamp(18rem, 42cqi, 36rem);
}

.face__claim p {
    font-family: var(--font-italic);
    font-style: italic;
    font-weight: 400;
    color: var(--color-white);
    font-size: clamp(1.1rem, 2.3cqi, 3rem);
    line-height: 1.3;
    text-shadow: 0 2px 14px rgba(0, 0, 0, 0.65);
}

.face__claim p + p {
    margin-top: 0.2em;
}

.face__claim-emph {
    font-style: italic;
    font-weight: 700;
}

/* ---------- big display title (BOTTOM-RIGHT, 3 lines, right-aligned)

   3 líneas (sec 04/05 tenían 2). Font-size un poco más chico (15cqi vs
   18cqi de sec 04) para que las 3 líneas entren sin desbordar la altura
   de la sección. El título se SUPERPONE al personaje desde la izquierda
   - la línea más larga ("SE VOLVIÓ LA CARA") extiende su borde izquierdo
   hasta donde llega el ejecutivo. Z-2 detrás → personaje cubre el extremo
   izquierdo de la línea, dejando ver el resto.

   margin-top y margin-bottom escalan con cqi (lección sec 04 - la masa
   del display no debe respirar con `gap` o `rem`). ------------------- */

.face__title {
    grid-area: title;
    grid-column: 1 / -1;
    justify-self: end;
    align-self: end;
    z-index: 2;
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-white);
    line-height: 0.95;
    letter-spacing: 0.005em;
    /* 3 líneas: font más chico que sec 04/05 (que tenían 2 líneas a 18cqi).
       13cqi escala 2 líneas en proporción al diseño (3:1 aspect) y permite
       que las 3 líneas entren verticalmente sin disparar la altura de la
       sección. Línea más larga "SE VOLVIÓ LA CARA" extiende su borde
       izquierdo hasta superponerse con el personaje (overlap intencional). */
    font-size: clamp(2.5rem, 13cqi, 19rem);
    text-align: right;
    text-shadow: 0 6px 30px rgba(0, 0, 0, 0.5);
    margin-top: clamp(2rem, 5cqi, 6rem);
    margin-bottom: clamp(1rem, 2cqi, 2.5rem);
    padding-right: clamp(0rem, 0.5cqi, 0.5rem);
}

.face__title-line {
    display: block;
}

/* ---------- signals (bullet list, BOTTOM-RIGHT, right-aligned) ------

   Layout right-aligned: la leader-line roja va a la DERECHA del texto
   (no a la izquierda como sec 04/05). Para mantener el padding-right que
   recibe la línea, invertimos: bullet text con padding-right, leader-line
   con right:0 + after en lugar de before. */

.face__signals {
    grid-area: signals;
    z-index: 5;
    justify-self: end;
    list-style: none;
    margin: 0;
    padding: 0;
    text-align: right;
}

.face__signal {
    position: relative;
    padding-left: 2.6em;
    margin-top: 0.35em;
    font-family: var(--font-sans);
    font-weight: 700;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.7rem, 1.05cqi, 1.3rem);
    letter-spacing: 0.1em;
    line-height: 1.3;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
    white-space: nowrap;
}

/* Leader-line roja a la izquierda del texto (consistente con secciones
   anteriores). El texto fluye derecha-a-izquierda visualmente porque
   el ::before fija la línea al borde izquierdo del bullet. */
.face__signal::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.55em;
    width: 1.8em;
    height: 2px;
    background: var(--color-red);
}

/* ---------- FACE - initial state gated por .js (para animar con GSAP) -- */

html.js .face__veil,
html.js .face__character,
html.js .face__tag,
html.js .face__claim p,
html.js .face__title-line,
html.js .face__signal {
    opacity: 0;
    visibility: hidden;
}

/* ---------- FACE - portrait (sólo orientación)

   Reorganización vertical:
   - Tag top-LEFT (no right como desktop) con red line abajo.
   - Claim italic CENTERED debajo del tag (el diseño mobile lo muestra
     centrado, no left-aligned como sec 04/05).
   - Title GIGANTE 3 líneas, full-width LEFT-aligned, SOBRE el personaje.
   - Personaje CENTRADO horizontalmente (left:50% + margin-left:-half),
     height-driven (62svh × 1.5 = 93svh width).
   - Bullets bottom-anchored cqi (mismo eje que el top del title, para
     que no colisionen).

   No hay cost stat en este sección. min-height: 125svh para respiro. */

@media (orientation: portrait) {
    .face {
        position: relative;
        min-height: 125svh;
        display: block;
        gap: 0;
        padding: 0;
        grid-template-columns: none;
        grid-template-areas: none;
    }

    /* ---- TAG (top-left, red line ABAJO del eyebrow) ---- */
    .face__tag {
        position: absolute;
        top: clamp(5.5rem, 14cqi, 8rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: auto;
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        text-align: left;
        z-index: 5;
    }

    .face__tag-eyebrow {
        font-size: clamp(1rem, 3.6cqi, 1.5rem);
        line-height: 1.2;
        padding-bottom: 0.7em;
        display: inline-block;
    }

    /* En portrait el line va alineado a la IZQUIERDA del eyebrow (lado
       opuesto al desktop right). */
    .face__tag-eyebrow::after {
        right: auto;
        left: 0;
        width: 3em;
    }

    .face__tag-sub {
        margin-top: 0.85em;
        font-size: clamp(0.65rem, 2.4cqi, 1.05rem);
    }

    /* ---- CLAIM (debajo del tag, CENTRADO horizontalmente)

       top más grande que sec 04/05 (clamp(10rem, 26cqi, 16rem)) porque
       el tag de sec 06 tiene el line abajo del eyebrow + sub debajo -
       total más alto. En widths medios (900cqi+) el gap se cierra. */
    .face__claim {
        position: absolute;
        top: clamp(11rem, 30cqi, 20rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        max-width: none;
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        margin-top: 0;
        text-align: center;
        z-index: 5;
    }

    .face__claim p {
        font-size: clamp(1.05rem, 3.6cqi, 1.7rem);
        line-height: 1.3;
    }

    /* ---- CHARACTER - CENTRADO, height-driven (igual que sec 05) ---- */
    .face__character {
        position: absolute;
        bottom: 0;
        top: auto;
        left: 50%;
        right: auto;
        height: 62svh;
        width: 93svh;
        margin-left: -46.5svh;
        max-width: none;
        margin-top: 0;
        margin-right: 0;
        margin-bottom: 0;
        align-self: auto;
        z-index: 4;
    }

    /* ---- TITLE - 3 LINES, left-aligned, SOBRE el personaje (z-5) ----

       3 líneas requieren font-size más chico que sec 04/05 portrait. A
       13cqi cap'd a 6rem (96px), 3 líneas × 0.95 line-height entran sin
       desbordar.

       Anclado por TOP en svh: el diseño mobile muestra el title BAJO el
       personaje (en la zona del torso/cintura). Necesita anchor ligado al
       eje vertical para mantener proporción consistente en aspect ratios
       distintos. Mix svh/cqi controlado: signals usa cqi-bottom; verificamos
       que el gap se mantenga positivo en 375x812, 768x1024, 900x950. */
    .face__title {
        position: absolute;
        top: clamp(15rem, 50svh, 32rem);
        bottom: auto;
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        text-align: left;
        font-size: clamp(2.5rem, 13cqi, 6rem);
        line-height: 0.95;
        margin: 0;
        padding: 0;
        z-index: 5;
    }

    /* ---- SIGNALS (bullets, left-aligned, bottom-anchored cqi) ------

       En portrait el alineamiento va a la IZQUIERDA (desktop era a la
       derecha). Override text-align y mantener el padding-left con
       leader-line a la izquierda. */
    .face__signals {
        position: absolute;
        top: auto;
        bottom: clamp(2rem, 6cqi, 5rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        align-self: auto;
        justify-self: auto;
        grid-area: auto;
        margin: 0;
        text-align: left;
        z-index: 5;
    }

    .face__signal {
        font-size: clamp(0.78rem, 2.7cqi, 1.15rem);
        text-align: left;
        white-space: normal;
        padding-left: 3em;
        margin-top: 0.5em;
        letter-spacing: 0.08em;
    }

    .face__signal::before {
        width: 2em;
        top: 0.6em;
    }
}

/* ==========================================================================
   RECAP - sección 07 - "RECUERDA QUE: cuando la corrosión se convierte en la cara"

   Sección distinta del resto: NO es narrativa con personaje, NO usa fondo
   oscuro. Es la SÍNTESIS de consecuencias en una lista de 5 cards.

   Diferencias estructurales:
   - Fondo CREMA (var(--color-white)) - único corte visual contra todo el
     resto de la landing que va en negro.
   - Texto principal en NEGRO (var(--color-ink)) - invertido del resto.
   - Cards con fondo NEGRO + texto crema - inversión local dentro de la
     sección cream.
   - Sin personaje. Sin background de paisaje. La sección es contenido puro.
   - Badge top-right con barra de progreso (representa reputación de marca).

   Layout:
   - Header: eyebrow + título de 4 líneas + badge. Grid 2 columnas
     (título a la izquierda spanning, badge top-right).
   - Cards: lista vertical, cada card es image-left + content-right.

   Sección width-driven (cqi). No usa container-type isolation porque no
   hay stacking ni overlap entre elementos. ==================================*/

.recap {
    position: relative;          /* ancla el ::before de costura 06→07 */
    background: var(--color-white);
    color: var(--color-ink);
    container-type: inline-size;
    /* padding-top ampliado: aloja la banda de fade ink→crema entera por
       encima del header, así el eyebrow/título nunca caen en zona oscura.
       Horizontal y bottom conservan sus valores originales. */
    padding: clamp(5rem, 11cqi, 12rem)
             clamp(1.25rem, 4cqi, 4rem)
             clamp(3rem, 6cqi, 7rem);
    overflow-x: clip;
}

/* Costura 06→07: el borde inferior de `.face` ya se fundió a ink (edge
   fade). Acá el tope de `.recap` arranca en ink y se aclara hacia el crema,
   cerrando el salto oscuro→claro. La banda vive ENTERA sobre el padding-top
   ampliado - el header crema/rojo siempre cae sobre crema puro. El contenido
   de recap pinta encima por orden de DOM (el ::before no lleva z-index alto). */
.recap::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: clamp(5rem, 11cqi, 12rem);   /* = padding-top desktop */
    z-index: 0;
    pointer-events: none;
    background: linear-gradient(to bottom, var(--color-ink) 0%, transparent 100%);
}

/* ---------- header (eyebrow + title) ---------------------------------

   Flujo vertical natural: eyebrow arriba (inline-block para que el
   ::after underline se pegue al ancho del texto), título full-width
   abajo. Sin grid de 2 columnas - el badge se eliminó. */

.recap__header {
    margin-bottom: clamp(2rem, 5cqi, 5rem);
    /* Tope de ancho de contenido (bg/seam siguen full-bleed). */
    max-width: var(--content-max);
    margin-inline: auto;
    /* Container-query context: el cqi del título se resuelve contra el header
       topado (1440), no contra la sección completa → deja de crecer. */
    container-type: inline-size;
}

.recap__eyebrow {
    /* inline-block sobre block context: el ::after underline ahora se
       pega al ancho del texto sin necesidad de justify-self (que sólo
       aplica en grid items). */
    display: inline-block;
    font-family: var(--font-sans);
    font-weight: 800;
    color: var(--color-red);
    text-transform: uppercase;
    font-size: clamp(0.8rem, 1.2cqi, 1.5rem);
    letter-spacing: 0.08em;
    line-height: 1.2;
    position: relative;
    padding-bottom: 0.5em;
    margin-bottom: clamp(0.75rem, 1.5cqi, 1.5rem);
}

.recap__eyebrow::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 2px;
    background: var(--color-red);
}

.recap__title {
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-ink);
    line-height: 1.05;
    letter-spacing: 0.005em;
    /* Bajado de 7cqi/9rem: era demasiado grande para un título de 4 líneas. */
    font-size: clamp(1.5rem, 4.5cqi, 4.5rem);
    margin: 0;
}

.recap__title-line {
    display: block;
}

/* La última línea cambia el color a rojo - "TODO SE VE COMPROMETIDO" es
   el remate del título. Mismo font, sólo color override. */
.recap__title-line--accent {
    color: var(--color-red);
}

/* ---------- cards list ----------------------------------------------

   Layout DESKTOP (default): 5 cards en fila, stack vertical de contenido
   dentro de cada card (number, title, image, desc, foot). Cards 1-4
   usan fondo crema con texto oscuro; card 5 (.--inverted) invierte a
   fondo negro con texto crema, como clímax visual de la lista.

   align-items: end deja las cards bottom-aligned. Las que tienen menos
   contenido quedan más bajas (top edge inferior), creando un stagger
   natural tipo "polaroid stack" como en el diseño.

   --divider-color via CSS custom property por card: oscuro en cream cards,
   claro en la inverted. Evita repetir reglas de border-color en cada
   selector hijo. */

.recap__cards {
    list-style: none;
    margin: 0 auto;
    max-width: var(--content-max);
    padding: 0;
    display: grid;
    /* Wide desktop: 4 cards en row 1 + card 5 expandida full-width row 2.
       Breakpoint a 3+2 cuando se achica (≤1099px), y a 1 col en mobile
       (≤720px). Sin auto-fit - el layout 4+1 con la 5ta full-width
       requiere control explícito de grid-column. */
    grid-template-columns: repeat(4, 1fr);
    align-items: stretch;
    gap: clamp(0.75rem, 1.4cqi, 1.8rem);
}

/* Card 5 (la inverted "Pérdida de vidas") cierra el recap como banda
   full-width - climax visual de la lista. */
.recap__card:nth-child(5) {
    grid-column: 1 / -1;
}

/* Cuando card 5 va full-width (modo 4+1, ≥1100px), reorganizar
   internamente a layout horizontal (img-left + body-right). De otra
   forma la imagen `aspect-ratio: 3/4` aplicada al ancho completo
   inflaría el alto a ~1600px. En horizontal, la imagen llena el alto
   natural del body y la card queda a la altura del resto. */
@media (min-width: 1100px) {
    .recap__card:nth-child(5) {
        grid-template-columns: minmax(0, 1.3fr) minmax(0, 3fr);
        grid-template-rows: auto auto 1fr auto;
        grid-template-areas:
            "img number"
            "img title"
            "img desc"
            "img foot";
        column-gap: clamp(1.4rem, 2.4cqi, 2.6rem);
    }

    .recap__card:nth-child(5) .recap__card-img {
        grid-area: img;
        aspect-ratio: auto;             /* libera la imagen del 3:4 vertical */
        height: 100%;
        width: 100%;
        object-fit: cover;
        object-position: center;
    }
}

/* ---------- RECAP - medio rango (3+2) ----------
   Cuando el viewport baja de 1099px y antes de pasar al stack mobile,
   pasamos a 3 cards arriba + 2 cards abajo. Grid de 6 cols permite
   span 2 (3 cards x 2 = 6) en row 1 y span 3 (2 cards x 3 = 6) en row 2. */
@media (max-width: 1099px) and (min-width: 721px) {
    .recap__cards {
        grid-template-columns: repeat(6, 1fr);
    }
    .recap__card {
        grid-column: span 2;
    }
    .recap__card:nth-child(4),
    .recap__card:nth-child(5) {
        grid-column: span 3;
    }
}

.recap__card {
    --divider-color: rgba(14, 14, 16, 0.18);
    --foot-color: rgba(14, 14, 16, 0.65);
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto auto auto;
    grid-template-areas:
        "number"
        "title"
        "img"
        "desc"
        "foot";
    background: var(--color-white);
    color: var(--color-ink);
    padding: clamp(1.4rem, 2.4cqi, 2.6rem);
    gap: clamp(0.7rem, 1.2cqi, 1.3rem);
    border: 1px solid rgba(14, 14, 16, 0.1);
}

/* Card 5 invierte el esquema - fondo negro, texto crema. El "remate"
   visual de la lista (PÉRDIDA DE VIDAS) destaca con el cambio. */
.recap__card--inverted {
    --divider-color: rgba(244, 241, 236, 0.22);
    --foot-color: rgba(244, 241, 236, 0.7);
    background: var(--color-ink);
    color: var(--color-white);
    border-color: rgba(244, 241, 236, 0.1);
}

.recap__card-number {
    grid-area: number;
    font-family: var(--font-sans);
    font-weight: 800;
    color: var(--color-red);
    font-size: clamp(2.2rem, 4cqi, 5rem);
    line-height: 1;
    letter-spacing: 0.02em;
    font-variant-numeric: tabular-nums;
}

.recap__card-title {
    grid-area: title;
    font-family: var(--font-sans);
    font-weight: 800;
    color: inherit;                                   /* dark en cream, light en inverted */
    text-transform: uppercase;
    font-size: clamp(1.3rem, 2.2cqi, 2.5rem);
    line-height: 1.1;
    letter-spacing: 0.04em;
    margin: 0;
    padding-bottom: clamp(0.6rem, 1.2cqi, 1.2rem);
    border-bottom: 1px solid var(--divider-color);
}

/* aspect-ratio 3/4 (portrait): el diseño muestra las imágenes verticales,
   más altas que anchas. Permite tener un PNG dark/desaturado que llene
   visualmente la mitad inferior de cada card. */
.recap__card-img {
    grid-area: img;
    width: 100%;
    aspect-ratio: 3 / 4;
    object-fit: cover;
    object-position: center;
    display: block;
    user-select: none;
}

.recap__card-desc {
    grid-area: desc;
    font-family: var(--font-sans);
    font-weight: 500;
    color: inherit;
    font-size: clamp(0.92rem, 1.2cqi, 1.25rem);
    line-height: 1.5;
    margin: 0;
    padding-top: clamp(0.6rem, 1.2cqi, 1.2rem);
    padding-bottom: clamp(0.6rem, 1.2cqi, 1.2rem);
    border-bottom: 1px solid var(--divider-color);
}

.recap__card-foot {
    grid-area: foot;
    font-family: var(--font-sans);
    font-weight: 600;
    color: var(--foot-color);                         /* via custom prop, no opacity, así el dot rojo no se atenúa */
    font-size: clamp(0.8rem, 1cqi, 1.15rem);
    line-height: 1.4;
    letter-spacing: 0.01em;
    margin: 0;
}

.recap__card-dot {
    color: var(--color-red);                          /* full red - no afectado por --foot-color porque sobrescribe color */
    margin: 0 0.15em;
    font-weight: 900;
}

/* ---------- RECAP - initial state gated por .js (para reveal con GSAP) -- */

html.js .recap__eyebrow,
html.js .recap__title-line,
html.js .recap__card {
    opacity: 0;
    visibility: hidden;
}

/* ---------- RECAP - portrait + narrow widths (≤ 720)

   Cuando el viewport es muy angosto, el header colapsa a 1 columna: badge
   se mueve al top (orden DOM original muestra eyebrow → title → badge, pero
   en portrait queremos badge al top, después eyebrow + title).

   Las cards mantienen image-left + body-right siempre, como en el diseño
   incluso en mobile. */

/* ---------- RECAP - mobile/tablet portrait (≤ 720px)

   Override completo del layout: cards cambian de "fila de 5 verticales"
   a "lista vertical, image-left + content-right" con grid-template-areas.

   Todas las cards en mobile usan fondo negro + texto crema (incluso las
   1-4 que en desktop son crema), coherente con el resto del landing
   oscuro y con el diseño mobile original. La --inverted no
   tiene efecto distinto en mobile (todas inverted por default). */

@media (max-width: 720px) {
    .recap {
        /* top ampliado para alojar la banda de fade; horiz/bottom original */
        padding: clamp(4rem, 12cqi, 7rem)
                 clamp(1rem, 5cqi, 2rem)
                 clamp(2rem, 7cqi, 4rem);
    }

    .recap::before {
        height: clamp(4rem, 12cqi, 7rem);   /* calza con el padding-top mobile */
    }

    .recap__eyebrow {
        font-size: clamp(0.75rem, 3.4cqi, 1rem);
    }

    .recap__title {
        font-size: clamp(1.4rem, 7cqi, 2.6rem);
    }

    /* Lista de cards en una columna vertical. */
    .recap__cards {
        grid-template-columns: 1fr;
        align-items: stretch;
        gap: clamp(0.75rem, 2cqi, 1.5rem);
    }

    /* Reset de spans del grid de 4 cols / 6 cols: en mobile cada card
       ocupa la única columna disponible. */
    .recap__card,
    .recap__card:nth-child(4),
    .recap__card:nth-child(5) {
        grid-column: auto;
    }

    /* Cada card vuelve a la composición horizontal: imagen a la izquierda
       spanning las 4 filas de contenido, todo el contenido apilado a la
       derecha. Mismo HTML que desktop (flat siblings), distinto layout. */
    .recap__card,
    .recap__card--inverted {
        --divider-color: rgba(244, 241, 236, 0.22);
        --foot-color: rgba(244, 241, 236, 0.7);
        grid-template-columns: 42% 58%;
        grid-template-rows: auto auto auto auto;
        grid-template-areas:
            "img number"
            "img title"
            "img desc"
            "img foot";
        background: var(--color-ink);
        color: var(--color-white);
        border: none;
        padding: 0;
        gap: 0;
        min-height: clamp(11rem, 42cqi, 16rem);
    }

    /* Imagen pierde el aspect-ratio explícito porque ahora llena la
       columna izquierda completa (alto definido por contenido del body). */
    .recap__card-img {
        aspect-ratio: auto;
        height: 100%;
        max-height: none;
    }

    /* Número y title arriba del body, padding inside el área derecha. */
    .recap__card-number {
        padding: clamp(1rem, 3.5cqi, 1.4rem) clamp(1rem, 3.5cqi, 1.4rem) 0;
        font-size: clamp(1.6rem, 5.5cqi, 2.4rem);
    }

    .recap__card-title {
        padding: clamp(0.25rem, 1cqi, 0.5rem) clamp(1rem, 3.5cqi, 1.4rem) clamp(0.6rem, 1.8cqi, 1rem);
        font-size: clamp(1.15rem, 3.6cqi, 1.5rem);
        letter-spacing: 0.04em;
    }

    .recap__card-desc {
        padding: clamp(0.6rem, 1.8cqi, 1rem) clamp(1rem, 3.5cqi, 1.4rem);
        font-size: clamp(0.86rem, 2.7cqi, 1.05rem);
        line-height: 1.45;
        /* Desktop ya tiene border-bottom; no necesitamos border-top extra. */
    }

    .recap__card-foot {
        padding: clamp(0.6rem, 1.8cqi, 1rem) clamp(1rem, 3.5cqi, 1.4rem) clamp(1rem, 3.5cqi, 1.4rem);
        font-size: clamp(0.74rem, 2.3cqi, 0.92rem);
    }
}

/* ==========================================================================
   CLOSING - sección 08 - cierre dramático con S/ 50M diarios

   Estructura mínima: bg full-cover (los tres personajes vienen embebidos
   en el PNG/video, NO hay <img> separados) + dos textos overlay.

   El cliente reemplazará el <img class="closing__bg"> por un <video>
   autoplay/loop/muted/playsinline manteniendo la misma clase. El CSS aplica
   object-fit:cover por igual - la swap es transparente.

   Z-index map:
     0  closing__bg     (imagen/video full-cover)
     5  closing__stat   (S/ 50M + caption, bottom-left)
     5  closing__claim  (italic claim, bottom-right)

   No hay container-type ni isolation porque no hay overlap entre stat y
   claim (están en lados opuestos del viewport).
   ========================================================================== */

.closing {
    position: relative;
    container-type: inline-size;
    min-height: 100svh;
    overflow: hidden;
    background: var(--color-ink);                    /* fallback antes que el bg cargue */
}
/* Banda topada para el stat (abajo-izq) y el claim (abajo-der): full-height,
   máx --content-max, centrada. El video y el vignette quedan full-bleed. */
.closing .cap {
    position: absolute;
    inset: 0;
    width: auto;
    z-index: 5;
    pointer-events: none;
}
.closing .cap > * { pointer-events: auto; }

.closing__bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    z-index: 0;
    pointer-events: none;
    user-select: none;
}

/* Viñeta cinematográfica: oscurecimiento radial de bordes para enfocar el
   centro y dar sensación de cine. pointer-events:none → no interfiere con
   nada. z-index 1 = sobre el video (z-index 0), debajo de stat/claim
   (z-index 5). El ellipse escala con el contenedor → proporcional en todo
   viewport sin media queries. */
.closing::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background:
        radial-gradient(ellipse at center,
            transparent 40%,
            rgba(0, 0, 0, 0.38) 78%,
            rgba(0, 0, 0, 0.72) 100%);
}

/* ---------- stat bottom-left (S/ 50M + caption) - mismo molde
   tipográfico que .hero__amount, escalado MÁS GRANDE porque es el
   foco visual de la sección. ---------------------------------------- */

.closing__stat {
    position: absolute;
    bottom: clamp(2rem, 5cqi, 5rem);
    left: clamp(1.5rem, 4cqi, 5rem);
    z-index: 5;
    text-align: left;
}

.closing__stat-prefix {
    font-family: var(--font-sans);
    font-weight: 800;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(1rem, 2.4cqi, 3rem);
    letter-spacing: 0.08em;
    line-height: 1;
    margin: 0 0 0.15em 0.05em;
    text-shadow: 0 2px 12px rgba(0, 0, 0, 0.7);
}

.closing__stat-amount {
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-red);
    font-size: clamp(4rem, 14cqi, 22rem);
    line-height: 0.9;
    letter-spacing: 0.01em;
    white-space: nowrap;
    text-shadow: 0 6px 30px rgba(0, 0, 0, 0.55);
    margin: 0;
}

.closing__stat-caption {
    margin-top: 0.6em;
    font-family: var(--font-sans);
    font-weight: 800;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.8rem, 1.4cqi, 1.8rem);
    letter-spacing: 0.06em;
    line-height: 1.3;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.7);
}

/* ---------- claim italic bottom-right (3 lines, right-aligned) ----- */

.closing__claim {
    position: absolute;
    bottom: clamp(2rem, 5cqi, 5rem);
    right: clamp(1.5rem, 4cqi, 5rem);
    z-index: 5;
    text-align: right;
    max-width: clamp(20rem, 38cqi, 40rem);
}

.closing__claim p {
    font-family: var(--font-italic);
    font-style: italic;
    font-weight: 400;
    color: var(--color-white);
    font-size: clamp(1rem, 1.9cqi, 2.4rem);
    line-height: 1.3;
    text-shadow: 0 2px 14px rgba(0, 0, 0, 0.7);
    margin: 0;
}

.closing__claim p + p {
    margin-top: 0.15em;
}

.closing__claim-emph {
    font-style: italic;
    font-weight: 700;
}

/* ---------- CLOSING - initial state gated por .js ------------------- */

html.js .closing__stat,
html.js .closing__claim p {
    opacity: 0;
    visibility: hidden;
}

/* ---------- CLOSING - portrait (sólo orientación)

   En portrait apilamos verticalmente: stat a la izquierda con más espacio
   abajo, claim debajo (también bottom-anchored pero más arriba que el
   stat). Como el bg tiene 3 personajes side-by-side a aspecto 16:9, en
   portrait se ven más recortados - object-position: center mantiene la
   figura central visible. */

@media (orientation: portrait) {
    .closing {
        min-height: 100svh;
    }

    .closing__bg {
        /* Mostrar más bg del lado central (los personajes están agrupados
           al medio). object-position: center evita perder a las personas
           cuando el aspect ratio del viewport es muy vertical. */
        object-position: center;
    }

    .closing__stat {
        bottom: clamp(11rem, 30svh, 22rem);          /* arriba del claim */
        left: clamp(1.25rem, 5cqi, 2.5rem);
    }

    .closing__stat-amount {
        font-size: clamp(3rem, 18cqi, 7rem);
    }

    .closing__stat-caption {
        font-size: clamp(0.7rem, 3cqi, 1.1rem);
    }

    .closing__claim {
        bottom: clamp(1.5rem, 4cqi, 3rem);
        left: clamp(1.25rem, 5cqi, 2.5rem);
        right: clamp(1.25rem, 5cqi, 2.5rem);
        text-align: left;
        max-width: none;
    }

    .closing__claim p {
        font-size: clamp(0.95rem, 3.6cqi, 1.5rem);
        line-height: 1.3;
    }
}

/* ==========================================================================
   RECOGNIZE - sección 09 - "Reconócela a tiempo" (lado solución)

   Primera sección con MOOD POSITIVO: cielo azul, personajes activos de JET
   inspeccionando una tubería. Estética opuesta a las dramáticas anteriores
   (sec 03-08). Personajes embebidos en el bg (no PNG separado).

   Composición desktop:
   - Tag, claim, title, checklist → columna izquierda
   - Quote italic → bottom-right
   - Bg full-cover con los inspectores

   Z-index map:
     0  recognize__bg     (bg con inspectores)
     5  textos (tag, claim, title, checklist, quote)

   Como no hay personajes sueltos, no hay overlap z-index. Layout 100%
   width-driven (cqi). ================================================*/

.recognize {
    position: relative;
    container-type: inline-size;
    min-height: 100svh;
    overflow: hidden;
    background: var(--color-ink);                    /* fallback antes que el bg cargue */
}
.recognize .cap {
    min-height: 100svh;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto auto 1fr auto;
    grid-template-areas:
        "tag        ."
        "claim      ."
        "title      ."
        "checklist  ."
        ".          quote";
    padding: clamp(5rem, 7cqi, 8rem)
             clamp(1.5rem, 4cqi, 4rem)
             clamp(2rem, 4cqi, 4rem);
    gap: clamp(0.5rem, 1.5cqi, 2rem);
}

.recognize__bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    z-index: 0;
    pointer-events: none;
    user-select: none;
}

/* ---------- tag (top-left, red line ABAJO del eyebrow) - patrón sec 06 */

.recognize__tag {
    grid-area: tag;
    z-index: 5;
    justify-self: start;
    text-align: left;
}

.recognize__tag-eyebrow {
    position: relative;
    font-family: var(--font-sans);
    font-weight: 800;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.8rem, 1.2cqi, 1.55rem);
    letter-spacing: 0.05em;
    line-height: 1.2;
    padding-bottom: 0.7em;
    display: inline-block;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
}

.recognize__tag-eyebrow::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    width: 4em;
    height: 2px;
    background: var(--color-red);
}

.recognize__tag-accent {
    color: var(--color-white);
}

.recognize__tag-sub {
    margin-top: 0.4em;
    font-family: var(--font-sans);
    font-weight: 600;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.65rem, 0.95cqi, 1.2rem);
    letter-spacing: 0.18em;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
}

/* ---------- claim italic (left, 3 lines) - "Hay una cara que sí..." ---*/

.recognize__claim {
    grid-area: claim;
    z-index: 5;
    justify-self: start;
    align-self: start;
    text-align: left;
    margin-top: clamp(1rem, 2cqi, 3rem);
    max-width: clamp(20rem, 45cqi, 38rem);
}

.recognize__claim p {
    font-family: var(--font-italic);
    font-style: italic;
    font-weight: 400;
    color: var(--color-white);
    font-size: clamp(1.3rem, 2.8cqi, 3.5rem);
    line-height: 1.2;
    text-shadow: 0 2px 14px rgba(0, 0, 0, 0.7);
}

.recognize__claim p + p {
    margin-top: 0.1em;
}

.recognize__claim-emph {
    font-style: italic;
    font-weight: 700;
}

/* ---------- big display title (left, 2 lines) - "RECONÓCELA / A TIEMPO." */

.recognize__title {
    grid-area: title;
    grid-column: 1 / -1;
    justify-self: start;
    align-self: end;
    z-index: 5;
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-white);
    line-height: 0.92;
    letter-spacing: 0.005em;
    font-size: clamp(3rem, 13cqi, 20rem);
    text-align: left;
    text-shadow: 0 6px 30px rgba(0, 0, 0, 0.6);
    margin-top: clamp(2rem, 5cqi, 6rem);
    margin-bottom: clamp(1.5rem, 4cqi, 4rem);
    padding-left: clamp(0rem, 0.5cqi, 0.5rem);
}

.recognize__title-line {
    display: block;
}

/* ---------- checklist (left, 5 items con ✓ rojo) -------------------- */

.recognize__checklist {
    grid-area: checklist;
    z-index: 5;
    justify-self: start;
    list-style: none;
    margin: 0;
    padding: 0;
    max-width: clamp(24rem, 50cqi, 50rem);
}

.recognize__check {
    position: relative;
    padding-left: 2em;
    margin-top: clamp(0.3rem, 0.6cqi, 0.6rem);
    font-family: var(--font-sans);
    font-weight: 700;
    color: var(--color-white);
    text-transform: uppercase;
    font-size: clamp(0.7rem, 1.05cqi, 1.3rem);
    letter-spacing: 0.08em;
    line-height: 1.3;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.65);
}

/* Checkmark ✓ rojo. Usamos unicode (no SVG/imagen) - el carácter U+2713
   en Afacad bold renderiza limpio, escala con font-size y mantiene
   accesibilidad (lectores de pantalla pueden ignorarlo via aria-hidden
   en JS si fuera necesario, pero generalmente lo leen como "check"). */
.recognize__check::before {
    content: "✓";
    position: absolute;
    left: 0;
    top: -0.05em;
    color: var(--color-red);
    font-weight: 900;
    font-size: 1.2em;
    line-height: 1;
}

/* Punto separador rojo entre las dos mitades de cada bullet. Mismo
   tratamiento que sec 06 (.face__dot). */
.recognize__dot {
    color: var(--color-red);
    margin: 0 0.15em;
    font-weight: 900;
}

/* ---------- quote italic (bottom-right) ---------------------------- */

.recognize__quote {
    grid-area: quote;
    z-index: 5;
    justify-self: end;
    align-self: end;
    margin: 0;
    text-align: right;
    max-width: clamp(18rem, 32cqi, 32rem);
}

.recognize__quote p {
    font-family: var(--font-italic);
    font-style: italic;
    font-weight: 400;
    color: var(--color-white);
    font-size: clamp(1rem, 1.5cqi, 1.9rem);
    line-height: 1.3;
    text-shadow: 0 2px 14px rgba(0, 0, 0, 0.7);
    margin: 0;
}

/* ---------- RECOGNIZE - initial state gated por .js ----------------- */

html.js .recognize__tag,
html.js .recognize__claim p,
html.js .recognize__title-line,
html.js .recognize__check,
html.js .recognize__quote {
    opacity: 0;
    visibility: hidden;
}

/* ---------- RECOGNIZE - portrait (sólo orientación)

   Composición vertical: tag → claim → title → checklist → quote, todo en
   columna izquierda con el bg detrás (object-position: center recortado
   para mostrar los inspectores).

   Como sec 04/05/06, usamos absolute para todos los textos cuando hay
   suficiente vertical room. Pero aquí mantenemos el flujo natural del
   grid colapsado a 1 columna - el contenido sólo necesita stackearse
   verticalmente sin overlap con un personaje absoluto. */

@media (orientation: portrait) {
    .recognize {
        min-height: 125svh;
    }
    /* El grid vive en .recognize .cap, no en .recognize: el colapso a 1 columna
       debe ir aquí para que los hijos (con grid-area:auto abajo) se apilen en
       vez de auto-colocarse en la grilla de 2 columnas del base. */
    .recognize .cap {
        grid-template-columns: 1fr;
        grid-template-rows: auto;
        grid-template-areas: none;
        padding: clamp(5rem, 14cqi, 7rem)
                 clamp(1.25rem, 5cqi, 2.5rem)
                 clamp(2rem, 5cqi, 4rem);
        gap: clamp(0.5rem, 1.5cqi, 1.5rem);
    }

    .recognize__bg {
        object-position: center;
    }

    /* Reset grid-area de cada elemento para que fluyan en orden DOM. */
    .recognize__tag,
    .recognize__claim,
    .recognize__title,
    .recognize__checklist,
    .recognize__quote {
        grid-area: auto;
        grid-column: auto;
        justify-self: start;
        align-self: auto;
    }

    .recognize__tag-eyebrow {
        font-size: clamp(0.8rem, 3cqi, 1.3rem);
    }

    .recognize__tag-sub {
        font-size: clamp(0.65rem, 2.4cqi, 1.05rem);
    }

    .recognize__claim {
        margin-top: clamp(1.5rem, 4cqi, 3rem);
        max-width: none;
    }

    .recognize__claim p {
        font-size: clamp(1.4rem, 5cqi, 2.3rem);
        line-height: 1.2;
    }

    .recognize__title {
        margin-top: clamp(0.5rem, 1.5cqi, 1rem);
        margin-bottom: clamp(1rem, 3cqi, 2rem);
        font-size: clamp(2.5rem, 12cqi, 6rem);
    }

    .recognize__checklist {
        max-width: none;
    }

    .recognize__check {
        font-size: clamp(0.75rem, 2.5cqi, 1.05rem);
        padding-bottom: clamp(0.4rem, 1.2cqi, 0.7rem);
        border-bottom: 1px solid rgba(244, 241, 236, 0.18);
    }

    .recognize__check:last-child {
        border-bottom: none;
    }

    /* Quote centered en mobile (el diseño muestra el quote al final con
       padding lateral igual al de la columna principal). */
    .recognize__quote {
        margin-top: clamp(1.5rem, 4cqi, 3rem);
        justify-self: center;
        text-align: center;
        max-width: clamp(18rem, 80cqi, 28rem);
    }

    .recognize__quote p {
        font-size: clamp(1rem, 3.5cqi, 1.5rem);
    }
}

/* ==========================================================================
   CTA - sección 10 - call-to-action final ("Registrarme al evento")

   Fondo rojo con TEXTURA GRAIN generada en CSS (sin imagen). Slider de 3
   placas en bottom-right que cycle automáticamente sin controles.

   El title gigante "RECONÓCELA / A TIEMPO." domina la composición. El
   slider queda DETRÁS del title (z-1 < z-2); el diseño muestra el title
   atravesando la zona del plate.

   Composición:
   - Bg rojo + grain overlay (full-cover)
   - Italic claim top-left
   - Title gigante middle-left (sobre el slider)
   - Body con lead/hint/button bottom-left
   - Slider auto-cycle bottom-right
   - Brand "jet. HAZLO BIEN." bottom-far-right

   Z-index map:
     0  bg + grain (vía background-image stack)
     1  cta__slider (placa + manos)
     2  cta__title (display gigante, encima del slider)
     5  textos secundarios (claim, body, brand) que no overlap-an con slider
   ========================================================================== */

.cta {
    position: relative;
    isolation: isolate;
    container-type: inline-size;
    min-height: 100svh;
    overflow: hidden;

    /* Fondo azul JET + grain via SVG fractalNoise como data URI. La opacidad
       baja (0.18) hace la textura sutil - no compite con la tipografía.
       baseFrequency 0.85 genera grano fino tipo "pintura sobre pared".
       numOctaves 2 da variación orgánica sin volverse ruido pesado. */
    background-color: var(--color-blue);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' seed='3'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.18 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
    background-size: 200px 200px;                    /* tile size del noise */
    background-repeat: repeat;
}
/* Contenido del CTA (claim/title/body) topado y centrado. El slider (rueda)
   y el brand-tag quedan FUERA del .cap → siguen full-bleed y crecen. */
.cta .cap {
    min-height: 100svh;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto 1fr auto;
    grid-template-areas:
        "claim    ."
        "title    title"
        "body     ."
        "body     .";
    /* Padding bottom mayor - la rueda emerge desde abajo y HAZLO BIEN.
       gigante necesita espacio. */
    padding: clamp(4rem, 6cqi, 6rem)
             clamp(1.5rem, 4cqi, 4rem)
             clamp(14rem, 22cqi, 22rem);
    gap: clamp(0.5rem, 1.5cqi, 2rem);
}

/* ---------- WHEEL slider - CÍRCULO bottom-center (ruleta brutalist) ----

   La rueda es un cuadrado con border-radius:50% (perfect circle), centrado
   horizontalmente y anclado al bottom de la sección con offset negativo -
   "emerge" del borde inferior como una luna en el horizonte. El overflow
   hidden del círculo recorta el contenido del wheel (que sigue siendo una
   columna de imágenes traducida con yPercent + motion blur).

   El círculo está en z-index:1 - la marca HAZLO BIEN. (z-5) y demás textos
   van por encima de la rueda, atravesándola visualmente. */

.cta__svg-filters {
    position: absolute;
    width: 0;
    height: 0;
    pointer-events: none;
    overflow: hidden;
}

.cta__slider {
    position: absolute;
    /* Centrado horizontal vía left:0 + right:0 + margin:0 auto.
       No usar translateX(-50%) - coexiste con cualquier transform que
       eventualmente se ponga al elemento. */
    left: 0;
    right: 0;
    margin-inline: auto;
    /* Bottom NEGATIVO - la rueda emerge desde abajo del viewport, sólo
       la parte superior queda visible. Sensación de planeta o ruleta
       horizontal vista de costado. clamp lo escala con cqi. */
    bottom: clamp(-30rem, -22cqi, -12rem);
    width: clamp(28rem, 60cqi, 80rem);
    height: clamp(28rem, 60cqi, 80rem);              /* cuadrado → círculo perfecto */
    border-radius: 50%;
    overflow: hidden;
    z-index: 1;
    pointer-events: none;
    background: rgba(0, 0, 0, 0.15);                 /* tinte sutil dentro del aro */
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1) inset;  /* aro interior tenue */
}

.cta__wheel {
    position: relative;                              /* containing block para slides absolute */
    width: 100%;
    height: 100%;
    transform-origin: center center;                 /* rotation pivot = centro del círculo */
    will-change: transform, filter;
    /* Filter url(#cta-vblur) se aplica vía JS sólo durante el giro. En
       reposo el wheel no tiene filtro (más rápido). */
}

/* Slides apilados en el MISMO lugar (absolute, inset:0). Sólo .--active
   queda visible (opacity 1); el resto autoAlpha 0. El crossfade ocurre
   durante el peak del blur, así el cambio de imagen es invisible -
   parece que la rueda giró y revela la siguiente "cara". */
.cta__slide {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    user-select: none;
    display: block;
    opacity: 0;
    visibility: hidden;
}

.cta__slide--active {
    opacity: 1;
    visibility: visible;
}

/* La lata vive con mucho padding transparente en su canvas y es un producto
   (no una escena full-bleed): contain para mostrarla entera + scale para que
   gane presencia dentro del aro. El transform es seguro: GSAP sólo escribe
   autoAlpha en los slides y rotation en el wheel padre. */
.cta__slide--can {
    object-fit: contain;
    transform: scale(1.15);
}

/* ---------- italic claim (top-left) --------------------------------- */

.cta__claim {
    grid-area: claim;
    z-index: 5;
    justify-self: start;
    align-self: start;
    margin: 0;
    font-family: var(--font-italic);
    font-style: italic;
    font-weight: 400;
    color: var(--color-white);
    /* Bumpeado vs sec 04/05 (2.3cqi) - brutalist quiere claim más grande. */
    font-size: clamp(1.3rem, 2.6cqi, 3rem);
    line-height: 1.2;
}

/* ---------- big display title (middle, full-width) ------------------

   El title de sec 10 es MÁS GRANDE que cualquier otro de la landing
   (es el remate del CTA). cqi cap a 22 (vs 18 en sec 04) para que
   "RECONÓCELA" domine el viewport. */

.cta__title {
    grid-area: title;
    grid-column: 1 / -1;
    justify-self: start;
    align-self: start;
    z-index: 2;
    margin: 0;
    padding: 0;
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-white);
    /* Brutalist: line-height TIGHT (0.85), letter-spacing 0, font cap
       a 30cqi (vs 22cqi anterior). El título DEBE dominar el viewport
       casi por completo - característica brutalist clave. */
    line-height: 0.85;
    letter-spacing: 0;
    /* Brutalist: la línea más larga debe LLENAR el viewport (dominarlo), no
       desbordarlo. Con Rubik Dirt (ancha) 30cqi se salía y cortaba; 14cqi/24rem
       mantiene el impacto llenando el ancho sin overflow horizontal. */
    font-size: clamp(3rem, 14cqi, 24rem);
    text-align: left;
    text-shadow: 0 6px 30px rgba(0, 0, 0, 0.25);
}

.cta__title-line {
    display: block;
}

/* ---------- body (lead + hint + button), bottom-left ---------------- */

.cta__body {
    grid-area: body;
    z-index: 5;
    justify-self: start;
    align-self: end;
    display: flex;
    flex-direction: column;
    gap: clamp(0.5rem, 1.2cqi, 1.5rem);
    max-width: clamp(20rem, 45cqi, 38rem);
    margin-top: clamp(1.5rem, 4cqi, 4rem);
}

.cta__lead {
    margin: 0;
    font-family: var(--font-italic);
    font-style: italic;
    font-weight: 400;
    color: var(--color-white);
    /* Bumpeado para coherencia brutalist con el resto. */
    font-size: clamp(1.2rem, 2.2cqi, 2.6rem);
    line-height: 1.3;
}

.cta__lead-emph {
    font-style: normal;                              /* "JET" en romano dentro del italic */
    font-weight: 700;
    font-family: var(--font-display);
    letter-spacing: 0.02em;
}

.cta__hint {
    margin: 0;
    font-family: var(--font-sans);
    font-weight: 700;
    color: var(--color-white);
    text-transform: uppercase;
    /* Bumpeado y con más letter-spacing (0.1em) - brutalist tracking. */
    font-size: clamp(0.8rem, 1.15cqi, 1.3rem);
    letter-spacing: 0.1em;
    line-height: 1.3;
}

/* Botón CTA: pill de ACCIÓN PRINCIPAL. Va en ROJO de marca sobre el azul
   navy - color complementario que da el máximo contraste y lo convierte en
   el punto focal de la sección. Pill rojo con halo neón (glow rojo difuso,
   sin borde ni bisel); en hover baja a un rojo más profundo. ---------- */

.cta__button {
    align-self: flex-start;
    display: inline-flex;
    align-items: center;
    gap: 1em;
    margin-top: 0.5em;
    /* Botón MÁS GRANDE para brutalist - padding generoso, font mayor. */
    padding: 1.1em 2em;
    background: var(--color-red);
    color: var(--color-white);
    font-family: var(--font-sans);
    font-weight: 800;
    font-size: clamp(1rem, 1.3cqi, 1.5rem);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    text-decoration: none;
    /* El label (+ flecha) siempre en una sola línea → pill más ancho, nunca
       se parte en dos renglones en móvil. */
    white-space: nowrap;
    /* Sin el borde por defecto del <button> (2px outset): ese estilo
       biselado daba un acabado "metálico" en los cantos. Pill 100% plano. */
    border: none;
    border-radius: 999px;
    box-shadow: 0 10px 30px rgba(216, 22, 43, 0.45);
    transition: transform 200ms ease, background-color 200ms ease,
                box-shadow 200ms ease;
}

.cta__button:hover,
.cta__button:focus-visible {
    background: var(--color-red-dark);
    color: var(--color-white);
    transform: translateY(-2px);
    box-shadow: 0 14px 38px rgba(216, 22, 43, 0.55);
    outline: none;
}

.cta__button:focus-visible {
    outline: 2px solid var(--color-white);
    outline-offset: 3px;
}

.cta__button-arrow {
    display: inline-block;
    font-weight: 400;
    transition: transform 200ms ease;
}

.cta__button:hover .cta__button-arrow {
    transform: translateX(4px);
}

/* ---------- HAZLO BIEN. - tagline brutalist sobre el slider ----------

   Se eliminó el "jet." brand-mark - sólo queda HAZLO BIEN. como tagline
   gigante. Posicionado absolute al bottom de la sección, full-width
   center-aligned, z-index 5 para quedar SOBRE el círculo de la rueda
   (z-1). Las letras del tagline "perforan" visualmente la rueda - la
   rueda se ve a través de los espacios entre letras. */

.cta__brand-tag {
    position: absolute;
    bottom: clamp(1.5rem, 3.5cqi, 4rem);
    left: 0;
    right: 0;
    margin: 0;
    z-index: 5;
    pointer-events: none;                            /* no interfiere con clicks al botón */
    text-align: center;
    /* Helvetica explícita (no via --font-sans porque ese tiene Afacad
       primero). Contraste deliberado contra el title display distressed:
       el remate del CTA usa una sans modernista limpia, no la display
       texturada. */
    font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
    font-weight: 900;
    color: var(--color-white);
    text-transform: uppercase;
    /* font-size más bajo que cuando usaba Thunderhouse (16cqi) porque
       Helvetica es ~50% más ancha por glifo - al mismo cqi, "HAZLO BIEN."
       en Helvetica desborda el viewport horizontal. 11cqi mantiene el
       impacto brutalist sin overflow. */
    font-size: clamp(2.5rem, 11cqi, 18rem);
    line-height: 0.9;
    letter-spacing: -0.02em;                         /* tracking apretado, sensación brutalist */
    text-shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
}

/* ---------- CTA - initial state gated por .js ----------------------- */

html.js .cta__claim,
html.js .cta__title-line,
html.js .cta__body,
html.js .cta__brand-tag {
    opacity: 0;
    visibility: hidden;
}

/* ---------- CTA - portrait (sólo orientación) ----------------------- */

@media (orientation: portrait) {
    .cta {
        /* En móvil la sección se ajusta al contenido (no 110svh): con poco
           contenido era demasiado alta. La rueda + "HAZLO BIEN" siguen
           asomando abajo gracias al padding-bottom reservado en .cta .cap. */
        min-height: auto;
    }
    /* El grid vive en .cta .cap, no en .cta: el colapso a 1 columna debe ir
       aquí, si no el contenido se queda en la mitad izquierda de la grilla de
       2 columnas del base (título desbordado, botón apretado).
       min-height:auto + align-content:start empacan el contenido arriba (sin
       filas estiradas que dejaban el vacío central). El padding-bottom grande
       reserva el espacio de la rueda/brand-tag anclados al fondo. */
    .cta .cap {
        min-height: auto;
        grid-template-columns: 1fr;
        grid-template-rows: auto;
        grid-template-areas: none;
        align-content: start;
        padding: clamp(4rem, 12cqi, 6rem)
                 clamp(1.25rem, 5cqi, 2.5rem)
                 clamp(11rem, 34cqi, 15rem);
        gap: clamp(1rem, 3cqi, 2rem);
    }

    .cta__claim,
    .cta__title,
    .cta__body {
        grid-area: auto;
        grid-column: auto;
        justify-self: start;
        align-self: auto;
    }

    .cta__claim {
        font-size: clamp(1.1rem, 4cqi, 1.6rem);
    }

    .cta__title {
        /* Brutalist en portrait: title sigue dominando aunque haya menos
           ancho disponible. */
        font-size: clamp(2.6rem, 13cqi, 7rem);
        margin-top: clamp(0.3rem, 0.8cqi, 1rem);
        line-height: 0.85;
    }

    /* En portrait el slider sigue siendo un círculo emergiendo desde
       abajo - mantiene la metáfora de "rueda fijada en el bottom" en
       todos los breakpoints. Más chico para no comerse el body. */
    .cta__slider {
        bottom: clamp(-20rem, -30cqi, -8rem);
        width: clamp(20rem, 90cqi, 40rem);
        height: clamp(20rem, 90cqi, 40rem);
    }

    .cta__body {
        max-width: none;
        align-self: stretch;
        margin-top: 0;
    }

    .cta__lead {
        font-size: clamp(1rem, 3.4cqi, 1.5rem);
    }

    .cta__hint {
        font-size: clamp(0.65rem, 2.4cqi, 0.95rem);
    }

    .cta__button {
        align-self: flex-start;
        font-size: clamp(0.85rem, 2.8cqi, 1.05rem);
    }

    /* HAZLO BIEN. en portrait - sigue siendo grande pero adaptado al
       ancho disponible. Bajado vs Thunderhouse anterior (14cqi) porque
       Helvetica es más ancha. */
    .cta__brand-tag {
        font-size: clamp(2rem, 10cqi, 4rem);
    }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
    }
}

/* ==========================================================================
   LENIS - clases que la lib añade al html cuando está activa.

   Estas reglas son las que Lenis recomienda incluir manualmente cuando
   se usa sin import del CSS bundleado. Sin esto el scroll nativo del
   navegador y el suavizado de Lenis pueden pelearse (ej. en anchors).
   ========================================================================== */

html.lenis,
html.lenis body {
    height: auto;
}

.lenis.lenis-smooth {
    scroll-behavior: auto !important;
}

.lenis.lenis-smooth [data-lenis-prevent] {
    overscroll-behavior: contain;
}

.lenis.lenis-stopped {
    overflow: hidden;
}

.lenis.lenis-smooth iframe {
    pointer-events: none;
}

/* ==========================================================================
   v2 OVERRIDES - capa final (mayor prioridad por orden de fuente)

   Aquí vive todo lo que ajusta el comportamiento heredado de styles.css
   sin reescribir las secciones: posicionamiento de las bandas de tarjetas,
   paneles glass sobre el copy de lectura, y el re-gate de estado inicial
   para que GSAP revele las tarjetas. Borrar este bloque devuelve la
   composición original (salvo el markup de tarjetas).
   ========================================================================== */

/* ---------- Re-gate de estado inicial para reveal GSAP de tarjetas ------ */
/* Sólo las 4 secciones narrativas: ocultamos las tarjetas de señales para
   que GSAP las revele (script-v2). El placement/glass lo maneja .story-lay.
   Las secciones 8/9/10 quedan como el original (sin paneles añadidos). */
html.js .moment__signals .signal-card,
html.js .advance__signals .signal-card,
html.js .holes__signals .signal-card,
html.js .face__signals .signal-card {
    opacity: 0;
    visibility: hidden;
}

/* ==========================================================================
   ARQUETIPOS DE DIAGRAMACIÓN - secciones de storytelling (3–6)

   Cada sección lleva una diagramación DISTINTA (decisión del cliente tras
   comparar en lab-secciones.html), para aprobarlas una a una:
     · moment  → .story-lay--f  (Split + banda de señales al pie)
     · advance → .story-lay--d  (Tarjeta + personaje asomando)
     · holes   → .story-lay--c  (Banda inferior)
     · face    → .story-lay--a  (Tarjeta central)

   .story-lay = base compartida (placa dossier, reset, título medio, etc.).
   Los modificadores sólo cambian la COLOCACIÓN (dossier/personaje/señales).
   Hooks de GSAP y fondos intactos: se conservan las clases .SECTION__*.
   El copy va envuelto en <div class="story-dossier glass">; las señales van
   dentro del dossier (A/C/D) o como banda hermana (F).
   ========================================================================== */

/* Wrapper genérico de tope de contenido: cualquier sección lo usa para topar
   su foreground a --content-max y centrarlo, dejando el/los background(s)
   full-bleed como hijos directos de la sección. Es contexto de container-query
   para que los cqi del contenido dejen de crecer. El grid/padding concreto lo
   añade cada sección con `.seccion .cap`. */
.cap {
    position: relative;
    width: 100%;
    max-width: var(--content-max);
    margin-inline: auto;
    container-type: inline-size;
}

/* ---------------- BASE compartida ---------------- */
.story-lay {
    /* La sección es sólo el lienzo full-bleed (bg/veil/tubo). El layout, el
       padding y el tope de ancho del contenido viven en .story-lay__inner.
       padding:0 anula el padding de la base per-sección (.moment/.advance/…)
       para que no se duplique con el del inner. */
    display: block !important;
    min-height: 100svh !important;
    padding: 0 !important;
}

/* Wrapper interno: TOPA el foreground a --content-max y lo centra; es el nuevo
   contexto de container-query, así los cqi del contenido dejan de crecer en
   pantallas grandes. Los backgrounds (hijos directos de la sección) siguen
   full-bleed. El personaje (position:absolute) se ancla a este wrapper. */
.story-lay__inner {
    position: relative;
    width: 100%;
    max-width: var(--content-max);
    margin-inline: auto;
    min-height: 100svh;
    container-type: inline-size;
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: auto;
    place-items: center;
    align-content: center;
    padding: clamp(5rem, 7cqi, 7rem) clamp(1.5rem, 4cqi, 4rem) clamp(2.5rem, 4cqi, 4rem);
}

/* dossier: placa glass sólida y pareja (lectura legible sobre cualquier foto). */
.story-lay .story-dossier {
    z-index: 5;
    display: flex;
    flex-direction: column;
    gap: clamp(0.8rem, 1.6cqi, 1.5rem);
    /* Más padding vertical: el texto respira mejor arriba/abajo. */
    padding: clamp(2.4rem, 3.8cqi, 3.6rem) clamp(1.4rem, 2.6cqi, 2.4rem);
    /* Placa FROSTED translúcida: se ve la foto desenfocada detrás (blur
       fuerte + saturación sostienen la lectura). Como el dossier ya NO se
       solapa con el personaje (desktop lado-a-lado, móvil apilado), la
       translucidez no compromete la legibilidad. */
    /* Fondo negro más editorial (más oscuro que --glass-bg-strong) pero
       manteniendo el vidrio translúcido/frosted: se intuye la foto detrás. */
    background: linear-gradient(150deg, rgba(14, 14, 17, 0.74), rgba(7, 7, 10, 0.62));
    -webkit-backdrop-filter: var(--glass-blur-strong);
    backdrop-filter: var(--glass-blur-strong);
    /* Sin bordes: look editorial limpio; solo la sombra ambiental da
       profundidad (se quita también el highlight inset que se leía como
       borde superior). */
    border: none;
    /* Esquinas casi rectas (~2px): look de revista, menos "redondo". */
    border-radius: 2px;
    box-shadow: 0 26px 52px -20px rgba(0, 0, 0, 0.55);
}

/* Estado inicial gated por .js: el panel arranca invisible para que GSAP lo
   haga fade-in junto con su contenido. Sin esto, la placa negra aparecería
   de golpe como un bloque sin animar sobre la foto (secciones 03-06). */
html.js .story-lay .story-dossier {
    opacity: 0;
    visibility: hidden;
}

/* Sin la línea roja izquierda (pseudo global .glass::before) en estos paneles. */
.story-lay .story-dossier::before { content: none; }

/* neutraliza el posicionamiento heredado de los hijos (NO toca transform:
   lo usa GSAP para los reveals). */
.story-lay .story-dossier > * {
    position: static;
    inset: auto;
    margin: 0;
    max-width: none;
    width: auto;
    justify-self: auto;
    align-self: auto;
    grid-area: auto;
    text-align: left;
}

/* señales dentro del dossier: ocupan el ancho de la placa (auto-fit decide
   columnas: 2 en tarjeta angosta, 4 en banda ancha). */
.story-lay .story-dossier .signal-cards { width: 100%; }

/* Marcador de etapa (kicker de capítulo) - conecta cada sección con su etapa
   de la sec 02. Minimal, sin caja: número en rojo + nombre claro, con una fina
   línea divisoria editorial debajo. */
.story-lay .story-stage {
    margin: 0 0 clamp(0.7rem, 1.3cqi, 1.1rem);
    padding-bottom: clamp(0.5rem, 1cqi, 0.85rem);
    border-bottom: 1px solid rgba(244, 241, 236, 0.14);
    font: 600 clamp(0.62rem, 0.9cqi, 0.95rem)/1.3 var(--font-sans);
    text-transform: uppercase;
    letter-spacing: 0.16em;
    text-align: right;
    color: rgba(244, 241, 236, 0.72);
}
/* Número y nombre del mismo color (blanco grisáceo), separados por un espacio
   (sin punto). */
.story-lay .story-stage__name { margin-left: 0.6em; }

/* Gate: el marcador entra en la cascada GSAP como el resto (oculto hasta el
   scroll); si no, aparecía de golpe antes de tiempo. */
html.js .story-lay .story-stage {
    opacity: 0;
    visibility: hidden;
}

/* Tarjetas de señales en estas secciones: acompañan el look editorial del
   panel - esquinas casi rectas y fondo un poco más oscuro. Scoped a
   .story-lay para no tocar la utilidad global .signal-card. */
.story-lay .signal-card {
    border-radius: 2px;
    border: none;
    box-shadow: none;
    background: linear-gradient(150deg, rgba(18, 18, 22, 0.6), rgba(10, 10, 13, 0.48));
}

/* título DES-BRUTALIZADO (escala de encabezado). */
.story-lay .moment__title,
.story-lay .advance__title,
.story-lay .holes__title,
.story-lay .face__title {
    font-size: clamp(3.2rem, 8.5cqi, 8rem) !important;
    line-height: 0.95;
    letter-spacing: 0.01em;
    text-align: left;
    margin: 0 !important;
    padding: 0 !important;
    text-shadow: 0 4px 18px rgba(0, 0, 0, 0.45);
}

/* quote de moment como lead italic (sin leader-line). */
.story-lay .moment__quote {
    font-family: var(--font-italic);
    font-style: italic;
    font-size: clamp(0.95rem, 1.5cqi, 1.3rem);
    color: rgba(244, 241, 236, 0.85);
    line-height: 1.3;
}
.story-lay .moment__quote::before,
.story-lay .moment__quote::after { display: none !important; }

/* personaje: base común (posición la define cada modificador). */
.story-lay .moment__character,
.story-lay .advance__character,
.story-lay .holes__character,
.story-lay .face__character {
    position: absolute;
    bottom: 0;
    margin: 0;
    width: auto;
    z-index: 4;
}

/* ================= F · moment - Split + banda ================= */
.story-lay--f .story-lay__inner {
    grid-template-columns: 1.15fr 1fr !important;
    grid-template-rows: 1fr auto auto !important;
    place-items: stretch;
    align-items: center;
    column-gap: clamp(1rem, 3cqi, 3rem);
}
.story-lay--f .story-dossier {
    grid-column: 1;
    grid-row: 1;
    justify-self: start;
    align-self: center;
    max-width: min(38rem, 100%);
}
.story-lay--f .moment__character {
    right: clamp(-7rem, -3cqi, -1rem);
    left: auto;
    height: 86svh;
}
.story-lay--f .moment__signals-heading {
    grid-column: 1 / -1 !important;
    grid-row: 2 !important;
    align-self: end;
    justify-self: stretch;
    width: 100%;
    z-index: 6;
    text-align: left;
    margin: 0 0 clamp(0.5rem, 1cqi, 1.2rem) 0;
}
.story-lay--f .moment__signals {
    grid-column: 1 / -1 !important;
    grid-row: 3 !important;
    align-self: end;
    justify-self: stretch;
    width: 100%;
    z-index: 6;
}
.story-lay--f .moment__veil {
    background: linear-gradient(90deg, rgba(8,8,10,.55) 0%, rgba(8,8,10,.3) 48%, rgba(8,8,10,.42) 100%);
}
.story-lay--f .moment__tubo { opacity: 0.35; }

/* ================= D · advance - Tarjeta + personaje asomando ================= */
.story-lay--d .story-dossier {
    justify-self: start;
    align-self: center;
    margin-left: clamp(1rem, 6cqi, 7rem);
    max-width: min(36rem, 86%);
}
.story-lay--d .advance__character {
    right: clamp(-9rem, -5cqi, -2rem);
    left: auto;
    height: 94svh;
}
.story-lay--d .advance__veil {
    background: linear-gradient(90deg, rgba(8,8,10,.68) 0%, rgba(8,8,10,.42) 55%, rgba(8,8,10,.2) 100%);
}

/* ============= C · holes - Split (personaje IZQUIERDA, lectura DERECHA) =====
   Antes "banda inferior" pero tapaba a la operaria; el cliente pidió
   lado-a-lado SIN solape. Operaria en su columna izquierda; dossier (con
   señales dentro) a la derecha. */
.story-lay--c .story-lay__inner {
    grid-template-columns: 1fr 1.1fr !important;
    grid-template-rows: 1fr !important;
    column-gap: clamp(1rem, 3cqi, 3rem);
    place-items: center;
    align-content: center;
}
.story-lay--c .story-dossier {
    grid-column: 2;
    justify-self: end;
    align-self: center;
    max-width: min(38rem, 100%);
}
.story-lay--c .holes__character {
    left: clamp(-7rem, -3cqi, -1rem);
    right: auto;
    top: auto;
    bottom: 0;
    margin-inline: 0;
    height: 86svh;
}
.story-lay--c .holes__veil {
    background: linear-gradient(270deg, rgba(8,8,10,.58) 0%, rgba(8,8,10,.34) 46%, rgba(8,8,10,.12) 100%);
}

/* ============= A · face - Split (personaje DERECHA, lectura IZQUIERDA) =======
   Antes "tarjeta central" sobre el personaje atenuado; ahora lado-a-lado SIN
   solape, con el ejecutivo visible a la derecha. */
.story-lay--a .story-lay__inner {
    grid-template-columns: 1.1fr 1fr !important;
    grid-template-rows: 1fr !important;
    column-gap: clamp(1rem, 3cqi, 3rem);
    place-items: center;
    align-content: center;
}
.story-lay--a .story-dossier {
    grid-column: 1;
    justify-self: start;
    align-self: center;
    max-width: min(38rem, 100%);
}
.story-lay--a .face__character {
    right: clamp(-7rem, -3cqi, -1rem);
    left: auto;
    top: auto;
    bottom: 0;
    margin-inline: 0;
    height: 86svh;
    opacity: 1;
    z-index: 4;
}
.story-lay--a .face__veil {
    background: linear-gradient(90deg, rgba(8,8,10,.58) 0%, rgba(8,8,10,.34) 46%, rgba(8,8,10,.12) 100%);
}

/* ==========================================================================
   PORTRAIT - APILADO: personaje arriba (en flujo, como banda), dossier
   debajo. Nada se solapa; la sección crece con el contenido.
   ========================================================================== */
@media (orientation: portrait) {
    .story-lay__inner {
        display: flex !important;
        flex-direction: column !important;
        align-items: center;
        justify-content: flex-start;
        min-height: 100svh !important;
        height: auto !important;
        padding: clamp(5rem, 17vw, 7rem) clamp(1.25rem, 5vw, 2.5rem) clamp(2.5rem, 8vw, 4rem) !important;
        gap: clamp(1.4rem, 5vw, 2.6rem);
        row-gap: clamp(1.4rem, 5vw, 2.6rem);
    }
    /* Personaje: imagen en flujo arriba (no absolute, sin atenuar). */
    .story-lay .moment__character,
    .story-lay .advance__character,
    .story-lay .holes__character,
    .story-lay .face__character {
        position: relative !important;
        order: -1;
        left: auto !important;
        right: auto !important;
        top: auto !important;
        bottom: auto !important;
        /* margin-bottom negativo (svh, aspect-independent): supera el row-gap
           del flex y deja que el card (z-5, frosted) se monte sobre el filo
           inferior del personaje. Los PNG tienen 0% de padding transparente
           abajo → el recorte cae justo en el borde, así que este solape lo
           oculta. El personaje "emerge" del card. */
        margin: 0 auto -7svh !important;
        width: auto !important;
        height: auto !important;
        max-height: 42svh;
        max-width: 100%;
        opacity: 1 !important;
        z-index: 1;
    }
    /* Dossier debajo, ancho de columna; deshacer grids internos. */
    .story-lay .story-dossier {
        position: relative;
        grid-column: auto !important;
        width: 100%;
        max-width: min(34rem, 94%);
        margin: 0 auto !important;
        text-align: left !important;
        display: flex !important;
        flex-direction: column !important;
        grid-template-columns: none !important;
        grid-template-areas: none !important;
    }
    .story-lay--c .holes__title { font-size: clamp(1.9rem, 7vw, 3rem) !important; }
    /* La 06 en portrait: 3 líneas largas en placa angosta con Rubik Dirt. */
    .story-lay--a .face__title { font-size: clamp(1.5rem, 5.2vw, 2.4rem) !important; }
    /* Heading + señales de moment (hermanas del dossier) en FLUJO debajo del
       card. Anulan el position:absolute/bottom heredado del bloque per-section
       (líneas 1757/1767) que las dejaba flotando y montadas. Stack resultante:
       personaje(-1) → card(0) → heading → señales. */
    .story-lay--f .moment__signals-heading {
        position: static !important;
        inset: auto !important;
        order: 1;
        width: 100%;
        max-width: min(34rem, 94%);
        margin: 0 auto clamp(0.4rem, 2vw, 0.9rem);
        text-align: left;
    }
    .story-lay--f .moment__signals {
        position: static !important;
        inset: auto !important;
        order: 2;
        width: 100%;
        max-width: min(34rem, 94%);
        margin: 0 auto;
        grid-template-columns: 1fr !important;   /* 3 señales apiladas (como 04/05/06) */
    }
    .story-lay--f .moment__tubo { display: none; }
    /* Velos tenues (el personaje ya no está detrás del texto). */
    .story-lay .moment__veil,
    .story-lay .advance__veil,
    .story-lay .holes__veil,
    .story-lay .face__veil {
        background: rgba(8, 8, 10, 0.42) !important;
    }
}

/* ---------- SIGNALS HEADING ---------- */
/* Etiqueta de bloque que precede a cada <ul class="signal-cards …">.
   No es un título display - es una intro corta tipo eyebrow que ata
   las 3-4 cards bajo un mismo paraguas semántico. */
.signals-heading {
    font-family: var(--font-sans);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.18em;
    color: var(--color-white);
    font-size: clamp(0.7rem, 1cqi, 1.2rem);
    line-height: 1.2;
    margin: 0 0 clamp(0.6rem, 1.2cqi, 1.4rem) 0;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.6);
    opacity: 0.85;
}

/* Dentro del story-dossier las signal-cards viven en grid-column 2 -
   el heading lo acompaña en la misma columna para alinearse arriba. */
.story-dossier .signals-heading {
    grid-column: 2;
    justify-self: end;
    text-align: right;
}

/* En sec 03 (.moment) las signal-cards viven DIRECTO en la section.
   El posicionamiento real del heading lo controla la regla
   `.story-lay--f .moment__signals-heading` que vive con el resto del
   diagramado de sec 03 - la ancla a la fila justo encima del banner
   de signal cards. Acá sólo arrastramos el reset visual genérico. */

/* ---------- SOURCES ---------- */
/* Pie legal - off-white tenue sobre negro, tamaño mínimo legible.
   Lista con hanging indent; sirve sólo como referencia citable y no
   debe competir con el CTA. .cite estiliza los <sup> inline del body. */
.sources {
    position: relative;
    background: var(--color-ink);
    color: rgba(244, 241, 236, 0.55);
    padding: clamp(2rem, 4vw, 4rem) clamp(1.25rem, 5vw, 5rem);
    font-family: var(--font-sans);
    font-size: clamp(0.62rem, 0.78vw, 0.78rem);
    line-height: 1.55;
    letter-spacing: 0.02em;
}

.sources__title {
    font-family: var(--font-sans);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.18em;
    font-size: clamp(0.7rem, 0.85vw, 0.85rem);
    color: rgba(244, 241, 236, 0.7);
    margin: 0 0 1.2em 0;
}

.sources__list {
    list-style: none;
    padding: 0;
    margin: 0 0 1.5em 0;
    display: grid;
    gap: 0.6em;
    max-width: 100ch;
}

.sources__list li {
    padding-left: 2.4em;
    text-indent: -2.4em;
    /* Cortar tokens largos (URLs/DOIs) para que no rompan el ancho en móvil. */
    overflow-wrap: anywhere;
}

.sources__marker {
    display: inline-block;
    width: 2em;
    color: rgba(244, 241, 236, 0.75);
    font-variant-numeric: tabular-nums;
}

.sources__note {
    margin: 0;
    color: rgba(244, 241, 236, 0.4);
    font-style: italic;
}

/* Marcadores inline en el cuerpo - pequeños y discretos. Heredan el color
   del texto que los rodea (negro sobre títulos blancos, rojo sobre rojo). */
.cite {
    font-size: 0.55em;
    vertical-align: super;
    margin-left: 0.15em;
    color: currentColor;
    opacity: 0.75;
    font-weight: 500;
    letter-spacing: 0.02em;
}

@media (max-width: 767px) {
    .sources {
        padding: 2rem 1.25rem;
        font-size: 0.7rem;
    }
    .sources__list li {
        padding-left: 2em;
        text-indent: -2em;
    }
}

/* ==========================================================================
   V3 - REFINAMIENTO TIPOGRÁFICO sec 3/4/5 (.moment / .advance / .holes)
   --------------------------------------------------------------------------
   Sólo reduce el tamaño del texto y compacta el dossier para que cada sección
   entre completa en pantalla. NO toca imágenes (__bg / __veil / __tubo /
   __character) ni la sección 06 (.face) - el escopado es explícito a las tres
   secciones narrativas. Mantiene el eje único del sistema activo (cqi, válido
   en landscape y portrait porque las secciones son container-type: inline-size).
   Gana por especificidad ≥ y orden de fuente (último bloque del archivo).
   Borrar este bloque revierte EXACTAMENTE a la escala v2.

   Jerarquía/masa preservada:  título > cifra focal > claim > tag/quote > señales
   ========================================================================== */

/* --- Dossier compacto (placa glass): menos aire interno --- */
.moment .story-dossier,
.advance .story-dossier,
.holes .story-dossier {
    gap: clamp(0.55rem, 1.1cqi, 1rem);
    /* Más padding vertical (como la 06); horizontal se mantiene compacto. */
    padding: clamp(2.4rem, 3.8cqi, 3.6rem) clamp(1.1rem, 2cqi, 1.8rem);
}

/* --- Título display grande (look editorial). Lleva !important porque la
   regla activa (.story-lay .X__title) lo usa. La 03 (moment) va un punto
   menor que 04/05 porque su texto es largo y a 8rem desbordaría. --- */
.story-lay--f .moment__title {
    font-size: clamp(2.2rem, 4.8cqi, 4.4rem) !important;
}
.story-lay--d .advance__title,
.story-lay--c .holes__title {
    font-size: clamp(2.6rem, 6.6cqi, 6rem) !important;
}
/* La 06 (.face) NO estaba en el bloque de refinamiento (usaba la base
   8.5cqi/8rem) y con Rubik Dirt su título de 3 líneas largas envolvía a 6-8
   líneas, inflando la placa negra y alargando la sección en pantallas grandes.
   Se le da su propia escala, más chica que 04/05 por tener líneas más largas. */
.story-lay--a .face__title {
    font-size: clamp(1.6rem, 3.6cqi, 3rem) !important;
}

/* --- Claim italic: 3rem → 1.95rem --- */
.moment__claim p,
.advance__claim p,
.holes__claim p {
    font-size: clamp(1rem, 1.75cqi, 1.95rem);
    line-height: 1.3;
}

/* --- Cifra focal (S/ 8M, S/ 25M): 16rem → 7.5rem. Sigue siendo el elemento
       más grande del dossier, pero deja de empujar la sección fuera del fold. */
.advance__cost-amount,
.holes__cost-amount {
    font-size: clamp(2rem, 5cqi, 6rem);
}
.advance__cost-caption,
.holes__cost-caption {
    font-size: clamp(0.62rem, 0.95cqi, 1.05rem);
}

/* --- Tag (eyebrow + sub): meta-categoría, escala discreta --- */
.moment__tag-eyebrow,
.advance__tag-eyebrow,
.holes__tag-eyebrow {
    font-size: clamp(0.72rem, 1cqi, 1.2rem);
}
.moment__tag-sub,
.advance__tag-sub,
.holes__tag-sub {
    font-size: clamp(0.62rem, 0.85cqi, 1rem);
}

/* --- Quote / claim italic de moment (lead) --- */
.story-lay--f .moment__quote {
    font-size: clamp(0.82rem, 1.2cqi, 1.05rem);
}

/* --- Señales (heading + cards) sólo en estas 3 secciones --- */
.moment .signals-heading,
.advance .signals-heading,
.holes .signals-heading {
    font-size: clamp(0.62rem, 0.9cqi, 1rem);
    margin-bottom: clamp(0.45rem, 0.9cqi, 1rem);
}
.moment .signal-cards,
.advance .signal-cards,
.holes .signal-cards {
    gap: clamp(0.4rem, 0.85cqi, 0.85rem);
}
.moment .signal-card,
.advance .signal-card,
.holes .signal-card {
    padding: clamp(0.55rem, 1.05cqi, 1rem) clamp(0.65rem, 1.2cqi, 1.15rem);
}
.moment .signal-card__icon,
.advance .signal-card__icon,
.holes .signal-card__icon {
    width: clamp(1.35rem, 2.2cqi, 2rem);
    height: clamp(1.35rem, 2.2cqi, 2rem);
}
.moment .signal-card__term,
.advance .signal-card__term,
.holes .signal-card__term {
    font-size: clamp(0.7rem, 0.95cqi, 1rem);
}
.moment .signal-card__desc,
.advance .signal-card__desc,
.holes .signal-card__desc {
    font-size: clamp(0.64rem, 0.82cqi, 0.9rem);
}

/* ==========================================================================
   MODAL DE DIAGNÓSTICO (sección 10 · CTA)
   <dialog> nativo que abre el botón "Solicita tu diagnóstico". Panel oscuro
   azulado on-brand; el form es un Contact Form 7 (.diag-form__*). El JS de
   apertura/cierre vive en assets/js/script-v2.js.
   ========================================================================== */
html.diag-open { overflow: hidden; }   /* lock del fondo (además del stop de Lenis) */

.diag-modal {
    /* reset del <dialog>: sin borde/fondo del UA. Centrado explícito (fixed +
       inset:0 + margin:auto) para no depender de las reglas del UA, que en
       algunos motores no centran cuando se redefine el width. */
    position: fixed;
    inset: 0;
    margin: auto;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--color-white);
    width: min(94vw, 34rem);
    height: fit-content;
    max-height: 92svh;
    overflow: visible;
}
.diag-modal::backdrop {
    background: rgba(6, 8, 14, 0.74);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
}

.diag-modal__panel {
    position: relative;
    max-height: 92svh;
    overflow-y: auto;
    padding: clamp(1.5rem, 5vw, 2.6rem);
    background: #101019;
    background-image: linear-gradient(155deg, rgba(32, 60, 115, 0.35), rgba(16, 16, 25, 0.2));
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 4px;
    box-shadow: 0 40px 80px -30px rgba(0, 0, 0, 0.8);
}

.diag-modal__close {
    position: absolute;
    top: clamp(0.6rem, 2vw, 1rem);
    right: clamp(0.6rem, 2vw, 1rem);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.4rem;
    height: 2.4rem;
    padding: 0;
    color: var(--color-white);
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 999px;
    cursor: pointer;
    transition: background-color 160ms ease, transform 160ms ease;
}
.diag-modal__close svg { width: 1.15rem; height: 1.15rem; }
.diag-modal__close:hover { background: rgba(255, 255, 255, 0.14); }
.diag-modal__close:focus-visible {
    outline: 2px solid var(--color-blue-accent);
    outline-offset: 2px;
}

.diag-modal__title {
    font-family: var(--font-sans);
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    font-size: clamp(1.3rem, 4.5vw, 1.9rem);
    line-height: 1.1;
    margin: 0 2.6rem 1.4rem 0;   /* deja aire a la derecha para la X */
    color: var(--color-white);
}
.diag-modal__title::after {
    content: "";
    display: block;
    width: 3rem;
    height: 3px;
    margin-top: 0.7rem;
    background: var(--color-blue-accent);
}

/* ---------- Contact Form 7 dentro del modal ---------- */
.diag-form__form { margin: 0; }
.diag-form__field { margin-bottom: clamp(0.7rem, 2vw, 1rem); }
.diag-form__row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(0.6rem, 2vw, 1rem);
}
.diag-form__label {
    display: block;
    margin-bottom: 0.35rem;
    font-family: var(--font-sans);
    font-weight: 700;
    font-size: 0.82rem;
    letter-spacing: 0.02em;
    color: rgba(244, 241, 236, 0.82);
}
.diag-form__optional {
    font-weight: 400;
    color: rgba(244, 241, 236, 0.5);
    text-transform: none;
    letter-spacing: 0;
}
.diag-form__input,
.diag-form textarea,
.diag-form input {
    width: 100%;
    padding: 0.7rem 0.85rem;
    font-family: var(--font-sans);
    font-size: 0.95rem;
    color: var(--color-white);
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 3px;
    transition: border-color 160ms ease, box-shadow 160ms ease;
    -webkit-appearance: none;
    appearance: none;
}
.diag-form__input::placeholder { color: rgba(244, 241, 236, 0.38); }
.diag-form__input:focus {
    outline: none;
    border-color: var(--color-blue-accent);
    box-shadow: 0 0 0 3px rgba(36, 171, 226, 0.25);
}
.diag-form__textarea { min-height: 5.5rem; resize: vertical; }

.diag-form__submit {
    width: 100%;
    margin-top: 0.4rem;
    padding: 0.95rem 1.5rem;
    font-family: var(--font-sans);
    font-weight: 800;
    font-size: 1rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #06263b;
    background: var(--color-blue-accent);
    border: none;
    border-radius: 999px;
    cursor: pointer;
    transition: background-color 180ms ease, transform 180ms ease, color 180ms ease;
}
.diag-form__submit:hover { background: var(--color-white); transform: translateY(-2px); }
.diag-form__submit:focus-visible {
    outline: 2px solid var(--color-white);
    outline-offset: 3px;
}
/* CF7 deshabilita el submit hasta marcar el checkbox de T&C: lo atenuamos para
   que se lea como no disponible. */
.diag-form__submit:disabled {
    opacity: 0.45;
    cursor: not-allowed;
    transform: none;
}
.diag-form__submit:disabled:hover { background: var(--color-blue-accent); transform: none; }

.diag-form__reassurance {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 1rem 0 0;
    font-family: var(--font-sans);
    font-size: 0.8rem;
    line-height: 1.3;
    color: rgba(244, 241, 236, 0.6);
}
.diag-form__lock { width: 1.05rem; height: 1.05rem; flex: none; }

/* Checkbox de aceptación de T&C (CF7 [acceptance]) — obligatorio. */
.diag-form__accept { margin-top: 0.2rem; }
.diag-form__accept .wpcf7-list-item { margin: 0; }
.diag-form__accept label {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    font-family: var(--font-sans);
    font-size: 0.85rem;
    line-height: 1.4;
    color: rgba(244, 241, 236, 0.82);
    cursor: pointer;
}
.diag-form__accept input[type="checkbox"] {
    flex: none;
    width: 1.15rem;
    height: 1.15rem;
    margin-top: 0.05rem;
    accent-color: var(--color-blue-accent);
    cursor: pointer;
}
.diag-form__accept a {
    color: var(--color-blue-accent);
    text-decoration: underline;
    text-underline-offset: 2px;
}
.diag-form__accept a:hover { color: var(--color-white); }

/* Mensajes/validación de CF7 */
.diag-modal__panel .wpcf7-response-output {
    margin: 1rem 0 0;
    padding: 0.7rem 0.9rem;
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 3px;
    font-family: var(--font-sans);
    font-size: 0.85rem;
    color: var(--color-white);
}
.diag-modal__panel .wpcf7-not-valid-tip {
    margin-top: 0.3rem;
    font-family: var(--font-sans);
    font-size: 0.78rem;
    color: #ff9ba3;
}
.diag-modal__panel .wpcf7-not-valid {
    border-color: #d8162b !important;
}
.diag-modal__panel form.invalid .wpcf7-response-output,
.diag-modal__panel form.spam .wpcf7-response-output { border-color: #d8162b; }
.diag-modal__panel form.sent .wpcf7-response-output { border-color: #4caf7d; }

/* Animación de entrada (respeta reduced-motion). */
@media (prefers-reduced-motion: no-preference) {
    .diag-modal[open] .diag-modal__panel {
        animation: diagIn 260ms cubic-bezier(0.16, 0.84, 0.44, 1) both;
    }
    @keyframes diagIn {
        from { opacity: 0; transform: translateY(14px) scale(0.98); }
        to   { opacity: 1; transform: none; }
    }
}

@media (orientation: portrait), (max-width: 560px) {
    .diag-form__row { grid-template-columns: 1fr; }
}

/* ==========================================================================
   FOOTER (portada) — marca + enlaces legales + copyright. Oscuro on-brand.
   La portada usa styles-v3.css; el footer de registro vive en registro.css.
   ========================================================================== */
.footer {
    background: var(--color-ink);
    color: rgba(244, 241, 236, 0.7);
    border-top: 1px solid rgba(244, 241, 236, 0.1);
    padding: clamp(2.5rem, 6vw, 4rem) clamp(1.25rem, 5vw, 5rem) clamp(1.5rem, 4vw, 2.5rem);
    font-family: var(--font-sans);
}
.footer__inner {
    max-width: var(--content-max);
    margin: 0 auto;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: flex-start;
    gap: clamp(1.5rem, 4vw, 3rem);
}
.footer__brand { max-width: 32rem; }
.footer__logo {
    height: 6rem;                                    /* apilado (móvil) - igual que el footer del selector */
    width: auto;
    display: block;
    margin-bottom: 0.9rem;
}
.footer__desc {
    margin: 0;
    font-size: clamp(0.85rem, 1.4vw, 1rem);
    line-height: 1.5;
    color: rgba(244, 241, 236, 0.6);
}
.footer__legal {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    align-items: flex-start;
}
.footer__legal-link {
    color: rgba(244, 241, 236, 0.82);
    text-decoration: none;
    font-size: clamp(0.85rem, 1.4vw, 1rem);
    font-weight: 600;
    transition: color 160ms ease;
}
.footer__legal-link:hover,
.footer__legal-link:focus-visible {
    color: var(--color-white);
    text-decoration: underline;
    text-underline-offset: 3px;
}
.footer__bar {
    max-width: var(--content-max);
    margin: clamp(1.5rem, 4vw, 2.5rem) auto 0;
    padding-top: clamp(1rem, 2.5vw, 1.5rem);
    border-top: 1px solid rgba(244, 241, 236, 0.1);
}
.footer__copy {
    margin: 0;
    font-size: clamp(0.75rem, 1.2vw, 0.9rem);
    color: rgba(244, 241, 236, 0.45);
}
/* En fila (≥641px, donde el footer deja de apilarse) el logo baja a 4rem,
   mismo tamaño que el footer del selector en desktop. */
@media (min-width: 641px) {
    .footer__logo { height: 4rem; }
}
@media (max-width: 640px) {
    .footer__inner { flex-direction: column; }
}
