:root{--primario:#1a1a1a;--texto:#14161a;--acento:#00a78a;--fondo:#ffffff;--fondo-alt:#f5f6f8;--f-principal:Georgia, "Times New Roman", serif;--f-secundaria:system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--f-texto:Georgia, "Times New Roman", serif;--radio:0px;--densidad:1;--escala:1;--ancho:88rem;--sep:1px;--logo-alto:51px}
/* Layout "base" — el primero de los 2-3 de docs/05.
 *
 * PROVISORIO: sirve para poder mirar el render en el navegador. Los layouts de
 * verdad son un entregable de la v0.1. Lo que si vale la pena que quede probado
 * acá es la premisa de docs/05: el HTML es el mismo para todos los layouts y lo
 * unico que cambia es esta hoja. Por eso no hay ni una clase inventada acá que no
 * emita ya el render.
 */

/* ACA NO SE DECLARA NINGUN TOKEN, y no es estilo: es correccion.
 *
 * Los tokens (`--primario`, `--f-principal`, `--radio`, `--densidad`, ...) los
 * emite `render/tokens.ts` en un `:root` que va ANTES de este archivo, asi que
 * cualquier `:root` de acá que repita uno lo pisaria en silencio — el ultimo
 * gana— y el cliente elegiria un color que no se ve en ningun lado.
 *
 * Lo unico que se declara acá son los DERIVADOS: colores que el producto saca de
 * la paleta en vez de pedirlos. Con `color-mix` siguen al tema solo — un fondo
 * oscuro se lleva las lineas y el texto secundario con el, sin que nadie los
 * elija ni pueda equivocarse eligiendolos. */
:root {
  --suave: color-mix(in srgb, var(--texto) 62%, var(--fondo));
  --linea: color-mix(in srgb, var(--texto) 13%, var(--fondo));
  /* El aire base del sitio, ya multiplicado por la densidad. Todo lo que separa
     usa estos dos y no un rem suelto, que es lo que hace que "compacta" y
     "amplia" signifiquen algo en TODA la pagina y no en los tres lugares donde
     alguien se acordo de ponerlo. */
  --aire: calc(1.5rem * var(--densidad));
  --aire-chico: calc(.7rem * var(--densidad));
  /* LA LINEA SOBRE FONDO INVERTIDO. La franja de la cabecera y el pie
     institucional van con la tinta de fondo, y ahi `--linea` —que se calcula
     hacia el papel— desaparece. Esta es la misma idea al reves, y sigue saliendo
     de la paleta: un cliente de tema oscuro las recibe bien sin elegir nada. */
  --linea-inv: color-mix(in srgb, var(--fondo) 14%, transparent);
}

/* LA ESCALA TIPOGRAFICA, EN UN SOLO LUGAR. Todo el resto de la hoja mide en
 * `rem`, asi que mover la raiz mueve la pagina entera y no hay una segunda lista
 * de tamaños que mantener. Las media queries siguen midiendo con el `rem`
 * inicial —asi lo define CSS— y eso es lo que se quiere: la escala cambia las
 * letras, no en que ancho el sitio pasa a una columna. */
html {
  font-size: calc(100% * var(--escala));
  /* EL RECORTE VA EN LA RAIZ Y NO SOLO EN EL BODY, y esto es un bug arreglado, no
     una precaucion.
     Lo vio Hernan: *"en la home se esta creando un scroll horizontal; algo esta
     haciendo mas ancho — no solo home, parece que todo el sitio"*. Medido: el
     documento daba 1913px de ancho contra 1905 de viewport. Los 8 px son EL ANCHO
     DE LA BARRA de scroll, y salen de `.wrap.fondo-pantalla`, que se estira con
     `100vw` — una unidad que INCLUYE la barra.
     El `overflow-x: clip` ya estaba escrito, pero en `body`. Y ahi no sirve: el
     que recorta el viewport es el elemento raiz, y **Chrome no propaga `clip` de
     `body` a la raiz** (a diferencia de `hidden`). O sea que la regla existia,
     decia lo correcto en su comentario, y no hacia nada.
     `clip` y no `hidden` a proposito: `hidden` en un eje obliga al otro a
     `auto` y convierte a `html` en contenedor de scroll, lo que rompe
     `position: sticky` de la cabecera. `clip` recorta y no toca el otro eje. */
  overflow-x: clip;
  /* EL LUGAR DE LA BARRA DE SCROLL SE RESERVA SIEMPRE, y esto es un salto de
     layout arreglado.

     El interstitial bloquea el scroll mientras esta abierto (`.ad-abierto`), y eso
     **esconde la barra**: el viewport se ensancha 15px y todo lo que esta centrado
     con `margin-inline: auto` —o sea la pagina entera— se corre 7px a la derecha.
     Y otra vez a la izquierda al cerrarse. Medido: 1905 -> 1920, y el `<main>`
     saltando de 249 a 256.

     Hernan lo reporto como "se sigue moviendo el leaderboard" y el leaderboard no
     tenia nada que ver: su hueco ya reservaba los 200px correctos. Lo que se movia
     era todo, en horizontal, y por eso se leia como que el aviso empujaba.

     `stable` deja el canal reservado aunque no haya barra, asi que esconderla no
     cambia el ancho. Es la respuesta estandar y vale para cualquier otra cosa que
     bloquee el scroll mañana. */
  scrollbar-gutter: stable;
}

* { box-sizing: border-box; }

body {
  /* Se deja tambien acá: no alcanza solo (ver `html`), pero cubre el caso de un
     descendiente que se salga sin llegar a la raiz. */
  overflow-x: clip;
  margin: 0;
  background: var(--fondo);
  color: var(--texto);
  font-family: var(--f-secundaria);
  font-size: 1rem;
  line-height: 1.5;
}

a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; }
/* ⚠️ LAS DOS JUNTAS, Y ESO ES EL ARREGLO. `img` tenia su regla desde el principio
   y `video` **no tenia ninguna**, asi que un video se dibujaba con su tamaño
   INTRINSECO: un mp4 de 3840x2160 puesto como principal salia de 3840px de ancho
   adentro de una columna de 704. Lo vio Hernan en produccion — *"cuando pones un
   video como multimedia principal no queda muy bien"*.

   Y no era solo el slot principal: el mismo `<video width height>` lo emite el
   CUERPO de la nota desde antes, con el mismo resultado. Una regla arregla los
   dos, que es justo el motivo por el que los dos emiten el mismo marcado.

   `height: auto` es la mitad que importa: pisa el atributo `height` y deja que la
   proporcion salga del ancho. Sin eso, acotar el ancho deforma el video. */
img,
video { display: block; width: 100%; height: auto; }
figure { margin: 0; }

/* --- el marco: cabecera y pie (`docs/31`, `render/marco.ts`) ------------------
 *
 * LA CONDICION QUE ESTE BLOQUE TIENE QUE CUMPLIR, y que es la que hace barato el
 * catalogo: las cuatro cabeceras comparten TODO lo de acá y cada una agrega un
 * bloque chico al final. Si agregar la quinta obliga a escribir otra vez el
 * menu, el buscador y la marca, volvimos al archivo por cliente de Amura — que
 * es de donde este diseño viene escapando.
 *
 * Se mide facil: contá las lineas de `--clasica`, `--centrada`, `--compacta` y
 * `--franja` juntas. Si alguna vez pesan mas que lo compartido, se rompio.
 */

/* La caja del sitio. Antes el ancho maximo estaba repetido en `header`, `main` y
   `footer`; ahora es una clase y la usan los tres. */
.container {
  max-width: var(--ancho);
  margin-inline: auto;
  padding-inline: 1.25rem;
}

/* LA CABECERA SE QUEDA ARRIBA. Es lo primero que se nota de demo y no cuesta
   nada: `sticky` es una linea y no necesita guion. En un diario importa mas que
   en otros sitios — se leen notas largas, y volver al menu no puede ser
   deslizar hasta arriba de todo.

   `background` explicito y no heredado: sin el, el contenido se ve pasar por
   detras. */
.header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--fondo);
  /* UNA LINEA FINA Y NO UNA BARRA. Eran 3px del color primario —el recurso
     clasico de diario— y al ponerlo al lado de demo se ve de donde viene el
     "parece una plantilla": una barra de color debajo de la cabecera es lo
     primero que hace cualquier tema gratuito. Demo cierra con
     `rgba(0,0,0,.06)`, o sea casi nada, y por eso la marca es lo unico que se
     ve arriba. La separacion real la da la franja oscura. */
  border-bottom: 1px solid var(--linea);
  transition: box-shadow .3s ease;
}
/* AL BAJAR SE ACHICA: se va la franja y la marca pierde alto. Lo marca el guion
   con `data-fija` (`global.js`) — es lo unico de la cabecera que necesita saber
   donde esta la pagina, y sin guion no falta nada: queda la cabecera entera,
   pegada arriba, que es lo que hace hoy.

   `max-height` y no `height`: de `auto` a cero no hay transicion, asi que la
   franja desapareceria de golpe. Con un techo generoso la animacion existe y el
   valor no la recorta en ningun ancho. */
.header[data-fija] { box-shadow: 0 2px 16px rgba(0, 0, 0, .1); }
.header__topbar { max-height: 6rem; overflow: hidden; transition: max-height .3s ease, opacity .2s ease; }
.header[data-fija] .header__topbar { max-height: 0; opacity: 0; }
.header__brand img { transition: height .3s ease; }
.header[data-fija] .header__brand img { height: calc(var(--logo-alto) * .62); }
/* Y LA MARCA EN TEXTO TAMBIEN, que es el caso de un cliente que todavia no
   subio su logo — o sea el de todos el dia del alta. Sin esto la cabecera se
   achicaba con logo y no sin el, que es la clase de diferencia que aparece
   justo cuando se muestra el sitio por primera vez. */
.header__brand--texto { transition: font-size .3s ease; }
.header[data-fija] .header__brand--texto { font-size: clamp(1.2rem, 3vw, 1.6rem); }
/* Y la fila se aprieta, como la de demo. */
.header[data-fija] .header__main > .container { padding-block: calc(var(--aire-chico) * .7); }

/* --- la franja superior: solo la variante que la declara ---------------------
 * LA BANDA VA INVERTIDA —fondo de tinta, letra del color del papel— y no es una
 * preferencia: es lo que la hace leerse como una banda de servicio y no como
 * "la cabecera pero mas clarita". Es lo que hace demo (`background: @textColor`)
 * y lo que separa visualmente los enlaces institucionales de las secciones.
 *
 * SALE DE LOS MISMOS DOS TOKENS, dados vuelta. Un cliente de tema oscuro la
 * recibe invertida tambien, sin que nadie elija un tercer color ni pueda
 * equivocarse eligiendolo. */
.header__topbar {
  background: var(--texto);
  color: var(--fondo);
  font-family: var(--f-secundaria);
  font-size: .76rem;
  letter-spacing: .02em;
}
.header__topbar > .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 2.2rem;
  flex-wrap: wrap;
}
.header__topbar-left, .header__topbar-right { display: flex; align-items: center; gap: 1rem; }
/* Sobre la banda oscura, lo secundario se atenua con opacidad y no con un color:
   asi sigue al fondo sea cual sea, que es lo que un color fijo no hace. */
.header__topbar .header__date { color: inherit; opacity: .8; font-weight: 300; }
.header__topbar .header__nav-top a { opacity: .8; }
.header__topbar .header__nav-top a:hover { opacity: 1; }
/* `color: inherit` y no el acento: sobre la banda oscura, el color de marca sale
   apagado o directamente ilegible —el acento suele ser un rojo pensado para
   fondo claro— y ademas compite con la marca, que es lo unico que tendria que
   tener color arriba. */
.header__topbar .social a { color: inherit; opacity: .6; }
.header__topbar .social a:hover { opacity: 1; }
.header__topbar .social__icon { width: 1.15em; height: 1.15em; }

/* EN EL TELEFONO LA FRANJA SE QUEDA CON LO QUE SIRVE AHI, Y SI NO QUEDA NADA, SE VA.
 *
 * Lo marco Hernan: *"la barra negra del header top queda mal en mobile; en demo
 * la eliminamos, o sea si no se puede ajustar se saca"*. Y quedaba mal por una
 * razon medible: a 371px la franja **se parte en dos renglones** —la fecha larga
 * arriba, siete iconos de redes abajo— y se lleva 47px de alto de banda negra
 * antes de que empiece el diario.
 *
 * SE AJUSTA ANTES DE SACARSE, y lo que se va es lo que no hace falta ahi:
 *
 *  - **la fecha**: es decoracion. Nadie entra a un diario en el telefono para
 *    saber que dia es.
 *  - **las redes**: el pie ya las repite completas, mas grandes y donde se las
 *    busca.
 *
 * LO QUE NO SE TOCA es el menu institucional (`header__nav-top`) ni el slot del
 * cliente: eso es NAVEGACION, y esconderla seria sacar enlaces que en el
 * escritorio si estan. Por eso la franja no se esconde a ciegas — se esconde
 * **solo si no le quedo nada adentro**, que es el caso de la variante que solo
 * lleva fecha y redes. Es la diferencia entre ajustar y romper. */
@media (max-width: 34rem) {
  .header__topbar .header__date,
  .header__topbar .social { display: none; }
  .header__topbar > .container { min-height: 0; padding-block: .25rem; }
  .header__topbar:not(:has(.header__nav-top)):not(:has(.slot)) { display: none; }
}

/* --- la fila principal ------------------------------------------------------- */
.header__main > .container {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding-block: var(--aire-chico);
}
.header__left, .header__right { display: flex; align-items: center; gap: .7rem; }
.header__right { margin-left: auto; }
.header__left:empty, .header__right:empty { display: none; }

.header__brand { color: var(--primario); display: block; }
.header__brand:hover { text-decoration: none; }
/* EL NOMBRE EN TEXTO Y EL LOGO NO SE ESTILIZAN IGUAL, y por eso son dos clases:
   el nombre necesita la tipografia principal y un tamaño grande; una imagen
   necesita un alto maximo y nada mas. Con una sola clase, las reglas del texto
   se le aplican a la imagen y al reves. */
.header__brand--texto {
  font-family: var(--f-principal);
  font-size: clamp(1.6rem, 4.5vw, 2.6rem);
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.05;
}
/* `margin-inline:auto` y no `text-align`: la imagen es `display:block` (regla
   global de la hoja), asi que el centrado del texto no la mueve. En las
   variantes de una fila el enlace se achica a su contenido y esto no hace nada;
   en las de marca centrada es lo que la pone al medio. */
/* EL ALTO ES DEFINIDO (`height`) Y NO UN TECHO (`max-height`), y esto lo trajo un
   logo que no se veia en produccion.
 *
 * UN SVG PUEDE NO TENER MEDIDAS PROPIAS: sólo un `viewBox`, o sea una PROPORCION.
 * Con `width:auto; height:auto` el navegador no tiene ninguna medida definida de
 * donde agarrarse, y `max-height` no le da una —un techo no es un valor—. Adentro
 * de la fila flex de la cabecera eso se resuelve como CERO: la marca desaparece,
 * los dos costados se reparten todo el ancho, y **la imagen esta cargada y sana**
 * (`naturalWidth` responde) pero su caja mide 0×0.
 *
 * Por que no lo vio nadie: con el NOMBRE EN TEXTO funciona perfecto, y con un PNG
 * o un JPEG tambien —esos si traen medidas—. Falla exactamente en el caso de un
 * logo SVG, que es lo que sube todo el mundo.
 *
 * Y el `width`/`height` del `<img>` no alcanza: son pistas de presentacion y las
 * pisa cualquier regla de la hoja, incluida la de acá al lado.
 *
 * LO QUE SE PIERDE con un alto definido es el "no agrandar": un logo de mapa de
 * bits mas chico que 3.2rem se va a estirar. Es el mal menor y ademas es lo que
 * un diario quiere —el logo ocupa el alto que se le da—; para que no se note, el
 * recorte pide `scale-down` y el archivo sale del tamaño que subieron. */
.header__brand img { width: auto; height: var(--logo-alto); max-width: 100%; margin-inline: auto; }
.header--compacta .header__brand img { height: calc(var(--logo-alto) * .62); }

/* El menu de la franja: enlaces de servicio, no secciones. Chico y sin
   mayusculas — compite con la fecha, no con el menu principal. */
