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

/* =============================================================================
   NawelBot Trends — sistema de diseno "dentsu Intelligence Editorial"

   Contrato: ../../dentsu-tender/DESIGN.md, que deriva de geo-ai-monitoring y
   este del Brand Hub de dentsu. Los nueve hex de marca no cambiaron; lo que
   cambio es el contrato de uso, que ahora es estricto.

   Reemplaza a la interpretacion anterior de este dashboard —Hanken Grotesk,
   morado como fondo de control, tema claro/oscuro— que es exactamente lo que el
   contrato describe como "la misma paleta con un contrato mucho mas laxo".

   Las cinco reglas de las que sale todo lo demas:

   1. El texto es negro, --muted o blanco. El indigo se reserva a hipervinculos
      y a filetes de estado; nunca es color de texto de jerarquia.
   2. Los acentos viven en trazos, bordes, filetes y data-viz. No son fondo de
      botones, badges, alertas ni tarjetas.
   3. El color nunca es la unica senal: todo estado se dice tambien en palabras
      o en forma. Por eso el eje y la franja de salud pueden usar color —son
      data-viz— y los badges no.
   4. Un solo tema. La nav es una zona oscura DELIBERADA con su propio par de
      colores (--ink-zone / --reverse), no un tema alternativo.
   5. Bordes rectos: 2px. Las pildoras quedan solo para badges.

   Lo que se fue, y por que: el grain overlay, el backdrop-filter de la nav, los
   gradientes decorativos y los glows son anti-patterns explicitos del contrato
   ("sin glassmorphism, sombras repetidas, glow, gradientes decorativos ni
   fondos de rejilla"). Los gradientes que quedan no son decorativos: son
   codificacion de datos (la media celda de salud) o una trama que significa
   "aca no se midio nada".
   ============================================================================= */

:root{
/* ---- Superficies. El lienzo es Natural White, no blanco puro, y es el fondo
   de la pagina Y de los paneles: no hay una superficie por bloque. ---- */
--canvas:#e6e6e6;
--panel:#b4b9c3;
--ink-zone:#323232;
--ink:#000000;
--muted:#4f4f4f;
--reverse:#ffffff;
/* Zona secundaria suave: el panel a baja opacidad, para franjas y hovers sin
   convertir cada bloque en una superficie distinta. */
--panel-soft:rgba(180,185,195,.24);

/* ---- Acentos de linea y data-viz. NO son fondos. ---- */
--signal:#ff5023;
--link:#646ed2;
--positive-line:#aaff6e;
--teal-line:#008287;
--soft-line:#f0bebe;
--cyan-line:#00d2e6;

/* ---- Reglas: la separacion es una linea, no una sombra ni una tarjeta. ---- */
--rule:rgba(0,0,0,.22);
--rule-soft:rgba(0,0,0,.12);

/* ---- Estados. Van siempre con etiqueta y forma, nunca solo con color.
   `attention` es indigo y no ambar porque el sistema reserva el rojo-naranja a
   errores, caidas y acciones destructivas: una advertencia que no es una falla
   se marca con indigo o con un neutral.

   EL INDIGO TIENE EXACTAMENTE DOS ROLES EN TODO EL DASHBOARD, y los dos los
   define el contrato:
     1. texto de hipervinculo (`a`, `.enlace`);
     2. --state-attention: "esto pide accion o mirada ahora", siempre como
        filete o marca de dato, nunca como fondo ni como color de texto.
   Nada mas lo lleva. En particular NO lo llevan la seleccion, los conectores,
   las reglas de panel ni la identidad de una fuente: eso es estructura, y
   pintarla de indigo deja al color significando tres cosas en la misma
   pantalla. Pasaba en el eje —urgencia, seleccion y conector al expediente
   compartian indigo— y como el eje abre seleccionando justamente el tema
   urgente, la ficha por defecto traia las tres marcas encimadas. ---- */
--state-ok:var(--teal-line);
--state-attention:var(--link);
--state-critical:var(--signal);

/* ---- Series por fuente. Es data-viz legitima —cada plataforma necesita ser
   distinguible de un vistazo— pero ahora son SERIES: se aplican como filete,
   punto o trazo, jamas como color de texto ni como fondo. El nombre de la
   fuente siempre esta escrito al lado, asi que el color es redundante y no
   informacion exclusiva. Se toman de los seis acentos del sistema en vez de
   los hex sueltos que habia (#0090a0, #c2185b, #6b7280, #4d8b1f), que eran una
   segunda paleta compitiendo con la de marca.

   Rankings se queda SIN acento y va en neutral. Le tocaba el indigo por
   descarte —es el sexto acento— y el indigo en este dashboard significa una
   sola cosa: esto pide accion ahora. Gastarlo como identidad de una fuente lo
   deja significando dos cosas a la vez, que es el mismo problema que el eje
   tenia con la seleccion y el conector. ---- */
--serie-google:var(--teal-line);
--serie-reddit:var(--signal);
--serie-youtube:var(--soft-line);
--serie-tiktok:var(--cyan-line);
--serie-news:var(--positive-line);
--serie-charts:var(--muted);

--font:"halcom",Verdana,Geneva,sans-serif;
--content-max:90rem;
--space-page:clamp(16px,3vw,48px);

/* Radio topeado en 2px por el contrato. --radius-pill sobrevive con un unico
   destino permitido: los badges. */
--radius:2px;--radius-sm:2px;--radius-pill:999px;

/* ---- Alias heredados ----------------------------------------------------
   El marcado de js/vistas/ todavia nombra los tokens del sistema anterior. En
   vez de romperlo, cada alias apunta a un valor LEGAL del contrato: asi un
   `color:var(--accent)` que quedo sin migrar degrada a negro —correcto, aunque
   menos expresivo— en lugar de sacar un acento fuera de su rol.

   Los alias de fuente (--google, --reddit...) apuntan a tinta y NO a su serie
   justamente por eso: casi todos sus usos vivos son `color:`, que el contrato
   prohibe. Para el filete legitimo estan los --serie-*. */
--surface:var(--canvas);--surface-muted:var(--canvas);--surface-strong:var(--panel-soft);
--bg:var(--canvas);--bg-deep:var(--canvas);
--bg-card:var(--canvas);--bg-card-hover:var(--panel-soft);--bg-surface:var(--panel-soft);
--foreground:var(--ink);--foreground-muted:var(--muted);--foreground-subtle:var(--muted);
--text:var(--ink);--text-bright:var(--ink);--text-muted:var(--muted);--text-dim:var(--muted);
--border-color:var(--rule);--border-strong:var(--ink);
--border:var(--rule);--border-hover:var(--ink);
--accent:var(--ink);--accent-foreground:var(--reverse);
--accent-light:var(--ink);--accent-hover:var(--ink);--purple:var(--ink);
--google:var(--ink);--reddit:var(--ink);--youtube:var(--ink);
--tiktok:var(--ink);--news:var(--ink);--charts:var(--ink);
}

html{background:var(--canvas);color:var(--ink);scrollbar-color:var(--muted) var(--canvas)}
body{font-family:var(--font);background:var(--canvas);color:var(--ink);
font-size:15px;line-height:1.55;-webkit-font-smoothing:antialiased;
text-rendering:optimizeLegibility;min-height:100vh}

/* Jerarquia por escala y peso, nunca por texto de color. Halcom viene con 400 y
   700 en el Web Project: cualquier otro peso lo sintetiza el navegador, asi que
   este archivo usa solo esos dos. */
h1,h2,h3,h4,h5,h6{font-weight:700;letter-spacing:-0.03em;line-height:1.1}

a{color:var(--link);text-underline-offset:0.18em}
a:hover{text-decoration:underline}

::selection{background:var(--panel);color:var(--ink)}

/* Foco visible y con separacion: requisito de accesibilidad del sistema. */
:focus-visible{outline:2px solid var(--ink);outline-offset:3px}

button,input,select,textarea{font:inherit;color:inherit}
button,[role="button"],select,summary,label[for]{cursor:pointer}

/* Las cifras se comparan en vertical: sin esto, las columnas bailan. */
table,.tabular{font-variant-numeric:tabular-nums}

/* Movimiento: 120-220ms, solo transform y opacity. */
@media(prefers-reduced-motion:reduce){
*,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;
transition-duration:.01ms !important;scroll-behavior:auto !important}
}

/* =============================================================================
   COMPONENTES DEL SISTEMA
   Existen como clases y no como estilos sueltos porque son contrato: el
   primario es charcoal —el morado dejo de ser fondo de boton— y el destructivo
   se marca con una regla Signal, nunca con rojo de fondo. Tenerlo en un solo
   lugar evita que cada vista vuelva a inventar el boton.
   ============================================================================= */

