/* ==========================================================================
   chrome.css · Monitor Fiscal — norma monitor-ui (§2, §3, §4, §5.1–5.3, §5.7)

   POR QUÉ TODO ESTÁ SCOPEADO (§5.9.1) — no "limpiar" esto:
   Esta hoja se enlaza en el <head>; el <style> del panel envuelto se emite
   DESPUÉS. A igual especificidad gana el último, así que el panel le pisaría
   las reglas al chrome. Ocho nombres colisionan de verdad entre las dos hojas
   (.card .badge .kpi-grid .tag .section-title .wrap .tabs .tab), y el síntoma
   es invisible en QA porque solo aparece en la página envuelta.

   Regla dura, verificada por gen_site.py (falla el build si se rompe):
   ninguna regla de esta hoja usa un nombre de clase suelto que también exista
   en la hoja del panel. Si hay que estilar algo del panel, va con ancestro
   (.mf-site .wrap → 0,2,0 le gana a .wrap → 0,1,0) sin tocar el panel.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens (§2). Ninguno de estos nombres lo define la hoja del panel, así
   que sobreviven aunque esa hoja se emita después. --muted es #626A78 y no
   #6B7280: el gris viejo da 4.43:1 sobre --bg y no pasa AA (§2.1).
   -------------------------------------------------------------------------- */
:root {
  --primary: #266FE0;
  --blue-dark: #184D9B;
  --blue-light: #E7F0FF;
  --ink: #171B21;
  --muted: #626A78;
  --line: #E5E7EB;
  --bg: #F5F5F5;
  --ok: #10B981;
  --warn: #F59E0B;
  --err: #EF4444;
  --violet: #8B5CF6;
  --cyan: #06B6D4;
  --footer-bg: #121212;

  --header-h: 64px;          /* token, no 64px literal: si cambia el alto del
                                header, las subpestañas sticky se arreglan acá */
  --page-max: 1100px;
  --pad-x: 16px;             /* §4.2 — 16 en móvil, 24 desde 640 */
  --radius-card: 12px;
  --radius-chip: 8px;
}
@media (min-width: 640px) { :root { --pad-x: 24px } }

/* --------------------------------------------------------------------------
   2. Base y accesibilidad (§7)
   -------------------------------------------------------------------------- */
/* Base tipográfica propia y no heredada del panel. La hoja del panel trae un
   `html, body { font-family: 'Hanken Grotesk'; font-size: 14px; ... }` del que
   el chrome venía dependiendo sin decirlo, y /buscador/ no la carga —no dibuja
   un gráfico, no tiene por qué bajarse la hoja del panel—: salía en el serif
   por defecto del navegador. Los valores son los mismos que los del panel, así
   que en las 11 rutas no cambia nada. */
/* El reset vivía SOLO en la hoja del panel (`* { box-sizing: border-box }`), y
   el chrome venía dependiendo de él sin decirlo. En /buscador/, que no carga
   esa hoja, las cajas con padding medían distinto que en las otras 11 rutas.
   Mismo valor que el panel, así que no cambia nada donde ya estaba. */
.mf-site *, .mf-site *::before, .mf-site *::after { box-sizing: border-box; }

body.mf-site {
  font-family: 'Hanken Grotesk', system-ui, sans-serif;
  font-size: 14px; line-height: 1.5;
  color: var(--ink); background: var(--bg);
  font-feature-settings: 'tnum' 1;
  margin: 0;
}

.mf-site :focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Skip link — «Saltar al contenido» → <main id="contenido"> */
.mf-skip {
  position: absolute; left: -9999px; top: 0; z-index: 60;
  background: #fff; color: var(--ink);
  font: 500 14px/1 'Hanken Grotesk', system-ui, sans-serif;
  padding: 12px 16px; border: 1px solid var(--line); border-radius: 0 0 8px 0;
}
.mf-skip:focus { left: 0; }

/* Contenedor de la norma: 1100px y el padding lateral de §4.2. */
.mf-page {
  max-width: var(--page-max);
  margin: 0 auto;
  padding-left: var(--pad-x);
  padding-right: var(--pad-x);
}

/* --------------------------------------------------------------------------
   3. Franja de estado (§5.1.1)
   Full-bleed, pero el contenido va en el MISMO contenedor y con el MISMO
   padding que la barra del header: si no coinciden, la franja y el wordmark
   quedan desalineados y se nota. No es sticky: la frescura se lee al llegar.
   -------------------------------------------------------------------------- */
.mf-topbar {
  background: var(--ink);
  color: #FAFAFA;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px; line-height: 1.4;
}
.mf-topbar .mf-page {
  display: flex; align-items: center; justify-content: center;
  /* `nowrap` ahora SÍ: la línea es «Generado con IA por Unholster», ~225px con
     el ícono. La que no cabía era la de frescura, que se fue al footer. */
  flex-wrap: nowrap; white-space: nowrap;
  gap: 8px; padding-top: 7px; padding-bottom: 7px;
}
.mf-ia-icono { width: 15px; height: 15px; flex: none; }
/* 440 —no 400 ni 500— y +0.02em: la franja es una sola línea corta y con el
   peso del cuerpo se lee floja sobre negro. El rango variable del @import es lo
   que hace que 440 sea 440 y no se redondee a 500. */
.mf-ia-txt { letter-spacing: .02em; font-weight: 440; }
/* El nombre de la casa va subrayado a propósito: en una franja de una sola
   línea, sin subrayado no se lee como enlace y nadie lo clickea. */
.mf-ia-txt a {
  color: inherit; text-decoration: underline;
  text-underline-offset: 2px; text-decoration-thickness: 1px;
}
.mf-ia-txt a:hover { text-decoration-thickness: 2px; }

/* En angosto se muestra una pieza a la vez, alternando cada 4s (chrome.js).
   Las dos no caben y apilarlas duplica el alto de la franja. */
/* --------------------------------------------------------------------------
   4. Header (§5.1) — h-16 sticky
   -------------------------------------------------------------------------- */
/* Las cuatro primeras declaraciones no son de diseño: neutralizan la fuga del
   `header { display:flex; align-items:flex-end; justify-content:space-between;
   padding-bottom:20px; margin-bottom:24px; border-bottom:1px }` de la hoja del
   panel, que se emite después de esta y le pega a nuestro
   <header class="mf-header"> por ser selector de ELEMENTO.
   El `display:flex` era el peor: volvía al `.mf-page` un flex item, que se
   encoge al ancho de su contenido (835px de 1100) y después se centra con su
   propio `margin:0 auto` — el header entero quedaba sangrado ~130px respecto
   de la franja de estado y del resto de la página. El padding y el margin
   sumaban 44px de alto fantasma debajo. Igual que en `.mf-footer`: el chequeo
   de colisión mira selectores de una clase y no ve los de elemento. */
.mf-header {
  display: block;
  padding-bottom: 0;
  margin-bottom: 0;
  border-bottom: 0;
  background: #fff;
  position: sticky; top: 0; z-index: 20;
}
/* Sombra permanente, no solo al scrollear. El header es sticky: flota sobre el
   contenido durante casi toda la lectura, y la sombra es lo que dice que está
   en un plano de arriba en vez de incrustado en la página.
   Antes aparecía recién con `scrollY > 0` para no dibujar un filete contra el
   hero de la portada. El filete existe —el hero arranca pegado al header—,
   pero a esta intensidad se lee como el canto del plano superior y no como una
   línea divisoria; y a cambio el header deja de cambiar de aspecto al primer
   píxel de scroll, que era el efecto más visible de los dos. Beneficio extra:
   sin JS el header ahora también tiene sombra.
   Los dos planos son el `shadow` de Tailwind, el mismo de
   monitormunicipios.cl: el de 3px pone la difusión y el de 2px con spread
   negativo aprieta el contacto para que el canto no salga lavado. */
.mf-header { box-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1); }
.mf-header .mf-page {
  height: var(--header-h);
  display: flex; align-items: center; gap: 12px;
}
/* Sin nav de escritorio la barra es marca + hamburguesa: 12px de gap entre dos
   piezas separadas por `margin-left: auto` no separan nada y sí le quitan
   ancho a la marca. */
@media (max-width: 1023px) { .mf-header .mf-page { gap: 2px } }