.header__nav-top ul {
  display: flex; flex-wrap: wrap; gap: .1rem .9rem;
  margin: 0; padding: 0; list-style: none; font-weight: 600;
}
.header__nav-top li ul { display: none; }

.header__date { color: var(--suave); white-space: nowrap; }
.header__date:empty { display: none; }   /* sin JavaScript no ocupa lugar */

/* --- el menu ----------------------------------------------------------------
 * ES UNA LISTA (`docs/30`), y eso no es prolijidad: un menu con hijos es una
 * lista adentro de otra, y quien navega con lector de pantalla escucha "lista de
 * 7 elementos" en vez de siete enlaces sueltos. */
.header__nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: 1.1rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-family: var(--f-secundaria);
  font-size: .82rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.header__nav li { position: relative; }
.header__nav a { display: block; padding: .45rem 0; border-bottom: 2px solid transparent; }
.header__nav a:hover { border-bottom-color: var(--acento); text-decoration: none; }

/* La barra propia del menu, cuando la variante lo pone abajo. */
.header__navbar { border-top: 1px solid var(--linea); }

/* EL DESPLEGABLE, SIN JAVASCRIPT. Se abre al pasar por encima y —esto es lo que
 * casi siempre falta— tambien al llegar con el teclado, que es `:focus-within`.
 * Un menu que solo responde al mouse deja afuera a quien no usa mouse. */
.header__nav li ul {
  display: none;
  position: absolute;
  top: 100%;
  left: -.6rem;
  z-index: 5;
  flex-direction: column;
  gap: 0;
  min-width: 11rem;
  padding: .3rem 0;
  background: var(--fondo);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .12);
}
.header__nav li:hover > ul,
.header__nav li:focus-within > ul { display: flex; }
.header__nav li ul a { padding: .35rem .6rem; border-bottom: 0; text-transform: none; }
.header__nav li ul a:hover { background: var(--fondo-alt); }


/* --- el cajon del menu (variante `franja`) -----------------------------------
 * SIN JAVASCRIPT: es un `<details>`. Abre, cierra, responde al teclado y le
 * anuncia su estado a un lector de pantalla sin una linea de guion. Demo lo
 * resuelve con `menu-toggle` + `mobile-menu` + overlay + listeners, y si su
 * guion no carga, el menu no existe. */
.header__drawer { position: relative; }

/* LOS DOS INTERRUPTORES DE LA CABECERA —hamburguesa y lupa— SE ESTILIZAN JUNTOS.
 * Son el mismo control: un `<summary>` que abre un panel. Escribirlos dos veces
 * es como terminaron los botones del gestor en seis lugares (`docs/22`).
 *
 * Redondo y de 2.5rem, como el de demo: un area de toque comoda sin un recuadro
 * que compita con la marca. */
.header__drawer > summary,
.header__search > summary {
  display: flex; align-items: center; justify-content: center;
  /* Por encima de su propia superposicion: si no, el boton queda tapado por lo
     que el mismo dibuja y el cajon no se puede cerrar desde el boton. */
  position: relative;
  z-index: 11;
  list-style: none;               /* saca el triangulito de Firefox */
  width: 2.5rem; height: 2.5rem;
  cursor: pointer;
  color: var(--texto);
  border-radius: 50%;
  transition: color .2s ease, background-color .2s ease;
}
.header__drawer > summary::-webkit-details-marker,
.header__search > summary::-webkit-details-marker { display: none; }
.header__drawer > summary:hover,
.header__search > summary:hover { background: var(--fondo-alt); color: var(--primario); }
.header__drawer > summary svg { width: 1.5rem; height: 1.5rem; }
.header__search > summary svg { width: 1.35rem; height: 1.35rem; }
/* EL CAJON OCUPA TODO EL ALTO Y ENTRA DESDE LA IZQUIERDA, como el de demo. Lo
   pidio Hernan mirando el primero, que era un panel chico que caia del boton.
   La diferencia no es estetica: un panel de 15rem con quince secciones obliga a
   deslizar adentro de una cajita; uno de alto completo muestra el menu entero.

   Y SIGUE SIN JAVASCRIPT. El panel es `position: fixed` y la superposicion es
   un `::before` del mismo `<details>`, asi que abrir y cerrar lo sigue haciendo
   el navegador. Demo necesita el guion para las tres cosas. */
/* LA SUPERPOSICION ES DEL <summary> Y NO DEL <details>, y esa es toda la
   diferencia entre un cajon que se cierra y uno que no.

   Lo encontro Hernan probandolo: *"no se puede cerrar el cajon"*. Colgada del
   <details>, la superposicion tapaba TAMBIEN el boton —es `position: fixed` y
   cubre la pantalla entera—, asi que el segundo clic no le llegaba nunca al
   unico elemento que puede cerrarlo. Y un clic en el `<details>` no lo cierra:
   solo el `<summary>` alterna.

   Colgada del `<summary>`, la superposicion ES el summary a los efectos del
   clic: tocar cualquier parte de la pantalla cierra el cajon, que es lo que
   hace demo con su overlay y sus listeners. Acá lo hace el navegador. */
.header__drawer[open] > summary::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 9;
  background: rgba(0, 0, 0, .45);
}
.header__drawer-panel {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  /* POR ENCIMA DEL BOTON, y por lo tanto de la superposicion que el boton
     dibuja. Estaba en 10 —debajo del boton, que esta en 11— y el resultado fue
     el que reporto Hernan: *"queda todo oscuro incluido el cajon"*. La
     superposicion vive adentro del `<summary>`, asi que hereda su altura: para
     que el panel no quede tapado tiene que estar por encima de los dos. */
  z-index: 12;
  width: min(21.25rem, 85vw);   /* los 340px de demo */
  overflow-y: auto;
  background: var(--fondo);
  box-shadow: 0 0 40px rgba(0, 0, 0, .25);
}
/* LA CABECERA DEL PANEL: la marca y el boton de cerrar, como el cajon de demo.
   Sin esto el panel es una lista de enlaces flotando — no dice de que sitio es
   ni donde se cierra. La marca es la MISMA funcion que la de la cabecera
   (`marcaHtml`), asi que cargar un logo cambia los dos lugares a la vez. */
/* LA CABECERA DEL PANEL VA INVERTIDA, como la franja y como la de demo. Por eso
   la marca de acá es el LOGO INVERSO y no el principal (`marco.ts`): sobre tinta,
   un logo de letras oscuras no existe. */
.header__drawer-head {
  display: flex; align-items: center;
  padding: 1rem 1.2rem;
  background: var(--texto);
  color: var(--fondo);
}
.header__drawer-brand { display: block; }
.header__drawer-brand img { display: block; width: auto; height: calc(var(--logo-alto) * .56); max-width: 9.5rem; }
/* El nombre en texto, cuando no hay logo: no se estiliza igual que una imagen
   —necesita la tipografia y un tamaño— y por eso `marcaHtml` lo marca aparte. */
.header__drawer-brand--texto {
  font-family: var(--f-principal); font-size: 1.05rem; font-weight: 700;
  color: inherit; text-decoration: none;
}
/* EL MENU DEL CAJON ES VERTICAL, y por eso pisa el `flex` horizontal de
   `.header__nav`: es la MISMA lista, acomodada como lista. Los hijos van
   sangrados adentro del padre en vez de en un desplegable, que es lo unico
   sensato en una columna angosta. */
/* `text-align: left` NO es decoración: la variante `franja` centra su fila
   principal, y ese centrado se hereda adentro del cajón — un menú vertical
   centrado se lee como una lista de opciones sueltas, no como navegación. */
.header__drawer-panel { text-align: left; }
.header__drawer-panel .header__nav ul { flex-direction: column; gap: 0; }
/* CADA SECCION ES UNA FILA CON SU LINEA, como el cajon de demo: en una columna
   angosta la separacion la tiene que dar la linea, no el aire — con aire solo,
   quince secciones se leen como un bloque de texto. */
.header__drawer-panel .header__nav li { border-bottom: 1px solid var(--linea); }
.header__drawer-panel .header__nav a {
  padding: .95rem 1.2rem;
  border-bottom: 0;
  transition: padding-left .2s ease, background-color .2s ease, color .2s ease;
}
/* EL DESPLAZAMIENTO AL PASAR POR ENCIMA es de demo y vale la pena: en una lista
   vertical de items iguales, mover el que esta debajo del cursor es lo que dice
   cual esta activo mejor que un cambio de color. */
.header__drawer-panel .header__nav a:hover {
  background: var(--fondo-alt);
  color: var(--primario);
  padding-left: 1.7rem;
  text-decoration: none;
}
.header__drawer-panel .header__nav li ul {
  display: flex;
  position: static;
  border: 0; box-shadow: none; padding: 0; min-width: 0; background: none;
}
.header__drawer-panel .header__nav li ul a {
  padding-left: 2rem;
  text-transform: none;
  font-weight: 500;
  color: var(--suave);
}

/* --- el buscador ------------------------------------------------------------
 * UNA LUPA QUE ABRE UN PANEL, y no un campo permanente al lado de la marca.
 *
 * Era la diferencia visual mas grande que quedaba contra demo, y no es capricho:
 * en un diario lo que manda arriba es la marca, y un campo de texto fijo le come
 * el lugar. Con la lupa la cabecera queda limpia y la busqueda sigue a un clic.
 *
 * MISMO MECANISMO QUE EL CAJON —`<details>`, superposicion colgada del summary—
 * asi que abre, cierra y responde al teclado sin una linea de guion. Lo unico
 * que el guion agrega es el foco al abrir y `Esc` para cerrar. */
.header__search { position: relative; }
.header__search[open] > summary::before {
  content: '';
  position: fixed; inset: 0; z-index: 9;
  /* CASI NEGRO Y NO UN GRIS: la busqueda tapa el sitio entero a proposito, que
     es lo que hace que el campo se lea como lo unico que hay. Es el valor de
     demo (`rgba(0,0,0,.92)`) y es una veladura, no un color de marca — por eso
     es literal y no un token: sobre ella lo unico legible es el blanco, sea cual
     sea la paleta del cliente. */
  background: rgba(0, 0, 0, .92);
}
/* EL PANEL NO TIENE FONDO: el fondo es la veladura de arriba, que cuelga del
   `<summary>` y por eso cierra al tocarla. El panel es solo el contenido,
   centrado y por encima.

   `pointer-events` es lo que hace que las dos cosas convivan: el panel ocupa la
   pantalla entera para poder centrar, pero deja pasar el click; solo el
   formulario y el boton de cerrar lo reciben. Sin esto, tocar "afuera" tocaria
   el panel y no cerraria nada.

   Y NADA DE `transform` ACA: un `position: fixed` adentro de un elemento
   transformado se posiciona contra ESE elemento y no contra la pantalla, asi
   que la X del rincon se iria al centro. Se centra con flex. */