.btn{min-height:2.75rem;display:inline-flex;align-items:center;justify-content:center;
gap:8px;padding:0 16px;border:1px solid var(--ink);border-radius:var(--radius);
background:var(--ink-zone);color:var(--reverse);font-family:var(--font);
font-size:14px;font-weight:700;text-decoration:none;
transition:background-color 160ms ease-out,color 160ms ease-out}
.btn:hover{background:var(--ink);color:var(--reverse);text-decoration:none}
.btn:disabled{cursor:not-allowed;opacity:.5}
/* Secundario: mismo sistema neutral, sin peso de superficie. */
.btn-secondary{background:transparent;color:var(--ink)}
.btn-secondary:hover{background:var(--panel);color:var(--ink)}
/* Destructivo: la regla roja avisa; el fondo sigue siendo neutral. */
.btn-destructive{border-top:4px solid var(--signal)}

/* Badge: borde y texto, nunca fondo de color. El estado se dice tambien con
   palabras — el color no puede ser la unica senal. Las variantes cambian el
   filete izquierdo, no el fondo. */
.badge{display:inline-flex;align-items:center;gap:6px;padding:3px 9px;
border:1px solid var(--ink);border-radius:var(--radius-pill);background:transparent;
color:var(--ink);font-size:11px;line-height:1.3;white-space:nowrap}
.badge-ok{border-left:3px solid var(--state-ok)}
.badge-attention{border-left:3px solid var(--state-attention)}
.badge-critical{border-left:3px solid var(--state-critical)}

.field{min-height:2.75rem;max-width:100%;padding:8px 12px;border:1px solid var(--ink);
border-radius:var(--radius);background:var(--canvas);color:var(--ink);font-family:var(--font)}
.field::placeholder{color:var(--muted)}

/* Rotulo de seccion: mayusculas cortas, nunca como cuerpo de texto. */
.eyebrow{font-size:11px;font-weight:700;letter-spacing:0.09em;text-transform:uppercase}

/* La firma de senal: seis segmentos de 4px con los colores de serie. Es la
   marca del shell —una regla, no un degradado ambiental— y el unico lugar donde
   los seis acentos aparecen juntos. */
.signal-rule{display:grid;grid-template-columns:repeat(6,1fr);width:100%;height:4px}
.signal-rule i:nth-child(1){background:var(--signal)}
.signal-rule i:nth-child(2){background:var(--link)}
.signal-rule i:nth-child(3){background:var(--positive-line)}
.signal-rule i:nth-child(4){background:var(--teal-line)}
.signal-rule i:nth-child(5){background:var(--soft-line)}
.signal-rule i:nth-child(6){background:var(--cyan-line)}

/* Enlace de salto: navegacion por teclado, requisito WCAG del sistema. */
.skip-link{position:fixed;top:8px;left:8px;z-index:10000;padding:11px 16px;
background:var(--reverse);color:var(--ink);border:2px solid var(--ink);
text-decoration:none;font-weight:700;font-size:13px;transform:translateY(-200%)}
.skip-link:focus{transform:translateY(0)}

/* Salida en texto. No hay componente nuevo: el boton es `.btn.btn-secondary` y
   lo unico que agrega esta regla es como conviven con el rotulo que los
   acompaña.

   El aviso de "copiado" es una PALABRA —el boton cambia de texto y este hueco
   lo repite para los lectores de pantalla—, nunca un color: el contrato prohibe
   que un estado se diga solo con matiz, y aca ademas seria inutil, porque quien
   copia esta mirando el boton que acaba de apretar.

   El area tactil sale del `min-height:2.75rem` de `.btn`, que ya son los 44px
   del contrato; esta regla no la toca. */
.copiar-fila{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.copiar-estado{font-size:12px;line-height:1.45;color:var(--muted);max-width:44ch}
/* Ultimo recurso cuando el navegador no deja copiar por codigo: el texto queda
   a la vista y seleccionado. Ocupa la fila entera —`flex-basis:100%`— porque al
   lado del boton entraria en una columna de dos centimetros. */
.copiar-manual{flex-basis:100%;width:100%;padding:10px 12px;border:1px solid var(--ink);
border-radius:var(--radius);background:var(--canvas);color:var(--ink);
font-family:var(--font);font-size:13px;line-height:1.5;resize:vertical}

/* Texto solo para lectores de pantalla. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* =============================================================================
   SHELL — NAV
   Zona oscura deliberada: --ink-zone con texto blanco. El estado activo se
   marca con PESO y una LINEA blanca, nunca con una pildora de color; ese era el
   uso mas visible del morado como fondo y es el que el contrato prohibe.
   ============================================================================= */
.nav{position:sticky;top:0;z-index:100;background:var(--ink-zone);color:var(--reverse)}
.nav-inner{max-width:var(--content-max);margin:0 auto;padding:0 var(--space-page);
display:flex;align-items:center;flex-wrap:wrap;gap:0 24px}

.nav-brand{display:flex;align-items:baseline;gap:8px;flex-shrink:0;
min-height:2.75rem;font-weight:700;white-space:nowrap}
.nav-brand-org{font-size:17px;letter-spacing:-0.055em}
.nav-brand-sep{width:1px;align-self:center;height:14px;background:rgba(255,255,255,.45)}
.nav-brand-prod{font-size:13px;letter-spacing:-0.02em}

/* Las pestanas van SIEMPRE en su propia fila, a ancho completo.
   Con las doce originales la razon era el ancho: necesitaban 1124px y no
   entraban ni a 1440 compartiendo fila con la marca y los selectores, asi que
   las ultimas —AI Insights, Pipeline— quedaban siempre ocultas. Justo Pipeline,
   que era la que avisaba que algo se rompio.
   Con cinco grupos el ancho ya no aprieta, y la fila propia se queda igual: la
   fila de arriba es identidad y contexto (mercado, periodo, origen de los
   datos) y la de abajo es navegacion. Mezclarlas hace que el selector de
   mercado se lea como una pestaña mas.
   Los selectores NUNCA scrollean: con todo en un mismo contenedor scrollable,
   .nav-right se iba con margin-left:auto mas alla del borde visible. */
.nav-tabs{order:3;width:100%;display:flex;align-items:center;min-width:0;
overflow-x:auto;scrollbar-width:none}
.nav-tabs::-webkit-scrollbar{display:none}
/* La ultima pestana se corta cuando no caben todas, y cortada en seco parece un
   error de maquetado en vez de contenido que sigue. El degradado dice que hay
   mas; donde si caben todas no se nota, porque no hay nada que desvanecer. */
.nav-tabs{-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent);
mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent)}

.nav-link{display:inline-flex;align-items:center;gap:6px;min-height:2.75rem;
padding:0 12px;flex-shrink:0;background:transparent;border:0;
border-bottom:2px solid transparent;font-family:var(--font);font-size:12px;
font-weight:400;letter-spacing:0.02em;color:rgba(255,255,255,.68);
text-decoration:none;white-space:nowrap;transition:color 160ms ease-out}
.nav-link:hover{color:var(--reverse);border-bottom-color:rgba(255,255,255,.45)}
.nav-link:focus-visible{outline:2px solid var(--reverse);outline-offset:-2px}
.nav-link.active{color:var(--reverse);font-weight:700;border-bottom-color:var(--reverse)}
.nav-link-nota{font-size:10px;font-weight:400;color:rgba(255,255,255,.55)}

/* Sin padding propio: la altura de la fila la fija la marca (2.75rem). Con
   padding vertical los selectores la estiraban y la nav sumaba 8px de alto
   pegajoso en todas las pantallas. */
.nav-right{margin-left:auto;flex-shrink:0;display:flex;align-items:center;gap:8px}
.nav-date-select{min-height:2.25rem;font-size:12px;font-weight:400;
background:transparent;color:var(--reverse);border:1px solid rgba(255,255,255,.45);
border-radius:var(--radius);padding:4px 8px;outline:none}
.nav-date-select:focus-visible{outline:2px solid var(--reverse);outline-offset:2px}
/* En la zona oscura el desplegable lo pinta el sistema operativo, que no hereda
   el color del control: sin esto las opciones salen blanco sobre blanco. */
.nav-date-select option{background:var(--canvas);color:var(--ink)}
/* El selector de mercado es el control que decide de que pais es TODO lo demas.
   Se separa del de periodo con peso y con un borde solido, no con un color: en
   este sistema un control de nav no lleva acento. */
.nav-market-select{font-weight:700;border-color:var(--reverse)}

/* El aviso de falla que escribe el propio modulo de salud. Lleva la palabra
   ademas del color —el contrato prohibe que el color sea la unica senal— y por
   eso el marcado trae "Falla" escrito y oculto: aparece solo cuando salud.js
   enciende .activa. Vive dentro de .nav-estado y es la etiqueta de severidad;
   el "que" lo dice .nav-estado-frase, al lado. */
.nav-alerta{display:none}
.nav-alerta.activa{display:inline-flex;align-items:center;padding:1px 5px;
border-left:3px solid var(--state-critical);font-size:10px;font-weight:700;
letter-spacing:0.06em;text-transform:uppercase;color:var(--reverse)}