/* Marca: el lockup oficial del monitor (§5.1.3), que ya dice «Monitor Fiscal
   by Unholster» y por eso reemplaza al par nombre-como-texto + lockup del
   publisher que había mientras no existía un SVG propio.
   Manda el ALTO y el ancho sale del viewBox (455×146 ≈ 3,1:1); nunca al revés,
   porque el header tiene alto fijo. 32px dejan la primera línea del lockup en
   ~13px de altura de mayúscula, la misma que tenía el wordmark en texto a
   19px/800: la marca no cambia de peso visual al cambiar de soporte. */
/* `flex: none` y NO `min-width: 0` — portado del monitor DT, donde ya costó un
   bug: con `min-width: 0` la marca es lo ÚNICO encogible de la barra (las
   acciones son `flex: none` y las píldoras son `nowrap`, así que nadie más
   cede), y al traducir el nav a alemán el logo se comprimía hasta 0px de ancho
   mientras el SVG seguía pintándose sobre su caja vacía: el nav impreso encima
   del wordmark. La identidad no es lo que se sacrifica cuando falta lugar; lo
   que cede es el nav, y si no cabe está la hamburguesa.
   `min-height: 44px` porque el enlace de la marca es un target táctil como
   cualquier otro (§6). */
.mf-brand {
  display: flex; align-items: center; gap: 8px;
  text-decoration: none; flex: none; min-height: 44px;
}
/* El ícono va subido 20%: la marca lo trae con aire abajo y sin esto no asienta
   con el wordmark. Los monitores publicados usan el mismo -20%. */
.mf-brand-icono {
  height: 32px; width: 32px; flex-shrink: 0; display: block;
  transform: translateY(-20%);
}
/* `[hidden]` con `display: none` explícito. El atributo se apoya en una regla
   del navegador (`[hidden] { display: none }`) y CUALQUIER `display` de autor le
   gana: con el `display: block` de arriba, esconder la estática desde JS no la
   escondía —quedaban los dos íconos en el header, el quieto y el animado— y
   `img.hidden` decía `true` igual, así que la comprobación no lo veía. */
.mf-brand-icono[hidden] { display: none; }
/* El wordmark escala en dos pasos y NUNCA se esconde: es la identidad. Antes
   acá se ocultaba bajo 420px para que entrara el header; lo que sobraba era el
   <select> de idioma de 128px, que ahora es un dropdown de «ES». */
.mf-brand-logo { height: 32px; width: auto; display: block; }
@media (max-width: 360px) { .mf-brand-logo { height: 26px } }
@media (min-width: 640px) { .mf-brand-logo { height: 40px } }

/* Nav de escritorio. Va en lg y no en md: seis puertas miden más de 420px
   (§5.1) y entre 768 y 1024 desbordaban. */
.mf-nav { display: none; margin-left: auto; align-items: center; gap: 2px; }
@media (min-width: 1024px) { .mf-nav { display: flex } }

/* Píldoras con los VALORES de §5.2. font-family, text-transform y
   letter-spacing van escritos aunque parezcan redundantes: son justo las
   propiedades que la hoja del panel pisa. */
.mf-nav .mf-pill,
.mf-menu-lista .mf-pill {
  font-family: inherit;
  font-size: 14px; font-weight: 500; line-height: 1;
  text-transform: none; letter-spacing: normal;
  border-radius: 6px; padding: 8px 12px;
  color: var(--muted); text-decoration: none; white-space: nowrap;
  transition: color .15s ease, background-color .15s ease;
}
.mf-nav .mf-pill:hover { color: var(--primary); background: var(--bg); }
/* Activo: --primary sobre --blue-light son los valores de la referencia.
   Da 4.13:1 y NO pasa AA — es un defecto conocido de la norma (§2.2) que se
   resuelve para los tres monitores a la vez, no acá. Queda anotado en
   MONITOR.md; no lo cambies solo en este monitor o rompes la fidelidad. */
/* Dos valores y no uno: la hoja de una puerta lleva aria-current="page"
   —es la página—, pero el summary de una puerta con desplegable lleva
   aria-current="true", porque no es un enlace a página sino el contenedor que
   la tiene dentro (gen_site.py · pills). Si acá sólo se lista "page", estar en
   /ingresos/ deja «Presupuesto» sin marcar. */
.mf-nav .mf-pill[aria-current="page"],
.mf-nav .mf-pill[aria-current="true"],
.mf-menu-lista .mf-pill[aria-current="page"],
.mf-menu-lista .mf-pill[aria-current="true"] { color: var(--primary); background: var(--blue-light); }

/* Acciones de móvil (§5.1.4): hamburguesa e idioma, los dos a 18px.
   El grupo vive FUERA del nav de escritorio — ese nav se esconde bajo 1024px
   y se llevaría el idioma con él. El reordenamiento va con `order`, no
   moviendo el markup: el DOM mantiene el orden que recorre el teclado. */
.mf-acciones { display: flex; align-items: center; gap: 4px; margin-left: auto; order: 1; flex: none; }
/* Con el nav visible el que separa es el nav; si las dos cosas llevan
   `margin-left: auto`, el espacio libre se reparte entre las dos y el bloque
   de acciones queda flotando en el medio en vez de pegado a la derecha. */
@media (min-width: 1024px) { .mf-acciones { margin-left: 0 } }
@media (min-width: 1024px) { .mf-acciones { margin-left: 12px } }

.mf-icono-btn {
  width: 44px; height: 44px;            /* target táctil ≥44px */
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--ink); border-radius: 8px;
  font-family: inherit;                 /* un <button> no hereda tipografía */
}
.mf-icono-btn:hover { background: var(--bg); }
.mf-icono-btn svg { width: 18px; height: 18px; }

/* --------------------------------------------------------------------------
   5. Selector de idioma (§5.1.2)
   Etiqueta honesta: NO cambia el idioma del sitio, cambia el de las
   explicaciones. Un «Idioma» pelado promete cinco idiomas que no existen.
   Es un <select> nativo a propósito (§5.16): el popup lo posiciona el sistema,
   siempre queda alineado y en móvil trae el picker del sistema.
   -------------------------------------------------------------------------- */
/* Sin rótulo visible: el globo + el propio <select> ya dicen qué es, y el
   texto largo competía con la nav. Por eso el globo tampoco desaparece en
   escritorio como antes, cuando cedía el lugar al rótulo. */
/* Valores portados del monitor DT (ui/monitor_ui.css, «Selector de idioma —
   dropdown <details>»), que es la implementación de referencia de la norma. */