.header__search-panel {
  position: fixed; inset: 0; z-index: 12;
  display: flex; align-items: center; justify-content: center;
  padding: 1.5rem;
  pointer-events: none;
}
.header__search-panel form {
  pointer-events: auto;
  display: flex; align-items: center; gap: .8rem;
  width: min(44rem, 90vw);
  padding-bottom: .6rem;
  border-bottom: 2px solid rgba(255, 255, 255, .22);
}
.header__search-panel form:focus-within { border-bottom-color: var(--acento); }
.header__search-panel input {
  flex: 1 1 auto; min-width: 0;
  border: 0; outline: none; background: none;
  padding: .3rem 0;
  font-family: var(--f-principal);
  font-size: clamp(1.3rem, 5vw, 2.1rem);
  font-weight: 300;
  color: #fff;
}
.header__search-panel input::placeholder { color: rgba(255, 255, 255, .3); }
.header__search-panel button[type="submit"] {
  border: 0; background: none; cursor: pointer;
  padding: .4rem 0;
  font-family: var(--f-secundaria); font-size: .8rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .14em;
  color: rgba(255, 255, 255, .5);
}
.header__search-panel button[type="submit"]:hover { color: #fff; }

/* --- cerrar: el unico control del marco que necesita guion -------------------
 * ESCONDIDO HASTA QUE EL GUION MARCA EL DOCUMENTO. `<details>` no se cierra
 * desde adentro sin JavaScript, asi que sin guion este boton no haria nada — y
 * un boton que no hace nada es peor que no tenerlo. Sin el no falta nada: los
 * dos paneles se cierran tocando afuera. */
.header__close { display: none; }
.js .header__close {
  display: flex; align-items: center; justify-content: center;
  width: 2.2rem; height: 2.2rem;
  margin-left: auto;
  border: 0; border-radius: 50%;
  background: none; color: inherit; cursor: pointer;
  opacity: .6;
  /* GIRA AL PASAR POR ENCIMA, como el de demo. Es de las pocas animaciones que
     dicen algo: una X que gira noventa grados es la misma forma, y eso se lee
     como "esto se cierra" y no como un adorno. */
  transition: opacity .2s ease, transform .2s ease;
}
.js .header__close:hover { opacity: 1; transform: rotate(90deg); }
.header__close svg { width: 1.3rem; height: 1.3rem; }
/* En la busqueda va al rincon de la pantalla —no al lado del campo— porque el
   campo esta centrado y una X pegada a el se lee como parte del formulario.
   `pointer-events` porque el panel los deja pasar (ver arriba). */
.js .header__search-panel .header__close {
  pointer-events: auto;
  position: absolute; top: 1.4rem; right: 1.4rem;
  margin-left: 0;
  width: 2.6rem; height: 2.6rem;
  color: #fff;
}

/* --- las redes ---------------------------------------------------------------
 * SIN ICONOS TODAVIA, y es una decision escrita en `marco.ts`: un glifo de marca
 * mal dibujado se ve peor que la palabra. El `data-red` ya viaja en el HTML, asi
 * que el dia que haya juego de iconos entra por acá sin tocar el render. */
.social {
  display: flex;
  flex-wrap: wrap;
  gap: .1rem .9rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-family: var(--f-secundaria);
  font-size: .72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
}
.social a { display: flex; align-items: center; gap: .35rem; color: var(--acento); }
/* EL ICONO MANDA Y EL NOMBRE ACOMPAÑA. El nombre NO se saca del HTML —se
   esconde— por tres razones: la pagina se lee sin la hoja, el buscador ve texto
   y un lector de pantalla anuncia "Instagram" y no "enlace". */
.social__icon { width: 1.05em; height: 1.05em; flex: 0 0 auto; }
.social a span {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.footer .social a { gap: .4rem; }
.footer .social__icon { width: 1.25em; height: 1.25em; }
/* Adentro de la cabecera NUNCA envuelven: al lado del buscador o en la franja,
   una segunda linea de redes le cambia el alto a la cabecera entera. En el pie
   si envuelven, que es donde hay lugar. */
.header .social { flex-wrap: nowrap; }

/* --- los slots ---------------------------------------------------------------
 * Vacios hoy y declarados igual (`docs/31`): retrofitear un slot en cuatro
 * variantes ya escritas es el caso que este diseño evita. No traen aspecto
 * propio — lo que va adentro lo escribe Sourtech. */
.slot { display: flex; align-items: center; }
.slot:empty { display: none; }

/* --- las cuatro cabeceras: lo unico que cambia -------------------------------- */

/* clasica — la marca a la izquierda, el menu en su barra. */
.header--clasica .header__main > .container { padding-block: var(--aire-chico) calc(var(--aire-chico) * .6); }

/* centrada y franja — LA MARCA EN SU PROPIA FILA, y esto se aprendio mirandolo.
 *
 * El primer intento fue una fila de tres columnas (`1fr auto 1fr`) para que la
 * marca quedara al medio. Falla de las dos formas posibles y no hay tercera: con
 * `1fr` las columnas no bajan de su contenido, asi que el buscador y las redes
 * de un solo lado le corren el centro a la marca; con `minmax(0, 1fr)` el centro
 * queda bien y la marca **se le monta encima** a las redes.
 *
 * La causa no era la rejilla: es que con un nombre largo y tres piezas
 * encendidas **no entra todo en una fila**. Dos filas —piezas arriba, marca
 * grande abajo— es lo que hacen gente y demo en Amura, y no puede chocar por
 * construccion. */
.header--centrada .header__main > .container {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-areas: "izq der" "marca marca";
  gap: .4rem 1rem;
  padding-block: var(--aire-chico) var(--aire);
  text-align: center;
}
.header--centrada .header__left { grid-area: izq; justify-self: start; }
.header--centrada .header__right { grid-area: der; justify-self: end; margin-left: 0; }
.header--centrada .header__brand { grid-area: marca; }
/* Vacios NO se ocultan acá: son celdas de la rejilla, y esconderlas
   descolocaria la otra. */
.header--centrada .header__left:empty, .header--centrada .header__right:empty { display: block; }

/* franja — UNA SOLA FILA: hamburguesa, marca al medio, lupa. La de demo.
 *
 * ESTA VARIANTE COMPARTIA LA REJILLA DE DOS FILAS DE `centrada`, y el comentario
 * de arriba explica por que: *"con un nombre largo y tres piezas encendidas no
 * entra todo en una fila"*. **Eso dejo de ser cierto acá** el dia que el buscador
 * paso a ser una lupa: sus dos costados son ahora un icono y un icono, asi que
 * entra — y entra centrada de verdad.
 *
 * `flex: 1 1 0` en los dos costados y no `auto`: con `auto` cada lado mide lo que
 * su contenido y la marca queda corrida hacia el lado mas liviano. Con cero de
 * base los dos miden igual y el centro es el centro. Demo no hace esto y su logo
 * queda unos pixeles corrido; se ve al superponerlos. */
.header--franja .header__main > .container {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding-block: calc(var(--aire-chico) * 1.5);
}
.header--franja .header__left,
.header--franja .header__right { flex: 1 1 0; min-width: 0; margin-left: 0; }
.header--franja .header__right { justify-content: flex-end; }
/* Los costados NO se ocultan vacios: sostienen el centro. */
.header--franja .header__left:empty, .header--franja .header__right:empty { display: flex; }
.header--franja .header__brand { flex: 0 1 auto; min-width: 0; text-align: center; }

.header--centrada .header__navbar > .container, .header--franja .header__navbar > .container { display: flex; justify-content: center; }

/* compacta — todo en una fila: la marca baja de tamaño y el menu va al lado.
 *
 * LO QUE HAY QUE DECIDIR ACA, y que las otras tres no tienen que decidir: en una
 * sola fila **algo tiene que ceder**. Ceden el menu y las redes, que se
 * deslizan; NO cede la marca, que se parte en dos lineas y arruina la cabecera
 * — un diario que dice "El Diario del / Sur" se ve roto, no compacto.
 *
 * Se vio en el navegador con cinco secciones y las tres piezas encendidas: sin
 * esto, la marca en dos lineas, el menu en dos lineas y las redes en columna. */
.header--compacta .header__brand { font-size: 1.35rem; white-space: nowrap; }
.header--compacta .header__nav { margin-left: 1.5rem; flex: 1 1 auto; min-width: 0; }
.header--compacta .header__nav ul {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  /* EL DESVANECIDO NO ES ADORNO: una tira que se desliza sin barra parece una
     lista cortada. El ultimo item a medio tono es lo que dice "sigue". */
  mask-image: linear-gradient(to right, #000 88%, transparent);
}
.header--compacta .header__nav ul::-webkit-scrollbar { display: none; }
.header--compacta .header__nav li { flex: 0 0 auto; }
.header--compacta .header__right { flex: 0 0 auto; }

/* --- angosto ----------------------------------------------------------------
 * NO HAY HAMBURGUESA, y es a proposito (`marco.ts`): el menu se vuelve una tira
 * que se desliza. Sin JavaScript, sin un estado que abrir y cerrar, y con las
 * secciones a la vista en vez de escondidas atras de tres rayas. */
@media (max-width: 60rem) {
  .header--centrada .header__main > .container { grid-template-columns: 1fr; gap: .6rem; }
  .header--centrada .header__left, .header--centrada .header__right { justify-self: center; }
  /* `franja` NO cambia de forma en angosto: una fila de tres con dos iconos es
     exactamente lo que un telefono necesita, y es la unica variante que ya
     nacio asi. Lo unico que cede es el alto de la marca. */
  .header--franja .header__brand img { height: calc(var(--logo-alto) * .7); }
  .header--compacta .header__main > .container { flex-wrap: wrap; }
  .header--compacta .header__nav { margin-left: 0; order: 3; width: 100%; }

  .header__nav ul {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    mask-image: linear-gradient(to right, #000 88%, transparent);
  }
  .header__nav ul::-webkit-scrollbar { display: none; }
  .header__nav li { flex: 0 0 auto; }
  /* Un desplegable no se puede desplegar adentro de una tira que se desliza: el
     padre recorta. Los hijos pasan a ser items mas de la tira. */
  .header__nav li ul {
    display: flex;
    position: static;
    flex-direction: row;
    border: 0;
    box-shadow: none;
    padding: 0;
    min-width: 0;
    background: none;
  }
  .header__nav li ul li { margin-left: 1.1rem; }
  .header__nav li ul a { text-transform: uppercase; opacity: .75; }
  .header__search input { flex-basis: 8rem; }
}

/* --- el pie ------------------------------------------------------------------ */
.footer {
  border-top: 1px solid var(--linea);
  margin-top: calc(var(--aire) * 1.5);
  background: var(--fondo-alt);
  font-family: var(--f-secundaria);
  font-size: .85rem;
  color: var(--suave);
}
.footer > .container { padding-block: var(--aire); }
.footer a { color: inherit; }
.footer a:hover { color: var(--acento); text-decoration: none; }

.footer__nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem 1.2rem;
  margin: 0 0 var(--aire-chico);
  padding: 0;
  list-style: none;
  font-weight: 600;
}
/* En el pie va lo institucional, que se lee — no se explora. Los hijos de un
   item no se despliegan acá; para eso esta el pie "en columnas". */
.footer__nav li ul { display: none; }

/* LA LINEA DE ABAJO: copyright y legales. Los legales son un SEGUNDO menu
   (), como en el pie de demo, que lee dos navs distintos. */
.footer__bottom {
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: space-between; gap: .3rem 1.5rem;
  margin-top: var(--aire-chico);
  padding-top: var(--aire-chico);
  border-top: 1px solid var(--linea);
}
.footer__copy { margin: 0; font-size: .8rem; }
.footer__legal ul {
  display: flex; flex-wrap: wrap; gap: .2rem 1.1rem;
  margin: 0; padding: 0; list-style: none; font-size: .78rem;
}
.footer__legal li ul { display: none; }

/* --- las cuatro variantes de pie ---------------------------------------------- */

/* minimo — una linea. Sin fondo propio: se apoya en la pagina. */
.footer--minimo { background: none; }
.footer--minimo .footer__bottom { margin-top: 0; padding-top: 0; border-top: 0; }

/* columnas — cada item de primer nivel es una columna con sus hijos (`docs/30`). */
.footer__cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--aire);
  margin-bottom: var(--aire);
}
.footer__col-title {
  margin: 0 0 .4rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  font-size: .76rem;
  color: var(--primario);
}
.footer__col ul { margin: 0; padding: 0; list-style: none; }
.footer__col li { padding: .18rem 0; }

/* institucional — el pie completo de un diario: quien lo dirige, desde cuando
   sale y como se lo contacta. Son DATOS y no aspecto, asi que las lineas que no
   estan cargadas no salen (`marco.ts`). */
/* Mismo par que en la cabecera: la base vale para las dos formas y el `--texto`
   sólo para el nombre escrito. El pie usa el LOGO INVERSO (`marco.ts`) porque va
   sobre el fondo alterno, y uno con letras oscuras desaparece ahí. */
.footer__brand { display: block; color: var(--primario); margin-bottom: var(--aire-chico); }
.footer__brand--texto { font-family: var(--f-principal); font-size: 1.4rem; font-weight: 700; }
.footer__brand img { width: auto; height: calc(var(--logo-alto) * .75); max-width: 100%; }
/* DOS COLUMNAS Y NO UNA REJILLA QUE SE ACOMODA SOLA: a un lado quien dirige el
   diario y desde cuando sale; al otro, como escribirle. Es el reparto del pie de
   demo (`__info-text` / `__info-contact`) y **es lo que la clase por campo hace
   posible** — con `auto-fit` los cinco datos caian en el orden en que vienen y
   el telefono podia quedar debajo del director. */
.footer__info {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: .2rem 2.5rem;
  padding-block: var(--aire);
  font-size: .82rem;
}
/* EL REPARTO EN DOS COLUMNAS SOLO CUANDO HAY DOS COLUMNAS.
 *
 * Lo vio Hernan en el telefono: *"footer no se esta acomodando las columnas"*, y
 * era peor que un desprolijo — **era la mitad del scroll horizontal del sitio**.
 * Medido a 371px: el pie llegaba a 445.
 *
 * La causa es la mezcla de las dos formas de colocar en una grilla. Arriba,
 * `auto-fit` con `minmax(16rem, 1fr)` deja UNA sola columna cuando no entran dos.
 * Pero estas reglas mandan tres items a `grid-column: 2` **sin preguntar si esa
 * columna existe**: la grilla la crea implicita, fuera del contenedor, y ahi
 * nace el desborde.
 *
 * El corte es el mismo `34rem` que ya usa el resto de la hoja para el telefono, y
 * abajo de ahi los cinco datos caen apilados en el orden en que vienen — que es
 * el orden correcto para leerlos de arriba a abajo. */
@media (min-width: 34.01rem) {
  .footer__item--director, .footer__item--fundado { grid-column: 1; }
  .footer__item--email, .footer__item--telefono, .footer__item--direccion { grid-column: 2; }
}
.footer__item { margin: .2rem 0; }
.footer__item span { font-weight: 700; color: var(--primario); }
/* El contacto es un enlace con su trazo: sin rotulo, porque el icono ya dice
   que es. `align-items: center` y el icono sin encoger, que es lo que evita que
   una direccion larga lo aplaste. */
.footer__item--email, .footer__item--telefono {
  display: flex; align-items: center; gap: .55rem;
  margin: .3rem 0;
}
.footer__item--email svg, .footer__item--telefono svg {
  width: 1.05rem; height: 1.05rem; flex: 0 0 auto; opacity: .55;
}
.footer__item--email:hover svg, .footer__item--telefono:hover svg { opacity: 1; }
.footer__item--direccion { margin-top: .9rem; }

/* EL PIE INSTITUCIONAL VA INVERTIDO, como el de demo (`background: #1a1a1a`).
 *
 * Es el pie "completo" —marca, menu, redes, quien dirige y como escribirle— y
 * sobre el fondo alterno del sitio esa cantidad de informacion se lee como un
 * apendice gris. Invertido cierra la pagina: es la unica banda oscura de abajo
 * y hace juego con la franja de arriba en la combinacion `franja` +
 * `institucional`, que es la de demo.
 *
 * Y las tres variantes que no son esta se quedan como estaban: es una decision
 * de variante, igual que `minimo` que no lleva fondo. */
.footer--institucional {
  background: var(--texto);
  color: var(--fondo);
  border-top: 0;
}
.footer--institucional > .container { padding-block: calc(var(--aire) * 1.6) 0; }

/* La marca centrada y sola en su franja, que es lo que le da peso: es lo unico
   que hay en esa altura. */
.footer--institucional .footer__brand {
  margin: 0 0 calc(var(--aire) * 1.2);
  padding-bottom: var(--aire);
  border-bottom: 1px solid var(--linea-inv);
  color: inherit;
  text-align: center;
}
.footer--institucional .footer__brand img { margin-inline: auto; height: calc(var(--logo-alto) * .85); }

.footer--institucional .footer__nav ul { justify-content: center; gap: .5rem 1.9rem; margin: 0; }
.footer--institucional .footer__nav a { opacity: .7; }
.footer--institucional .footer__nav a:hover { opacity: 1; }

/* LAS REDES EN CIRCULO, que es la unica parte del pie de demo que es puro
   adorno y aun asi vale: son cinco enlaces del mismo tamaño y el circulo los
   convierte en una fila ordenada en vez de cinco palabras de largo distinto. */
.footer--institucional .social {
  justify-content: center;
  gap: 1rem;
  margin-top: var(--aire);
  padding-bottom: calc(var(--aire) * 1.3);
  border-bottom: 1px solid var(--linea-inv);
}
.footer--institucional .social a {
  justify-content: center;
  width: 2.4rem; height: 2.4rem;
  border: 1px solid var(--linea-inv);
  border-radius: 50%;
  color: inherit;
  opacity: .65;
}
.footer--institucional .social a:hover { opacity: 1; border-color: var(--acento); }

.footer--institucional .footer__info { border-bottom: 1px solid var(--linea-inv); }
.footer--institucional .footer__item { color: inherit; opacity: .6; }
.footer--institucional .footer__item span { color: inherit; opacity: .9; }
.footer--institucional .footer__item--email:hover, .footer--institucional .footer__item--telefono:hover {
  opacity: 1;
}
.footer--institucional .footer__bottom {
  border-top: 0;
  padding-block: var(--aire) calc(var(--aire) * 1.3);
  opacity: .45;
  font-size: .78rem;
}

/* --- buscador: la pagina de resultados -------------------------------------- */
.search { display: flex; gap: .5rem; margin: 0 0 1.5rem; }
.search label { position: absolute; left: -9999px; }
.search input { flex: 1 1 auto; min-width: 0; padding: .5rem .7rem; font: inherit; }
.search button { padding: .5rem 1rem; font: inherit; cursor: pointer; }
.results, .empty { color: var(--suave); font-size: .9rem; }
.bio { color: var(--suave); font-size: .95rem; margin: -.5rem 0 1.5rem; }

/* --- 404: la pagina que nadie quiere ver ------------------------------------
 *
 * Se centra y se angosta —no se estira al ancho del diario— porque no es un
 * listado: son cuatro cosas cortas que se leen de una. Y todo lo demas sale de
 * los mismos tokens que el resto del sitio, asi que cambia con el tema del
 * cliente sin tener que tocar nada aca. */
.e404 {
  max-width: 34rem;
  margin-inline: auto;
  padding-block: calc(var(--aire) * 2) var(--aire);
  text-align: center;
}
/* El numero grande, en el color de las lineas: se ve como una marca de agua y no
   compite con el titulo, que es lo que de verdad hay que leer. */
.e404__num {
  margin: 0;
  font-family: var(--f-principal);
  font-size: clamp(4rem, 15vw, 7.5rem);
  font-weight: 700;
  line-height: .85;
  color: var(--linea);
}
/* El `<h1>` va suelto y no con el trato de `main > h1` --el subrayado de titulo
   de seccion-- porque aca no encabeza un listado: es el centro de la pagina. */
.e404 h1 {
  margin: .3rem 0 .5rem;
  font-family: var(--f-principal);
  font-size: clamp(1.4rem, 3vw, 2rem);
  font-weight: 700;
  line-height: 1.15;
  color: var(--primario);
}
.e404__texto { margin: 0 0 var(--aire); color: var(--suave); }
.e404 .search { margin-bottom: .9rem; text-align: left; }
.e404__volver { font-size: .9rem; }
/* La linea de arriba separa "no encontramos lo que buscabas" de "esto si esta",
   que son dos mensajes distintos y seguidos se leen como uno solo. */
.e404__ultimas {
  margin-top: calc(var(--aire) * 2);
  padding-top: var(--aire);
  border-top: 1px solid var(--linea);
}
.e404__ultimas h2 {
  margin: 0 0 var(--aire);
  font-family: var(--f-principal);
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--primario);
}

main { padding-block: var(--aire) calc(var(--aire) * 2); }

/* --- grilla: wraps y zonas -------------------------------------------------- */
/* El wrap define cuantas zonas hay y como se reparten; el coltype (cols-N) define
   en cuantas columnas se acomoda el contenido DENTRO de la zona.

   CUATRO COLUMNAS PARA TODOS LOS WRAPS (2026-08-26), y cada zona se lleva las que
   declara con `grid-column: span N`. Antes cada wrap traia sus proporciones acá
   —`.wrap-2 { 3fr 1fr }`— o sea que una grilla nueva era una linea en `WRAPS` Y
   una regla en esta hoja, y el dia que no coincidieran no fallaba nada: salia
   otra portada.

   Y es lo que hace posible ANIDAR: un contenedor adentro de una zona es otro
   `.wrap` con las mismas cuatro columnas, aplicadas al ancho de esa zona. Por eso
   subdividir no necesita una grilla nueva — usa las que ya hay. */
.wrap {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: calc(1.75rem * var(--densidad));
  margin-bottom: calc(2.25rem * var(--densidad));
}