/* ---- ORIGEN DE LOS DATOS ----
   La salud dejo de ser una pestana y paso a ser un estado permanente de la
   barra. Es un boton, no un badge: abre el detalle.
   Sigue las reglas de la zona oscura —sin fondo de acento, el activo por borde
   y peso— y el color entra solo en el punto, que es una marca de dato del mismo
   tipo que .eje-punto, nunca el fondo del control. */
.nav-estado{display:inline-flex;align-items:center;gap:8px;min-height:2.25rem;
padding:4px 10px;background:transparent;border:1px solid transparent;
border-radius:var(--radius);font-family:var(--font);font-size:12px;
font-weight:400;color:rgba(255,255,255,.68);text-align:left;
transition:color 160ms ease-out}
.nav-estado:hover{color:var(--reverse);border-color:rgba(255,255,255,.45)}
.nav-estado:focus-visible{outline:2px solid var(--reverse);outline-offset:2px}
.nav-estado.active{color:var(--reverse);font-weight:700;border-color:var(--reverse)}
.nav-estado-etiqueta{white-space:nowrap;color:rgba(255,255,255,.55)}
.nav-estado.active .nav-estado-etiqueta{color:rgba(255,255,255,.7)}
.nav-estado-frase{white-space:nowrap;color:var(--reverse);font-weight:700}

/* Sano NO lleva color: es lo esperable, y gastar un acento en el unico estado
   que no pide nada deja sin fuerza a los que si. Va como aro, no como relleno.
   No medido va mas tenue todavia: "no pude leer" y "todo bien" no se pueden
   ver igual. */
.nav-estado-punto{width:9px;height:9px;flex-shrink:0;border-radius:50%;
border:2px solid rgba(255,255,255,.55);background:transparent}
.nav-estado[data-tono="mudo"] .nav-estado-punto{border-color:rgba(255,255,255,.3)}
.nav-estado[data-tono="mudo"] .nav-estado-frase{color:rgba(255,255,255,.55);font-weight:400}
/* Corrio a medias: pide mirada y no es una caida. Es el mismo significado con
   el que .salud-titular[data-tono="aviso"] usa este token en el detalle. */
.nav-estado[data-tono="aviso"] .nav-estado-punto{border-color:var(--state-attention);background:var(--state-attention)}
.nav-estado[data-tono="alarma"] .nav-estado-punto{border-color:var(--state-critical);background:var(--state-critical)}

/* =============================================================================
   SUB-NAVEGACION DEL GRUPO
   Segundo nivel de la misma navegacion, en el lienzo. Mismo lenguaje que la
   barra —peso mas linea, nunca una pildora de color— traducido a tinta sobre
   claro. Se dibuja desde js/tabs.js y solo en los grupos de mas de una vista.
   ============================================================================= */
.subnav{display:flex;align-items:center;flex-wrap:wrap;gap:0 2px;
margin-bottom:clamp(20px,3vw,30px);border-bottom:1px solid var(--rule)}
.subnav[hidden]{display:none}
.subnav-link{display:inline-flex;align-items:baseline;gap:5px;min-height:2.5rem;
padding:0 12px;margin-bottom:-1px;background:transparent;border:0;
border-bottom:2px solid transparent;font-family:var(--font);font-size:13px;
font-weight:400;letter-spacing:-0.01em;color:var(--muted);white-space:nowrap;
transition:color 160ms ease-out}
.subnav-link:hover{color:var(--ink);border-bottom-color:var(--rule)}
.subnav-link:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}
.subnav-link.active{color:var(--ink);font-weight:700;border-bottom-color:var(--ink)}
.subnav-link-nota{font-size:10px;font-weight:400;color:var(--muted)}

/* =============================================================================
   LAYOUT
   ============================================================================= */
.container{max-width:var(--content-max);margin:0 auto;
padding:clamp(24px,3vw,40px) var(--space-page)}
.section{display:none}
.section.active{display:block}
.section-title{font-size:clamp(22px,2.5vw,30px);font-weight:700;letter-spacing:-0.035em;
line-height:1.05;color:var(--ink);margin-bottom:6px}
.section-subtitle{font-size:14px;line-height:1.5;color:var(--muted);margin-bottom:28px;
max-width:70ch}
/* min() en el minimo de la pista: con minmax(340px,1fr) a secas, un viewport de
   360px pide una columna de 340px mas el padding y la PAGINA scrollea en
   horizontal. Antes no se notaba porque body tenia overflow-x:hidden, que
   escondia el sintoma en vez de arreglarlo. */
.grid-3{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(340px,100%),1fr));gap:16px}
/* align-items:start evita que una tarjeta expandida estire a su vecina
   colapsada: sin esto, abrir un cruce deja al lado un bloque vacio del mismo
   alto, y ahora que las tarjetas traen comentarios ese alto es considerable. */
.grid-2{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(420px,100%),1fr));
gap:16px;align-items:start}

/* =============================================================================
   CONTROLES DE FILTRO
   El activo se marca con peso y una linea, igual que la nav. Era el otro lugar
   donde el morado hacia de fondo.
   ============================================================================= */
.search-bar{display:flex;align-items:center;gap:12px;margin-bottom:24px;flex-wrap:wrap}
.search-input{flex:1;min-width:180px;min-height:2.75rem;background:var(--canvas);
border:1px solid var(--ink);border-radius:var(--radius);padding:8px 12px;
color:var(--ink);font-family:var(--font);font-size:14px;outline:none}
.search-input::placeholder{color:var(--muted)}
.filter-btn{min-height:2.25rem;font-size:12px;font-weight:400;letter-spacing:0.02em;
background:transparent;border:1px solid var(--rule);border-radius:var(--radius);
padding:6px 12px;color:var(--ink);font-family:var(--font);white-space:nowrap;
transition:background-color 160ms ease-out}
.filter-btn:hover{background:var(--panel-soft)}
.filter-btn.active{font-weight:700;border-color:var(--ink);
box-shadow:inset 0 -2px 0 var(--ink)}
.filter-select{min-height:2.25rem;font-size:12px;background:var(--canvas);color:var(--ink);
border:1px solid var(--ink);border-radius:var(--radius);padding:6px 10px;
font-family:var(--font);outline:none}
.filter-select option{background:var(--canvas);color:var(--ink)}

/* =============================================================================
   PANELES
   `.card` no envuelve nada en una tarjeta con relieve: es un panel plano sobre
   el mismo lienzo, separado por una regla. El contrato pide lista o tabla con
   reglas antes que un mosaico de tarjetas identicas; mientras las vistas usen
   .card, al menos que sea plana.
   ============================================================================= */
.card{background:var(--canvas);border:1px solid var(--rule);border-radius:var(--radius);
padding:20px;position:relative;transition:background-color 160ms ease-out}
.card:hover{background:var(--panel-soft)}
.card-expandable{cursor:pointer}
.card-expandable .card-detail{max-height:0;overflow:hidden;transition:max-height .2s ease-out}
.card-expandable.expanded .card-detail{max-height:1200px}
.card-expandable .expand-icon{display:inline-block;font-size:10px;color:var(--muted);
transition:transform .18s ease-out}
.card-expandable.expanded .expand-icon{transform:rotate(90deg)}

/* Panel de lectura AI. Era un gradiente indigo-verde con borde tintado: es el
   ejemplo de manual de "gradiente decorativo". Queda como panel plano con una
   regla en tinta arriba — la regla lo separa, no lo califica: que un texto sea
   generado no es un estado que pida accion. */
.insight-card{background:var(--canvas);border:1px solid var(--rule);
border-top:2px solid var(--ink);border-radius:var(--radius);padding:20px}
.insight-card h3{font-size:14px;font-weight:700;color:var(--ink);margin-bottom:8px}

/* =============================================================================
   BADGES Y MARCAS DE FUENTE
   `.pill` es el badge del sistema: borde y texto, fondo transparente. Cada
   fuente se distingue por su filete de serie, no por texto de color ni por un
   fondo tintado — y el nombre de la fuente va escrito adentro, asi que el color
   nunca es la unica senal.
   ============================================================================= */
.pill{display:inline-flex;align-items:center;gap:5px;font-size:10px;font-weight:700;
letter-spacing:0.05em;text-transform:uppercase;padding:3px 9px;
border:1px solid var(--ink);border-radius:var(--radius-pill);background:transparent;
color:var(--ink);white-space:nowrap}
.pill-google{border-left:3px solid var(--serie-google)}
.pill-reddit{border-left:3px solid var(--serie-reddit)}
.pill-tiktok{border-left:3px solid var(--serie-tiktok)}
.pill-youtube{border-left:3px solid var(--serie-youtube)}
.pill-news{border-left:3px solid var(--serie-news)}
.pill-charts{border-left:3px solid var(--serie-charts)}
/* Sin filete: "cruce", "AI" y "accent" son etiquetas de que ES una cosa, no de
   como esta. El filete de atencion las hacia leerse como si pidieran algo. */