.mf-lang-drop { position: relative; flex: none; }
.mf-lang-drop > summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; gap: 4px;
  font-family: inherit; font-size: 14px; font-weight: 500;
  color: var(--muted); padding: 8px 10px; border-radius: 6px;
  white-space: nowrap; transition: color .15s, background .15s;
}
.mf-lang-drop > summary::-webkit-details-marker { display: none; }
.mf-lang-drop > summary::marker { content: ''; }
.mf-lang-drop > summary:hover,
.mf-lang-drop[open] > summary { color: var(--primary); background: var(--bg); }
.mf-lang-drop > summary > svg:first-of-type { width: 18px; height: 18px; flex: none; }
.mf-flecha { width: 8px; height: 8px; flex: none; transition: transform .15s; }
.mf-lang-drop[open] .mf-flecha { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .mf-lang-drop > summary, .mf-lang-drop .mf-flecha { transition: none; }
}
.mf-lang-pop {
  position: absolute; right: 0; top: 100%; margin-top: 8px;
  /* 46 y no 30: el botón «volver arriba» es fixed a la derecha con z-index 45
     y en un teléfono le tapaba la última opción. Un popup recién abierto gana
     contra un control flotante permanente; el modal (50) sigue arriba. */
  z-index: 46;
  /* 95px alcanza para «Português», el nombre más largo, y deja el bloque
     pegado al texto: con más aire una lista alineada a la izquierda no se lee
     como alineada, se lee como texto suelto en una caja. `min-width` y no
     `width`, para que un idioma más largo la haga crecer sola. */
  min-width: 95px;
  background: #fff; border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 10px 24px rgba(23, 27, 33, .12);
  padding: 6px 0;
}
.mf-lang-pop button {
  display: block; width: 100%; text-align: left;
  /* Familia nombrada y no heredada: el `.lang-select` del panel trae
     JetBrains Mono y la lista salía monoespaciada. */
  font-family: 'Hanken Grotesk', system-ui, sans-serif;
  font-size: 12px; font-weight: 400; letter-spacing: 0; text-transform: none;
  color: var(--ink); background: none; border: 0; border-radius: 0;
  padding: 8px 16px; cursor: pointer;
  transition: background .15s, color .15s;
}
.mf-lang-pop button:hover { background: #F6F8FB; color: var(--primary); }
.mf-lang-pop button.active { color: var(--primary); font-weight: 600; background: none; }
/* El <select> del panel viaja acá adentro para conservar su listener, pero no
   se muestra. Fuera de pantalla y no `display:none`: sin caja hay navegadores
   que no disparan `change`. */
.mf-lang-nativo {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* --------------------------------------------------------------------------
   6. Menú móvil full-screen sobre <details> nativo (teclado gratis) — §5.2
   -------------------------------------------------------------------------- */
.mf-menu { position: static; }
.mf-menu > summary { list-style: none; }
.mf-menu > summary::-webkit-details-marker { display: none; }
.mf-menu > summary::marker { content: ''; }
.mf-menu > summary {
  width: 44px; height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; border-radius: 8px; color: var(--ink);
}
.mf-menu > summary:hover { background: var(--bg); }
/* El ícono, 18×18 dentro del target de 44. Sin esto un SVG con viewBox y sin
   width/height se estira a su contenedor: la hamburguesa se estaba pintando a
   44×44 y se veía como un bloque, no como un ícono. */
.mf-menu > summary svg { width: 18px; height: 18px; flex: none; }
@media (min-width: 1024px) { .mf-menu { display: none } }

/* Con el <details> cerrado, un hijo `position: fixed` NO lo esconde el UA: el
   panel se sigue maquetando —colapsado— y sus enlaces quedan en el orden de
   tabulación, invisibles pero enfocables. Un usuario de teclado pasa por once
   links fantasma antes de llegar al contenido. El display:none explícito es lo
   que lo saca del layout y del foco. */
.mf-menu:not([open]) .mf-menu-pop { display: none; }

.mf-menu-pop {
  position: fixed; inset: 0; z-index: 50;
  background: #fff; overflow-y: auto;
  display: flex; flex-direction: column;
}
/* Trampa de §5.1.5: la barra del panel hereda max-width y margin:0 auto de
   .mf-header .mf-page. En un contenedor flex en columna un margen lateral
   `auto` ANULA el stretch y la barra se encoge al ancho de su contenido. Hay
   que resetear las dos. La divisoria queda a ancho completo de pantalla. */
.mf-menu-barra {
  max-width: none; margin: 0;
  /* +10px de aire ARRIBA del logo, no repartidos: con `align-items: center` un
     padding simétrico solo movería el centro 5px. `min-height` en vez de
     `height` para que el padding sume alto en vez de comerle espacio al
     contenido —con border-box, `height` fijo más padding aprieta el logo—. */
  min-height: calc(var(--header-h) + 10px);
  padding-top: 10px;
  display: flex; align-items: center; justify-content: space-between;
  padding-left: var(--pad-x); padding-right: var(--pad-x);
  border-bottom: 1px solid var(--line);
}
.mf-menu-lista {
  list-style: none; margin: 0; padding: 0;
  padding-left: var(--pad-x); padding-right: var(--pad-x);
}
.mf-menu-lista li { border-bottom: 1px solid var(--line); }
.mf-menu-lista .mf-pill {
  display: block; font-size: 17px; padding: 16px 0; border-radius: 0;
  color: var(--ink);
}
.mf-menu-lista .mf-pill[aria-current="page"],
.mf-menu-lista .mf-pill[aria-current="true"] { background: none; color: var(--primary); font-weight: 600; }
.mf-menu-lista .mf-pill:hover { background: none; color: var(--primary); }
/* Todos en 500: con una sola lista y sin el rótulo «Más secciones», un cambio
   de peso a mitad de camino se lee como un error, no como jerarquía. */
.mf-menu-lista .mf-pill { font-weight: 500; }
/* Pie del menú: rótulo chico y el sello centrado. */
.mf-menu-pie {
  margin-top: auto; flex: none;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 40px var(--pad-x);
}
.mf-menu-pie-rotulo {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9px; text-transform: uppercase; letter-spacing: .14em;
  color: var(--muted);
}
/* `brightness(0)` y NO «sin filtro»: el sello viene dibujado en claro (#EEEEF0)
   porque está hecho para el pie oscuro del sitio, y sobre el panel blanco del
   menú desaparecía. brightness(0) lo pasa a negro conservando el alfa, así que
   las letras caladas siguen caladas y se lee igual en negativo. No es
   `invert(1)`: invertir depende del color de origen y ataría este estilo a que
   el sello siga siendo claro; brightness(0) da negro venga de donde venga. */
.mf-menu-pie img {
  height: 30px; width: auto; display: block;
  filter: brightness(0); opacity: .55;
}

/* Keyframes SEPARADOS, no negociable: el mismo animation-name no re-dispara,
   `animationend` nunca llega y el overlay queda pegado bloqueando clicks. */
@keyframes menu-pop     { from { opacity: 0; transform: translateX(10px) } to { opacity: 1; transform: translateX(0) } }
@keyframes menu-pop-out { to   { opacity: 0; transform: translateX(10px) } }
details[open] > .mf-menu-pop { animation: menu-pop .25s cubic-bezier(.34,1.4,.64,1); }
details[open] > .mf-menu-pop.mf-menu-out { animation: menu-pop-out .2s ease-in forwards; }
@media (prefers-reduced-motion: reduce) { details[open] > .mf-menu-pop { animation: none } }

/* --------------------------------------------------------------------------
   7. Hero (§5.7)
   Banda full-bleed FUERA del <main> (el ancho lo pone el .mf-page interno).
   Lleva la foto de identidad bajo un velo blanco. Las tres variables las
   inyecta gen_site.py desde el contrato (brand.portada): la ruta del archivo
   no se escribe acá, o habría que tocar dos lugares para cambiar una foto.
   El `blue-light` queda de respaldo en `background-color`: si la foto no carga
   —o si algún día no hay foto en el contrato— la banda no sale blanca y sin
   identidad, sale como salía antes.
   -------------------------------------------------------------------------- */
.mf-hero {
  position: relative;
  background: var(--blue-light);      /* respaldo si la foto no carga */
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}
/* La foto en DOS capas, como la norma: grises abajo, velo blanco encima. En una
   sola capa con `linear-gradient(...), url(...)` el velo funciona pero la foto
   no se puede pasar a grises —`filter` sobre un background tiñe también el
   texto—, así que el gris dependía de que el archivo ya viniera desaturado.
   Con `grayscale(1)` acá, cualquier foto que entre al contrato sale en grises. */
.mf-hero::before {
  content: ''; position: absolute; inset: 0;
  background-image: var(--hero-foto, none);
  background-size: cover; background-position: center;
  filter: grayscale(1);
}
.mf-hero::after {
  content: ''; position: absolute; inset: 0;
  background: rgb(255 255 255 / var(--hero-velo, .8));
}
/* La variante liviana hasta 960 CSS px: bajar los 1426px de ancho completo a un
   teléfono son ~165 kB de más por una imagen que igual se recorta. */
@media (max-width: 960px) {
  .mf-hero::before { background-image: var(--hero-foto-960, var(--hero-foto, none)); }
}
/* El contenido va SOBRE las dos capas; sin esto el velo lo tapa. */
.mf-hero .mf-page { position: relative; z-index: 1; }
.mf-hero .mf-page { padding-top: 32px; padding-bottom: 32px; }
@media (min-width: 640px) { .mf-hero .mf-page { padding-top: 48px; padding-bottom: 48px } }

/* Trampa de especificidad de §5.7.1: `.mf-hero a` es (0,1,1) y le ganaría a
   `.mf-btn` (0,1,0), así que los dos botones saldrían con color de enlace. */
.mf-hero a:not(.mf-btn) { color: var(--blue-dark); }

.mf-hero-ctas { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 24px; }
/* Las cuatro últimas declaraciones existen para que un <button class="mf-btn">
   se vea IGUAL que un <a class="mf-btn">. Los botones del hero son enlaces y el
   de /buscador/ es un submit, y el UA le da al <button> cosas que al <a> no:
   `border: 2px outset`, `line-height: normal`, su propia tipografía y su propio
   `appearance`. Sin esto el mismo par de clases daba un botón con bisel negro y
   medio píxel más bajo. `cursor` porque un <a> ya trae la manito y un <button>
   solo la trae si se la das. */
.mf-btn {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: inherit; font-size: 13px; font-weight: 600;
  padding: 10px 16px; border-radius: var(--radius-chip);
  text-decoration: none; transition: background-color .15s ease;
  -webkit-appearance: none; appearance: none;
  border: 1px solid transparent;
  line-height: 1.5;
  cursor: pointer;
}
/* El borde va en el mismo color del fondo y no en 0: con `border: 0` el
   primario mediría 2px menos que el fantasma —que sí lleva borde— y los dos
   botones del hero, que van uno al lado del otro, quedaban desparejos. */
.mf-btn-primary { background: var(--primary); border-color: var(--primary); color: #fff; }
.mf-btn-primary:hover { background: var(--blue-dark); border-color: var(--blue-dark); }
.mf-btn-ghost { background: #fff; border-color: var(--line); color: #141414; }
.mf-btn-ghost:hover { background: var(--bg); }

/* El hero es el ENCABEZADO de la ruta: se le mueve el .tab-intro del panel
   (§5.9.3) para que la página tenga un solo <h1>. Ese nodo es el mismo que
   traduce la capa i18n, por eso se mueve y no se copia. */
.mf-hero .tab-intro {
  margin: 0; padding: 0; border-bottom: 0;
}
/* El rótulo va en #141414, el mismo literal que la bajada del hero. Estuvo en
   `blue-dark` mientras era el único acento de color del bloque; ahora el color
   lo lleva la segunda línea del <h1>, y dos azules distintos en tres líneas
   seguidas competían entre sí. Contraste: sobre el punto más oscuro de la foto
   velada —rgb(226,226,226), el mazo cae bajo el texto en todos los anchos—
   #141414 da 15,1:1, muy por encima del 6,30:1 que daba `blue-dark`. */
.mf-hero .tab-intro .tag {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; line-height: 14px; letter-spacing: .14em;
  text-transform: uppercase; color: #141414; margin-bottom: 8px;
}
.mf-hero .tab-intro h1 {
  font-family: 'Hanken Grotesk', system-ui, sans-serif;
  font-size: clamp(26px, 3.2vw, 40px); line-height: 1.05; font-weight: 800;
  letter-spacing: -.01em; color: var(--ink); margin: 0 0 12px;
}
/* Segunda línea del <h1>, en azul. La regla también vive en la hoja del panel
   —de ahí salen los <h1> de las once secciones— pero /buscador/ no carga esa
   hoja: no dibuja un solo gráfico y bajarle el panel entero por una regla de
   color sería absurdo. Con la copia acá, el hero se ve igual en las doce rutas.
   El contraste está medido: #266FE0 sobre la foto velada da 3,66:1, que pasa AA
   para texto grande —el umbral ahí es 3:1— y este <h1> nunca baja de 26px en
   peso 800. Los textos chicos del hero siguen en blue-dark (MONITOR.md #4g). */
.mf-hero .tab-intro h1 .hero-l2 { display: block; color: var(--primary); }
/* El salto y el color, por separado: `.hero-negro` devuelve el color del <h1> a
   las palabras de enlace que abren la segunda línea, y `.hero-azul` pinta el
   azul sin forzar salto, para los títulos de una línea. Mismo par que la hoja
   del panel. Sobre la foto velada --ink da 15,1:1, así que el negro no tiene el
   problema de contraste del azul. */
.mf-hero .tab-intro h1 .hero-negro { color: var(--ink); }
.mf-hero .tab-intro h1 .hero-azul  { color: var(--primary); }
/* #141414 es un literal de la norma, no un token de §2: difiere de --ink en
   algo imperceptible (17,9:1 contra 16,4:1 sobre blanco) y queda anotado como
   desvío por si algún día se normaliza. `62ch` y no un ancho en px: la medida
   de lectura se mide en caracteres. */
.mf-hero .tab-intro p {
  font-size: 14px; font-weight: 300; line-height: 1.5;
  color: #141414; margin: 0; max-width: 62ch;
}

/* --------------------------------------------------------------------------
   Página de error (404.html)
   -------------------------------------------------------------------------- */
/* Centrada en la ventana y sin chrome: la única jerarquía es marca → qué pasó →
   salida. `min-height: 100svh` y no `100vh`: en móvil la barra del navegador se
   come parte del viewport y con vh el botón quedaba debajo del borde. */
.mf-404 {
  min-height: 100svh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; text-align: center;
  padding: 48px 24px;
}
.mf-404-marca { margin-bottom: 28px; }
.mf-404 h1 {
  font-family: 'Hanken Grotesk', system-ui, sans-serif;
  font-size: clamp(24px, 3vw, 34px); line-height: 1.15; font-weight: 800;
  letter-spacing: -.01em; color: var(--ink); margin: 0;
}
.mf-404 p {
  font-size: 15px; font-weight: 300; line-height: 1.5;
  color: var(--muted); margin: 10px 0 0; max-width: 46ch;
}
.mf-404 .mf-btn { margin-top: 28px; }

/* --------------------------------------------------------------------------
   8. Footer (§5.3) — 5/4/3
   -------------------------------------------------------------------------- */
/* `text-align` y `padding-top` NO son decorativos acá: la hoja del panel trae
   un `footer { text-align: center; padding-top: 18px; font-size: 10px }` con
   selector de ELEMENTO, se emite después de esta y le pega a nuestro
   <footer class="mf-footer">. Por eso el footer del chrome salía centrado
   entero —marca, columnas y todo— sin que ninguna regla de acá lo pidiera. El
   chequeo de colisión no lo agarra: mira selectores de una clase, no de
   elemento. Declararlos acá los recupera por especificidad (0,1,0 > 0,0,1). */
.mf-footer {
  margin-top: 64px;
  padding-top: 0;
  text-align: left;
  /* Base honesta: el panel deja `font-size: 10px` heredable en el footer. Hoy
     todo lo que lleva texto acá declara su tamaño, así que no se ve — pero el
     próximo párrafo que alguien agregue saldría a 10px sin explicación. */
  font-size: 14px;
  background: var(--footer-bg);
  border-top: 1px solid rgb(255 255 255 / .08);
  color: #fff;
  font-family: 'Hanken Grotesk', system-ui, sans-serif;
}
.mf-footer .mf-page { padding-top: 48px; padding-bottom: 24px; }
.mf-footer-grid { display: grid; grid-template-columns: 1fr; gap: 32px; }
@media (min-width: 768px) {
  .mf-footer-grid { grid-template-columns: repeat(12, 1fr); gap: 24px; }
  .mf-col-marca { grid-column: span 5 }
  .mf-col-explorar { grid-column: span 4 }
  .mf-col-fuentes { grid-column: span 3 }
}
/* Solo las etiquetas de columna van en mono. El resto —bajada, enlaces,
   contacto— en Hanken. */
.mf-footer-rotulo {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; line-height: 14px; letter-spacing: .14em;
  text-transform: uppercase; color: rgb(255 255 255 / .45);
  margin-bottom: 14px;
}
.mf-footer-bajada {
  font-size: 14px; font-weight: 300; line-height: 1.6;
  color: rgb(255 255 255 / .6); max-width: 26rem; margin-top: 14px;
}
/* La frescura del dato, bajo la bajada. El CSS de la franja no servía acá: allá
   era una línea centrada que no envuelve, y en una columna de 5/12 esto tiene
   que apilarse. */
.mf-frescura {
  display: flex; flex-direction: column; gap: 4px; margin-top: 14px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px; line-height: 1.5;
  color: rgb(255 255 255 / .55);
}
.mf-frescura b { color: rgb(255 255 255 / .9); font-weight: 600; }
/* El punto verde acompaña a «Actualizado el»: es lo que dice que el dato está
   vivo. Va DENTRO del <span> para que no se separe de su frase al envolver. */
.mf-dot {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--ok); margin-right: 7px; vertical-align: middle;
}
.mf-footer ul { list-style: none; margin: 0; padding: 0; }
.mf-footer li + li { margin-top: 10px; }
.mf-footer a { text-decoration: none; }
.mf-col-explorar a { color: rgb(255 255 255 / .75); font-size: 14px; }
.mf-col-explorar a:hover { color: var(--primary); }
.mf-col-fuentes a { color: rgb(255 255 255 / .9); font-size: 13px; line-height: 1.45; display: inline-block; }
.mf-col-fuentes a:hover { color: var(--primary); }

/* La marca del footer lleva el lockup completo, invertido, envuelto en un
   link a la portada. */
/* Fila de la marca del footer: el wordmark a la izquierda y, en pantalla
   angosta, el selector de idioma empujado a la derecha. */
.mf-marca-fila { display: flex; align-items: center; gap: 12px; }
.mf-footer-lang { margin-left: auto; }
/* Vacío en escritorio, cuando el selector volvió al header: sin esto deja un
   hueco flexible que corre la marca. */
.mf-footer-lang:empty { display: none; }
/* Dentro del footer el globo va en claro sobre fondo oscuro… */
.mf-footer-lang .mf-lang-drop > summary { color: rgb(255 255 255 / .7); }
.mf-footer-lang .mf-lang-drop > summary:hover,
.mf-footer-lang .mf-lang-drop[open] > summary {
  color: #fff; background: rgb(255 255 255 / .08);
}
/* …y el panel abre hacia ARRIBA: el footer es lo último de la página y hacia
   abajo no hay lugar. Solo se invierte el eje vertical: el `right: 0` de la
   regla base se conserva, porque el disparador está pegado a la derecha y
   abrir hacia la derecha mandaría el panel fuera de la pantalla. */
.mf-footer-lang .mf-lang-pop { top: auto; bottom: calc(100% + 8px); }

.mf-footer-marca { display: inline-flex; align-items: center; gap: 11px; }
/* El lockup viene en negro y el footer es oscuro: brightness(0) lo aplana a
   negro puro e invert(1) lo deja blanco entero, sin depender de qué tintas
   traiga el SVG adentro. Más alto que en el header porque acá la marca es el
   ancla de la columna, no una puerta de 64px.
   Al ícono le toca el mismo filtro a propósito: su azul (#2150E8) y su azul
   marino (#121331) no se leen sobre fondo oscuro, así que sale en blanco plano
   igual que el wordmark de al lado. */
.mf-footer-marca img { filter: brightness(0) invert(1); height: 32px; width: auto; }

.mf-footer-barra {
  display: flex; flex-direction: column; gap: 20px;
  /* Sin línea divisoria: el aire de margin+padding ya separa la barra de las
     columnas, y un filete al 8% sobre negro se lee como un borde suelto. */
  margin-top: 40px; padding-top: 24px;
}
@media (min-width: 768px) {
  .mf-footer-barra { flex-direction: row; align-items: center; justify-content: space-between; }
}
.mf-redes { display: flex; gap: 10px; }
.mf-redes a {
  width: 36px; height: 36px; border-radius: 999px;
  border: 1px solid rgb(255 255 255 / .2);
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff; transition: transform .15s ease, border-color .15s ease;
}
.mf-redes a:hover { transform: translateY(-2px); border-color: var(--primary); }
.mf-redes svg { width: 16px; height: 16px; }
/* El logo del publisher ya viene en su variante clara (#EEEEF0) para fondo
   oscuro: NO lleva el filtro de inversión que sí necesita el wordmark negro
   del monitor. Forzarlo a blanco puro le cambiaría la tinta a la marca. */
.mf-publisher { display: inline-flex; align-items: center; opacity: .9; }
.mf-publisher:hover { opacity: 1; }
.mf-publisher img { height: 34px; width: auto; display: block; }

/* La invitación a escribir va al final, a ancho completo. */
.mf-contacto {
  font-size: 10px; line-height: 14px; color: rgb(255 255 255 / .5);
  margin-top: 24px; text-align: left; padding-bottom: 24px;
}
@media (min-width: 768px) { .mf-contacto { text-align: right } }
.mf-contacto a { color: rgb(255 255 255 / .7); text-decoration: underline; }

/* --------------------------------------------------------------------------
   9. Volver arriba (§5.14) — <button>, no <a href="#">, que ensucia el
   historial y deja un hash.
   -------------------------------------------------------------------------- */
.mf-arriba {
  position: fixed; right: 16px; z-index: 30;
  bottom: calc(16px + env(safe-area-inset-bottom));
  width: 44px; height: 44px; border-radius: 999px;
  background: #fff; border: 1px solid var(--line); color: var(--ink);
  box-shadow: 0 4px 12px rgb(0 0 0 / .12);
  display: none; align-items: center; justify-content: center; cursor: pointer;
}
.mf-arriba[data-visible] { display: inline-flex; }
.mf-arriba svg { width: 18px; height: 18px; }

/* --------------------------------------------------------------------------
   10. Estado de datos (§5.8, perfil estático)
   El equivalente de error.tsx acá es que falle la carga del JSON que alimenta
   los gráficos. Un dashboard que pinta un lienzo en blanco miente igual que
   una tabla vacía sin mensaje.
   -------------------------------------------------------------------------- */
.mf-estado {
  border: 1px solid var(--line); background: #fff;
  padding: 16px; border-radius: var(--radius-card);
  margin: 24px 0;
}
.mf-estado-titulo { font-size: 18px; font-weight: 600; color: var(--ink); margin: 0 0 4px; }
.mf-estado p { font-size: 14px; font-weight: 300; color: var(--muted); margin: 0; }
.mf-estado .mf-btn { margin-top: 14px; }

/* ==========================================================================
   11. OVERRIDES DE LA HOJA DEL PANEL
   Todas con ancestro .mf-site para ganarle por especificidad sin tocar el
   panel (§5.9.1). Estas SÍ nombran clases del host — es el único bloque que
   puede, y gen_site.py lo exime del chequeo de colisión justamente porque
   ninguna regla de acá usa un nombre de clase suelto.
   ========================================================================== */

/* §4.2 — el panel usa 24px fijos de padding lateral: a 320px se van 48 de 320
   en aire. Se alinea con el contenedor de la norma. */
.mf-site .wrap {
  max-width: var(--page-max);
  padding-left: var(--pad-x); padding-right: var(--pad-x);
  padding-top: 24px; padding-bottom: 64px;
}
@media (min-width: 640px) { .mf-site .wrap { padding-top: 32px } }

/* El header y la nav de pestañas del panel los reemplaza el chrome. */
.mf-site > .wrap > header,
.mf-site .tabs { display: none; }

/* El .tab-intro del panel activo se movió al hero. Los de los panels
   inactivos siguen en el DOM (los necesita la capa i18n) pero no se ven,
   porque su panel está en display:none de todos modos. */
.mf-site .tab-panel > .tab-intro { display: none; }

/* §5.4 — toda tabla ancha: contenedor con scroll DENTRO del padding lateral,
   sin márgenes negativos, y primera columna fija en móvil. Sin la columna fija,
   dos columnas a la derecha ya no se sabe de qué fila es el número; sin el
   scroll, la tabla desborda la página.

   Los contenedores del panel no tienen clase: son <div style="overflow-x:auto">
   escritos inline. Por eso se los toma por el atributo, y las tablas por su
   clase real (.cuadro1, .min-tabla, .heatmap). */
.mf-site [style*="overflow-x"],
.mf-site .tbl-wrap,
.mf-site .table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* Para que `background: inherit` en la celda fija signifique algo, la fila
   necesita un fondo. Se lo damos con :where(), especificidad CERO, para no
   pisar ni el hover ni las filas con tinte propio. */
:where(.mf-site table.cuadro1 tbody tr,
       .mf-site table.min-tabla tbody tr,
       .mf-site table.heatmap tbody tr,
       .mf-site [style*="overflow-x"] table tbody tr) { background: #fff; }

@media (max-width: 767px) {
  .mf-site table.cuadro1 th:first-child,
  .mf-site table.cuadro1 td:first-child,
  .mf-site table.min-tabla th:first-child,
  .mf-site table.min-tabla td:first-child,
  .mf-site table.heatmap th:first-child,
  .mf-site table.heatmap td:first-child,
  .mf-site [style*="overflow-x"] table th:first-child,
  .mf-site [style*="overflow-x"] table td:first-child {
    position: sticky;
    left: 0;
    box-shadow: 1px 0 0 var(--line);
  }
  /* La celda de dato hereda el fondo de su fila: una fila con tinte propio
     mantiene el tinte también en la columna congelada. */
  .mf-site table.cuadro1 td:first-child,
  .mf-site table.min-tabla td:first-child,
  .mf-site table.heatmap td:first-child,
  .mf-site [style*="overflow-x"] table td:first-child {
    background: inherit;
    z-index: 1;                       /* bajo los encabezados */
  }
  /* El encabezado fijo va SOBRE el thead sticky (11 contra 10) o al scrollear
     horizontal el encabezado de la primera columna queda tapado. */
  .mf-site table.cuadro1 th:first-child,
  .mf-site table.min-tabla th:first-child,
  .mf-site table.heatmap th:first-child,
  .mf-site [style*="overflow-x"] table th:first-child {
    background: var(--bg);
    z-index: 11;
  }
  /* Las dos filas con color propio del panel: sin esto, la celda congelada
     saldría blanca mientras el resto de su fila está gris. */
  .mf-site table.cuadro1 tr.total td:first-child { background: var(--bg); }
  .mf-site table.min-tabla tr:hover td:first-child { background: var(--bg); }
}

/* §5.14 — las subpestañas del panel vienen sticky con un top calculado para
   un layout que ya no existe, y con z-index por encima del header: al
   scrollear se pegaban ENCIMA del chrome. Van bajo el header en z. */
.mf-site .subtabs {
  top: calc(var(--header-h) + 1px);
  z-index: 15;
}

/* §5.15.3 — bajar el contenedor de 1180 a 1100 hace envolver etiquetas que
   estaban justas. El panel ya usa 1100, así que no aplica; queda el
   recordatorio para el próximo que lo mueva. */

/* Un <details> cerrado no puede dejar su panel fixed ocupando lugar: sin esto
   el overlay del menú mide en el layout aunque no se vea, y el chequeo de
   padding lateral lo reporta como infractor en todos los anchos. */
.mf-menu:not([open]) > .mf-menu-pop { display: none; }
/* El skip link vive fuera de la pantalla a propósito hasta recibir foco. */
.mf-skip { --mf-fuera-de-flujo: 1; }
/* Estado de serie vacía (§5.8): «Sin datos de X», nunca un eje con ceros. */
.mf-estado-vacio { font-size: 14px; font-weight: 300; color: var(--muted); margin: 12px 0; }

/* --------------------------------------------------------------------------
   11. Buscador (§5.1 la lupa · /buscador/ la página)
   -------------------------------------------------------------------------- */
/* La lupa del header: LLEVA a /buscador/, no es un campo. Un campo de 240px
   compite con las puertas del nav y crea un segundo lugar donde buscar. */
.mf-buscar-lupa {
  width: 44px; height: 44px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px; color: var(--muted);
  transition: color .15s, background .15s;
}
.mf-buscar-lupa:hover { color: var(--primary); background: var(--bg); }
.mf-buscar-lupa svg { width: 18px; height: 18px; }

.mf-buscador { padding-top: 32px; padding-bottom: 64px; }
.mf-buscar-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; }
.mf-buscar-lbl {
  flex: 1 1 100%;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; line-height: 14px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted);
}
/* La caja ocupa la fila entera y es el ancla del desplegable: el panel se
   posiciona contra ella para quedar exactamente bajo el campo y con su ancho. */
.mf-buscar-caja { position: relative; flex: 1 1 100%; min-width: 0; }
.mf-buscar-campo {
  min-width: 0;
  display: flex; align-items: center; gap: 8px;
  padding: 0 12px;
  background: #fff; border: 1px solid var(--line);
  border-radius: var(--radius-chip);
}
/* Foco: UN solo borde. El `.mf-site :focus-visible` general le dibujaba al
   <input> su propio contorno azul a 2px de separación, y como la caja de
   alrededor ya se pone azul con `:focus-within`, se veían dos bordes
   concéntricos. Acá se apaga el contorno del input —el indicador no se pierde,
   se muda al contenedor— y el borde de la caja se engrosa con una sombra
   interior en vez de subir a 2px: así no hay salto de layout al enfocar. */
.mf-buscar-campo:focus-within {
  border-color: var(--primary);
  box-shadow: inset 0 0 0 1px var(--primary);
}
.mf-buscar-campo input:focus-visible,
.mf-buscar-campo input:focus { outline: none; }
.mf-buscar-campo svg { flex: none; color: var(--muted); }
.mf-buscar-campo input {
  flex: 1; min-width: 0; height: 42px;
  border: 0; background: none; outline: none;
  font-family: inherit; font-size: 14px; color: var(--ink);
}
/* La cruz nativa de `type="search"` se esconde: sólo existe en WebKit, no se
   puede estilar, y con la propia serían dos. */
.mf-buscar-campo input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.mf-buscar-x {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; padding: 0;
  border: 0; border-radius: 50%; background: none;
  color: var(--muted); cursor: pointer;
  transition: color .15s ease, background-color .15s ease;
}
.mf-buscar-x:hover { color: var(--ink); background: var(--bg); }
.mf-buscar-x[hidden] { display: none; }

/* Coincidencias resaltadas. `background: none` a propósito: el amarillo del
   navegador sobre una lista de resultados se lee como error resaltado. Lo que
   marca es el peso, que es lo que se pidió. */
.mf-buscador mark {
  background: none; color: inherit; font-weight: 700;
}
.mf-res-n mark { font-weight: 800; }

/* Panel de resultados. Borde, radio, sombra y z-index son los MISMOS que el
   desplegable del idioma y el de los <select> del panel: es el mismo componente
   del sitio con otro contenido, y tres popovers distintos serían tres. Con tope
   de alto y scroll propio: «sa» devuelve nueve entradas y sin tope el panel
   tapaba la página entera. */
.mf-buscar-pop {
  position: absolute; left: 0; right: 0; top: 100%; margin-top: 8px;
  z-index: 46;
  background: #fff; border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 10px 24px rgba(23, 27, 33, .12);
  max-height: min(62vh, 460px); overflow-y: auto;
  padding: 4px 20px 12px;
}
.mf-buscar-pop[hidden] { display: none; }
/* Dentro del panel el aire entre grupos se achica: los 32px del flujo de la
   página dejaban un desplegable con más hueco que contenido. */
.mf-buscar-pop .mf-grupo { margin-top: 18px; }
.mf-buscar-pop .mf-res a { padding: 11px 0; }
.mf-buscar-nota { font-size: 13px; font-weight: 300; color: var(--muted); margin: 14px 0 0; }

.mf-grupo { margin-top: 32px; }
/* `[hidden]` con display:none explícito: el grupo es un <section> y el atributo
   solo gana si nada le pone otro display. */
.mf-grupo[hidden] { display: none; }
.mf-grupo-t {
  display: flex; align-items: center; gap: 8px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; line-height: 14px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted);
  margin: 0 0 12px; font-weight: 500;
}
.mf-grupo-n {
  font-size: 10px; padding: 2px 7px; border-radius: 999px;
  background: var(--blue-light); color: var(--blue-dark); letter-spacing: 0;
}
.mf-res-lista { list-style: none; margin: 0; padding: 0; }
.mf-res[hidden] { display: none; }
.mf-res + .mf-res { border-top: 1px solid var(--line); }
.mf-res a {
  display: block; padding: 14px 0; text-decoration: none;
  border-radius: 6px;
}
.mf-res a:hover .mf-res-n { color: var(--primary); }
/* 500 y no 600: el nombre del resultado es donde se resaltan las coincidencias,
   y con la base ya en 600 el <mark> a 800 no se distinguía — menos todavía
   cuando el título coincide ENTERO y no queda texto sin marcar al lado con qué
   compararlo. Bajando la base, el salto se ve. */
.mf-res-n {
  display: block; font-size: 16px; font-weight: 500; color: var(--ink);
  transition: color .15s;
}
.mf-res-d {
  display: block; font-size: 13px; font-weight: 300; line-height: 1.5;
  color: var(--muted); margin-top: 2px;
}
/* «en Gastos» dice a dónde lleva el resultado antes del clic. Va dentro de la
   descripción para que envuelva con ella, no como una columna aparte. */
.mf-res-en {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); margin-left: 8px; white-space: nowrap;
}