.zona { min-width: 0; display: flex; flex-direction: column; gap: var(--aire); }
/* Cuantas columnas se lleva la zona. Es el mismo numero que el `cols-N` que ya
   usaba el contenido de adentro, asi que no hay una segunda escala que aprender. */
.zona.cols-1 { grid-column: span 1; }
.zona.cols-2 { grid-column: span 2; }
.zona.cols-3 { grid-column: span 3; }
.zona.cols-4 { grid-column: span 4; }
/* UN CONTENEDOR ADENTRO DE UNA ZONA (`Pieza` en `render/portada.ts`).
   Es un `.wrap` normal —o sea la misma grilla de cuatro columnas, aplicada al
   ancho de la zona— con dos ajustes: sin el margen de abajo, porque el hueco
   entre piezas ya lo pone la zona, y sin sangrar a pantalla completa, que
   adentro de una columna angosta derramaria el color sobre lo de al lado. */
.wrap--dentro { margin-bottom: 0; }

/* --- encabezado de modulo --------------------------------------------------- */
/* EL TITULO DE MODULO ES UN TITULO, no una etiqueta.
 *
 * Era una linea chica en mayusculas del color de acento, con un filete arriba —
 * el recurso de cualquier tema gratuito. Demo lo trata al reves y tiene razon:
 * **grande, con la tipografia de los titulares, en el color del texto**, y el
 * color de marca aparece solo en el filete de abajo y al pasar por encima. Asi
 * "Deportes" pesa lo que pesa una seccion del diario en vez de leerse como el
 * rotulo de un widget.
 *
 * EL FILETE VA ABAJO Y NO ARRIBA: arriba separa el modulo del que esta encima
 * —que ya estaba separado por el aire— y abajo hace lo unico que hace falta,
 * que es unir el titulo con las notas que lo siguen. */
.heading {
  margin-bottom: var(--aire);
  padding-bottom: .35rem;
  border-bottom: 2px solid var(--primario);
}
.heading h2 {
  margin: 0;
  font-family: var(--f-principal);
  font-size: clamp(1.15rem, 2vw, 1.5rem);
  font-weight: 700;
  line-height: 1.1;
  color: var(--primario);
}
.heading a:hover { color: var(--acento); text-decoration: none; }

/* --- partials --------------------------------------------------------------- */
/* LA FOTO DE UNA TARJETA LLEVA EL RADIO DEL CLIENTE. Es el unico lugar donde
   `--radio` se nota de verdad en la portada, y es lo que separa un sitio de
   esquinas duras de uno amable sin que nadie escriba un pixel. Va en la
   `<figure>` Y en la imagen: sin el segundo, la foto se desborda del recorte. */
.card figure { margin: 0 0 .8rem; border-radius: var(--radio); overflow: hidden; }
.card figure img { border-radius: var(--radio); }
/* Un toque al pasar por encima: la foto se acerca un poco. Es lo que dice que la
   tarjeta entera es un enlace, sin tener que subrayar el titular. */
.card figure img { transition: transform .35s ease; }
.card:hover figure img { transform: scale(1.03); }

.kicker {
  margin: 0 0 .35rem;
  font-family: var(--f-secundaria);
  font-size: .72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--acento);
}
/* EL TITULO ES `primario` Y LA BAJADA ES `texto`, y no es una eleccion de esta
   hoja: es el rol que `docs/31` le asigno a cada pieza. El cliente no elige el
   color de un titulo — elige que es el primario, y todos los titulos del sitio
   se mueven juntos. */
.title {
  margin: 0;
  font-family: var(--f-principal);
  font-weight: 700;
  line-height: 1.15;
  color: var(--primario);
}
.title a:hover { color: var(--acento); text-decoration: none; }
/* LA BAJADA CON LA TIPOGRAFIA DE TEXTO y no con la de rotulos: es prosa, se lee
   en renglones, y con la secundaria —que suele ser una de palo seco pensada
   para etiquetas— compite con el titular en vez de acompañarlo. Es lo que hace
   demo, que la pone en su tercera familia. */
.excerpt {
  margin: .45rem 0 0;
  font-family: var(--f-texto);
  font-size: .95rem;
  line-height: 1.5;
  color: var(--suave);
}
.byline { margin: .5rem 0 0; font-size: .76rem; font-weight: 600; color: var(--suave); }
.byline a:hover { color: var(--acento); }
time { display: block; margin-top: .2rem; font-size: .72rem; color: var(--suave); }
.section {
  font-family: var(--f-secundaria);
  font-size: .7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--acento);
}
.section:hover { text-decoration: none; opacity: .75; }
article .info { margin-top: 0; }

/* --- los modulos de portada (`render/catalogo.ts`) ---------------------------
 *
 * LAS CLASES LLEVAN NOMBRE Y NO NUMERO (`mod--noticias`, no `box-23`). Lo pidio
 * Hernan: *"puse ids porque los manejaba en tablas todos los modulos que existen,
 * pero podemos ponerle nombres sin problemas"*. Una hoja que dice `.box-45`
 * obliga a abrir otro archivo para saber de que habla.
 *
 * Y LA DISPOSICION ES DEL PRODUCTO, NO DEL MODULO: `.d-derecha` significa lo
 * mismo en el destacado y en la grilla, porque los dibuja la misma funcion. Eso
 * es lo que permite que el editor ofrezca "foto a la derecha" sin explicar en
 * cual de los dos se ve distinto. */

/* LAS CUATRO DISPOSICIONES, en un solo lugar para todos los modulos con foto.
   Van ANTES de los bloques por modulo: `.nota.d-derecha` y
   `.mod--noticias.es-apertura .d-derecha` tienen la MISMA especificidad, asi que si lo
   compartido va despues le pisa el ajuste al modulo. Se vio con el destacado
   saliendo con una columna de texto de 8rem.

   `abajo` no necesita regla: es el orden natural del DOM (el render emite el
   texto primero), y una regla que repite lo que ya pasa es una regla que despues
   alguien tiene que entender. */
/* ⚠️ LA FOTO AL COSTADO SE MIDE EN PROPORCION A LA TARJETA, no en `rem`.
   Estaba en `8rem` fijas y lo cobró el listado vertical: *"en los listados
   verticales la imagen queda muy chica"*. Y era cierto — 8rem es una MINIATURA,
   pensada para una tarjeta de un tercio de ancho. En un listado de a una la
   tarjeta mide el sitio entero y la misma foto queda perdida al costado.

   PERO 18rem FIJAS ROMPEN EL OTRO LADO: la misma clase la usa un modulo de
   portada con cuatro por fila, donde 18rem son mas anchas que la tarjeta
   entera. Es la lección que `escalaDe` ya tiene escrita para el recorte: **lo
   que decide el tamaño de la foto es cuanto mide la tarjeta**, y acá el ancho
   estaba escrito como si todas midieran lo mismo.

   `min(18rem, 34%)` dice las dos cosas de una: el 34% sigue a la tarjeta —en
   una de un tercio da 128px, o sea las 8rem de siempre— y el tope de 18rem
   evita que a ancho completo la foto se coma la mitad del renglon. En un
   teléfono se achica sola, sin media query: el 34% ya es de un ancho chico. */
.card.d-derecha {
  display: grid; grid-template-columns: 1fr min(18rem, 34%); gap: .9rem; align-items: start;
}
.card.d-izquierda {
  display: grid; grid-template-columns: min(18rem, 34%) 1fr; gap: .9rem; align-items: start;
}
.card.d-derecha .info, .card.d-izquierda .info { margin-top: 0; }
.card.d-sin-foto .info { margin-top: 0; }

/* LA FIRMA Y LA FECHA VAN AL PIE DE LA TARJETA, no debajo de la bajada.
 *
 * LO TRAJO HERNAN mirando su home: dos notas en la misma fila, *"la segunda, al
 * ser mas cuadrada, quedan mal los altos"*. Las fotos estaban bien —medidas: 378
 * y 377 px, el mismo recorte, la misma caja— y los dos titulares empezaban a la
 * misma altura. Lo que se desalineaba era **todo lo que viene despues**: un
 * titular de dos lineas y otro de una corren la bajada y la fecha 28 px, y en una
 * fila de dos eso se lee como si las tarjetas midieran distinto.
 *
 * NO SE RECORTA EL TITULAR PARA EMPAREJARLO. Amura lo resuelve asi (`limitText(3)`
 * en su LESS) y es la solucion que cuesta lo que no se ve: un titular cortado con
 * puntos suspensivos es la redaccion perdiendo la ultima palabra de su titulo,
 * decidido por una hoja de estilos.
 *
 * Con la firma abajo, el hueco que sobra queda ENTRE la bajada y la firma —donde
 * se lee como aire— en vez de correr la ultima linea de cada tarjeta.
 *
 * VALE PARA CUALQUIER TARJETA, incluida la del listado de seccion —que no lleva
 * clase de disposicion y tenia el mismo problema. `derecha` e `izquierda` son una
 * grilla de dos columnas cuyo texto ya alinea con la foto, asi que se pisan el
 * `display` mas abajo con mas especificidad.
 *
 * ⚠️ PERO `sobre` NO, Y ESTE COMENTARIO LO DECIA MAL. Decia que estaba "anclado
 * al pie de la imagen" y por eso cubierto — y esa mitad es cierta: su `.info` es
 * una columna con `justify-content: flex-end`. Lo que no es cierto es que eso lo
 * dejara afuera: **un margen automatico se come el hueco ANTES de que
 * `justify-content` lo reparta**, asi que el margen de la firma empujaba todo lo
 * demas para ARRIBA. El titular quedaba pegado al borde de la foto y la firma
 * abajo, con un agujero en el medio.
 *
 * Lo reporto Hernan mirando su `/dolar`: *"cuando es con texto sobre la imagen el
 * titulo lo pone arriba y el resto abajo, deberia estar todo junto abajo"*. El
 * guardia estaba puesto en la regla del `display` y faltaba en estas tres, que
 * son las que de verdad mueven las piezas. */
/* LA TARJETA ENTERA LLEVA A LA NOTA, y la foto es la mitad de eso.
 *
 * LO TRAJO HERNAN mirando el rotador: *"no se puede hacer click a la nota"*. Y
 * era cierto ahi y en todo el resto del sitio — medido con `elementFromPoint`
 * sobre la home: en una tarjeta de 670x287, **lo unico clickeable eran los dos
 * renglones del titular**. La foto, que ocupa el 80%, no era un enlace en ningun
 * modulo ni en ningun listado.
 *
 * Se nota mas en «texto sobre la foto» porque ahi la tarjeta ES la foto y parece
 * un boton entero, pero el problema no era de esa disposicion: en un diario,
 * hacer clic en la foto es el gesto mas natural que hay.
 *
 * SE RESUELVE ESTIRANDO EL ENLACE QUE YA EXISTE, no envolviendo la tarjeta en
 * otro. Envolverla anidaria enlaces —adentro estan la seccion y la firma, que
 * llevan a otro lado— y eso no es HTML valido ni se puede navegar con el
 * teclado. Con el `::after` hay **un solo enlace**, que es el titular: es lo que
 * anuncia un lector de pantalla y lo unico que tiene que ser.
 *
 * Los enlaces de adentro suben con `position: relative` para quedar por encima
 * de la capa estirada; si no, la seccion y el autor dejarian de funcionar y
 * habriamos cambiado un problema por otro. */
.card { display: flex; flex-direction: column; position: relative; }
/**
 * LA CAPA QUE HACE CLICKEABLE LA TARJETA ENTERA, Y SU `z-index`, QUE ES UN BUG
 * ARREGLADO.
 *
 * Hernan lo reporto TRES veces —*"el modulo rotador sigue sin link a la nota"*— y
 * las dos primeras no se pudo reproducir: medido punto por punto sobre el sitio
 * publicado, la tarjeta era clickeable entera. La tercera trajo el dato que
 * faltaba: **"hace hover y elimina el titulo"**.
 *
 * Y ahi se ve. `.card:hover figure img { transform: scale(1.03) }` **convierte a
 * la imagen en un contexto de apilado** —un elemento transformado pinta como si
 * estuviera posicionado— y en las disposiciones donde el TEXTO VA PRIMERO en el
 * DOM (`sobre`, `abajo`, `derecha`; ver `primeroLaFoto` en `catalogo.ts`) la
 * figura queda DESPUES, asi que al pasar el mouse se pinta encima del texto y de
 * esta capa. En `sobre`, que superpone los dos, el titular literalmente
 * desaparece; en las otras, el enlace deja de responder sobre la foto.
 *
 * Por eso no se veia midiendo: `elementFromPoint` sin el mouse encima no aplica
 * `:hover`, asi que la capa estaba donde tenia que estar. **El bug solo existe
 * mientras el puntero esta sobre la tarjeta — o sea siempre que alguien va a
 * hacer clic.**
 *
 * `z-index: 1` la deja por encima de la figura transformada (que pinta como 0).
 */
.card .title a::after { content: ''; position: absolute; inset: 0; z-index: 1; }
.card .section, .card .byline a { position: relative; }
.card:not(.d-sobre) > .info { display: flex; flex-direction: column; flex: 1; }
/* UN SOLO MARGEN AUTOMATICO POR TARJETA: dos se reparten el hueco a la mitad y
   dejarian la firma flotando en el medio. La firma lo lleva siempre —va justo
   antes de la fecha (`info` en `catalogo.ts`)— y la fecha lo toma solo cuando
   viene sin firma, o sea cuando sigue directo al titular o a la bajada.

   SE DICE CON HERMANOS ADYACENTES Y NO CON `:has()` A PROPOSITO. Con `:has()` se
   escribe en una linea, pero un navegador que no lo entienda **descarta la regla
   entera** y la tarjeta vuelve a quedar como estaba, sin que nada avise. Esto es
   lo unico de la hoja que arregla un defecto que se reporto, asi que no puede
   depender de un selector moderno; `+` lo entiende cualquier cosa. */
.card:not(.d-sobre) .info > .byline { margin-top: auto; }
.card:not(.d-sobre) .info > .title + time,
.card:not(.d-sobre) .info > .excerpt + time { margin-top: auto; }

/* TEXTO SOBRE LA FOTO. Lo pidió Hernán como una disposición más —*"agreguemos la
   opción texto sobre imagen, así como ofrecemos foto derecha, izquierda"*— y es
   exactamente eso: la misma tarjeta con las mismas partes, acomodadas encima.

   EL DEGRADADO NO ES ADORNO: es lo único que garantiza que el titular se lea
   sobre CUALQUIER foto. Sin él, una foto clara con texto blanco es texto
   invisible, y quién sube la foto no puede saberlo de antemano.

   Y los colores se redefinen como VARIABLES y no pieza por pieza: es el mismo
   recurso que `.wrap.sobre-oscuro` — todo lo de adentro ya lee estas variables,
   así que ninguna parte tiene que saber que está parada sobre una foto. */
.card.d-sobre { position: relative; display: block; }
.card.d-sobre figure { margin: 0; }
/* EL TEXTO OCUPA LA TARJETA ENTERA Y SE APOYA ABAJO, en vez de ser una franja
   pegada al pie. Se ve exactamente igual —el degradado ya era transparente
   arriba— y arregla lo que no se veia:

   la capa que estira el enlace del titular (`.card .title a::after`) se ancla al
   ANTECESOR POSICIONADO MAS CERCANO, y acá ése era `.info`. O sea que en «texto
   sobre la foto» el enlace se estiraba sobre la franja de texto y **la foto
   seguia sin ser clickeable**: medido, 5 de 25 puntos de la tarjeta llevaban a la
   nota, contra 25 de 25 en las demas disposiciones.

   Con `inset: 0` el ancla pasa a cubrir la tarjeta, que es lo que hace falta. */
.card.d-sobre .info {
  /* Por encima de la foto TAMBIEN CON EL MOUSE ENCIMA: al escalarse, la imagen
     pasa a pintar como un elemento posicionado y —al venir despues en el DOM—
     tapaba el texto entero. Ver el comentario de `.card .title a::after`. */
  z-index: 1;
  --primario: #fff;
  --texto: #fff;
  --suave: rgba(255, 255, 255, .82);
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  margin: 0;
  padding: calc(var(--aire) * .9) var(--aire) var(--aire);
  color: #fff;
  background: linear-gradient(to top, rgba(0, 0, 0, .82), rgba(0, 0, 0, .45) 55%, transparent);
  border-radius: var(--radio);
}
/* El acento propio del cliente puede ser ilegible sobre la veladura; la volanta
   y la sección van en blanco atenuado, que sobre negro siempre se lee. */