.pill-cross,.pill-accent,.pill-ai{border-color:var(--ink)}
.pill-muted{border-color:var(--rule);color:var(--muted)}

/* El punto de plataforma es data-viz pura: un marcador, no un fondo. */
.platform-dot{width:8px;height:8px;border-radius:50%;display:inline-block;
background:var(--muted)}
.dot-google{background:var(--serie-google)}
.dot-reddit{background:var(--serie-reddit)}
.dot-tiktok{background:var(--serie-tiktok)}
.dot-youtube{background:var(--serie-youtube)}
.dot-news{background:var(--serie-news)}
.dot-charts{background:var(--serie-charts)}

/* Barra de score: una serie, con la pista en regla y el relleno en tinta. El
   gradiente que tenia no codificaba nada. */
.score-bar{height:3px;background:var(--rule-soft);overflow:hidden;margin-top:8px}
.score-bar-fill{height:100%;background:var(--ink)}

/* El movimiento del ranking se lee por la FLECHA, no por el color: subir y
   bajar ya vienen con forma propia (^ v) y el sistema no admite texto de color
   como jerarquia. Lo nuevo se distingue por peso. */
.move-up,.move-down,.move-new{color:var(--ink);font-weight:700}
.move-same{color:var(--muted)}

.vol-badge{font-size:12px;font-weight:700;color:var(--ink);margin-left:8px;
font-variant-numeric:tabular-nums}
.opp-alta{color:var(--ink);font-weight:700}
.opp-media{color:var(--ink);font-weight:400}
.opp-baja{color:var(--muted);font-weight:400}

/* =============================================================================
   EJE DE PERMANENCIA
   La herramienta sostiene una tesis: no toda la atencion dura lo mismo. Sobre
   235 dias de historial, 80% de los temas aparece un solo dia y apenas un 5%
   vuelve mes tras mes. Eso vivia dentro de una etiqueta gris en una tarjeta
   igual a las demas, o sea: no se veia.

   Aca la tesis ES la estructura. Cada tema ocupa un lugar segun cuanto lleva
   vivo, medido de verdad (dias entre su primera y su ultima aparicion). Lo
   fugaz y lo permanente dejan de parecerse porque estan en lugares distintos.

   El peso visual va INVERTIDO a proposito: lo fugaz se dibuja grande y oscuro
   porque se apaga en horas, y lo permanente chico y tenue porque manana sigue
   ahi. Contradice el reflejo de "importante = grande", y es lo cierto sobre
   estos datos: la urgencia no es la importancia.

   El eje es data-viz, que es donde el contrato SI permite acento: el indigo
   marca lo que exige accion hoy, como punto y como linea, nunca como fondo.
   ============================================================================= */

/* La apertura. El ancho ya no lo pone el bloque sino cada pieza: el titular
   necesita romper en tres lineas --ahi esta su escala-- y la franja de cifras
   necesita el ancho entero. Con un max-width comun, la franja heredaba el del
   titular y se apilaba en columna. */
.lede{margin:clamp(28px,5vw,56px) 0 clamp(32px,5vw,60px)}
/* DOS COLUMNAS cuando hay lectura del dia. El titular rompe en tres lineas
   cortas —ahi esta su escala— y eso dejaba la mitad derecha de la apertura
   vacia en cualquier monitor ancho. La llena el resumen del analisis, que antes
   vivia al final de la pagina.
   `align-items:start` para que la cita se apoye arriba y no se centre contra un
   titular que mide el triple. */
.lede.con-lectura{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);
gap:clamp(24px,4vw,64px);align-items:start}
/* La franja se queda en la columna izquierda. Ver el comentario en lede.js:
   cruzando las dos, con el titular en dos lineas quedaba un hueco vertical
   entre la bajada y las cifras. */
.lede-texto{min-width:0}
/* La voz del analisis, no la de la herramienta: va como CITA EDITORIAL. Era un
   parrafo gris con un filete y se leia como un pie de pagina largo, cuando es
   lo unico de la pantalla que lee el dia completo en vez de tema por tema.
   El peso se lo dan la escala, la comilla y la regla superior —los tres
   recursos que el sistema editorial si admite—: ningun fondo, ningun acento.
   El filete izquierdo se fue con ellos: con la regla arriba y la comilla,
   sumarlo encerraba la cita en una esquina. */
.lede-lectura{min-width:0;padding-top:4px}
.lede-lectura-rotulo{font-size:11px;font-weight:700;letter-spacing:0.09em;
text-transform:uppercase;color:var(--ink);padding-bottom:12px;
border-bottom:2px solid var(--ink)}
.lede-lectura-cita{position:relative;margin:0;padding-top:18px}
/* La comilla es un signo tipografico, no un icono: sale de la fuente del
   sistema y hereda la tinta. Va detras del texto y en gris de regla para que
   marque el arranque sin competir con la primera palabra. */
.lede-lectura-cita::before{content:'\201C';position:absolute;left:-4px;top:-6px;
font-size:64px;line-height:1;color:var(--rule);pointer-events:none}
.lede-lectura-texto{position:relative;font-size:clamp(15px,1.35vw,17px);
line-height:1.65;color:var(--ink);letter-spacing:-0.01em;margin:0;max-width:52ch}
/* Quien escribio esto importa para saber cuanto confiar, y es justo lo que el
   proyecto no deja implicito en ningun otro lado. */
.lede-lectura-firma{margin-top:14px;font-size:11px;letter-spacing:0.04em;
color:var(--muted)}
@media(max-width:900px){
  .lede.con-lectura{grid-template-columns:1fr;gap:26px}
  .lede-lectura{padding-left:14px}
}
.lede-fecha{font-size:11px;font-weight:700;letter-spacing:0.09em;text-transform:uppercase;
color:var(--muted);margin-bottom:14px}
/* La escala se bajo de 80px a 64px y el ancho subio de 9ch a 13ch. A 80/9ch el
   titular rompia en TRES lineas y la columna izquierda medía el triple que la
   derecha: el hero quedaba con un bloque enorme y otro flotando arriba. En dos
   lineas las dos columnas se parecen y el titular sigue siendo la unica escala
   grande de la pantalla. */
.lede-titulo{font-size:clamp(34px,5.4vw,64px);font-weight:700;letter-spacing:-0.05em;
line-height:1.02;color:var(--ink);max-width:13ch}
/* El enfasis del titular era texto morado. Ahora es un subrayado grueso: la
   misma jerarquia, pero es una linea y el texto sigue negro.
   En tinta y no en indigo porque el mismo <em> envuelve las dos salidas del
   titular: "Un tema pide *reaccion hoy*" y "Hoy nada exige *reaccionar*". Con
   el acento, el color que significa "esto pide accion" estaria marcando tambien
   la frase que dice que hoy no hay nada que hacer. */
.lede-titulo em{font-style:normal;text-decoration:underline;
text-decoration-color:var(--ink);text-decoration-thickness:4px;
text-underline-offset:0.06em}
.lede-bajada{font-size:15px;line-height:1.55;color:var(--muted);margin-top:18px;max-width:46ch}

/* Las cifras del dia. Separadas del titular por una regla y no por una tarjeta:
   la jerarquia de este sistema nace de escala, espacio y linea.
   Sin color: el numero pesa por tamaño y la etiqueta lo dice en palabras. */
/* El ancho va en px y no en `ch` a proposito: `ch` se mide sobre la fuente del
   elemento, asi que con Halcom y con el respaldo Verdana la franja cortaba en
   distinto lugar y una cifra caia sola a una segunda fila. */
.lede-cifras{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));
gap:22px clamp(20px,3vw,40px);max-width:840px;
margin-top:clamp(24px,3.5vw,38px);padding-top:20px;border-top:2px solid var(--rule)}
.lede-cifra{min-width:0}
/* Deliberadamente mas chico que el titular. La escala grande es UNA en esta
   pantalla; cuatro numeros compitiendo con la frase la dejan sin jerarquia. */
.lede-cifra-n{font-size:clamp(24px,2.6vw,32px);font-weight:700;line-height:1;
letter-spacing:-0.04em;color:var(--ink)}
.lede-cifra-et{font-size:12px;line-height:1.35;color:var(--muted);margin-top:7px}

.eje{position:relative;margin-bottom:clamp(40px,6vw,72px);overflow-x:auto;scrollbar-width:thin}
.eje-lienzo{position:relative;min-width:760px}
/* La regla y las marcas se ubican en absoluto: necesitan su propio contenedor
   posicionado, o se calculan contra el encabezado y quedan sobre el texto. */
.eje-grafico{position:relative;padding-top:34px}

/* El eje se entendia solo si ya sabias que estabas mirando: no habia titulo,
   las barras no decian que eran y nada indicaba que los temas se clicean.
   Elegante y mudo. Estas etiquetas son el minimo para que se lea sin que nadie
   lo explique al lado. */