/* --------------------------------------------------------------------------
   12. Puertas con desplegable (§5.1) — las 11 secciones en 6 puertas
   -------------------------------------------------------------------------- */
/* Mismo patrón que el selector de idioma: <details> nativo + panel absoluto.
   Trae teclado y foco gratis; el cierre al clickear fuera lo pone chrome.js. */
.mf-pill-drop { position: relative; flex: none; display: flex; }
.mf-pill-drop > summary {
  list-style: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
}
.mf-pill-drop > summary::-webkit-details-marker { display: none; }
.mf-pill-drop > summary::marker { content: ''; }
.mf-pill-drop > summary .mf-flecha { opacity: .55; }
.mf-pill-drop[open] > summary .mf-flecha { transform: rotate(180deg); opacity: 1; }
/* Abierta se ve como la puerta activa: es la sección que estás mirando. */
.mf-pill-drop[open] > summary { background: var(--bg); color: var(--primary); }
@media (prefers-reduced-motion: reduce) {
  .mf-pill-drop > summary .mf-flecha { transition: none; }
}
/* El panel se ancla a la IZQUIERDA de su puerta y no a la derecha: el nav se
   lee de izquierda a derecha, y uno que creciera hacia adentro taparía las
   puertas siguientes. Mismos valores que el panel del idioma —borde, radio,
   sombra, z-index—: es el mismo componente con otro contenido. */
