/* ============================================================
   POPUP DE PROGRAMA — ficha de viaje interactiva (1:1 con el PDF)
   ------------------------------------------------------------
   Hoja de estilos COMPARTIDA. La usa el home y cada subpágina de
   deporte, porque un mismo programa se abre desde ambos lados.
   Depende solo de tokens de stc.css (--bg, --line, --surface,
   --font-display, --ease-out...) y de la clase .eyebrow, que también
   vive en stc.css. NO depende de home.css: por eso una subpágina
   como futbol.html puede cargar solo este archivo.

   Reusa la mecánica de overlay de .album-ov/.album-sheet/.ov-close
   (mismo scrim, misma animación de entrada) pero con su propio
   contenido: dos "hojas" de papel que replican las dos páginas del
   programa en PDF, con mapa de zonas zoomeable y CTA de WhatsApp real.

   z-index 960: por encima del nav fijo (900) y de .scroll-progress
   (950). Con un valor menor, el nav tapaba el botón de cerrar en móvil.
   ============================================================ */
.prog-ov { position: fixed; inset: 0; z-index: 960; display: none; }
.prog-ov.open { display: block; }
.prog-ov .scrim { position: absolute; inset: 0; background: rgba(20, 15, 8, 0.55); backdrop-filter: blur(3px); opacity: 0; transition: opacity 0.35s; }
.prog-ov.open .scrim { opacity: 1; }
.prog-sheet {
  --paper: #f6efda; --paper-2: #eee0bd; --ink: #211b12;
  /* --ink-3 estaba en .5 = 3,2:1 sobre el papel. Se usa a 10–12.5px (códigos
     STC, notas del precio, legal, etiquetas del tiquete): eso no es texto
     grande por mucho que vaya en negrita, así que fallaba en todos esos
     sitios. .62 da 4,6:1. Mismo cambio que --text-3 en stc.css. */
  --ink-2: rgba(33,27,18,.72); --ink-3: rgba(33,27,18,.62);
  position: absolute; inset: clamp(10px, 2.4vw, 34px); background: var(--bg);
  border-radius: 10px; overflow: hidden; display: flex; flex-direction: column;
  box-shadow: 0 40px 90px rgba(0,0,0,.45);
  transform: translateY(24px) scale(.985); opacity: 0;
  transition: transform .4s var(--ease-out), opacity .4s;
}
.prog-ov.open .prog-sheet { transform: none; opacity: 1; }
.prog-sheet .ov-close { position: absolute; top: 14px; right: 14px; z-index: 20; width: 42px; height: 42px; border-radius: 50%; border: 1.5px solid var(--line); background: var(--surface); color: var(--cream); font-size: 20px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background .2s, color .2s, transform .2s; }
.prog-sheet .ov-close:hover { background: var(--ink); color: var(--paper); transform: rotate(90deg); }
.prog-body { flex: 1; overflow-y: auto; padding: clamp(40px, 6vw, 70px) clamp(16px, 4vw, 40px) clamp(40px, 6vw, 64px); }

.prog-doc { max-width: 760px; margin: 0 auto; display: flex; flex-direction: column; gap: 26px; }
.prog-page { position: relative; background: var(--paper); color: var(--ink); border: 1px solid rgba(33,27,18,.14); border-radius: 14px; padding: clamp(24px, 4.5vw, 46px); box-shadow: 0 14px 34px rgba(40,30,12,.16); }

.prog-divider { display: flex; align-items: center; gap: 12px; color: var(--ink-3); font-family: var(--font-body); font-weight: 700; font-size: 10.5px; letter-spacing: .18em; text-transform: uppercase; padding: 0 8px; }
.prog-divider::before, .prog-divider::after { content: ""; flex: 1; border-top: 1.5px dashed rgba(33,27,18,.28); }

/* --- página 1 --- */
.prog-code-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 20px; }
.prog-page .eyebrow { margin-top: 4px; }
.prog-title { font-family: var(--font-display); font-weight: 400; text-transform: uppercase; font-size: clamp(32px, 5.2vw, 56px); line-height: .92; color: var(--ink); margin-top: 12px; }
.prog-sub { font-family: var(--font-body); font-weight: 600; font-size: 13px; letter-spacing: .04em; color: var(--ink-2); margin-top: 12px; }