.eje-encabezado{margin-bottom:26px}
.eje-titulo{font-size:15px;font-weight:700;letter-spacing:-0.02em;color:var(--ink)}
.eje-glosa{font-size:13px;line-height:1.5;color:var(--muted);margin-top:4px;max-width:62ch}
.eje-polos{display:flex;justify-content:space-between;font-size:11px;font-weight:700;
letter-spacing:0.09em;text-transform:uppercase;color:var(--muted);margin-bottom:5px}
/* Separa la masa de fondo de los temas analizados: son dos lecturas distintas y
   sin aire se leen como un solo bloque apretado. */
.eje-seccion{font-size:11px;font-weight:700;letter-spacing:0.09em;text-transform:uppercase;
color:var(--muted);margin:26px 0 0;padding-top:14px;border-top:1px solid var(--rule)}
.eje-regla{position:absolute;left:0;right:0;top:26px;height:1px;background:var(--ink)}
.eje-marca{position:absolute;top:0;transform:translateX(-50%);text-align:center;
font-size:11px;font-weight:700;letter-spacing:0.09em;text-transform:uppercase;
color:var(--muted);white-space:nowrap}
.eje-marca::after{content:'';position:absolute;left:50%;top:20px;width:1px;height:7px;
background:var(--ink)}
/* La masa de fondo: TODAS las tendencias del dia, sin etiqueta. Sin esto el eje
   mostraba solo los cinco temas del cruce, que por construccion son casi
   siempre estructurales, y los cinco se apilaban en el mismo punto. La masa es
   la que da la forma —densa a la izquierda, rala a la derecha— y hace que
   ubicar un tema signifique algo. */
.eje-densidad{position:relative;height:34px;margin-top:8px}
.eje-barra{position:absolute;bottom:0;background:var(--ink);opacity:.28}
/* La masa efimera se declara con un numero, no con una barra: la barra la
   aplastaba todo lo demas, y ademas el dato que importa es la proporcion. */
.eje-efimeras{position:absolute;left:0;top:-4px;display:flex;align-items:baseline;gap:9px}
.eje-efimeras-n{font-size:30px;font-weight:700;letter-spacing:-0.045em;line-height:1;
color:var(--ink);font-variant-numeric:tabular-nums}
.eje-efimeras-t{font-size:11px;font-weight:400;letter-spacing:0.06em;text-transform:uppercase;
color:var(--muted);line-height:1.35}

/* La lente por industria. Filtra la PRESENTACION del eje: expone la
   clasificacion por industria que el analisis AI ya guardaba sin mostrar. */
.eje-lente{margin-bottom:22px}
.eje-lente:empty{display:none}
.eje-lente-fila{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.eje-lente-rotulo{font-size:11px;font-weight:700;letter-spacing:0.09em;text-transform:uppercase;
color:var(--muted)}
.eje-lente-caption{font-size:13px;color:var(--muted);line-height:1.4}
/* Dos filas de lente, una debajo de otra: industria y disciplina. */
.eje-lente-fila + .eje-lente-fila{margin-top:10px}
/* La pregunta que responde el lente. En cursiva y no en otro color: el sistema
   reserva el color a estados, y esto es una glosa. */
.eje-lente-pregunta{font-style:italic}
/* Limitaciones DEL MERCADO. Van como pie de foto y no como alerta: que en
   Mexico la demanda permanente todavia no sea medible es una propiedad del
   tablero, no una falla que alguien deba ir a arreglar. */
.eje-lente-limites{list-style:none;margin:8px 0 0;padding:0 0 0 12px;
border-left:2px solid var(--rule-soft);max-width:72ch}
.eje-lente-limites li{font-size:12px;color:var(--muted);line-height:1.45;margin-top:3px}

.eje-carriles{position:relative;padding-top:22px}
.eje-carril{position:relative;height:62px}

/* Con la lente activa, los temas de otra industria se atenuan en vez de
   ocultarse: la tesis del eje es su forma —lo fugaz grande, lo permanente
   tenue— y sacar fichas la rompe. Siguen clickeables por si el equipo quiere
   inspeccionarlos igual. */
.eje-tema.atenuado{opacity:.25}
.eje-tema.atenuado:hover{opacity:.6}
.eje-tema.atenuado.sel{opacity:1}

/* Los temas eran texto suelto flotando: nada decia que se pudieran clickear ni
   que estuvieran colgando del eje. Ahora son fichas con borde —afordancia de
   control— y cada una baja con una guia desde la linea de arriba, que es lo que
   las ata a su posicion en el eje en vez de dejarlas sueltas en el vacio. */
/* El anclaje se corre con la posicion (ver eje.js): en x=0 la ficha se apoya
   por la izquierda, en x=100 por la derecha, y en el medio queda centrada como
   siempre. Con -50% fijo, los temas de "un dia" —el 80% del total— perdian
   media ficha fuera del lienzo. El respaldo de 50% deja la ficha centrada si
   alguien la dibuja sin la variable. */
.eje-tema{position:absolute;--anclaje:50%;
transform:translateX(calc(-1 * var(--anclaje)));text-align:center;cursor:pointer;
background:var(--canvas);border:1px solid var(--rule);padding:6px 12px 7px;
font-family:var(--font);color:inherit;border-radius:var(--radius);
transition:transform .18s ease-out,background-color .18s ease-out}
/* Enganche corto, no una guia hasta el eje: como los temas se agrupan casi en
   la misma posicion, las guias largas de los carriles de abajo cruzaban por
   encima de las fichas de arriba y se veia roto. Un tallo corto alcanza para
   decir "esto cuelga de ahi" sin atravesar nada. */
.eje-tema::before{content:'';position:absolute;left:var(--anclaje);bottom:100%;width:1px;height:12px;
background:var(--rule)}
.eje-tema:hover{transform:translateX(calc(-1 * var(--anclaje))) translateY(-2px);
background:var(--panel-soft)}
.eje-tema:focus-visible{outline:2px solid var(--ink);outline-offset:3px}

/* SELECCION: es ESTRUCTURA, no estado. Va en tinta.
   Tuvo un filete indigo arriba y ahi el color pasaba a significar tres cosas en
   la misma ficha —urgencia, seleccion y conector—, encimadas justo en el caso
   normal, porque el eje abre seleccionando el tema que exige accion. Ahora la
   seleccion se dice como el resto del sistema: peso y una linea, en negro.
   La linea va como box-shadow y no como borde para no pelear con el borde
   superior indigo de la ficha urgente, que es lo unico que debe verse indigo. */
.eje-tema.sel{border-color:var(--ink);box-shadow:inset 0 -2px 0 var(--ink)}
.eje-tema.sel .eje-nombre{font-weight:700}

/* URGENCIA: el unico indigo del eje. Va DESPUES de .sel a proposito — misma
   especificidad, gana el ultimo— para que un tema urgente y seleccionado siga
   mostrando su filete de urgencia arriba. */
.eje-tema[data-urge="1"]{border-top:2px solid var(--state-attention)}
/* El rotulo de la jugada. Es un `.badge` y se achica: el badge generico esta
   dimensionado para texto de cuerpo (11px) y aca es una marca de dato dentro de
   una ficha. A tamano de cuerpo la ficha fugaz urgente medía 65px contra los
   62px del carril; achicar el rotulo cuesta menos que subir el carril, que
   gastaria alto en TODAS las fichas y no solo en las urgentes. */
.eje-urge{margin-left:8px;font-size:9.5px;padding:2px 7px}

/* El conector baja desde la ficha elegida hasta el borde del expediente. Puesto
   en la propia ficha apuntaba a la ficha del carril siguiente, no al documento:
   senalaba al vecino en vez de a la consecuencia del clic.
   En tinta, por lo mismo que la seleccion: une dos partes del documento, no
   avisa nada. */
.eje-conector{position:absolute;transform:translateX(-50%);
display:flex;flex-direction:column;align-items:center}
.eje-conector-linea{width:1px;flex:1;background:var(--ink)}
.eje-conector-punta{border:7px solid transparent;border-top-color:var(--ink)}

/* El punto es el dato en el eje. Aca el indigo SI es legitimo —data-viz— y
   significa lo mismo que en todo el dashboard: este tema exige accion hoy. */
.eje-punto{width:9px;height:9px;border-radius:50%;background:var(--ink);
margin:0 auto 8px;transition:background-color .18s ease-out}
.eje-tema[data-urge="1"] .eje-punto{background:var(--state-attention);
box-shadow:0 0 0 4px var(--canvas),0 0 0 5px var(--state-attention)}
.eje-nombre{display:block;white-space:nowrap;letter-spacing:-0.02em;line-height:1.1}
.eje-meta{display:block;font-size:11px;font-weight:400;letter-spacing:0.04em;
color:var(--muted);margin-top:4px;white-space:nowrap;font-variant-numeric:tabular-nums}

/* La inversion de peso. Cuanto menos vive un tema, mas presencia tiene. Con dos
   pesos reales (400/700) la escala la sostienen el tamano y el contraste. */
.eje-tema[data-vida="fugaz"]   .eje-nombre{font-size:21px;font-weight:700;color:var(--ink)}
.eje-tema[data-vida="dias"]    .eje-nombre{font-size:17px;font-weight:700;color:var(--ink)}
.eje-tema[data-vida="semanas"] .eje-nombre{font-size:15px;font-weight:400;color:var(--ink)}
.eje-tema[data-vida="meses"]   .eje-nombre{font-size:13px;font-weight:400;color:var(--muted)}
.eje-tema[data-vida="meses"]   .eje-punto{width:6px;height:6px;background:var(--muted)}
.eje-tema[data-vida="semanas"] .eje-punto{width:7px;height:7px;background:var(--muted)}

/* El dossier. No es una tarjeta: es el expediente del tema seleccionado, y
   ocupa el ancho de lectura de un documento, no una celda de una rejilla.
   Su regla superior es estructura —abre un documento—, asi que va en tinta. */
.dossier{border-top:2px solid var(--ink);padding-top:clamp(20px,2.6vw,30px)}
.dossier-origen{font-size:11px;font-weight:700;letter-spacing:0.09em;text-transform:uppercase;
color:var(--muted);margin-bottom:10px}
/* El rotulo del expediente y su salida comparten linea.
   `align-items:baseline` y no `center`: cuando el respaldo manual abre su caja
   de texto, la fila del boton crece hacia abajo y con centrado el rotulo se iba
   flotando a media altura. Alineados por la linea base del texto, el rotulo y
   la etiqueta del boton quedan a la misma altura crezca lo que crezca. */
.dossier-barra{display:flex;align-items:baseline;justify-content:space-between;
gap:16px;flex-wrap:wrap;margin-bottom:10px}
.dossier-barra .dossier-origen{margin-bottom:0}
.dossier-cabecera{display:flex;align-items:baseline;gap:16px;flex-wrap:wrap;margin-bottom:6px}
.dossier-titulo{font-size:clamp(26px,3.4vw,38px);font-weight:700;letter-spacing:-0.04em;
line-height:1;color:var(--ink);text-transform:capitalize}
.dossier-cuerpo{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);
gap:clamp(24px,3vw,44px);margin-top:26px;align-items:start}
.dossier-eyebrow{font-size:11px;font-weight:700;letter-spacing:0.09em;text-transform:uppercase;
color:var(--muted);margin-bottom:12px}
/* A que industrias le sirve el tema. Es la misma senal que alimenta la lente,
   puesta en el expediente para que se vea sin necesidad de filtrar. */