.mf-pill-pop {
  position: absolute; left: 0; top: 100%; margin-top: 8px;
  z-index: 46; min-width: 100%;
  background: #fff; border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 10px 24px rgba(23, 27, 33, .12);
  padding: 6px 0;
}
.mf-pill-pop a {
  display: block; padding: 8px 16px;
  font-size: 13px; color: var(--ink); text-decoration: none;
  white-space: nowrap; transition: background .15s, color .15s;
}
.mf-pill-pop a:hover,
.mf-pill-pop a:focus-visible { background: #F6F8FB; color: var(--primary); }
.mf-pill-pop a[aria-current="page"] { color: var(--primary); font-weight: 600; }

/* Rótulo de grupo en el menú móvil: no es un enlace, es el nombre de la puerta
   a la que pertenecen las secciones de abajo. Sin borde, para que no se lea
   como una fila más de la lista. */
.mf-menu-grupo {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; line-height: 14px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted);
  padding: 22px 0 6px; border-bottom: 0 !important;
}

/* --------------------------------------------------------------------------
   13. Dropdown propio para los <select> del panel
   Un <select> nativo NO se puede abrir debajo del control: en macOS el sistema
   dibuja el popup ENCIMA, centrado en la opción elegida y con su propio look
   —el tilde azul—, y eso no se toca por CSS. Es el mismo motivo por el que los
   tres monitores publicados lo reemplazaron: «Dropdown propio, para que el menú
   se abra DEBAJO del control» (SelectorCaja.tsx de Municipios), y en el DT el
   selector de filas dejó de ser un <select> por ser «la única pieza del sitio
   que no se parecía a las demás».
   Antes esto se intentó con `appearance: base-select`, que hace justo eso pero
   solo existe en Chrome reciente: en el resto quedaba el popup del sistema.
   El disparador conserva la caja que el panel ya le daba al <select>, para que
   las toolbars no cambien de forma. El panel es el MISMO de los otros
   dropdowns: una sola definición para todo el sitio.
   -------------------------------------------------------------------------- */