.card.d-sobre .kicker, .card.d-sobre .section { color: rgba(255, 255, 255, .9); }
/* Sin foto no hay nada sobre qué poner el texto: se comporta como una tarjeta
   normal en vez de dejar el titular flotando sobre el fondo del sitio. */
.card.d-sobre:not(:has(figure)) .info {
  position: static; background: none; padding: 0;
  --primario: initial; --texto: initial; --suave: initial; color: inherit;
}


/* LA GRILLA, CON SEPARADOR ENTRE COLUMNAS. Es la diferencia entre una grilla de
   diario y cuatro tarjetas sueltas: la linea fina dice que las cuatro notas son
   una unidad editorial. Sale de `--sep`, o sea que el cliente que eligio "sin
   separadores" no la tiene. */
.mod--noticias { display: grid; gap: var(--aire); }
.mod--noticias.cols-2 { grid-template-columns: repeat(2, 1fr); }
.mod--noticias.cols-3 { grid-template-columns: repeat(3, 1fr); }
.mod--noticias.cols-4 { grid-template-columns: repeat(4, 1fr); }
/* CINCO Y SEIS POR FILA: es el `noticias simple chica` de Amura, que a ancho
   completo pone cinco. Acá no es otro modulo — es el mismo con otro reparto
   (`columnasDe`). */
.mod--noticias.cols-5 { grid-template-columns: repeat(5, 1fr); }
.mod--noticias.cols-6 { grid-template-columns: repeat(6, 1fr); }
/* EL TAMAÑO DEL TITULAR, en tres pasos (`TEXTOS`), como MULTIPLICADOR y no como
   tres tamaños escritos.
 *
 * Con una variable el reparto y el tamaño son dos decisiones que se componen: el
 * titular de `cols-5` y el de `cols-1` miden distinto y los dos se agrandan lo
 * mismo. Escribiendo el tamaño en cada combinacion harian falta dieciocho reglas
 * y una tabla que mantener.
 *
 * Y ESCALA SOLO EL TITULAR: la volanta, la firma y la fecha se quedan donde
 * estan. Es lo que mantiene la jerarquia — agrandar todo junto no cambia nada,
 * solo hace la tarjeta mas grande. */
/* LA APERTURA: lo que era el módulo `destacado`, ahora una opción. Es la nota
   que abre la portada, asi que respira mas y su titular pesa mas — y con la
   foto al costado, la foto MANDA (3fr contra 2fr del texto). */
.mod--noticias.es-apertura { margin-block: calc(var(--aire) * .5); }
.mod--noticias.es-apertura .title { font-size: calc(2.1rem * var(--t)); line-height: 1.08; }
.mod--noticias.es-apertura .excerpt { font-size: 1.05rem; }
.mod--noticias.es-apertura .card.d-derecha { grid-template-columns: 2fr 3fr; align-items: center; }
.mod--noticias.es-apertura .card.d-izquierda { grid-template-columns: 3fr 2fr; align-items: center; }
/* Con la foto arriba o abajo, la foto ocupa todo el ancho y lo que se acota es
   el TEXTO: una linea de 90rem no se lee, una foto de 90rem si. */
.mod--noticias.es-apertura .card.d-arriba .info,
.mod--noticias.es-apertura .card.d-abajo .info { max-width: 46rem; }

.mod--noticias { --t: 1; }
.mod--noticias.t-chico { --t: .86; }
.mod--noticias.t-grande { --t: 1.28; }
.mod--noticias .title { font-size: calc(1.1rem * var(--t)); }
.mod--noticias.cols-1 .title { font-size: calc(1.6rem * var(--t)); }
.mod--noticias.cols-2 .title,
.mod--noticias.cols-3 .title { font-size: calc(1.2rem * var(--t)); }
.mod--noticias.cols-5 .title,
.mod--noticias.cols-6 .title { font-size: calc(.98rem * var(--t)); }
/* EL SEPARADOR SE ESCRIBE UNA VEZ PARA LAS DOS GRILLAS: la de un modulo de
   portada y la de un listado de seccion son la misma decision —tarjetas iguales
   en columnas— asi que comparten la regla en vez de tenerla escrita dos veces.
   Es la regla de `docs/22` aplicada al sitio: una decision visual, un lugar.

   El separador va en el hueco y no como borde de la tarjeta, asi no queda una
   linea colgando al final de cada fila.

   Y LA CUENTA TIENE QUE CERRAR: el margen negativo y el relleno son el MISMO
   valor, si no la primera tarjeta queda mas ancha que las demas. Se ve al
   instante con tres notas del mismo largo — la de la izquierda entra en dos
   lineas y las otras en tres. */
.mod--noticias.cols-2 .card + .card,
.mod--noticias.cols-3 .card + .card,
.mod--noticias.cols-4 .card + .card,
.mod--noticias.cols-5 .card + .card,
.mod--noticias.cols-6 .card + .card {
  border-left: var(--sep) solid var(--linea);
  padding-left: calc(var(--aire) * .5);
  margin-left: calc(var(--aire) * -.5);
}
/* EN UNA COLUMNA EL SEPARADOR ES HORIZONTAL, que es la misma regla que el corte
   de movil aplica a todas. Hacia falta al hacer configurable el listado: un
   «listado vertical» son veinte tarjetas apiladas, y sin esto no hay nada entre
   una y la siguiente. En un modulo de portada con `columnas: 1` pasaba igual y
   no se veia, porque ahi casi siempre hay una sola nota. */
.mod--noticias.cols-1 .card + .card {
  border-top: var(--sep) solid var(--linea); padding-top: var(--aire);
}
/* EL PRIMERO DE CADA FILA NO LLEVA SEPARADOR. `+ .card` mira el DOM y no la
   rejilla, asi que en la segunda fila le pone una linea al de la izquierda —
   una raya suelta contra el borde del contenido, sin nada del otro lado. Se ve
   apenas hay mas notas que columnas, que es siempre en un listado. */
.mod--noticias.cols-2 .card:nth-child(2n+1),
.mod--noticias.cols-3 .card:nth-child(3n+1),
.mod--noticias.cols-4 .card:nth-child(4n+1),
.mod--noticias.cols-5 .card:nth-child(5n+1),
.mod--noticias.cols-6 .card:nth-child(6n+1) {
  border-left: 0; padding-left: 0; margin-left: 0;
}
/* LA PRIMERA DESTACADA OCUPA LA FILA ENTERA (`render/listado.ts`), y con eso el
   separador vertical se queda sin cuenta que hacer.

   `nth-child` cuenta HIJOS, no filas, y funciona mientras cada hijo ocupe una
   celda — incluido el hueco de la publi in-feed, que el guion mete como una
   tarjeta mas y por eso nunca desacomodo nada. Una tarjeta que ocupa `cols`
   celdas rompe esa equivalencia, y con un aviso en el medio se corre otra vez:
   NO HAY CUENTA que cierre en los dos casos, porque CSS no sabe donde empieza
   una fila.

   Antes que una raya suelta contra el borde en un lugar impredecible, ninguna:
   con destacada el listado se separa por el hueco de la grilla. Es la misma
   decision que el corte de movil ya toma para todas.

   ⚠️ LA REGLA VA DESPUES DE LOS DOS CORTES DE ABAJO, no acá: los dos vuelven a
   poner el borde con la MISMA especificidad, y el que va ultimo gana. */
/* CUANTAS COLUMNAS TIENE CADA GRILLA EN CADA ANCHO lo decide el bloque
   `responsive` del final —que ya existia y hacia esto mismo— y acá va sólo lo
   que depende de ese numero: cual es el primero de cada fila. Tenerlo en los dos
   lados era escribir la misma decision dos veces, que es como el gestor termino
   con seis definiciones del mismo boton (`docs/22`). */
@media (max-width: 60rem) {
  .mod--noticias.cols-3 .card, .mod--noticias.cols-4 .card,
  .mod--noticias.cols-5 .card, .mod--noticias.cols-6 .card {
    border-left: var(--sep) solid var(--linea);
    padding-left: calc(var(--aire) * .5);
    margin-left: calc(var(--aire) * -.5);
  }
  .mod--noticias.cols-3 .card:nth-child(2n+1),
  .mod--noticias.cols-4 .card:nth-child(2n+1),
  .mod--noticias.cols-5 .card:nth-child(2n+1),
  .mod--noticias.cols-6 .card:nth-child(2n+1) {
    border-left: 0; padding-left: 0; margin-left: 0;
  }
}
@media (max-width: 34rem) {
  /* En una columna el separador vertical no significa nada: pasa a ser horizontal. */
  .mod--noticias .card { border-left: 0; padding-left: 0; margin-left: 0; }
  .mod--noticias .card + .card {
    border-top: var(--sep) solid var(--linea); padding-top: var(--aire);
  }
}
/* La destacada, prometida arriba: va al final para ganarle a los dos cortes. */
.mod--noticias.es-destacada .card {
  border-left: 0; padding-left: 0; margin-left: 0;
}
/* LA PRIMERA OCUPA LA FILA ENTERA. Es todo lo que «primera destacada» significa
   en el marcado: la tarjeta es la misma, la foto la pide mas grande porque el
   hueco es mas grande (`OpcionesGrilla.destacada`), y el titular pesa lo que
   pesa una tarjeta sola a ese ancho. */
.mod--noticias.es-destacada .card:first-child { grid-column: 1 / -1; }
.mod--noticias.es-destacada .card:first-child .title {
  font-size: calc(1.6rem * var(--t));
}
/* Con la foto arriba, lo que se acota es el TEXTO y no la foto: una linea de
   90rem no se lee, una foto de 90rem si. Misma decision que la apertura. */
.mod--noticias.es-destacada .card:first-child.d-arriba .info,
.mod--noticias.es-destacada .card:first-child.d-abajo .info { max-width: 46rem; }
/* Con la foto al costado, la foto manda — igual que en la apertura de portada. */
.mod--noticias.es-destacada .card:first-child.d-derecha { grid-template-columns: 2fr 3fr; }
.mod--noticias.es-destacada .card:first-child.d-izquierda { grid-template-columns: 3fr 2fr; }
@media (max-width: 60rem) {
  .mod--noticias.es-destacada .card:first-child.d-derecha,
  .mod--noticias.es-destacada .card:first-child.d-izquierda { grid-template-columns: 1fr; }
}

/* --- rotador ------------------------------------------------------------------

   LA TIRA LA CORRE EL NAVEGADOR, no una libreria. `overflow-x` con `scroll-snap`
   da el arrastre con el dedo, la rueda horizontal, el teclado y la barra de
   desplazamiento, y eso ya es el modulo entero: sin JavaScript el rotador
   funciona. Lo que el guion agrega despues son los dos botones y el paso solo.

   Amura hace lo mismo con Swiper — ~140 KB para esto. */
.mod--rotador { position: relative; }
.mod--rotador .slides {
  display: grid;
  grid-auto-flow: column;
  gap: var(--aire);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* Que no arrastre la pagina entera cuando la tira llega al final. */
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  /* La barra se esconde pero el desplazamiento queda: el que no tiene rueda
     horizontal usa los botones, y el que arrastra con el dedo no la veia igual. */
  -ms-overflow-style: none;
}
.mod--rotador .slides::-webkit-scrollbar { display: none; }
/* `min-width: 0` porque una tarjeta con un titular largo, en una celda de grilla,
   se niega a achicarse por debajo de su contenido y desalinea toda la tira. */
.mod--rotador .slide { scroll-snap-align: start; min-width: 0; }

/* CUANTAS SE VEN A LA VEZ. La cuenta descuenta los huecos: con cuatro visibles
   hay tres huecos, y sin restarlos la cuarta queda cortada por el borde. */
.mod--rotador.cols-1 .slides { grid-auto-columns: 100%; }
.mod--rotador.cols-2 .slides { grid-auto-columns: calc((100% - var(--aire)) / 2); }
.mod--rotador.cols-3 .slides { grid-auto-columns: calc((100% - 2 * var(--aire)) / 3); }
.mod--rotador.cols-4 .slides { grid-auto-columns: calc((100% - 3 * var(--aire)) / 4); }
.mod--rotador.cols-5 .slides { grid-auto-columns: calc((100% - 4 * var(--aire)) / 5); }

/* EN EL TELEFONO ASOMA LA SIGUIENTE, a proposito. Es lo unico que dice que la
   tira se corre: sin barra de desplazamiento y con la ultima tarjeta terminando
   justo en el borde, se lee como una grilla de tres y nadie la empuja. */
@media (max-width: 34rem) {
  .mod--rotador:not(.r-una) .slides { grid-auto-columns: 78%; }
}

/* De a una: la que se pasa sola. Ocupa el ancho entero y el que manda es el
   tiempo, asi que los botones van al medio y no arrinconados. */
.mod--rotador.r-una .slides { grid-auto-columns: 100%; }
.mod--rotador.r-una .rot-nav { justify-content: center; }

/* LOS BOTONES NO EXISTEN SIN GUION. Salen en el HTML —su texto lo escribe el
   cliente, y eso vive en un solo lugar— pero un boton que no hace nada porque el
   guion no cargo es peor que no tenerlo. `.js` lo pone `global.js` en el <html>. */
.mod--rotador .rot-nav { display: none; }
.js .mod--rotador .rot-nav {
  display: flex; gap: .4rem; justify-content: flex-end; margin-top: .6rem;
}
.mod--rotador .rot-prev,
.mod--rotador .rot-next {
  display: grid; place-items: center;
  width: 2.1rem; height: 2.1rem;
  padding: 0; border: var(--sep) solid var(--linea); border-radius: 50%;
  background: transparent; color: var(--primario);
  font-size: 1.3rem; line-height: 1; cursor: pointer;
  transition: border-color .2s ease, color .2s ease, opacity .2s ease;
}
.mod--rotador .rot-prev:hover,
.mod--rotador .rot-next:hover { border-color: var(--acento); color: var(--acento); }
/* En la punta el boton se queda, apagado. Sacarlo mueve al otro de lugar y el
   siguiente clic cae en el vacio. */
.mod--rotador .rot-prev[disabled],
.mod--rotador .rot-next[disabled] { opacity: .35; cursor: default; }

.mod--rotador { --t: 1; }
.mod--rotador.t-chico { --t: .86; }
.mod--rotador.t-grande { --t: 1.28; }
.mod--rotador .title { font-size: calc(1.1rem * var(--t)); }
.mod--rotador.cols-1 .title { font-size: calc(1.5rem * var(--t)); }
.mod--rotador.cols-2 .title { font-size: calc(1.2rem * var(--t)); }
.mod--rotador.cols-5 .title { font-size: calc(.98rem * var(--t)); }

/* Quien pidio menos movimiento no quiere que una caja se pase sola. El guion
   tambien lo mira —no alcanza con no animar el salto— pero la hoja lo dice
   primero, para que valga aunque el guion no corra. */
@media (prefers-reduced-motion: reduce) {
  .mod--rotador .slides { scroll-behavior: auto; }
}


.mod--mas-visto { list-style: none; margin: 0; padding: 0; }
.mod--mas-visto li {
  display: grid;
  grid-template-columns: 2rem 1fr;
  gap: .6rem;
  align-items: baseline;
  padding: var(--aire-chico) 0;
  border-bottom: var(--sep) solid var(--linea);
}
.mod--mas-visto .n { font-family: var(--f-principal); font-size: 1.5rem; font-weight: 700; color: var(--acento); }
.mod--mas-visto li a { font-weight: 600; color: var(--primario); }
.mod--mas-visto .section { display: block; margin-bottom: .1rem; }

.mod--separador { border: 0; border-top: 1px solid var(--linea); margin: 0; }
.mod--espacio { min-height: 2rem; }
/* --- titulo suelto (modulo `encabezado`) -------------------------------------
   LOS CUATRO ESTILOS SE DIFERENCIAN POR UNA COSA CADA UNO, no por cuatro. Es lo
   que los hace elegibles a ciegas desde un desplegable: «con una linea abajo» y
   «con una barra de color arriba» se pueden imaginar sin verlos.

   Y NINGUNO TRAE UN COLOR PROPIO: todos salen de `--primario` y `--acento`, que
   son los del cliente. Amura resuelve esto con un CSS por cliente (`docs/33`
   explica por que nosotros no podemos), asi que lo que alla es una plantilla
   nueva aca tiene que ser una variante de la misma hoja. */