.dossier-industrias{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:12px}
.dossier-industrias-rotulo{font-size:11px;font-weight:700;letter-spacing:0.09em;
text-transform:uppercase;color:var(--muted)}
@media(max-width:900px){.dossier-cuerpo{grid-template-columns:1fr}}

/* =============================================================================
   TABLAS, IDEAS, SPARKLINE
   ============================================================================= */
.seo-table{width:100%;border-collapse:collapse;font-size:14px}
.seo-table th{text-align:left;font-size:11px;font-weight:700;text-transform:uppercase;
letter-spacing:0.09em;color:var(--muted);padding:10px 12px;border-bottom:1px solid var(--ink)}
.seo-table td{padding:10px 12px;border-bottom:1px solid var(--rule-soft);vertical-align:top}
.seo-table tr:hover td{background:var(--panel-soft)}

.idea-card{background:var(--canvas);border:1px solid var(--rule);border-radius:var(--radius);
padding:20px;transition:background-color 160ms ease-out}
.idea-card:hover{background:var(--panel-soft)}
.idea-hook{font-size:15px;font-weight:700;color:var(--ink);margin:10px 0 8px;line-height:1.35}
.idea-meta{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}

.sparkline{display:inline-flex;align-items:flex-end;gap:2px;height:20px;vertical-align:middle}
.sparkline-bar{width:4px;background:var(--muted)}
.sparkline-bar:last-child{background:var(--ink)}

/* =============================================================================
   ESTADOS: CARGA, VACIO, AVISO, ERROR
   ============================================================================= */
.loading{text-align:center;padding:60px 20px;color:var(--muted);font-size:14px}
.loading-spinner{width:28px;height:28px;border:2px solid var(--rule);
border-top-color:var(--ink);border-radius:50%;animation:spin .8s linear infinite;
margin:0 auto 16px}
@keyframes spin{to{transform:rotate(360deg)}}
.empty-state{padding:40px 0;color:var(--muted);font-size:14px;max-width:62ch}

/* AVISO DE MERCADO
   Un tab vacio sin explicacion se lee como que el sistema esta roto. Estos dos
   estados se ven distinto porque significan lo opuesto:
   - neutro: esta fuente no se recolecta en este mercado. Vacio es lo correcto.
   - .alarma: se recolecta y no llego nada. Ese es el modo de falla de este
     proyecto —el silencio— y se marca con el filete Signal, que el sistema
     reserva justamente para fallas.
   El fondo tintado que tenia la alarma se fue: el acento es filete, no fondo.
   grid-column porque varios contenedores (#google-list, #reddit-list) son
   .grid-3, y sin esto el aviso queda encajado como una tarjeta mas en la
   primera columna, que es justo donde se lee como "una tarjeta rota". */
.aviso-mercado{grid-column:1/-1;max-width:62ch;margin:8px 0;padding:14px 18px;
border:1px solid var(--rule);border-left:4px solid var(--rule);
background:var(--panel-soft);border-radius:var(--radius)}
.aviso-mercado-titulo{font-size:11px;font-weight:700;text-transform:uppercase;
letter-spacing:0.09em;color:var(--muted);margin-bottom:5px}
.aviso-mercado-texto{font-size:14px;line-height:1.5;color:var(--ink)}
.aviso-mercado-pie{font-size:13px;line-height:1.5;color:var(--muted);margin-top:8px}
.aviso-mercado.alarma{border-left-color:var(--state-critical)}
.aviso-mercado.alarma .aviso-mercado-titulo{color:var(--ink)}

.error-banner{background:var(--canvas);border:1px solid var(--rule);
border-left:4px solid var(--state-critical);border-radius:var(--radius);
padding:14px 18px;margin-bottom:24px;color:var(--ink);font-size:14px}

/* =============================================================================
   SALUD DEL PIPELINE
   Esta pantalla tiene una sola regla de color, y de ella sale todo lo demas:

     LO SANO NO LLEVA COLOR.

   No es minimalismo. En este proyecto el modo de falla es el silencio —diez
   dias de cron caido con 340 corridas marcadas 'success', veinticinco dias de
   Reddit en cero— y una pantalla donde lo bueno tambien grita obliga a leerla
   entera para encontrar lo malo. Pintando solo la falla, mirar de reojo alcanza.

   La falla usa --state-critical, que es el rol que el sistema reserva a errores
   y caidas. Antes usaba --reddit (el mismo hex) por analogia con el aviso de
   mercado; ahora ambos apuntan al mismo rol y no a una plataforma, que era una
   coincidencia de color disfrazada de significado.

   Y la distincion que sostiene la vista entera:
     COLOR = se midio.   TRAMA = no se sabe.
   El rayado no es un estado peor ni mejor: es la ausencia de medicion. Sin esa
   separacion, las corridas anteriores al desglose por mercado se leerian como
   un mes de caidas que nunca ocurrio.
   ============================================================================= */

.salud-titular{border:1px solid var(--rule);border-left:4px solid var(--rule);
padding:14px 18px;margin-bottom:22px;background:var(--panel-soft);
border-radius:var(--radius);max-width:78ch}
.salud-titular-frase{font-size:clamp(18px,2.2vw,24px);font-weight:700;letter-spacing:-0.035em;
line-height:1.15;color:var(--ink)}
.salud-titular-detalle{font-size:14px;line-height:1.5;color:var(--muted);margin-top:6px}
.salud-titular-pie{font-size:12px;color:var(--muted);margin-top:10px}
/* 'aviso' dice "falto un mercado" y 'alarma' dice "no trajo nada". Se separan
   por el grosor del filete, no por un fondo de color. */
.salud-titular[data-tono="aviso"]{border-left-color:var(--state-attention)}
.salud-titular[data-tono="alarma"]{border-left-width:6px;border-left-color:var(--state-critical)}

/* CON QUE CODIGO CORRIO.
   Bloque propio y debajo del titular: "¿se guardó?" y "¿con qué código?" son
   dos preguntas, y la segunda estuvo invisible hasta ahora.

   El tono maximo es 'aviso' y usa --state-attention, NUNCA --state-critical:
   correr codigo viejo no es una caida —los datos entraron— y el contrato
   reserva el rojo-naranja a errores y caidas. El caso 'mudo' (ninguna corrida
   registra su version) va sin filete de color, por la misma regla que sostiene
   la franja: la ausencia de dato no se pinta. */