/* `font-size` propio y no heredado: hay un <select> que vive DENTRO de un
   `.hint`, así que el dropdown tomaba el tamaño del título de la card —cuando
   ese título subió a 22px, la caja del panel se fue a 22px con él— mientras sus
   opciones seguían en 12px. Un control no debería cambiar de tamaño según de
   qué párrafo cuelga. */
.mf-select { position: relative; display: inline-flex; flex: none; font-size: 13px; }
.mf-select > summary {
  list-style: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 8px;
  font-family: 'Hanken Grotesk', system-ui, sans-serif;
  font-size: 13px; color: var(--ink);
  background: #fff; border: 1px solid var(--line);
  border-radius: var(--radius-chip);
  /* 34px de alto exactos, los mismos que `.segmented` del panel: en una toolbar
     los dos controles conviven en la misma línea y con 37,5 contra 34 la línea
     se veía quebrada. La cuenta cierra con el `line-height` DECLARADO —18 + 7
     + 7 + 1 + 1— y no con el que salga de la métrica de la fuente, que es lo
     que la descuadraba. */
  line-height: 18px; padding: 7px 12px; white-space: nowrap;
  transition: border-color .15s, box-shadow .15s;
}
.mf-select > summary::-webkit-details-marker { display: none; }
.mf-select > summary::marker { content: ''; }
.mf-select > summary:hover,
.mf-select[open] > summary { border-color: var(--primary); }
.mf-select > summary:focus-visible {
  outline: none; border-color: var(--primary);
  box-shadow: 0 0 0 2px rgba(38, 111, 224, .2);
}
/* El valor empuja al chevrón contra el borde derecho, así el control no cambia
   de forma según el largo de la opción elegida. */