.mod--encabezado { margin-bottom: var(--aire); }
.mod--encabezado .enc__t {
  margin: 0;
  font-family: var(--f-principal);
  font-size: clamp(1.3rem, 2.4vw, 1.85rem);
  font-weight: 700;
  line-height: 1.1;
  color: var(--primario);
}
.mod--encabezado .enc__t a { color: inherit; }
.mod--encabezado .enc__t a:hover { color: var(--acento); text-decoration: none; }
.mod--encabezado .enc__baja {
  margin: .3rem 0 0;
  font-family: var(--f-secundaria);
  font-size: .95rem;
  /* `--suave` y no `--apagado`, que era el unico uso de una variable que NO
     declara nadie (`render/tokens.ts`): la regla estaba muerta y la bajada salia
     del color del texto comun. */
  color: var(--suave);
}

/* La misma linea que el titulo de un modulo, para que un titulo suelto y uno
   pegado a su grilla no se lean como dos sistemas distintos. */
.mod--encabezado.e-linea { padding-bottom: .35rem; border-bottom: 2px solid var(--primario); }

/* La barra corta arriba: el `title-two` de Amura, que es el que mas se repite. */
.mod--encabezado.e-barra { padding-top: .9rem; position: relative; }
.mod--encabezado.e-barra::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 2.2rem;
  height: 4px;
  border-radius: 2px;
  background: var(--acento);
}

.mod--encabezado.e-centrado { text-align: center; }
.mod--encabezado.e-centrado .enc__t { color: var(--acento); }

/* EL BOTON NO LLEVA `.enc__t`: no es un encabezado (ver el modulo). Por eso su
   regla cuelga de `.enc__boton` y no hereda nada de arriba. */
.mod--encabezado.e-boton { text-align: center; }
.mod--encabezado .enc__boton { margin: 0; }
.mod--encabezado .enc__boton a {
  display: inline-block;
  padding: .6rem 1.4rem;
  border-radius: var(--radio);
  background: var(--acento);
  color: var(--fondo);
  font-family: var(--f-secundaria);
  font-weight: 600;
  font-size: .95rem;
}
.mod--encabezado .enc__boton a:hover { background: var(--primario); text-decoration: none; }

/* --- Texto: el bloque de prosa, y la caja destacada ------------------------
   Los tres marcos son el MISMO bloque con otro fondo: la estructura no cambia,
   asi que las reglas de tipografia viven una sola vez y `.c-*` solo enmarca. */
.mod--texto { margin-bottom: var(--aire); }
.mod--texto .txt__t {
  margin: 0 0 .5rem;
  font-family: var(--f-principal);
  font-size: clamp(1.2rem, 2.2vw, 1.6rem);
  font-weight: 700;
  line-height: 1.15;
  color: var(--primario);
}
.mod--texto .txt__t a { color: inherit; }
.mod--texto .txt__t a:hover { color: var(--acento); text-decoration: none; }
.mod--texto .txt__p {
  margin: 0 0 .7rem;
  font-family: var(--f-secundaria);
  font-size: 1rem;
  line-height: 1.6;
}
.mod--texto .txt__p:last-child { margin-bottom: 0; }

/* `suelto` no lleva clase NI regla: el modulo directamente no la emite, porque
   una clase sin regla se lee como una que alguien olvido estilar. */
.mod--texto.c-caja,
.mod--texto.c-aviso {
  padding: 1.1rem 1.2rem;
  border-radius: var(--radio);
}
.mod--texto.c-caja {
  background: var(--fondo-alt);
  border: 1px solid color-mix(in srgb, var(--texto) 12%, var(--fondo));
}
.mod--texto.c-aviso {
  background: var(--acento);
  color: var(--fondo);
}
/* En la caja de color el titulo NO puede quedarse con el primario: sobre el
   acento se lee mal o no se lee. Hereda, que es el color del texto de la caja. */
.mod--texto.c-aviso .txt__t,
.mod--texto.c-aviso .txt__t a { color: inherit; }
.mod--texto.c-aviso .txt__t a:hover { color: inherit; text-decoration: underline; }

/* --- Multimedia: la grilla de fotos y la galeria ---------------------------
   La grilla usa el MISMO `cols-N` que el resto de los modulos, asi que "tres por
   fila" quiere decir lo mismo en una grilla de notas y en una de fotos. */
.mod--multimedia { margin-bottom: var(--aire); }
.mm__grilla {
  display: grid;
  gap: var(--aire-chico);
  grid-template-columns: repeat(var(--mm-cols, 3), minmax(0, 1fr));
}
.mm__grilla.cols-1 { --mm-cols: 1; }
.mm__grilla.cols-2 { --mm-cols: 2; }
.mm__grilla.cols-3 { --mm-cols: 3; }
.mm__grilla.cols-4 { --mm-cols: 4; }
.mm__grilla.cols-5 { --mm-cols: 5; }
.mm__grilla.cols-6 { --mm-cols: 6; }

/* EN EL TELEFONO LA GRILLA SE ACHICA SOLA. Seis fotos por fila en 375px son
   tarjetas de un centimetro: no es una galeria, es una tira de puntos. Se corta
   en dos, que es lo que entra sin que la foto deje de decir algo. */
@media (max-width: 544px) {
  .mm__grilla { --mm-cols: 2; }
  .mm__grilla.cols-1 { --mm-cols: 1; }
}

.mm__celda { margin: 0; }
.mm__celda img { display: block; width: 100%; height: auto; border-radius: var(--radio); }
.mm__pie {
  margin: .35rem 0 0;
  font-family: var(--f-secundaria);
  font-size: .82rem;
  line-height: 1.35;
  color: var(--suave);
}

/* El boton que abre la foto no se ve como boton: la foto ES el control. Se
   resetea lo que el navegador le pone y se deja el foco, que es lo unico que no
   se puede sacar sin romperle la pagina a quien navega con teclado. */
.mm__abrir {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  text-align: inherit;
  font: inherit;
  color: inherit;
}
.mm__abrir:focus-visible { outline: 2px solid var(--acento); outline-offset: 3px; }
.mm__celda--abre img { transition: opacity .15s ease; }
.mm__abrir:hover img { opacity: .88; }

/* --- La foto agrandada ---------------------------------------------------- */
.mm__lupa {
  border: 0;
  padding: 0;
  max-width: 100vw;
  max-height: 100vh;
  width: 100%;
  height: 100%;
  background: transparent;
  color: #fff;
  overflow: hidden;
}
.mm__lupa::backdrop { background: rgba(0, 0, 0, .92); }
.mm__lupa-caja {
  margin: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .8rem;
  padding: 3.2rem 3.6rem;
}
.mm__lupa-img {
  max-width: 100%;
  /* El alto se acota contra la ventana y no contra el padre: en un flex el
     `max-height: 100%` de un hijo se mide contra una altura que todavia no esta
     resuelta, y la foto se desborda. */
  max-height: calc(100vh - 8rem);
  width: auto;
  height: auto;
  object-fit: contain;
}
.mm__lupa-pie {
  font-family: var(--f-secundaria);
  font-size: .9rem;
  line-height: 1.4;
  text-align: center;
  max-width: 46rem;
  color: rgba(255, 255, 255, .82);
}
.mm__lupa button {
  position: absolute;
  border: 0;
  background: rgba(0, 0, 0, .45);
  color: #fff;
  font-size: 2rem;
  line-height: 1;
  width: 2.8rem;
  height: 2.8rem;
  border-radius: 50%;
  cursor: pointer;
}
.mm__lupa button:hover { background: rgba(0, 0, 0, .75); }
.mm__lupa button:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.mm__lupa-x { top: .8rem; right: .8rem; }
.mm__lupa-prev { left: .8rem; top: 50%; transform: translateY(-50%); }
.mm__lupa-next { right: .8rem; top: 50%; transform: translateY(-50%); }
/* Con una sola foto no hay a donde pasar: el guion las apaga y ademas se sacan
   del recorrido del tabulador. */
.mm__lupa button[hidden] { display: none; }
.mm__lupa-cuenta {
  position: absolute;
  bottom: .9rem;
  left: 0;
  right: 0;
  text-align: center;
  font-family: var(--f-secundaria);
  font-size: .8rem;
  color: rgba(255, 255, 255, .7);
}

/* En el telefono las flechas ocupan media pantalla: van abajo, al lado de la
   cuenta, que es donde llega el pulgar. */
@media (max-width: 544px) {
  .mm__lupa-caja { padding: 3.2rem .6rem 4.6rem; }
  .mm__lupa-prev, .mm__lupa-next { top: auto; bottom: .6rem; transform: none; }
  .mm__lupa-prev { left: 1.2rem; }
  .mm__lupa-next { right: 1.2rem; }
}

/* --- Libre: lo que pega el cliente ----------------------------------------
   UNA SOLA REGLA, Y ES CONTENCION. Adentro hay HTML que no escribimos nosotros:
   un <iframe> con `width="1200"` o una tabla ancha desbordan la columna y
   empujan el layout de toda la pagina. `max-width` sobre los sospechosos es lo
   unico que se puede prometer sin pretender validar lo que hay adentro. */
.mod--libre { margin-bottom: var(--aire); }
.mod--libre img,
.mod--libre iframe,
.mod--libre video,
.mod--libre table { max-width: 100%; }


/* --- listado de seccion ------------------------------------------------------ */
/* EL TITULO DE UN LISTADO SE VE IGUAL QUE EL DE UN MODULO, y eso no es una
   coincidencia que haya que mantener a mano: «Deportes» arriba de la seccion y
   «Deportes» arriba de un modulo de la portada son la misma cosa para el lector.
   Comparten la regla —el mismo filete, la misma familia, la misma escala— y por
   eso el selector va junto al de `.heading`, no en otro bloque. */
main > h1 {
  margin: 0 0 var(--aire);
  padding-bottom: .35rem;
  border-bottom: 2px solid var(--primario);
  font-family: var(--f-principal);
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  font-weight: 700;
  line-height: 1.1;
  color: var(--primario);
}
/* ⚠️ ACA VIVIA `.list`, la grilla del listado de una seccion: tres columnas
   fijas y un titular de 1.2rem. Ya no existe.

   Era una copia de `.mod--noticias.cols-3` —los mismos tres, el mismo 1.2rem— y
   el separador ya lo compartian en el bloque de la grilla, con el comentario que
   lo decia: *"la de un modulo de portada y la de un listado de seccion son la
   misma decision"*. Ahora el listado emite las clases del modulo
   (`render/listado.ts`), asi que hereda el reparto, las disposiciones, el tamaño
   de titular y los cortes de movil sin una sola regla propia. */

/* LA PAGINACION VA CENTRADA Y SEPARADA, no pegada a la ultima tarjeta: es un
   control, no contenido. Y los dos botones se reparten a los costados cuando
   estan los dos, que es lo que hace que «Anterior» quede donde uno lo busca aun
   cuando falta «Siguiente». */
.pager {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin-top: calc(var(--aire) * 2);
  padding-top: var(--aire);
  border-top: 1px solid var(--linea);
  font-family: var(--f-secundaria);
  font-size: .82rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
}
/* Con un solo boton, `space-between` lo dejaria siempre a la izquierda. Esto
   manda «Siguiente» a la derecha cuando viene solo. */
.pager a:only-child:last-child { margin-left: auto; }
.pager a {
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  padding: .6rem 1.1rem;
  transition: border-color .2s ease, color .2s ease;
}
.pager a:hover {
  border-color: var(--primario);
  color: var(--primario);
  text-decoration: none;
}

/* --- ficha de nota ----------------------------------------------------------- */

/* LAS TRES VARIANTES SE RESUELVEN ACA, CON EL MISMO MARCADO (`render/ficha.ts`).
 *
 * El render emite siempre las mismas clases —`story__head`, `story__photo`,
 * `story__body`— y dice cual variante es en `data-ficha`. Esta es la mitad que
 * hace que agregar una cuarta sea escribir una entrada en el catalogo y unas
 * reglas aca, y no una hoja nueva: **las variantes comparten el vocabulario de
 * clases**, que es la condicion dura que `marco.ts` ya se habia puesto arriba.
 *
 * Lo que NO se resuelve aca es la columna lateral: esa es la grilla del SITIO
 * (`.container--rail`), compartida con el listado. La variante dice si la lleva;
 * el `<main>` la dibuja. Dos grillas para lo mismo es como la nota y el listado
 * terminan viendose distinto por un descuido. */
.story { max-width: 44rem; margin: 0 auto; }

/* LA APERTURA DE UNA NOTA DESTACADA (`render/ficha.ts`).
 *
 * Es la foto y el encabezado JUNTOS, a todo el ancho: *"con el titulo, bajada,
 * autores en ese full width, no sobre la foto sino abajo"*. Por eso el texto va
 * en su propia caja de lectura adentro de la franja — la foto se estira, el texto
 * no: un titular de 64rem de ancho no lo lee nadie.
 *
 * ⚠️ VIVE FUERA DE `.container--rail`, o sea que NO es hija del articulo. Con la
 * grilla de dos columnas el articulo es UNA de ellas, asi que una franja adentro
 * seria tan ancha como el texto y "full width" seria mentira. Lo emite
 * `documento()` como hermana de la grilla. */
.hero { margin: 0 0 2rem; }
.hero .story__photo { margin: 0; }
/* ⚠️ Y LA FOTO NO PUEDE SER UNA PARED. A todo el ancho y en 16:9, una apertura
   medía 662px en un viewport de 842: el lector abre la nota y no ve NADA mas que
   foto. El recorte de la destacada se pide mas panoramico (`origin.ts`); esto es
   el techo duro, por si la foto original no da para tanto. */
.hero .story__photo img { width: 100%; max-height: 60vh; object-fit: cover; }
/* ⚠️ A TODO EL ANCHO, y no a la medida de lectura: *"todo esto deberia ser 100
   w"*. Es lo que distingue la apertura de una destacada — el titular acompaña a
   la foto, no al parrafo. La medida de lectura vuelve a mandar en el cuerpo, que
   es donde importa: un parrafo de 1176px no lo lee nadie. */
.hero__texto { margin: 0 0 1.2rem; }
/* El titulo de una destacada pesa mas que el de una comun: es lo unico que
   distingue la apertura una vez que la foto ya se vio. */
.hero__texto h1 { font-size: clamp(2.1rem, 5.2vw, 3.2rem); }
/* ⚠️ EL ENCABEZADO SE ESTILA POR `.story__head`, NO POR `.story`, y es un bug
   arreglado.

   Estaba como `.story h1` y `.story .excerpt` — y en una nota destacada el
   encabezado vive en la FRANJA, que es hermana del artículo y no hija. O sea que
   ahí el titular y la bajada perdían toda su tipografía y caían en los márgenes
   por defecto del navegador: *"todo esto tiene mucho aire"*.

   No fallaba: salía con otro tamaño y separado, y sólo se ve abriendo una
   destacada. Con la clase del encabezado, las dos ubicaciones se estilan igual —
   que es la misma regla de vocabulario compartido que ordena `marco.ts`. */
.story__head h1 {
  font-family: var(--f-principal);
  font-size: clamp(1.9rem, 4.5vw, 2.8rem);
  line-height: 1.12;
  margin: .3rem 0 0;
  color: var(--primario);
}
.story__head .excerpt { font-size: 1.15rem; margin-top: .8rem; }
.story .story__photo { margin: 1.5rem 0; }
/* El pie de foto: el epígrafe y el crédito (`render/pie.ts`).
 *
 * Sans y chico contra el cuerpo, que es serif y grande: el pie acompaña la foto,
 * no compite con el texto de la nota. Es la convención de cualquier diario, y la
 * razón por la que el `<span>` del crédito existe — sin distinguirlo, "La plaza
 * el jueves Ana Pérez" se lee como una sola frase mal escrita. */
figcaption {
  font-family: var(--f-secundaria);
  font-size: .84rem;
  line-height: 1.45;
  color: var(--suave);
  margin-top: .5rem;
}
figcaption .credit {
  font-size: .76rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  white-space: nowrap;
}
.story__body { font-family: var(--f-texto); font-size: 1.12rem; line-height: 1.65; }
.story__body p { margin: 0 0 1.1rem; }
/* Tres niveles de subtítulo (`rutas-notas.ts` acota a h2..h4; el h1 es el título
   de la nota). Los tamaños bajan poco a poco: son escalones de una misma nota, no
   secciones de un sitio. */