.salud-version{border:1px solid var(--rule);border-left:4px solid var(--rule);
padding:12px 16px;margin-bottom:22px;background:var(--panel-soft);
border-radius:var(--radius);max-width:78ch}
.salud-version[data-tono="aviso"]{border-left-color:var(--state-attention)}
.salud-version .salud-eyebrow{margin:0 0 6px}
.salud-version-frase{font-size:15px;font-weight:700;letter-spacing:-0.02em;color:var(--ink)}
.salud-version-detalle{font-size:13px;line-height:1.5;color:var(--muted);margin-top:5px}

/* El registro de versiones: un renglon por commit, con el rango de dias en que
   se lo vio correr. Reemplaza a repetir el SHA en las treinta celdas. */
.salud-versiones{list-style:none;margin-top:10px;padding-top:9px;
border-top:1px solid var(--rule-soft);display:flex;flex-direction:column;gap:4px}
.salud-versiones li{display:flex;gap:10px;align-items:baseline;font-size:12px}
.salud-version-rango{color:var(--muted);font-variant-numeric:tabular-nums}

/* El SHA. Sin monospace a proposito: el contrato prohibe una segunda familia
   tipografica, asi que la legibilidad la dan el tracking y las cifras
   tabulares. El commit vigente se distingue por PESO, no por color. */
.salud-commit{font-weight:400;letter-spacing:0.05em;font-variant-numeric:tabular-nums;
color:var(--ink);white-space:nowrap}
.salud-commit[data-vigente="1"]{font-weight:700}

/* LA CELDA: un dia, cinco lecturas posibles. Data-viz, el lugar donde el color
   si informa. */
.salud-celda{flex:1 1 0;min-width:4px;height:24px;display:block}
.salud-celda[data-e="con_datos"]{background:color-mix(in srgb,var(--ink) 55%,transparent)}
.salud-celda[data-e="sin_datos"]{background:var(--state-critical)}
/* Media celda. "Entro algo, pero falto una parte" se explica con la forma y no
   necesita un color propio: la mitad de abajo es lo que si llego. */
.salud-celda[data-incompleta="1"]{background:linear-gradient(to top,
color-mix(in srgb,var(--ink) 55%,transparent) 50%,var(--state-critical) 50%)}
/* Un dia sin corrida no es un dia caido. Se dibuja como lo que es: un hueco. */
.salud-celda[data-e="sin_corrida"]{background:transparent;
box-shadow:inset 0 0 0 1px var(--rule)}
/* Trama, nunca color: aca no se midio nada. */
.salud-celda[data-e="desconocido"]{background:repeating-linear-gradient(45deg,
var(--rule) 0 1.5px,transparent 1.5px 4px);box-shadow:inset 0 0 0 1px var(--rule-soft)}

.salud-leyenda{display:flex;flex-wrap:wrap;gap:6px 20px;margin-bottom:16px;
font-size:12px;color:var(--muted)}
.salud-leyenda-item{display:inline-flex;align-items:center;gap:7px}
.salud-leyenda-item .salud-celda{flex:0 0 14px;width:14px;height:16px}

.salud-nota{font-size:13px;line-height:1.5;color:var(--muted);max-width:78ch;margin-bottom:12px}
.salud-nota b{color:var(--ink);font-weight:700}
.salud-nota-ancha{padding:11px 14px;background:var(--panel-soft);
border-radius:var(--radius);margin-bottom:20px}

/* LA FILA: una plataforma. <details> nativo — el estado colapsado no depende de
   ningun handler, asi que no puede quedar desincronizado con nada. */
.salud-lista{display:flex;flex-direction:column;gap:10px}
.salud-fila{background:var(--canvas);border:1px solid var(--rule);
border-radius:var(--radius);padding:14px 18px 12px}
.salud-fila[data-estado="caido"],.salud-fila[data-estado="detenido"],
.salud-fila[data-estado="sin_registro"]{border-left:4px solid var(--state-critical)}
.salud-fila>summary{list-style:none;cursor:pointer}
.salud-fila>summary::-webkit-details-marker{display:none}
.salud-fila>summary:focus-visible{outline:2px solid var(--ink);outline-offset:4px}
.salud-fila-cab{display:flex;justify-content:space-between;align-items:baseline;
gap:14px;flex-wrap:wrap}
.salud-fila-id{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-width:0}
.salud-nombre{font-size:15px;font-weight:700;letter-spacing:-0.02em;color:var(--ink)}
.salud-fila-meta{font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums;
white-space:nowrap}

/* El badge no estrena colores ni se rellena: cambia el filete, como todo badge
   del sistema. Sin filete = sano; filete de atencion = le falto algo; filete
   critico = no trajo nada. La palabra la escribe salud.js. */
.salud-badge{font-size:10px;font-weight:700;letter-spacing:0.07em;text-transform:uppercase;
padding:3px 9px;border:1px solid var(--rule);border-radius:var(--radius-pill);
color:var(--muted);white-space:nowrap}
.salud-badge[data-estado="incompleto"]{border-color:var(--ink);color:var(--ink);
border-left:3px solid var(--state-attention)}
.salud-badge[data-estado="caido"],.salud-badge[data-estado="detenido"],
.salud-badge[data-estado="sin_registro"]{border-color:var(--ink);color:var(--ink);
border-left:3px solid var(--state-critical)}
/* "Hace cuantos dias" solo aparece cuando hay falla: un contador presente todos
   los dias se deja de leer, que es como se perdieron las dos caidas largas. */
.salud-desde{font-size:12px;font-weight:700;color:var(--ink)}

.salud-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:9px}
.salud-chip{font-size:11px;font-weight:400;letter-spacing:0.02em;padding:2px 9px;
border:1px solid var(--rule);border-radius:var(--radius-pill);color:var(--muted);
white-space:nowrap}
.salud-chip b{font-weight:700;color:var(--ink)}
.salud-chip-cero{border-color:var(--ink);color:var(--ink);
border-left:3px solid var(--state-critical)}
/* "Sin desglose" tiene que verse como lo que es —una ausencia de medicion— y no
   como un mercado en cero. Misma logica que la celda desconocida: trama, no color. */
.salud-chip-mudo{color:var(--muted);border-style:dashed}
/* "Corrio con codigo que ya quedo atras", o "esta corrida no salio del deploy".
   Filete de atencion y no critico: el dato entro, lo que esta en duda es de
   donde salio. La palabra viaja en el chip — el color no es la unica señal. */
.salud-chip-atencion{border-color:var(--ink);color:var(--ink);
border-left:3px solid var(--state-attention)}

/* La franja se acota. A ancho completo cada dia mide 40px y treinta dias de
   caida se leen como un bloque de color plano; a este ancho se lee como lo que
   es —una linea de tiempo— y el ojo puede contar los dias. */
.salud-franja-fila{margin-top:12px}
.salud-franja{display:flex;gap:2px;align-items:flex-end;max-width:660px}
.salud-franja-pie{display:flex;justify-content:space-between;margin-top:5px;max-width:660px;
font-size:11px;font-weight:700;letter-spacing:0.06em;text-transform:uppercase;color:var(--muted)}
/* La afordancia de que la fila abre. Sin esto el <details> no se anuncia: no
   hay triangulo nativo (se saca) y la franja parece el final del panel. */
.salud-abrir{margin-top:10px;font-size:12px;font-weight:400;color:var(--muted)}
.salud-abrir::before{content:'\25B8\00a0';display:inline-block}
.salud-fila[open] .salud-abrir::before{content:'\25BE\00a0'}
.salud-fila>summary:hover .salud-abrir{color:var(--ink)}

.salud-detalle{margin-top:16px;padding-top:14px;border-top:1px solid var(--rule-soft)}
.salud-eyebrow{font-size:11px;font-weight:700;letter-spacing:0.09em;text-transform:uppercase;
color:var(--muted);margin:14px 0 8px}
/* La franja de mercado va DEBAJO de su rotulo, no al lado.
   Toda la comparacion se apoya en que la columna N sea el mismo dia en las tres
   franjas —"la plataforma trajo, y cada mercado?"—, y un rotulo al costado
   corre la franja del mercado unos 45px a la derecha de la de la plataforma:
   las columnas dejan de coincidir y la lectura se vuelve falsa. Con el rotulo
   arriba, las tres arrancan en el mismo x y con el mismo ancho. */
.salud-mercado-fila{margin-bottom:10px}
.salud-mercado-rotulo{display:block;font-size:11px;font-weight:700;letter-spacing:0.06em;
color:var(--muted);margin-bottom:3px}
.salud-mercado-fila .salud-celda{height:16px}
.salud-errores{list-style:none;display:flex;flex-direction:column;gap:5px}
.salud-errores li{display:flex;gap:10px;font-size:13px;line-height:1.45;align-items:baseline}
.salud-error-dia{font-size:11px;font-weight:700;color:var(--muted);
font-variant-numeric:tabular-nums;white-space:nowrap;flex-shrink:0}
.salud-error-msg{color:var(--ink);word-break:break-word}