.mf-select-valor { flex: 1; }
.mf-select .mf-flecha { opacity: .55; }
.mf-select[open] .mf-flecha { transform: rotate(180deg); opacity: 1; }

/* El selector de mes de «Temas destacados» es el único que no vive en una
   toolbar: cuelga solo entre la bajada de la card y el informe. Se ve IGUAL que
   los demás —la caja de 13px— y lo único propio es el aire de abajo, que en los
   otros lo da el `gap` de la toolbar y acá no hay toolbar que lo dé.
   Tuvo un aspecto de título (18px/600, sin caja) heredado del disparador que el
   panel traía; se descartó por consistencia con el resto de los selectores. */
.mf-select-bloque { margin-bottom: 12px; }

/* La caja: borde, radio y sombra. NO scrollea — de eso se encarga la lista de
   adentro. Antes el scroll y el borde vivían en el mismo elemento y el
   desvanecido se hacía con `mask-image` sobre él, así que la máscara se comía
   también el BORDE: cuando había más opciones abajo, el panel se quedaba sin
   canto inferior y su contenido se mezclaba con el de la página. Se veía en el
   selector «Desde» y no en «Hasta», porque el segundo abre en su última opción
   y ahí no hay nada más abajo que anunciar. */
/* Cerrado, el panel no existe. Hace falta decirlo: un <details> cerrado esconde
   su contenido con `content-visibility`, que salta el PINTADO pero le deja la
   caja al elemento, y esa caja —`min-width: 100%` sobre un control pegado al
   borde derecho— empujaba el ancho del documento. Medido en /modificaciones/ a
   375: 420px de scrollWidth contra 375 de ventana. Importa más de lo que parece,
   porque con el documento más ancho que la ventana el botón flotante de «volver
   arriba» se ancla al viewport de LAYOUT y en el teléfono se sale por la
   derecha. */
.mf-select:not([open]) .mf-select-pop { display: none; }
.mf-select-pop {
  position: absolute; left: 0; top: 100%; margin-top: 8px;
  z-index: 46; min-width: 100%;
  background: #fff; border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 10px 24px rgba(23, 27, 33, .12);
  /* Recorta la lista contra el radio y contiene las capas del desvanecido. */
  overflow: hidden;
}
.mf-select-lista { max-height: 320px; overflow-y: auto; padding: 6px 0; }

/* Sin barra de scroll a la vista, en ningún dropdown. Un panel de 176 opciones
   con la barra del sistema encima se lee como una tabla, no como un menú; y en
   macOS aparece y desaparece según el gesto, así que la lista cambia de ancho
   sola. Se sigue pudiendo scrollear: solo se esconde la barra. */
.mf-select-lista, .mf-lang-pop, .mf-pill-pop {
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* Edge viejo */
}
.mf-select-lista::-webkit-scrollbar,
.mf-lang-pop::-webkit-scrollbar,
.mf-pill-pop::-webkit-scrollbar { width: 0; height: 0; }

/* El desvanecido, ahora como CAPA dentro de la caja y no como máscara sobre
   ella: difumina el contenido y deja el borde intacto. `pointer-events: none`
   para no comerse el clic de la última opción. */