.prog-price { margin-top: 26px; padding-top: 22px; border-top: 1.5px dashed rgba(33,27,18,.28); display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 22px; }
.prog-price .lbl { width: 100%; font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3); }
.prog-price .amt { font-family: var(--font-display); font-weight: 400; font-size: clamp(36px, 5.6vw, 54px); line-height: 1; color: var(--acc, #b4452e); }
/* Programas con dos opciones de tribuna (US Open): cada cifra lleva su
   etiqueta debajo. Sin esto los dos precios quedan uno al lado del otro
   sin decir a qué corresponde cada uno. */
.prog-price .amt small { display: block; margin-top: 7px; font-family: var(--font-body); font-size: 10.5px; font-weight: 800; letter-spacing: .13em; text-transform: uppercase; color: var(--ink-3); }
.prog-price:has(.amt + .amt) .note { width: 100%; flex: none; margin-top: 10px; }
.prog-price .note { flex: 1; min-width: 220px; font-size: 12.5px; line-height: 1.55; color: var(--ink-2); }

.prog-cta { margin-top: 22px; display: flex; flex-wrap: wrap; align-items: center; gap: 14px 20px; }
/* El verde de WhatsApp con texto blanco da 2,28:1 — el CTA de reserva de los
   nueve programas era el peor contraste del sitio. Con la tinta de la marca
   sobre el mismo verde son 7,49:1 y el botón sigue leyéndose como WhatsApp. */
.btn-wa { background: #22c55e; color: #211b12; }
.btn-wa:hover { box-shadow: 0 8px 40px rgba(34,197,94,.42); }
.prog-cta-note { font-size: 11.5px; line-height: 1.5; color: var(--ink-3); max-width: 30ch; }

/* ⚠️ Las cuatro columnas van con `1fr` PELADO y las dos con `minmax(0, 1fr)`.
   Parece incoherente y no lo es: una pista `1fr` lleva mínimo automático
   `min-content`, y ese mínimo unas veces estorba y otras salva.

   Medido el 2026-08-23 el min-content real de las 44 celdas de los once
   programas. El suelo lo ponen dos cosas: la etiqueta «ALOJAMIENTO», que llevan
   los once (Saira 800 a 10px con .14em de tracking = 73px), y el valor
   «Grandstand» de Canadá (Anton 22px = 101px), que es el más ancho del sitio.
   Con los 32px de padding, esa celda pide 133px irreductibles.

   - A cuatro columnas la caja de la tira mide 561px a 1440, o sea 140 por
     pista: con `1fr` salen las cuatro iguales igualmente, porque sobra sitio.
     El mínimo automático sólo se nota en la banda estrecha del pliego
     (1180-1260px de ventana, donde cada hoja se queda en ~506) y ahí es
     justamente lo que evita el destrozo: las pistas se descuadran a 87|112|117|134
     pero ninguna palabra se sale de su celda. Con `minmax(0,1fr)` quedarían las
     cuatro a 110 y «Grandstand» cruzaría 8px la perforación punteada, que es un
     defecto que sí se ve. O sea: a cuatro columnas el mínimo automático se queda.
   - A dos columnas es al revés. Ahí no sobra sitio, así que el mínimo manda
     siempre y las pistas salían 105|133 en vez de mitad y mitad, con la
     perforación al 44 % en vez de al 50 %. Con el mínimo en 0 se reparten iguales
     y —comprobado de 380 a 700px en los once— nada se desborda.
     ⚠️ El techo de esa banda: a 390px de ventana cada celda deja 112px de
     contenido. Si algún programa nuevo trae un valor de más de eso en Anton 22
     (hoy el peor es «Grandstand», 101), se saldrá de su celda. */
.prog-ticket { margin-top: 30px; display: grid; grid-template-columns: repeat(4, 1fr); border-top: 1.5px solid var(--ink); border-bottom: 1.5px solid var(--ink); }
@media (max-width: 700px) { .prog-ticket { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.prog-ticket .ti { padding: 16px 16px; display: flex; flex-direction: column; gap: 5px; border-left: 1px dashed rgba(33,27,18,.28); }
.prog-ticket .ti:first-child, .prog-ticket .ti:nth-child(3) { border-left: none; }
/* 700.02 y no 701: entre 700 y 701 hay anchos reales (pantallas con zoom o
   con densidad fraccionaria) donde ninguna de las dos reglas aplicaba y la
   tercera celda se quedaba sin línea divisoria. */
@media (min-width: 700.02px) { .prog-ticket .ti:nth-child(3) { border-left: 1px dashed rgba(33,27,18,.28); } }
/* ⚠️ Por debajo de 380px la tira se APILA, y no es una preferencia: dos columnas
   no caben, ni apretándolas. El mínimo de una celda son 105px irreductibles
   —«ALOJAMIENTO» 73 + los 32 de padding— y en Canadá 133 por «Grandstand»; dos
   pistas piden 238-250px contra los 218 que deja la hoja en un teléfono de 320.
   Con `minmax(0,1fr)` eso ya no estira la pista: ahora el texto se saldría de su
   propia celda y se metería en la vecina, que es peor que lo que había. Apilada,
   cada celda dispone del ancho entero y sobra de largo.
   El corte va en 380 y no más arriba a propósito: a 390px (el iPhone de siempre)
   dos columnas dan 112px de contenido contra los 101 del peor programa, así que
   ahí la tira sigue siendo tira. Y va en 379.98 por lo mismo que el 700.02 de la
   línea de arriba: sin decimales, un ancho fraccionario entre 379 y 380 se queda
   sin ninguna de las dos reglas.
   Las perforaciones pasan de vertical a horizontal — sigue siendo un talón de
   entrada, sólo que de pie. Medido en los once programas a 320, 360 y 375. */
@media (max-width: 379.98px) {
  .prog-ticket { grid-template-columns: 1fr; }
  .prog-ticket .ti { border-left: none; border-top: 1px dashed rgba(33,27,18,.28); }
  .prog-ticket .ti:first-child { border-top: none; }
}
.prog-ticket .ti .k { font-size: 10px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3); }
.prog-ticket .ti .v { font-family: var(--font-display); font-weight: 400; font-size: 22px; color: var(--ink); line-height: 1; }
.prog-ticket .ti .s { font-size: 11.5px; color: var(--ink-2); }

.prog-notes { margin-top: 22px; list-style: none; display: flex; flex-direction: column; gap: 8px; }
.prog-notes li { position: relative; padding-left: 18px; font-size: 12px; line-height: 1.55; color: var(--ink-2); }
.prog-notes li::before { content: "★"; position: absolute; left: 0; top: 1px; font-size: 9px; color: var(--acc, #b4452e); }
/* Las condiciones normalmente cierran la hoja 1 y el aire se lo da el padding
   de la hoja, así que .prog-notes no lleva margen abajo. En los programas de
   circuito (Moto GP, México) bajan a la hoja 2 para equilibrar el pliego y allí
   sí tienen algo debajo: sin esta regla se pegan al banner, que solo trae 4px. */
.prog-notes + .prog-banner { margin-top: 26px; }

/* El sello va por debajo de la línea de código superior: a 24px se
   montaba encima de "EST. 2011 · Bogotá". */
.prog-seal { position: absolute; top: 86px; right: 24px; width: 84px; height: 84px; border-radius: 50%; border: 2.5px solid var(--acc, #b4452e); color: var(--acc, #b4452e); display: flex; align-items: center; justify-content: center; text-align: center; font-family: var(--font-body); font-weight: 800; font-size: 10.5px; letter-spacing: .04em; text-transform: uppercase; line-height: 1.25; opacity: .55; transform: rotate(-9deg); pointer-events: none; }
@media (max-width: 640px) { .prog-seal { display: none; } }

/* --- página 2 --- */
.prog-p2-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 10px; margin-bottom: 28px; }
.prog-p2-head h3 { font-family: var(--font-display); font-weight: 400; text-transform: uppercase; font-size: clamp(22px, 3.2vw, 30px); margin-top: 8px; color: var(--ink); }
.prog-p2-head .code { font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }

.prog-incl-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 30px; margin-bottom: 32px; }
/* Cuando el "incluye / no incluye" va al pie de la hoja 1, justo detrás
   del botón verde, necesita respirar y una línea que lo separe: si no,
   el titular se monta contra el botón. */
.prog-cta + .prog-incl-grid { margin-top: 32px; padding-top: 28px; border-top: 1.5px dashed rgba(33,27,18,.3); }
@media (max-width: 620px) { .prog-incl-grid { grid-template-columns: 1fr; } }
.prog-incl-grid h4, .prog-stadium h4, .prog-map h4 { font-family: var(--font-display); font-weight: 400; text-transform: uppercase; font-size: 17px; margin-bottom: 13px; color: var(--ink); }
.prog-check, .prog-cross { list-style: none; display: flex; flex-direction: column; gap: 9px; }
.prog-check li, .prog-cross li { position: relative; padding-left: 25px; font-size: 13px; line-height: 1.5; color: var(--ink-2); }
.prog-check li::before { content: "✓"; position: absolute; left: 0; top: 0; font-weight: 800; color: #2e8b45; }
.prog-cross li::before { content: "✕"; position: absolute; left: 0; top: 0; font-weight: 800; color: var(--st-red, #b4452e); }

.prog-stadium { margin-bottom: 32px; }
/* Cuando "sobre el estadio" se sube a la hoja 1 para equilibrar el pliego,
   queda pegado al subtítulo. Ahí necesita aire propio. */
.prog-sub + .prog-stadium { margin-top: 26px; }
/* Mismo aire cuando la tira de fotos va directa detrás del subtítulo (F1). */
.prog-sub + .prog-photos { margin-top: 26px; }
.prog-stadium p { font-size: 13.5px; line-height: 1.65; color: var(--ink-2); max-width: 64ch; }

/* El plano va completo y estático, como en el PDF: sin recorte y sin
   zoom. El alto lo marca la propia imagen, así que no se corta nada. */
.prog-map { margin-bottom: 30px; }
.prog-map-frame { margin-top: 15px; border-radius: 10px; overflow: hidden; background: #e7dab8; border: 1px solid rgba(33,27,18,.18); }
.prog-map-frame img { width: 100%; height: auto; display: block; }

.prog-legend { margin-top: 16px; list-style: none; display: flex; flex-direction: column; gap: 8px; }
.prog-legend li { display: flex; align-items: flex-start; gap: 10px; font-size: 12.5px; line-height: 1.5; color: var(--ink-2); }
.prog-legend li b { color: var(--ink); font-weight: 700; }
.prog-legend .sw { flex: none; width: 14px; height: 14px; margin-top: 3px; border-radius: 4px; background: var(--c); border: 1px solid rgba(0,0,0,.15); }
.prog-legend .tx { flex: 1; }

/* Los dos Grandes Premios de 2027 (Canadá y Miami) traen el plano ENTERO del
   circuito, con las 15 y las 10 tribunas ajenas dibujadas una por una. En la
   leyenda normal —una columna, una línea de 8 px de hueco por entrada— eso
   medía 430 px en Canadá y desnivelaba el pliego sin aportar nada: son sólo
   nombres, sin descripción. `--densa` los reparte en columnas automáticas,
   igual que el PDF, y devuelve unos 300 px a la hoja 2.
   ⚠️ La tribuna INCLUIDA no entra aquí: va arriba, sola, en una `.prog-legend`
   normal y con su descripción completa, que es la única que el cliente lee. */
.prog-legend--densa { display: grid; grid-template-columns: repeat(auto-fit, minmax(126px, 1fr)); gap: 7px 18px; margin-top: 9px; }
.prog-legend--densa li { font-size: 12px; gap: 8px; }
.prog-legend--densa .sw { width: 11px; height: 11px; margin-top: 4px; border-radius: 3px; }
/* Rótulo del grupo. No es un "eyebrow" de sección: es la etiqueta que dice qué
   son los 15 colores de abajo, y sin ella el lector no sabe que están fuera. */
.prog-legend-tit { margin-top: 18px; font-family: var(--font-display); font-weight: 400; text-transform: uppercase; font-size: 12.5px; letter-spacing: .05em; color: var(--ink-2); }

.prog-map-note { margin-top: 13px; font-size: 11px; line-height: 1.55; color: var(--ink-3); }

/* ═══════════════════════════════════════════════════════════════════════
   EL CIERRE — la foto que remata la hoja 2

   Juan, 2026-08-23: «quiero que todos los programas sean como el de
   champions: que la foto del final de la segunda página tenga un brillo de
   colores (nosotros estábamos usando rosado pero puede ser cualquiera) y
   una frase». La referencia que mandó era el propio banner de Champions.

   Ese archivo traía el barrido Y el rótulo QUEMADOS dentro del JPG. Aquí se
   reconstruyen con CSS y con texto de verdad, y no por purismo:
   · la frase se lee, se selecciona, se traduce y la anuncia un lector de
     pantalla — dentro del JPG era invisible para todo eso;
   · escala con el CONTENEDOR. El banner mide 594px en el pliego, ~668 en
     una columna y 288 en un teléfono, y eso **no** va atado al ancho de la
     ventana, así que las media queries no sirven: por eso `container-type`
     y `cqw`. Quemado en el JPG, el rótulo se encogía hasta ser ilegible;
   · un color por programa sin re-exportar nueve archivos.

   Al banner de Champions se le borraron el rótulo y el marco crema ese mismo
   día (2451×441; copia del original en la papelera), así que hoy los nueve
   programas entran por la misma puerta. Champions es el único que NO lleva
   `--luz`: su foto ya trae el color dentro y superponerle otro barrido la
   ensucia. Ver la nota del modificador, abajo.

   ⚠️ Se probaron seis tratamientos sobre los banners reales antes de elegir.
   Los tres que perdieron, por si alguien quiere repetir el camino:
   · foto intacta + luz `screen` encima → no hay «brillo de colores», sólo
     una foto oscurecida con viñeta. No cumple el encargo;
   · duotono gris completo + barrido → es lo más parecido al original, pero
     borra la foto: el pelotón de Interlagos y la moto de Valencia quedan en
     fantasmas. Justo lo que Juan acababa de mandar arreglar;
   · duotono duro con luz mínima → además pierde el campo hondo de la
     derecha y el remate se vuelve marrón.
   Gana el de abajo porque hace las dos cosas a la vez: el barrido de color
   del original **y** la foto sigue viva debajo.
   ═══════════════════════════════════════════════════════════════════════ */
.prog-banner {
  position: relative; isolation: isolate; container-type: inline-size;
  margin: 4px 0 28px; border-radius: 10px; overflow: hidden;
}
/* ⚠️ `height: auto` NO es decorativo, y va ANTES del aspect-ratio. Los <img>
   de los fragmentos llevan atributos width/height (van para reservar el hueco
   y evitar el salto de maquetación al cargar). Ese `height` entra como
   *presentational hint*, y si ninguna regla de autor pisa la altura, el alto
   queda DEFINIDO: con ancho y alto definidos el `aspect-ratio` se ignora (así
   lo manda la spec) y el banner se dibuja a sus píxeles naturales. Sin esta
   línea un banner de 2147×256 sale de 663×256, deformado. Lo mismo vale para
   .prog-photos img y .prog-map-frame img.

   El 63/10 UNIFICA: los archivos vienen en tres proporciones distintas (8,39
   los cuatro anchos · 6,32 los cuatro medianos · 5,56 Champions) y el cierre
   tiene que ser el mismo objeto en los nueve programas, además de una altura
   predecible para el equilibrio del pliego. 6,3 es la mediana, así que cuatro
   no se tocan; los anchos pierden un 12,5% por cada lado y Champions un 6%
   arriba y abajo. Comprobado uno a uno: no se cae nada del motivo. */
.prog-banner img {
  width: 100%; height: auto; aspect-ratio: 63 / 10; object-fit: cover; display: block;
}
/* En un teléfono el contenedor baja a ~288px y con 6,3 el banner queda en 46px
   de alto: la frase de dos líneas lo llena entero y se ahoga. 5/1 le devuelve
   ~12px de aire sin cambiar nada más. */
@container (max-width: 420px) {
  .prog-banner img { aspect-ratio: 5 / 1; }
}

.prog-banner figcaption {
  position: absolute; z-index: 3; right: 4.6cqw; top: 50%; transform: translateY(-50%);
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(15px, 4.2cqw, 30px); line-height: .94;
  text-align: right; text-transform: uppercase; text-wrap: balance;
  color: #fff; text-shadow: 0 2px 18px rgba(10, 6, 16, .6);
}
/* Las dos líneas van en el mismo cuerpo a propósito: son una sola frase partida,
   no un título con subtítulo, y el <b> sólo fuerza el salto donde lo quiere el
   remate ("La Bombonera / no tiembla, late"). Por eso `font-weight: inherit`.
   ⚠️ Hasta el 2026-08-23 esto era "Así se vive + el estadio" en los nueve, y el
   comentario decía que la segunda línea era el dato. Ya no: los PDF nuevos traen
   una frase propia por programa y ésa es la gracia. Si algún programa nuevo llega
   sin frase, la de reserva es la de Champions ("Así se vive / una final"), pero
   escribirle una suya es lo correcto. */
.prog-banner figcaption b { display: block; font-weight: inherit; }

/* ── el barrido de color ──────────────────────────────────────────────────
   Modificador, no regla base: un programa sin `--luz` se queda con su foto
   limpia y su frase, que es una degradación digna (Champions vive ahí a
   propósito). El color va inline en el <figure> como `--cierre`; si falta,
   cae en el acento del programa.

   Son DOS capas y cada una hace un trabajo distinto — ésa es toda la idea:
   ::before  multiply → tiñe la foto y hunde la derecha hasta el negro, que
                        es donde se sienta el texto blanco;
   ::after   screen   → SUMA luz por la izquierda. Sin ésta hay tinte pero no
                        brillo, y «brillo de colores» era el encargo. */
.prog-banner--luz {
  --cierre: var(--acc, #b3126f);
  /* Respaldo universal (color-mix, soportado desde 2023). Se queda puesto en
     cualquier navegador que no entienda la línea de abajo. */
  --cierre-hondo: color-mix(in oklab, var(--cierre) 30%, #17101f);
  --cierre-medio: color-mix(in oklab, var(--cierre) 72%, #17101f);
  --cierre-luz:   color-mix(in oklab, var(--cierre) 45%, #fff);
  /* Lo bueno: sintaxis de color relativa. Fija la LUMINOSIDAD y conserva el
     tono, así que el mismo bloque sirve para un azul oscuro y para un amarillo
     —que es justo donde un `color-mix` contra negro se vuelve barro—. */
  --cierre-hondo: oklch(from var(--cierre) .23 calc(c * .9)   h);
  --cierre-medio: oklch(from var(--cierre) .46 calc(c * 1.05) h);
  --cierre-luz:   oklch(from var(--cierre) .90 calc(c * .5)   calc(h + 14));
}
/* Baja la saturación propia de la foto para que el barrido mande, pero NO la
   quita: en gris puro la foto desaparece (ver la nota de arriba). El contraste
   compensa el aplanado que trae el multiply. */
.prog-banner--luz img { filter: saturate(.35) contrast(1.14); }
.prog-banner--luz::before,
.prog-banner--luz::after { content: ""; position: absolute; inset: 0; pointer-events: none; }
.prog-banner--luz::before {
  z-index: 1; mix-blend-mode: multiply; opacity: .94;
  background: linear-gradient(101deg,
    var(--cierre) 0%, var(--cierre-medio) 34%, var(--cierre-hondo) 82%);
}
.prog-banner--luz::after {
  z-index: 2; mix-blend-mode: screen; opacity: .78;
  background: radial-gradient(88% 230% at -8% 50%,
    var(--cierre-luz) 0%,
    color-mix(in oklab, var(--cierre) 72%, #fff) 12%,
    var(--cierre) 26%,
    transparent 54%);
}
/* ⚠️ `isolation: isolate` en `.prog-banner` es lo que encierra los dos
   mix-blend-mode. Sin él, el `multiply` atraviesa el banner y se mezcla con
   el papel crema de la hoja. */

.prog-photos { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 32px; }
/* Los programas de F1 sólo traen dos fotos. Con la rejilla de 3 columnas
   quedaría una celda vacía al lado derecho; con dos columnas las fotos
   crecen y la tira se lee como una sola pieza. */
.prog-photos:has(img:nth-child(2):last-child) { grid-template-columns: 1fr 1fr; }
/* A dos columnas cada foto es un 50% más ancha, y con el 4/3 de abajo la tira
   crecía ~70px de alto: lo suficiente para desequilibrar el pliego frente a un
   programa de tres fotos. El 16/9 la devuelve a la misma altura. */
.prog-photos:has(img:nth-child(2):last-child) img { aspect-ratio: 16 / 9; }
@media (max-width: 560px) {
  .prog-photos { grid-template-columns: 1fr 1fr; }
  /* Si el número de fotos es impar, la última queda huérfana en la
     segunda fila. En vez de dejar el hueco, se lleva el ancho entero
     y se vuelve panorámica. */
  .prog-photos img:last-child:nth-child(odd) { grid-column: 1 / -1; aspect-ratio: 16 / 9; }
}
/* ⚠️ El `height: auto` es imprescindible y va ANTES que el aspect-ratio.
   Los <img> traen atributos width/height del HTML; ese height llega como
   presentational hint y deja la altura DEFINIDA. Con ancho y alto definidos
   el `aspect-ratio` se ignora (así lo manda la spec), la foto se dibuja a su
   alto natural —190×399 en vez de 190×142— y el `object-fit: cover` recorta
   un primerísimo plano del centro. Es exactamente el "se ven espantosas".
   `height: auto` devuelve la altura a indefinida y el 4/3 vuelve a mandar. */
.prog-photos img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: 8px; filter: sepia(.15) saturate(.92); }

.prog-foot { border-top: 1.5px dashed rgba(33,27,18,.3); padding-top: 22px; display: flex; flex-direction: column; gap: 15px; }
.prog-mrz { font-family: ui-monospace, "SFMono-Regular", Menlo, monospace; font-size: 11.5px; letter-spacing: .12em; color: var(--ink-3); overflow-wrap: anywhere; }
.prog-contact { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 22px; font-size: 12.5px; color: var(--ink-2); }
.prog-contact .btn { padding: 13px 22px; font-size: 12px; }
.prog-legal { font-size: 10px; line-height: 1.55; color: var(--ink-3); max-width: 82ch; }

body.ov-lock { overflow: hidden; }

/* El anillo de foco general de stc.css es azul; sobre el fondo oscuro del
   botón de cerrar se pierde. Aquí va en crema, que es lo que contrasta. */
.prog-sheet .ov-close:focus-visible { outline: 3px solid var(--cream); outline-offset: 3px; }

/* El cuerpo con scroll es una parada de tabulación (tabindex="0" en el HTML,
   ver el comentario de allí). El anillo general va con `outline-offset: 3px` y
   aquí lo dibujaría FUERA de la hoja, donde lo recorta el `overflow: hidden`
   del .prog-sheet: el usuario tabula y no ve nada. Con offset negativo el
   anillo se pinta por dentro, contra el papel del programa. */
.prog-body:focus-visible { outline: 3px solid var(--acc, #b4452e); outline-offset: -3px; border-radius: 0; }

/* El popup entra con desplazamiento + escala y el scrim con desenfoque. Con
   movimiento reducido aparece sin más: la información es la misma. */
@media (prefers-reduced-motion: reduce) {
  .prog-ov .scrim { transition: none; }
  .prog-sheet { transform: none; transition: opacity .01s; }
  .prog-sheet .ov-close { transition: background .01s, color .01s; }
  .prog-sheet .ov-close:hover { transform: none; }
}

/* ============================================================
   PLIEGO — las dos hojas lado a lado, como el programa abierto
   ------------------------------------------------------------
   Va al FINAL del archivo a propósito: tiene que pisar las reglas
   base de .prog-doc y .prog-divider, que se declaran más arriba con
   la misma especificidad. Si se sube este bloque, gana la de abajo
   y el divisor vuelve a ocupar una celda del grid.

   Se activa solo cuando de verdad caben las dos hojas sin apretar el
   texto; por debajo de 1180px se apilan, que es lo legible en
   portátil y en móvil.
   ============================================================ */
@media (min-width: 1180px) {
  .prog-doc {
    max-width: 1560px;
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: stretch;   /* las dos hojas miden lo mismo: la 1 es más
                               corta y su papel llega hasta abajo, en vez
                               de dejar un hueco recortado al costado */
    gap: 24px;
  }
  .prog-divider { display: none; }   /* "Página 2 de 2" no aplica en pliego */
  .prog-page { padding: clamp(26px, 2.2vw, 38px); }
}