/* =============================================================================
   RESPONSIVE
   Puntos de control del contrato: 360, 768, 1024 y 1440 px.
   ============================================================================= */
@media(max-width:768px){
.nav-brand-org{font-size:15px}
.nav-link{padding:0 10px;font-size:11px}
.nav-date-select{font-size:11px;padding:4px 6px}
/* .nav-right NO scrollea —eso fue un bug real: margin-left:auto empujaba los
   selectores fuera del borde visible— asi que en pantalla chica lo que sobra
   tiene que bajar de fila, no recortarse ni desbordar.
   Medido a 360px: el indicador de origen de los datos pide 178px en su caso mas
   largo ("Falla · Reddit sin datos") y con los dos selectores y la sesion suma
   429px contra 328px utiles. Compartiendo fila con la marca, eso saca los
   selectores de la pantalla.
   Cae el rotulo "Origen de los datos" y quedan el punto y la frase, que es lo
   que cambia. El rotulo sigue en el aria-label, asi que quien navega por lector
   de pantalla no lo pierde. */
.nav-right{width:100%;order:2;margin-left:0;flex-wrap:wrap;gap:6px;
padding-bottom:6px}
/* Medido a 360px: con el indicador en 62px ("al dia") la fila entra entera y la
   barra queda en 142px, lo mismo que antes de que el indicador existiera. Los
   casos largos —"Google Trends sin datos"— la parten en dos y la barra sube a
   184px, y esta bien que asi sea: es justo cuando hay algo que mirar. */
.nav-estado{gap:6px;padding:4px 6px;font-size:11px}
.nav-estado-etiqueta{display:none}
.subnav-link{padding:0 9px;font-size:12px}
.seo-table{font-size:12px}
.seo-table th,.seo-table td{padding:8px 6px}
.salud-celda{min-width:3px;height:20px}
.salud-fila-meta{white-space:normal}
/* El chip de version puede llevar dos notas ("no salió del deploy · sin
   commitear") y con nowrap se sale del panel: medido a 390px, empujaba el borde
   derecho de la fila fuera de la pantalla. Un chip de dos lineas es feo; un
   panel que desborda rompe el contrato. */
.salud-chip{white-space:normal}
}

/* =============================================================================
   ENTRADA
   Una sola aparicion de opacidad, sin desplazamiento y sin escalonar: el
   contrato prohibe la animacion de entrada masiva y las cascadas por defecto.
   Las clases -1..-4 sobreviven sin efecto para no romper el marcado que las usa.
   ============================================================================= */
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
.fade-in{animation:fadeIn .16s ease-out both}
.fade-in-1,.fade-in-2,.fade-in-3,.fade-in-4{animation-delay:0s}


/* =============================================================================
   LA LISTA DEL DIA — ver js/vistas/lista.js
   Reemplaza al eje de permanencia. Cuatro columnas: numero, quien es, que
   hacer, cuanto dura. La tercera es la ancha a proposito: la accion es el
   contenido de la fila, no un detalle que se abre.

   Ninguna regla de aca usa un acento como fondo. Los acentos aparecen como
   filete de 3px en el borde izquierdo de la fila, y en los tres casos la
   palabra esta escrita al lado en el badge: el color es redundante, nunca la
   unica señal.
   ============================================================================= */
.lista-selector{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:12px}
.lista-cab{margin:22px 0 0;max-width:72ch}
.lista-cab-cifra{font-size:clamp(17px,1.9vw,21px);font-weight:700;line-height:1.25;
letter-spacing:-0.02em;margin-top:12px}
.lista-cab-glosa{font-size:13px;line-height:1.5;color:var(--muted);margin-top:6px}

.lista-temas{list-style:none;margin:22px 0 0;padding:0}

/* El separador de tramo es una regla con su rotulo: la lista no cambia de forma
   entre tramos, solo declara donde esta el corte. */
.lista-grupo{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;
margin-top:34px;padding-top:10px;border-top:2px solid var(--ink)}
.lista-grupo:first-child{margin-top:0}
.lista-grupo .eyebrow{color:var(--ink)}
.lista-grupo-glosa{font-size:12px;color:var(--muted);line-height:1.4}

.lista-fila{display:grid;grid-template-columns:2.2rem minmax(0,15rem) minmax(0,1fr) 15rem;
gap:0 20px;align-items:start;padding:16px 0 16px 14px;
border-top:1px solid var(--rule-soft);border-left:3px solid var(--rule);
transition:background-color 140ms ease-out}
.lista-fila:hover{background:var(--panel-soft)}
/* Direccion. El filete cambia; el badge de al lado dice la palabra. */
.lista-fila.dir-encontra{border-left-color:var(--state-critical)}
.lista-fila.dir-afavor{border-left-color:var(--state-ok)}
.lista-fila.dir-reparos{border-left-color:var(--ink)}
.lista-fila.dir-neutra{border-left-color:var(--rule-soft)}
/* SELECCION: en tinta y con filete, igual que en el resto del sistema. Es la
   fila cuyo expediente esta abierto abajo. */
.lista-fila.sel{background:var(--panel-soft);box-shadow:inset 0 -2px 0 var(--ink)}
/* Atenuada por la lente de industria: se apaga, no se oculta. */
.lista-fila.atenuada{opacity:.35}
.lista-fila.atenuada:hover{opacity:.8}

.lista-n{font-size:12px;font-weight:700;color:var(--muted);
font-variant-numeric:tabular-nums;padding-top:3px}
.lista-ident{min-width:0}
/* El nombre del tema es el boton: no hay una segunda zona clickeable que haga
   otra cosa, y quien navega con teclado llega a el con Tab. */
/* `capitalize` es lo que hace .dossier-titulo con el mismo dato: los temas
   llegan en minuscula del motor y sin esto la lista mezcla «jetsmart» con
   «José Antonio», que se lee como un error de la herramienta. Su costo es
   visible y conocido —«Estrecho De Magallanes»— y se paga igual que en el
   expediente: dos vocabularios tipograficos para el mismo dato serian peor. */
.lista-tema{display:block;padding:0;background:transparent;border:0;text-align:left;
font-family:var(--font);font-size:17px;font-weight:700;line-height:1.2;
letter-spacing:-0.02em;color:var(--ink);cursor:pointer;margin-bottom:7px;
text-transform:capitalize}
.lista-tema:hover{text-decoration:underline;text-underline-offset:3px}
.lista-tema:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
.lista-fuentes{display:inline-flex;gap:5px;flex-wrap:wrap;margin-top:8px}

.lista-hacer{min-width:0}
/* La instruccion pesa como el nombre del tema: son las dos cosas que la fila
   tiene que decir sin que nadie expanda nada. */
.lista-instr{font-size:15px;font-weight:700;line-height:1.35}
.lista-razon{font-size:13px;line-height:1.5;color:var(--muted);margin-top:5px}
/* La ausencia se dibuja distinto de la explicacion, o "el analisis no lo
   escribio" se leeria como algo que el analisis dijo. */
.lista-razon.ausente{font-style:italic}
.lista-extras{list-style:none;margin:5px 0 0;padding:0;font-size:13px;color:var(--muted)}
/* La nota de riesgo se separa con un filete y no con un fondo tintado. */
.lista-nota{margin-top:9px;padding-left:10px;border-left:2px solid var(--state-critical);
font-size:13px;line-height:1.45;color:var(--ink)}
.lista-aviso{margin-top:9px;padding-left:10px;border-left:2px solid var(--rule);
font-size:12px;line-height:1.45;color:var(--muted)}

.lista-dur{min-width:0;text-align:right}
.lista-dur-palabra{display:block;font-size:13px;font-weight:700;line-height:1.3}
.lista-dur-cifra{display:block;font-size:12px;color:var(--muted);line-height:1.4;
margin-top:3px;font-variant-numeric:tabular-nums}

/* Bajo 1000px la fila deja de ser una rejilla de cuatro columnas: el numero se
   queda a la izquierda y lo demas se apila. La duracion pasa a alinear a la
   izquierda —alineada a la derecha en una columna angosta queda flotando lejos
   del texto al que pertenece—. */
@media(max-width:1000px){
  .lista-fila{grid-template-columns:2.2rem minmax(0,1fr);gap:0 16px}
  .lista-hacer,.lista-dur{grid-column:2;margin-top:10px}
  .lista-dur{text-align:left}
}

/* Los terminos en alza son consultas completas, no etiquetas de estado: se les
   permite romper en dos lineas. Ver el comentario en js/vistas/fuentes/momentum.js. */
.momentum-terminos .badge{white-space:normal;max-width:100%;text-align:left}