.story__body h2 { font-size: 1.4rem; margin: 2rem 0 .8rem; }
.story__body h3 { font-size: 1.2rem; margin: 1.7rem 0 .7rem; }
.story__body h4 { font-size: 1.06rem; margin: 1.5rem 0 .6rem; }
.story__body a { color: var(--acento); text-decoration: underline; }
/* Resaltado. LA FUENTE ES `compartido/resaltados.ts`, y un test compara esta
   hoja con la del gestor y con la de AMP. `mark` pelado es el amarillo: es lo
   que guardaron las notas escritas antes de que hubiera colores. */
.story__body mark { background: #fdf3c4; padding: 0 .1em; border-radius: 2px; }
.story__body mark.res-verde { background: #d9f2e3; }
.story__body mark.res-celeste { background: #d8ecfb; }
.story__body mark.res-rosa { background: #fbdde3; }
.story__body mark.res-lila { background: #e8ddf7; }
.story__body blockquote {
  margin: 1.5rem 0;
  padding-left: 1.1rem;
  border-left: 3px solid var(--acento);
  font-style: italic;
  color: var(--suave);
}
.tags { display: flex; flex-wrap: wrap; gap: .5rem; list-style: none; margin: 2rem 0 0; padding: 0; }
.tags a {
  display: block;
  padding: .3rem .7rem;
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  font-size: .8rem;
}


/* --- responsive unico (docs/03): una sola variante, no una version movil ----- */
@media (max-width: 60rem) {
  /* UNA SOLA COLUMNA, y alcanza con la regla de `.wrap` porque un contenedor
     anidado ES un wrap: colapsa con la misma linea que el de la raiz. */
  .wrap { grid-template-columns: minmax(0, 1fr); }
  .zona.cols-1, .zona.cols-2, .zona.cols-3, .zona.cols-4 { grid-column: span 1; }
  /* Y el anidado colapsa igual, porque es un `.wrap` como cualquier otro: la
     regla de arriba ya lo alcanza. */
  .mod--noticias.es-apertura .card.d-derecha,
  .mod--noticias.es-apertura .card.d-izquierda { grid-template-columns: 1fr; }
  .mod--noticias.cols-3, .mod--noticias.cols-4,
  .mod--noticias.cols-5, .mod--noticias.cols-6 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 34rem) {
  .mod--noticias.cols-2, .mod--noticias.cols-3, .mod--noticias.cols-4,
  .mod--noticias.cols-5, .mod--noticias.cols-6 { grid-template-columns: 1fr; }
}

/* --- UN CONTENEDOR CON FONDO PROPIO ---------------------------------------
   Redefine los colores de SU contenido, y por eso alcanza con la clase: todo lo
   de adentro ya lee estas variables, asi que ningun modulo tiene que saber que
   esta parado sobre un fondo distinto.

   Cual de las dos clases va lo decide la luminancia del color elegido
   (`render/tokens.ts`), no una segunda pregunta al lado del selector. El acento
   NO se toca: es el color con el que el medio senala, y pisarlo seria apagar lo
   unico que el contenedor de color venia a resaltar. */
/* HASTA DONDE LLEGA EL COLOR. Tres opciones, las mismas que Amura.

   `pantalla` rompe la caja del sitio con el truco de siempre: el bloque se
   estira a todo el viewport y el padding devuelve el contenido a su lugar. El
   `overflow-x: clip` del body es su companion obligatorio — `100vw` incluye la
   barra de scroll, asi que sin eso aparecen unos pixeles de scroll horizontal.

   `sitio` y `caja` se quedan adentro de la caja del sitio; la unica diferencia
   entre las dos es el redondeo. Las dos llevan padding: sin el, el titular queda
   pegado al borde del color y se lee como un error. */
.wrap[class*="fondo-"] { background: var(--fondo-wrap); }
.wrap.fondo-pantalla {
  margin-inline: calc(50% - 50vw);
  padding: var(--aire) calc(50vw - 50%);
}
.wrap.fondo-sitio,
.wrap.fondo-caja { padding: var(--aire) var(--aire); }
.wrap.fondo-caja { border-radius: calc(var(--radio) * 2); }

/* Y EL `color` DEL PROPIO BLOQUE, que es la mitad que faltaba.

   Lo encontro Hernan sobre un fondo rojo: el antetitulo ya se corregia
   (`acentoSobre`) pero **la firma del autor seguia negra e ilegible**. No era un
   olvido del autor: redefinir `--texto` acá solo alcanza a los elementos que
   NOMBRAN la variable —`.titulo` pide `--primario`, `.bajada` y `time` piden
   `--suave`, `.seccion` pide `--acento`—, y `.autor` no declara ningun color:
   HEREDA. Y lo que hereda es el color ya COMPUTADO en `body`, que se resolvio
   con el `--texto` de afuera mucho antes de llegar al contenedor.

   Declarar `color` en el bloque reabre la herencia adentro del wrap, asi que
   arregla el autor y **todo lo que venga despues sin color propio**. Parchear
   `.autor` habria tapado este caso y dejado el siguiente para que lo encuentre
   otra vez alguien mirando el sitio. */
.wrap.sobre-oscuro {
  --texto: #fff;
  --primario: #fff;
  --suave: rgba(255, 255, 255, .72);
  --linea: rgba(255, 255, 255, .22);
  color: var(--texto);
}
.wrap.sobre-claro {
  --texto: #12161c;
  --primario: #12161c;
  --suave: rgba(0, 0, 0, .6);
  --linea: rgba(0, 0, 0, .14);
  color: var(--texto);
}

/* --- el pie de la ficha: dos piezas que NO son lo mismo (`docs/32`) ---------
 *
 * Las RELACIONADAS las eligió la redacción para esta nota: listado vertical, una
 * debajo de la otra, sin foto. Las ÚLTIMAS DE LA SECCIÓN no las eligió nadie y
 * son iguales para todas las notas de la sección: tarjetas horizontales con foto
 * grande.
 *
 * SE VEN DISTINTO A PROPÓSITO, y lo pidió así Hernán: *"las del pie suelen ser un
 * listado vertical una abajo de la otra, y más noticias de la sección es un
 * listado con foto más grande, horizontal"*. Si se vieran igual, el lector no
 * podría distinguir "esto lo eligió alguien para mí" de "esto salió solo" — que
 * es la única diferencia que tienen.
 *
 * Las dos se salen del ancho del texto (`.story` mide 44rem): ahí termina la
 * lectura y empieza otra cosa. */
.related, .more {
  max-width: 52rem;
  margin: calc(2.5rem * var(--densidad)) auto 0;
  padding-top: calc(1.5rem * var(--densidad));
  border-top: 2px solid var(--linea, #e5e5e5);
}
/* Vacío no se dibuja: sin JavaScript el hueco de "más de la sección" queda sin
   llenar, y un borde suelto al final de la nota se lee como un error. */
.more:empty { display: none; border: 0; margin: 0; padding: 0; }

.related__label, .more__label {
  font-family: var(--f-secundaria);
  font-size: .82rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em;
  color: var(--acento);
  margin: 0 0 .9rem;
}

/* --- las relacionadas: vertical, sin foto --- */
.related ul { list-style: none; margin: 0; padding: 0; }
.related li + li { border-top: 1px solid var(--linea, #e5e5e5); }
.related a {
  display: block; padding: .7rem 0;
  color: inherit; text-decoration: none;
}
.related a:hover .related__title { text-decoration: underline; }
.related__kicker {
  display: block;
  font-family: var(--f-secundaria);
  font-size: .74rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .05em;
  color: var(--acento);
}
.related__title {
  font-family: var(--f-principal);
  font-size: 1.05rem; font-weight: 700; line-height: 1.3;
}

/* --- más de la sección: horizontal, con foto grande --- */
.more__list {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: calc(1.4rem * var(--densidad));
  /* `auto-fit` y no un número de columnas: la misma regla sirve para tres
     tarjetas y para cinco, y en el teléfono cae sola a una. */
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}
.more__item a { display: block; color: inherit; text-decoration: none; }
.more__item img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: 2px; margin-bottom: .5rem;
}
.more__kicker {
  display: block;
  font-family: var(--f-secundaria);
  font-size: .72rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .05em;
  color: var(--acento);
}
.more__title {
  font-family: var(--f-principal);
  font-size: 1rem; font-weight: 700; line-height: 1.25;
}
.more__item a:hover .more__title { text-decoration: underline; }

/* --- PUBLICIDAD (`docs/34`) -------------------------------------------------

   EL HUECO NO OCUPA NADA HASTA QUE SE LLENA, y esa es la regla que hace que todo
   lo demas se pueda emitir siempre. El render emite los huecos sin preguntarle
   nada al inventario —si preguntara, crear una posicion invalidaria el sitio
   entero— asi que un cliente sin publicidad tiene los huecos igual. Escondidos,
   no se ve ni un espacio en blanco.

   `[data-lleno]` lo pone el guion al colocar. Es un atributo y no `:empty`
   porque la franja trae su boton de cerrar de fabrica: nunca esta vacia.

   EL LUGAR RESERVADO ES LA EXCEPCION, Y VA ADENTRO DE ESTE MISMO SELECTOR: el
   hueco que el cliente pidio reservar se ve aunque este vacio, que es todo el
   punto —el alto ya esta hecho cuando llega el aviso, asi que la pagina no baja
   de golpe—. Lo enciende el cliente y POR LUGAR: reservar donde no se vende
   cambia un salto por una banda en blanco, que es peor.

   ⚠️ LA EXCEPCION NO PUEDE SER UNA REGLA APARTE, y esto es un bug arreglado.
   Estaba escrita como `.ad--reserva { display: block }` debajo, y **perdia**:
   una clase (0,1,0) contra clase mas atributo (0,2,0), asi que ganaba el
   `display: none` aunque viniera antes. El hueco salia con su `min-height` bien
   puesto en el HTML **y escondido**: reservando cero. Por eso el sintoma
   sobrevivio a dos arreglos del lado del HTML —*"el espacio sigue sin quedar
   reservado y el contenido se esta moviendo"*—: los dos miraban el lado que ya
   estaba bien. Con el `:not()` adentro, la regla no depende del orden ni de que
   alguien se acuerde de contar especificidad. Y son DOS: el modulo de portada
   (`.ad--modulo`) reserva igual, con el formato que declaro quien armo la
   portada. */
.ad:not([data-lleno]):not(.ad--reserva):not(.ad--modulo) { display: none; }
/* EL LUGAR RESERVADO MIDE DISTINTO EN EL TELEFONO, y por eso el alto sale del
   HTML como dos variables y se resuelve acá.

   Lo marco Hernan: *"puse 200 en Leaderboard pero en celular no podemos dejar ese
   espacio"*. Y no es un ajuste fino: el aviso de escritorio y el del telefono son
   dos piezas distintas (`PANTALLAS`), asi que reservar el alto de una en la otra
   cambia el salto que se venia a evitar por una banda en blanco del tamaño de un
   aviso que ahi no va.

   EL CORTE ES 544px, el mismo que ya usa el recorte de las fotos
   (`CORTE_MOVIL`) y el resto de esta hoja: asi un lector no puede quedar parado
   en un ancho donde la foto ya es la grande y el hueco todavia es el chico.
   Cero es «no reserves», y sale como alto cero sin banda. */
.ad--reserva { min-height: var(--ad-alto, 0px); }
@media (max-width: 544px) { .ad--reserva { min-height: var(--ad-alto-movil, 0px); } }
.ad {
  /* Centrado y sin desbordar NUNCA: la creatividad viene con el tamaño que el
     anunciante mando y en un telefono puede ser mas ancha que la pantalla. Sin
     esto, un 728x90 le agrega scroll horizontal a la pagina entera. */
  max-width: 100%;
  margin-inline: auto;
  overflow: hidden;
}
/* LOS QUE TRAEN CHROME NO RECORTAN, recorta su caja interna. El boton de cerrar
   de la franja se dibuja a caballo del borde de arriba, y el `overflow: hidden`
   de la regla de arriba **se lo comia entero**: el boton estaba en el DOM y no se
   veia. Es la segunda mitad del mismo sintoma que resolvio `.ad__pieza`. */
.ad--franja, .ad--modal { overflow: visible; }
.ad__pieza { max-width: 100%; overflow: hidden; }
.ad img { display: block; max-width: 100%; height: auto; margin-inline: auto; }
.ad--cabecera, .ad--pie { margin-block: var(--aire); }
.ad--antes, .ad--despues, .ad--cuerpo { margin-block: var(--aire); }
/* EL IN-FEED OCUPA UNA CELDA, COMO UNA TARJETA MAS. Es un bug arreglado y el
   comentario anterior decia justo lo contrario —"ocupa la fila entera […] no hay
   tamaño de aviso que entre en una columna"—, asi que conviene decir que pasa de
   verdad.

   OCUPANDO LA FILA ENTERA, EL FEED SE ROMPE. La grilla es de tres columnas y el
   hueco se intercala DESPUES DE LA TARJETA QUE SE ELIJA: puesto despues de la
   primera, un elemento que ocupa las tres columnas no entra en esa fila, arranca
   una nueva y **deja dos celdas vacias al lado de la primera tarjeta**. Lo vio
   Hernan puesto: *"probaron la publicidad In-feed luego de la tarjeta 1 pero
   visualmente rompe el feed"*. Y el agujero no se puede tapar con
   `grid-auto-flow: dense` sin romper otra cosa: rellenar con las tarjetas
   siguientes cambia el orden, o sea que "despues de la tarjeta 1" deja de ser
   cierto.

   Como celda, el aviso se lee como lo que In-feed es en cualquier lado: una
   pieza nativa con forma de tarjeta. Los tamaños que el catalogo ofrece para este
   lugar son de columna (MPU 300x250 y su gemelo movil); un leaderboard tambien
   entra, encogido por `max-width: 100%`.

   ARRIBA Y NO ESTIRADO: un aviso de 250 de alto en una fila de 356 se estira
   entero si no se dice, y una imagen estirada se ve mal antes de que nadie sepa
   por que. */
.ad--entre { align-self: start; }

/* LA FRANJA PEGADA ABAJO. Tapa contenido por definicion, asi que **siempre** se
   puede cerrar (`.ad__cerrar`) y nunca se lleva mas que un tercio de la altura:
   una franja alta en un telefono deja la nota adentro de una ventanita. */
.ad--franja[data-lleno] {
  position: fixed; inset-inline: 0; bottom: 0; z-index: 40;
  display: flex; justify-content: center;
  max-height: 33vh;
  padding: .4rem;
  background: var(--papel, #fff);
  box-shadow: 0 -2px 12px rgb(0 0 0 / .18);
}
/* UNA PESTAÑA DE LA FRANJA, no un recuadro apoyado encima. Y sigue siendo un
   recuadro claro con borde y no un circulo negro, que es la correccion anterior
   de Hernan: el circulo negro se lee como una PIEZA de la franja —una marca, un
   boton del anunciante— y esto no es del aviso, es del sitio. Un recuadro claro
   se lee como lo que es: el control que cierra la caja, el mismo que cierra una
   ventana en cualquier lado.

   LO QUE CAMBIO ES DONDE APOYA. Estaba a caballo del borde (`top: -.85rem`), asi
   que la mitad de abajo del recuadro —su borde inferior incluido— quedaba
   dibujada SOBRE el aviso: cuatro lados cerrados encima de la creatividad, que se
   lee como una calcomania. *"Que la parte de abajo del recuadro no este, como que
   este mas integrado"*.

   Ahora apoya en el borde de arriba (`bottom: 100%`, que no depende del alto) y
   **no tiene lado de abajo**: el borde se abre, las esquinas de abajo son rectas
   y el fondo es el mismo `--papel` de la franja. Los dos dejan de ser dos cajas y
   pasan a ser una superficie con una lengueta.

   EL BORDE NO ES ADORNO: la franja es blanca y la creatividad puede ser blanca
   tambien, asi que sin el la pestaña se pierde justo contra el aviso que tiene
   que dejar cerrar. Por lo mismo la sombra es la MISMA de la franja y va hacia
   arriba: una sombra propia hacia abajo dibujaria una linea justo donde se
   quiere continuidad. */
.ad__cerrar {
  position: absolute; bottom: 100%; inset-inline-end: .4rem;
  width: 1.9rem; height: 1.5rem;
  display: grid; place-items: center;
  border: 1px solid rgb(0 0 0 / .25); border-bottom: 0;
  border-radius: 3px 3px 0 0;
  background: var(--papel, #fff); color: #1a1a1a;
  box-shadow: 0 -2px 12px rgb(0 0 0 / .18);
  font-size: 1rem; line-height: 1; cursor: pointer;
}
.ad__cerrar:hover { border-color: rgb(0 0 0 / .5); }
/* La cruz la dibuja la hoja y no el HTML: es un icono, no una palabra. Lo que
   el cliente escribe es el `aria-label`, que es lo unico que se lee de esto. */
.ad__cerrar::before { content: '\00d7'; }

/* --- LA COLUMNA DE LA DERECHA -----------------------------------------------

   SE RESERVA DESDE ACA Y NO LA AGREGA EL GUION. Es la decision de Hernan
   (2026-08-23) entre las dos posibles: si la agregara el guion, el cliente que
   vende publicidad pagaria un reacomodo de la pagina entera al terminar el
   fetch — la nota corriendose 150px cuando el lector ya empezo a leer. Reservada
   desde la hoja no se mueve nada nunca, y lo que ocupa es margen que hoy esta
   muerto: `.story` mide 44rem centradas adentro de un contenedor mucho mas
   ancho.

   ABAJO DEL CORTE EL RAIL CAE AL FINAL DEL FLUJO, que es donde no le saca lugar
   a nada. */
.rail { display: flex; flex-direction: column; gap: var(--aire); }
.rail:not(:has([data-lleno])) { display: none; }

@media (min-width: 1100px) {
  /* ⚠️ LA FRANJA DE UNA DESTACADA COMPARTE ESTA GRILLA, y no es economía de
     líneas: es lo único que hace que su titular caiga en la MISMA columna que el
     cuerpo de la nota.

     Con una grilla propia —o centrando el texto en el ancho completo— el titular
     quedaba 168px a la derecha del primer párrafo. Se vio midiendo el DOM, no
     leyendo el CSS: los dos textos miden 44rem y los dos están «centrados», pero
     uno en 1176px y el otro en la columna izquierda, que mide 868. */
  .container--rail,
  .hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: calc(var(--aire) * 1.5);
    align-items: start;
  }
  /* La foto SÍ cruza las dos columnas: eso es «full width». El texto no. */
  .hero .story__photo { grid-column: 1 / -1; }
  .hero__texto { grid-column: 1 / -1; }
  /* El rail acompaña la lectura en vez de quedarse arriba: es lo que hace que el
     segundo lugar de la columna valga algo en una nota larga. */
  .rail { position: sticky; top: 5rem; }
}

/* La columna del contenido cuando hay rail. Es un envoltorio y no un adorno: sin
   el, cada hijo de `<main>` seria una celda de la grilla por su cuenta y el
   listado, el titulo y el paginador se repartirian las dos columnas. El
   `min-width: 0` es lo que impide que una tabla o un `<pre>` largo estiren la
   columna y se coman el rail. */
.container__ancho { min-width: 0; }
/* En el rail el aviso no lleva margen propio: la columna ya separa con su `gap`,
   y sumarle margen dejaria el primero despegado del titulo. */
.ad--lateral { margin-block: 0; }

/* EL INTERSTITIAL (pantalla completa). Es el formato que mas molesta y por eso el
   que mas cuidado necesita: **la salida esta desde el primer segundo**, arriba a
   la derecha, donde todo el mundo la busca. Esconderla es lo que lo convierte en
   una trampa — y el que no la encuentra se va del sitio, no mira el aviso. */
/* POR ENCIMA DE TODO, Y EL NUMERO IMPORTA. La cabecera del sitio es `sticky` con
   `z-index: 100`, asi que con 60 el interstitial quedaba DEBAJO: no tapaba la
   cabecera —*"no tapa todo"*— y, peor, el boton de saltar vive arriba a la
   derecha, o sea justo el pedazo que la cabecera escondia. La salida existia y no
   se veia, que es como un interstitial se convierte en una trampa. */
.ad--modal[data-lleno] {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center;
  max-width: none; padding: 1.5rem;
  background: rgb(0 0 0 / .82);
}
.ad--modal .ad__pieza { max-width: 100%; max-height: 80vh; overflow: auto; }
.ad__saltar {
  position: absolute; top: 1rem; inset-inline-end: 1rem;
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .45rem .9rem;
  border: 0; border-radius: 999px;
  background: #fff; color: #111;
  font-family: var(--f-secundaria); font-size: .85rem; font-weight: 600;
  cursor: pointer;
}
/* Los segundos que faltan, en ancho fijo: sin esto el boton se encoge al pasar de
   10 a 9 y el que va a apretarlo le erra. */
.ad__cuenta {
  min-width: 1.4em; text-align: center;
  font-variant-numeric: tabular-nums; color: var(--apagado, #666);
}
.ad__cuenta:empty { display: none; }
/* La pagina no se lee detras del interstitial, asi que tampoco se desplaza: sin
   esto se scrollea a ciegas con el dedo. */
.ad-abierto, .ad-abierto body { overflow: hidden; }

/* EL HUECO DE PUBLICIDAD PUESTO COMO MODULO DE PORTADA (`docs/34`, paso 3).
   ES EL UNICO QUE RESERVA EL LUGAR DESDE EL HTML, y puede porque **el formato lo
   declaro quien armo la portada**: el ancho y el alto vienen en el `style` del
   propio hueco. En los otros lugares el tamaño lo trae el aviso y no se sabe
   hasta que llega el documento, asi que el guion lo reserva al colocar; acá se
   sabe antes, y por eso este hueco no deja saltar la pagina ni un pixel.
   Por lo mismo NO se esconde con `.ad:not([data-lleno])`: si se escondiera hasta
   llenarse, la reserva no serviria para nada — por eso esta en la lista de
   excepciones de esa regla, alla arriba, y no con una regla propia que dependa
   del orden. Vacio se ve como lo que es —un lugar reservado— y no dibuja nada. */
.mod--publicidad {
  display: grid; place-items: center;
  width: 100%; max-width: var(--ad-ancho, 100%);
  min-height: var(--ad-alto, 0);
  margin-inline: auto;
}

/* RICHTEXT: lo que el periodista pone ADENTRO del cuerpo de una nota.
 *
 * Vive en su propio archivo y no adentro del módulo que emite el marcado, y lo
 * pidió Hernán viendo una nota publicada: *"veo mucho CSS inline; es importante
 * que crees CSS separados porque seguramente embebidos se comporta igual para
 * futuros clientes"*. Tiene razón dos veces:
 *
 *  1. **Es el mismo para todos los clientes.** Un embebido de YouTube se ve
 *     igual en cualquier diario: lo que cambia es el color de acento, y eso ya
 *     viaja como variable. Inline, esos 2,7 KB viajaban repetidos en el HTML de
 *     CADA nota, sin cachearse nunca — el peor lugar posible para algo que no
 *     cambia.
 *  2. **Un archivo se puede leer.** Buscar por qué un embebido se ve raro
 *     adentro de un template literal de TypeScript no es lo mismo que abrir un
 *     `.css`.
 *
 * SE COMPONE, NO SE SIRVE SUELTO. `render/hoja.ts` junta base + richtext + las
 * variables del cliente en UNA hoja con el hash del contenido en el nombre, que
 * es el modelo de Amura —*"cada cliente su propio less, y este tiene varios less
 * que termina saliendo un único css con string por el cacheo"*— con la ventaja
 * de que acá el "string" es el hash del contenido y no un número que alguien
 * tiene que acordarse de subir.
 *
 * Lo que NO entra acá: el layout del sitio (`base.css`) y AMP, que exige su CSS
 * inline por especificación y arma el suyo aparte (`render/amp.ts`).
 */

/* --- embebidos ------------------------------------------------------------
 * Marcado nuestro, cero JavaScript de terceros (`compartido/embebidos.ts`).
 * `aspect-ratio` puesto siempre: el recuadro ocupa su lugar desde que llega el
 * HTML, así que al montarse no empuja el párrafo que se estaba leyendo. Es la
 * mitad del CLS de cualquier nota con video. */
.emb { margin: 1.5em 0; }
.emb--marco { position: relative; background: #111; border-radius: 4px; overflow: hidden; }

/* LA PROPORCION SE DECLARA UNA SOLA VEZ, en una variable, y la usan las dos
 * formas de embebido —el que espera un click y el que se monta solo—.
 *
 * Antes estaba escrita dos veces, y el segundo juego tenía **tres de las seis**:
 * un mapa `directo` se quedaba sin proporción, así que el `<iframe>` caía en su
 * alto por defecto —150px— y el mapa salía como una franja aplastada. Se vio en
 * una nota de verdad, y es la falla típica de una lista repetida: agregar una
 * proporción funciona en un lado y no en el otro, sin que nada avise.
 *
 * Con la variable, un proveedor nuevo declara `--emb-prop` en un solo lugar. */
.emb--video { --emb-prop: 16/9; }
.emb--mapa { --emb-prop: 16/10; }
.emb--audio { --emb-prop: 4/1; }
.emb--tira { --emb-prop: 5/1; }
.emb--tira-alta { --emb-prop: 3/4; }
.emb--retrato { --emb-prop: 4/5; }
.emb--marco { aspect-ratio: var(--emb-prop, 16/9); }

/* Un posteo de red es ALTO, no ancho: forzarlo a 16/9 deja el iframe con scroll
   adentro, que es la peor forma de leer un tweet. Se capan en ancho porque un
   posteo estirado a 1200px se lee peor que centrado en 540. */
.emb--tira-alta,
.emb--retrato { max-width: min(100%, 540px); margin-inline: auto; background: #fafafa; }

/* EL QUE SE MONTA SOLO: el que no tiene miniatura que mostrar.
 *
 * La proporción la lleva la caja de adentro y no la figura: con el pie abajo,
 * ponerla en la figura la repartiría entre las dos cosas y el iframe quedaría
 * más bajo de lo pedido. */
.emb--directo { aspect-ratio: auto; background: none; }
.emb--directo .emb__caja {
  aspect-ratio: var(--emb-prop, 16/9);
  background: #fafafa; border: 1px solid #e3e3e3; border-radius: 4px; overflow: hidden;
}
/* El cap de ancho es SOLO para los posteos verticales. Un mapa o un video
   centrados en 540px dejan el resto de la columna en blanco sin ganar nada:
   la razón del cap era que un tweet estirado se lee peor, no el ancho en sí. */
.emb--retrato.emb--directo,
.emb--tira-alta.emb--directo { max-width: min(100%, 540px); margin-inline: auto; }
.emb--directo iframe { width: 100%; height: 100%; border: 0; display: block; }
.emb__pie { margin-top: .4em; font-size: .82rem; text-align: right; }
.emb__pie a { color: #666; text-decoration: none; }
.emb__pie a:hover { color: var(--acento, #c00); text-decoration: underline; }

/* La fachada con miniatura: se ve el contenido y el reproductor se monta al click. */
.emb--marco iframe { width: 100%; height: 100%; border: 0; display: block; }
.emb__play {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  text-decoration: none; cursor: pointer;
}
.emb__lamina { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.emb__boton {
  position: relative; width: 68px; height: 48px; border-radius: 10px;
  background: rgba(0, 0, 0, .65); transition: background .15s;
}
.emb__boton::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  transform: translate(-38%, -50%);
  border-style: solid; border-width: 10px 0 10px 17px;
  border-color: transparent transparent transparent #fff;
}
.emb__play:hover .emb__boton { background: var(--acento, #c00); }
.emb--marco .emb__quien {
  position: absolute; left: 10px; bottom: 8px;
  color: #fff; font-size: .78rem; text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}

/* El que no se puede enmarcar: se dice de quién es y se enlaza. */
.emb--tarjeta .emb__link {
  display: block; padding: 1em 1.1em;
  border: 1px solid #e3e3e3; border-radius: 4px;
  text-decoration: none; color: inherit;
}
.emb--tarjeta .emb__link:hover { border-color: var(--acento, #c00); }
.emb--tarjeta .emb__quien {
  display: block; font-weight: 700; font-size: .8rem;
  text-transform: uppercase; letter-spacing: .04em; color: var(--acento, #c00);
}
.emb--tarjeta .emb__url {
  display: block; font-size: .85rem; color: #666; word-break: break-all; margin: .3em 0;
}
.emb--tarjeta .emb__ir { font-size: .85rem; font-weight: 600; }

/* --- video de la mediateca ------------------------------------------------
 * NO es un embebido: son bytes nuestros, servidos desde nuestro dominio. Por eso
 * no lleva fachada ni espera un clic — no hay script de tercero que evitar, que
 * es lo unico que la fachada existe para postergar.
 *
 * `aspect-ratio: auto 16 / 9` y no `16 / 9` a secas, que es la diferencia entre
 * reservar bien y deformar: con `auto` adelante, la proporcion REAL del video
 * manda apenas se conoce y el 16/9 es solo el respaldo mientras no se sepa. Hace
 * falta porque hoy no medimos el video al subirlo —de la imagen si, lo hace
 * `sharp`—, asi que sin esto el navegador reserva 150px de alto y el texto salta
 * cuando llegan los metadatos. */
figure.video { margin: 1.4rem 0; }
figure.video video {
  display: block; width: 100%; height: auto;
  aspect-ratio: auto 16 / 9; background: #000;
}

/* --- una relacionada puesta EN MEDIO DEL TEXTO ----------------------------
 * Es lo que la solapa no puede dar: la nota al lado del párrafo que habla del
 * tema, decidido por quien escribe (`docs/32`). Va acá y no en `base.css` porque
 * es contenido que pone el periodista adentro del cuerpo, como el embebido.
 *
 * SE VE COMO UN APARTE Y NO COMO UNA TARJETA DEL LISTADO, a propósito: interrumpe
 * la lectura, así que tiene que decir por qué. El rótulo hace ese trabajo — sin
 * él, un titular suelto en medio del texto se lee como parte de la nota.
 *
 * Y NO SE PARECE A LAS DEL PIE, que son un listado vertical de cinco. Son dos
 * piezas distintas —una la eligió el periodista para ESTE lugar, la otra es la
 * lista de la nota— y verse igual las confundiría. */
.inline-related {
  margin: 1.6rem 0;
  padding: .9rem 1rem;
  border-left: 4px solid var(--acento, #c00);
  background: var(--fondo-suave, #f6f7f8);
  border-radius: 0 3px 3px 0;
}
.inline-related__label {
  margin: 0 0 .4rem;
  font-size: .74rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .07em;
  color: var(--acento, #c00);
}
/* El enlace es TODA la ficha —foto y texto—, que es el objetivo más grande
   posible: en el teléfono, apuntarle a un titular de dos renglones es la
   diferencia entre que se use y que no.

   VA CON `.cuerpo` ADELANTE, y no es adorno: este bloque vive ADENTRO del cuerpo
   de la nota, donde manda `.cuerpo a { color: var(--acento); text-decoration:
   underline }` de `base.css`. Esa regla pesa `0,1,1` —una clase y un elemento— y
   `.rel__enlace` sola pesa `0,1,0`, así que perdía: el titular salía subrayado y
   del color de los enlaces del texto, como si fuera un link más de un párrafo.
   Lo vio Hernán en la nota publicada.

   Con `.cuerpo .rel__enlace` pesa `0,2,0` y gana **sin depender del orden de los
   archivos**, que es la otra forma de arreglarlo y la que se rompe el día que
   alguien reordena la hoja. El subrayado vuelve al pasar el mouse, que es donde
   sirve. */
.story__body .inline-related__link {
  display: flex; align-items: center; gap: .8rem;
  color: inherit; text-decoration: none;
}
.inline-related__link img {
  flex: 0 0 auto; width: 8rem; height: 4.5rem;
  object-fit: cover; border-radius: 3px;
}
.inline-related__text { min-width: 0; }
.inline-related__kicker {
  display: block; font-size: .78rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .04em; color: var(--acento, #c00);
}
.inline-related__title { font-weight: 700; line-height: 1.25; }
.inline-related__link:hover .inline-related__title { text-decoration: underline; }

/* En el teléfono la foto se va: a 320px de ancho, una miniatura de 8rem le deja
   al titular cuatro palabras por renglón. */
@media (max-width: 30rem) {
  .inline-related__link img { display: none; }
}