.mf-select-pop::before, .mf-select-pop::after {
  content: ''; position: absolute; left: 0; right: 0; height: 42px;
  pointer-events: none; opacity: 0;
  transition: opacity .12s ease;
}
.mf-select-pop::before {
  top: 0;
  background: linear-gradient(to bottom, #fff 20%, transparent);
}
.mf-select-pop::after {
  bottom: 0;
  background: linear-gradient(to top, #fff 20%, transparent);
}
.mf-select-pop[data-hay-antes]::before { opacity: 1; }
.mf-select-pop[data-hay-mas]::after { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .mf-select-pop::before, .mf-select-pop::after { transition: none; }
}
/* Cerca del borde inferior abre hacia ARRIBA: hay selectores al final de tablas
   largas y el panel se salía de la pantalla. Lo marca chrome.js al abrir. */
.mf-select-pop[data-arriba] { top: auto; bottom: 100%; margin: 0 0 8px; }
.mf-select-pop button {
  display: block; width: 100%; text-align: left;
  font-family: 'Hanken Grotesk', system-ui, sans-serif;
  font-size: 12px; font-weight: 400; letter-spacing: 0; text-transform: none;
  color: var(--ink); background: none; border: 0; border-radius: 0;
  padding: 8px 16px; cursor: pointer; white-space: nowrap;
  transition: background .15s, color .15s;
}
.mf-select-pop button:hover { background: #F6F8FB; color: var(--primary); }
.mf-select-pop button.active { color: var(--primary); font-weight: 600; }
/* El <select> viaja escondido pero CON caja: sin caja hay navegadores que no
   disparan `change`, y el panel escucha ese evento. */
/* `select.` y no sólo la clase: el mínimo tiene que ganarle a `.pag-tam { min-
   width: 68px }` de la hoja del panel, que se emite DESPUÉS de esta y con la
   misma especificidad se llevaba el desempate. Un selector de elemento sobre un
   `.mf-*` no es una fuga de las que la norma prohíbe: el elemento acota la regla
   en vez de abrirla. */
select.mf-select-nativo {
  position: absolute; width: 1px; height: 1px;
  /* Padding y borde a cero: con `box-sizing: border-box` los 10px de padding y
     el 1px de borde que la hoja del panel le pone a todo `select` no caben en
     1px de ancho, así que la caja terminaba midiendo 22 en vez de 1. */
  padding: 0; border: 0;
  /* `min-width` explícito y no sólo `width`: el <select> puede venir con un
     mínimo propio de la hoja del panel y un mínimo le gana siempre a un `width`
     menor, así que el «1px» no era 1px: eran 68 empujando el ancho del documento
     desde una caja que nadie ve. */
  min-width: 0; min-inline-size: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* --------------------------------------------------------------------------
   14. La fuente del dato, en un tooltip
   El título de cada card terminaba en «· Fuente: DIPRES». Es trazabilidad, no
   título: se repite en casi todas las cards, alarga la línea y empuja lo que
   la card sí está diciendo. Pasa a un ícono de info al lado del título.
   No se borra: sigue ahí, a un hover o un Tab de distancia.
   -------------------------------------------------------------------------- */
.mf-info { position: relative; display: inline-flex; vertical-align: middle; margin-left: 6px; }
.mf-info > button {
  display: inline-flex; align-items: center; justify-content: center;
  /* 24px de caja para el dedo, ícono de 15: el target táctil no puede ser el
     tamaño del dibujo (§6). */
  width: 24px; height: 24px; padding: 0;
  background: none; border: 0; border-radius: 999px;
  color: var(--muted); cursor: help;
  transition: color .15s, background .15s;
}
.mf-info > button:hover { color: var(--primary); background: var(--bg); }
.mf-info > button svg { width: 15px; height: 15px; }
.mf-info-burbuja {
  position: absolute; left: 50%; bottom: calc(100% + 8px);
  --mf-burbuja-dx: 0px;
  transform: translateX(-50%) translateX(var(--mf-burbuja-dx));
  z-index: 47;
  /* `max-width` en ch y no en px: la burbuja lleva prosa y lo que importa es
     cuántos caracteres por línea, no cuántos píxeles. Con el tope de la ventana
     al lado, porque en un teléfono 40ch son más anchos que la pantalla: la
     burbuja se salía —medido, 441px de documento contra 375 de ventana en
     /bonos/— y arrastraba el ancho del documento aunque esté escondida, porque
     `visibility: hidden` no le quita la caja. El desplazamiento lateral lo pone
     chrome.js con `--mf-burbuja-dx`, que la corre lo justo para que no cruce la
     canaleta de la página. */
  max-width: min(40ch, calc(100vw - 2 * var(--pad-x)));
  width: max-content;
  padding: 8px 10px;
  background: var(--ink); color: #fff;
  font-family: 'Hanken Grotesk', system-ui, sans-serif;
  font-size: 12px; font-weight: 400; line-height: 1.45;
  letter-spacing: 0; text-transform: none; text-align: left;
  border-radius: 8px;
  box-shadow: 0 6px 18px rgba(23, 27, 33, .18);
  /* Oculta con `visibility` y no con `display`: así hay transición y el nodo
     sigue existiendo para que `aria-describedby` lo pueda apuntar siempre. */
  visibility: hidden; opacity: 0;
  transition: opacity .12s ease, visibility .12s ease;
  pointer-events: none;
}
.mf-info > button:hover + .mf-info-burbuja,
.mf-info > button:focus-visible + .mf-info-burbuja { visibility: visible; opacity: 1; }
@media (prefers-reduced-motion: reduce) { .mf-info-burbuja { transition: none; } }
/* Cerca del borde superior la burbuja abre hacia abajo — lo marca chrome.js. */
.mf-info-burbuja[data-abajo] { bottom: auto; top: calc(100% + 8px); }

/* --------------------------------------------------------------------------
   15. Acordeón de «Temas destacados»
   Las cuatro secciones del informe eran un muro: cuatro títulos con sus listas,
   todo abierto, y la card medía varias pantallas. Pasan a cards internas
   colapsables, una abierta a la vez.
   -------------------------------------------------------------------------- */
.mf-acordeon {
  border: 1px solid var(--line); border-radius: 10px;
  background: #fff; margin-bottom: 8px;
}
.mf-acordeon > summary {
  list-style: none; cursor: pointer;
  /* El chevrón contra el borde derecho: `space-between` y no un margen, así la
     flecha queda alineada entre las cuatro secciones aunque sus títulos midan
     distinto. */
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px;
  color: var(--ink);
  transition: color .15s;
}
.mf-acordeon > summary::-webkit-details-marker { display: none; }
.mf-acordeon > summary::marker { content: ''; }
/* El summary no cambia de color: lo que responde es el chevrón, más abajo. */
/* El <h2> se conserva DENTRO del summary y no se cambia por un <span>: sigue
   siendo un encabezado para un lector de pantalla, que es lo que es. Lo que se
   resetea son los estilos que `.md-content h2` le pone para cuando vive suelto
   en el flujo del informe: borde inferior, márgenes. */
.mf-acordeon > summary h2 {
  margin: 0; padding: 0; border: 0;
  /* 15px y no los 10 del rótulo de la card: esto es el encabezado de una
     sección, no la etiqueta de la card que las contiene. Mono y versalitas se
     heredan de `.card h2`; el color NO —estos van en --ink y no en el azul de
     las etiquetas, porque son títulos de contenido y no rótulos. */
  font-size: 15px; font-weight: 600; color: var(--ink);
}
/* El título NO cambia de color en NINGÚN estado —ni hover, ni foco, ni
   abierto—: es un título, no un enlace, y teñirlo al clickear lo hacía parecer
   otra cosa. Que la fila es clickeable lo dice el chevrón, que sí responde. */
.mf-acordeon > summary .mf-flecha {
  color: var(--muted); transition: transform .15s;
}
.mf-acordeon[open] > summary .mf-flecha { transform: rotate(180deg); }
.mf-acordeon > summary:hover .mf-flecha { color: var(--primary); }
@media (prefers-reduced-motion: reduce) {
  .mf-acordeon > summary, .mf-acordeon > summary .mf-flecha { transition: none; }
}
/* El cuerpo hereda el padding lateral del summary para que el texto arranque en
   la misma vertical que su título. */
.mf-acordeon-cuerpo { padding: 0 14px 4px; }
.mf-acordeon-cuerpo > :first-child { margin-top: 0; }
.mf-acordeon-cuerpo > :last-child { margin-bottom: 10px; }

/* El contenedor del Lottie: alto y ancho fijos ANTES de que cargue, para que el
   header no salte cuando el SVG aparece. Mismas medidas que la <img> estática a
   la que reemplaza. */
.mf-brand-lottie { width: 32px; height: 32px; flex-shrink: 0; display: block; }
.mf-brand-lottie > svg { display: block; width: 100%; height: 100%; }
/* El atributo pierde contra el `display: block` de la clase, así que se
   declara: mientras el reproductor carga, la caja no ocupa lugar. */
.mf-brand-lottie[hidden] { display: none; }
