/* FrontalCortexAI — sistema visual.
 *
 * Oscuro y comprometido: es un panel de instrumentos que se mira durante
 * horas, no una web de marketing. Un solo acento (ámbar de señal) sobre
 * grises fríos; el color se reserva para el estado, nunca para decorar.
 *
 * Sin fuentes externas a propósito: el VPS sirve estático detrás de Caddy y
 * una petición a un CDN es una dependencia de terceros en la ruta crítica de
 * la primera pintada.
 */

:root {
  /* Rejilla de la página. La cabecera, el menú y el pie ocupan el ancho
     completo —su línea inferior tiene que cruzar la pantalla— pero su
     contenido se alinea con el de `main`, que está limitado y centrado. */
  --ancho-contenido: 1280px;
  --margen-lateral: clamp(20px, 4vw, 48px);
  --margen-alineado: max(
    var(--margen-lateral),
    calc((100% - var(--ancho-contenido)) / 2 + var(--margen-lateral))
  );

  /* Superficies: casi negro con un punto de azul, no gris puro. */
  --fondo:            #05070a;
  --fondo-elevado:    #0d1117;
  --fondo-hundido:    #030507;
  --borde:            #1c212b;
  --borde-vivo:       #2a323f;

  /* Texto: nunca blanco puro sobre oscuro, cansa la vista. */
  --texto:            #e6e9ef;
  --texto-medio:      #98a1b2;
  --texto-tenue:      #5d6675;

  /* Dos acentos con semántica estricta, no decorativa:
     - ámbar  = señal operativa (estados, flujo, marca)
     - cian   = cognición del modelo (todo lo que la IA escribió o decidió)
     La regla que sostiene el lenguaje: si un texto lo produjo el motor, lleva
     cian en algún punto; si lo midió el sistema, no. Así se puede saber de un
     vistazo qué es dato y qué es juicio del modelo. */
  /* El ámbar del sistema de diseño es #d9a13b —lo medido y lo accionable—
     con #e8b755 como claro de hover. El #e8b464 anterior era de una época
     previa al rediseño y hacía que TODO se viera más pálido que los mockups;
     sobrevive solo como --estado-active (el latido de «ejecutando»). */
  --senal:            #d9a13b;
  --senal-clara:      #e8b755;
  --senal-suave:      rgba(217, 161, 59, 0.14);
  /* Texto sobre ámbar sólido: casi negro con el matiz del acento, no #000. */
  --sobre-senal:      #0d0a04;
  --ia:               #6fd3e8;
  --ia-suave:         rgba(111, 211, 232, 0.12);
  --ia-borde:         rgba(111, 211, 232, 0.35);
  --ia-brillo:        rgba(111, 211, 232, 0.22);
  /* Prosa larga del modelo: cuerpo legible con un punto de cian, para que un
     párrafo entero no grite como grita un rótulo. */
  --ia-texto:         #a8ccd6;

  /* Estados. Deliberadamente distinguibles también por posición y forma,
     no solo por color: el daltonismo rojo-verde es el más común. */
  --estado-idle:      #3f4756;
  --estado-active:    #e8b464;
  --estado-success:   #5ec48a;
  --estado-warning:   #e0a33a;
  --estado-error:     #e2685f;

  /* Derivados: tintes y lineas. Existen para que el tema claro sea un
     cambio de paleta y no una reescritura de reglas. */
  --linea:              rgba(28, 33, 43, 0.7);
  --fondo-activo:       #14161c;
  --fondo-campo:        #10151c;
  --malla-linea-viva:   rgba(232, 180, 100, 0.055);
  --chapa-alto:         #151a22;
  --chapa-bajo:         #0d1116;
  --brillo-cabecera:    rgba(232, 180, 100, 0.03);
  --brillo-diagrama:    rgba(232, 180, 100, 0.035);
  --borde-exito:        rgba(94, 196, 138, 0.5);
  --borde-error:        rgba(226, 104, 95, 0.5);
  --borde-aviso:        rgba(224, 163, 58, 0.5);
  --tinte-exito:        rgba(94, 196, 138, 0.12);
  --tinte-error:        rgba(226, 104, 95, 0.16);
  --tinte-error-suave:  rgba(226, 104, 95, 0.07);
  --tinte-aviso:        rgba(224, 163, 58, 0.14);
  --tinte-aviso-suave:  rgba(224, 163, 58, 0.06);
  --tinte-neutro:       rgba(255, 255, 255, 0.05);
  --sombra:             none;
  /* Realce del canto de una pieza sobre fondo hundido. En oscuro el
     contraste entre superficies es débil y hace falta dibujar el borde
     superior con luz en vez de con una línea. */
  --sombra-pieza:       inset 0 1px 0 rgba(255, 255, 255, 0.04);

  --radio:            10px;
  --radio-chico:      6px;

  /* Public Sans para hablar, IBM Plex Mono para medir. La serif se retira:
     era voz de editorial y esto es un instrumento.

     Public Sans viene del sistema de diseño del gobierno federal
     estadounidense. Es casi sin gestos propios, y aquí eso se busca: en una
     pantalla que se opera de un vistazo, la letra no debe competir con el
     dato. Reemplaza a Space Grotesk, cuya geometría era tan marcada que
     delataba de dónde salió la interfaz antes de que se leyera nada. */
  --display: "Public Sans", -apple-system, "Segoe UI", sans-serif;
  --serif: "Public Sans", -apple-system, "Segoe UI", sans-serif;
  --sans: "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

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

/* Micro-rótulo técnico: la tipografía de instrumento que cose la interfaz. */
.rotulo-tec {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  /* Bóveda: la luz cae desde arriba al centro, como en una sala de control.
     Fija, para que el scroll mueva el contenido y no la iluminación. */
  background:
    radial-gradient(120% 70% at 50% -10%, rgba(232, 180, 100, 0.05), transparent 60%),
    radial-gradient(90% 60% at 85% 110%, rgba(111, 211, 232, 0.04), transparent 55%),
    var(--fondo);
  background-attachment: fixed;
  color: var(--texto);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
}

/* Filo de luz en el canto superior de cada panel: un degradado de un píxel
   que sugiere una superficie iluminada desde arriba. Es el detalle que separa
   una tarjeta plana de una pieza de instrumento; a plena atención ni se ve. */
.panel { position: relative; }
.panel::before {
  content: '';
  position: absolute;
  top: 0;
  left: 8%;
  right: 8%;
  height: 1px;
  pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--senal-suave) 30%, var(--senal-suave) 70%, transparent);
}

/* --- Cabecera ------------------------------------------------------------ */

.cabecera {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  /* El fondo y la línea siguen cruzando la pantalla entera; lo que se alinea
     con el contenido es lo de dentro. De ahí el padding calculado en vez de
     un contenedor extra en el HTML. */
  padding: 22px var(--margen-alineado);
  border-bottom: 1px solid var(--borde);
  background: linear-gradient(180deg, var(--brillo-cabecera), transparent);
}

/* El isotipo se alinea con el RÓTULO, no con el bloque de dos líneas.
   Con `align-items: center` quedaba centrado contra el conjunto —rótulo más
   nombre del cliente— y parecía pertenecer a la segunda línea, que es la que
   cambia según a quién se observe. El isotipo es de la marca y se alinea con
   la marca. */
.marca { display: flex; align-items: flex-start; gap: 13px; }

/* Telemetría del motor. El sistema entero depende del juicio de un modelo:
   cuál es y si está pensando no puede ser un dato enterrado en una pestaña.
   Vive en la cabecera, como el cuentarrevoluciones en un tablero. */
.motor {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 14px;
  border: 1px solid var(--borde);
  border-radius: 999px;
  background:
    linear-gradient(180deg, rgba(111, 211, 232, 0.045), transparent 65%),
    var(--fondo-hundido);
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--texto-medio);
  white-space: nowrap;
}
.motor-nucleo {
  position: relative;
  width: 9px;
  height: 9px;
  flex: none;
}
.motor-nucleo::before,
.motor-nucleo::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--ia);
}
.motor-nucleo::after {
  animation: nucleo 2.2s ease-out infinite;
}
/* Cuando el motor está ejecutando de verdad, el pulso se acelera: la
   diferencia entre «en escucha» y «analizando» se ve sin leer nada. */
.motor[data-pensando="true"] .motor-nucleo::after { animation-duration: .8s; }
.motor[data-pensando="true"] .motor-modelo { color: var(--ia); }
@keyframes nucleo {
  0%   { opacity: .7; transform: scale(1); }
  100% { opacity: 0;  transform: scale(2.6); }
}
.motor-modelo { color: var(--texto); transition: color .3s ease; }
.motor-sep { color: var(--texto-tenue); opacity: .6; }
.motor-detalle { color: var(--texto-tenue); }
@media (max-width: 900px) { .motor-detalle, .motor-sep { display: none; } }
@media (prefers-reduced-motion: reduce) { .motor-nucleo::after { animation: none; } }

/* Sello de la cabecera. El logotipo son 91 puntos rellenos, no anillos con
   trazo: el color va por `currentColor` desde aquí, así el mismo fichero
   sirve en tema claro y oscuro sin duplicarlo. */
.sello {
  /* A 34 px, junto a una tipografía tan ancha como Bruno Ace, el punteado se
     leía como una mota. Con 44 px se distinguen los puntos dispersos del
     borde, que son los que cuentan de qué va la marca. */
  width: 44px;
  height: 44px;
  flex: none;
  color: var(--senal);
  /* Alineado por el CENTRO ÓPTICO de las letras, no por la caja de la línea.
     La caja de un renglón incluye el espacio para las bajantes —que en
     «FrontalCORTEX» casi no existen— así que su centro cae más abajo que el
     centro real de la tinta. Medido sobre la fuente ya cargada: el centro de
     la tinta está 2,9 px por debajo del centro de la caja, y este margen es
     esa diferencia. Si se cambia la tipografía o el cuerpo del rótulo, hay
     que volver a medirlo. */
  margin-top: -6px;
}


.cabecera h1 { margin: 0; }

.marca-ia {
  color: var(--senal);
  font-weight: 400;
}

.pulso {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 12.5px;
  color: var(--texto-medio);
  font-variant-numeric: tabular-nums;
}
.pulso-sep { color: var(--texto-tenue); }
.pulso-ciclo b { color: var(--texto); font-family: var(--mono); font-weight: 500; }

.pulso-punto {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--estado-idle);
  flex: none;
  position: relative;
}
.pulso-punto[data-estado="vivo"] { background: var(--estado-success); }
.pulso-punto[data-estado="vivo"]::after {
  content: "";
  position: absolute; inset: -4px;
  border-radius: 50%;
  border: 1px solid var(--estado-success);
  animation: latido 2.4s ease-out infinite;
}
.pulso-punto[data-estado="caido"] { background: var(--estado-error); }

@keyframes latido {
  0%   { transform: scale(0.7); opacity: 0.9; }
  100% { transform: scale(1.7); opacity: 0; }
}

/* --- Estructura ---------------------------------------------------------- */

main {
  position: relative;
  z-index: 1;
  flex: 1;
  width: 100%;
  max-width: var(--ancho-contenido);
  margin: 0 auto;
  padding: clamp(20px, 3vw, 34px) var(--margen-lateral) 48px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}

/* --- Cifras -------------------------------------------------------------- */

/* Seis cifras en 3×2. `auto-fit` las repartía según sobrara ancho y podía
   dejar una sola colgando en la segunda fila, que es la forma más rápida de
   que un panel parezca inacabado. */
.cifras {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
}

/* La última tarjeta cierra la fila si se quedaría a media.
   En la audiencia de voz propia son cuatro canales más la de vigilancia: con
   tres columnas, la quinta caía en la segunda celda y dejaba un hueco a su
   derecha que se lee como si faltara una tarjeta. Estirarla es más honesto
   que el vacío, y la regla vale para cualquier número de tarjetas —solo actúa
   cuando la última cae en la posición central de su fila—. */
@media (min-width: 981px) {
  .cifras > .cifra:last-child:nth-child(3n + 2) { grid-column: span 2; }
}

@media (max-width: 980px) { .cifras { grid-template-columns: repeat(2, 1fr); } }

/* En móvil siguen siendo dos columnas, no una pila.
   Apiladas, las seis cifras ocupaban tres pantallas y media y había que
   desplazarse para comparar dos números que existen precisamente para leerse
   juntos: el volumen no dice nada sin el sentimiento al lado. En dos columnas
   entran cuatro de un vistazo. Lo que se reduce es el cuerpo de la cifra, no
   el número de columnas. */
@media (max-width: 560px) {
  .cifras { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .cifra { padding: 13px 14px; }
  .cifra-etiqueta { font-size: 9.5px; letter-spacing: .05em; }
  .cifra-valor { font-size: 27px; }
  .cifra-valor--texto { font-size: 17px; }
  .cifra-pie { font-size: 11px; line-height: 1.35; }
}

.cifra {
  background: var(--fondo-elevado);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 16px 18px;
  position: relative;
  overflow: hidden;
}
/* Filo superior: detalle de instrumento, apenas visible. */
.cifra::before {
  content: "";
  position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: linear-gradient(90deg, transparent, var(--borde-vivo) 30%, transparent);
}

.cifra-etiqueta {
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}


/* --- Ataques coordinados: la tarjeta que avisa ----------------------------
   Va primera y a lo ancho porque no es una cifra de inventario como las
   otras: es la única que dice que algo está pasando ahora mismo contra ella.

   Y cuando pasa, tiene que verse sin leer. Un número que cambia de 0 a 1 en
   una rejilla de siete tarjetas no lo nota nadie que abra el panel de paso;
   algo que se mueve, sí. El haz recorre el canto una vez cada cuatro segundos
   —lo bastante lento para no ser una alarma de incendio, lo bastante vivo para
   captar el ojo desde el otro lado del escritorio—. */
.cifra--ataque { grid-column: 1 / -1; }

/* El ángulo tiene que declararse como propiedad tipada para poder animarse:
   una variable CSS corriente interpola como texto y el gradiente daría saltos
   en vez de girar. */
@property --haz-angulo {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

/* En reposo no hay nada: la tarjeta se comporta como cualquier otra. El
   `::after` solo existe cuando hay un ataque activo. */
.cifra--ataque[data-activo="true"] {
  border-color: color-mix(in oklab, var(--estado-error) 45%, var(--borde));
  background:
    radial-gradient(120% 160% at 0% 0%,
      color-mix(in oklab, var(--estado-error) 9%, transparent), transparent 55%),
    var(--fondo-elevado);
}

/* El haz. Un cónico casi transparente salvo un tramo corto que va del rojo al
   blanco y vuelve: eso es la partícula. La máscara deja ver solo el borde de
   un píxel, así que el gradiente gira por el canto en vez de teñir la caja. */
.cifra--ataque[data-activo="true"]::after {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1.5px;
  pointer-events: none;
  background: conic-gradient(
    from var(--haz-angulo),
    transparent 0deg 300deg,
    color-mix(in oklab, var(--estado-error) 55%, transparent) 330deg,
    var(--estado-error) 350deg,
    #fff 357deg,
    var(--estado-error) 360deg
  );
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  mask-composite: exclude;
  animation: haz-ataque 4s linear infinite;
}

@keyframes haz-ataque {
  to { --haz-angulo: 360deg; }
}

/* Respaldo para navegadores sin `@property`: el gradiente no gira, así que en
   vez de un haz quieto —que parecería un borde roto— se usa un latido del
   canto entero. Dice lo mismo con los medios que hay. */
@supports not (background: conic-gradient(from var(--haz-angulo), red, blue)) {
  .cifra--ataque[data-activo="true"]::after {
    background: none;
    box-shadow: 0 0 0 1.5px var(--estado-error);
    animation: latido-ataque 2s ease-in-out infinite;
  }
  @keyframes latido-ataque {
    0%, 100% { opacity: .25; }
    50%      { opacity: 1; }
  }
}

/* La cifra en rojo y con un halo tenue cuando hay ataque: el color solo no
   basta en una pantalla llena de números de colores. */
.cifra--ataque[data-activo="true"] .cifra-valor {
  color: var(--estado-error);
  text-shadow: 0 0 18px color-mix(in oklab, var(--estado-error) 40%, transparent);
}

/* Quien pidió no ver movimiento no lo ve. La tarjeta sigue avisando —borde
   rojo fijo y cifra en rojo—, que es lo que importa; lo que se retira es la
   animación, no la información. */
@media (prefers-reduced-motion: reduce) {
  .cifra--ataque[data-activo="true"]::after {
    animation: none;
    background: none;
    box-shadow: 0 0 0 1.5px var(--estado-error);
  }
}

/* Rótulo de simulacro. Solo aparece cuando el bloque activo es el de la
   demostración. Va en ámbar y no en rojo: el rojo de esta tarjeta significa
   «hay un ataque», y esto dice justo lo contrario. */
.marca-simulacro {
  position: absolute;
  top: 14px;
  right: 14px;
  padding: 3px 8px;
  border: 1px dashed var(--estado-warning);
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--estado-warning);
}
.cifra--ataque:not([data-simulacro="true"]) .marca-simulacro { display: none; }

/* --- Cifra que lleva a algún sitio ----------------------------------------
   Cada cifra del resumen abre la pantalla donde se puede hacer algo con ella.
   Son `<a>` de verdad, así que hay que apagar el subrayado y heredar el color
   —si no, seis tarjetas azules y subrayadas— sin perder el foco por teclado,
   que lo da el navegador. */
.cifra--enlace {
  display: block;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: border-color .12s ease, transform .12s ease;
}
.cifra--enlace:hover { border-color: var(--senal); transform: translateY(-1px); }
.cifra--enlace:focus-visible { outline: 2px solid var(--senal); outline-offset: 2px; }

/* La flecha vive en la esquina y solo se afirma al pasar por encima: presente
   para que se entienda que la tarjeta lleva a algún sitio, callada para no
   competir con la cifra, que es lo que se viene a leer. */
.cifra-ir {
  position: absolute;
  right: 14px;
  bottom: 12px;
  font-size: 13px;
  line-height: 1;
  color: var(--texto-tenue);
  opacity: .45;
  transition: opacity .12s ease, transform .12s ease, color .12s ease;
}
.cifra--enlace:hover .cifra-ir,
.cifra--enlace:focus-visible .cifra-ir {
  opacity: 1;
  color: var(--senal);
  transform: translateX(2px);
}
@media (prefers-reduced-motion: reduce) {
  .cifra--enlace, .cifra-ir { transition: none; }
  .cifra--enlace:hover { transform: none; }
  .cifra--enlace:hover .cifra-ir { transform: none; }
}

.cifra {
  position: relative;
}
/* Marca de esquina única, arriba a la izquierda: registro de visor, no marco
   completo. Cuatro esquinas serían disfraz; una es firma. */
.cifra::before {
  content: '';
  position: absolute;
  top: 10px;
  left: 10px;
  width: 9px;
  height: 9px;
  border-top: 1px solid var(--senal);
  border-left: 1px solid var(--senal);
  opacity: .45;
}

.cifra-valor {
  text-shadow: 0 0 22px var(--senal-suave);
  margin: 8px 0 4px;
  font-family: var(--mono);
  font-size: 42px;
  font-weight: 500;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
}
.cifra-valor--texto { font-size: 19px; font-family: var(--sans); }
.cifra-valor[data-tono="alerta"] { color: var(--estado-error); }
.cifra-valor[data-tono="aviso"]  { color: var(--estado-warning); }
.cifra-valor[data-tono="bien"]   { color: var(--estado-success); }

.cifra-pie { margin: 0; font-size: 12px; color: var(--texto-medio); }

/* --- Paneles ------------------------------------------------------------- */

.panel {
  background: var(--fondo-elevado);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  overflow: hidden;
}

.panel-cabecera {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 15px 18px;
  border-bottom: 1px solid var(--borde);
}

.panel-cabecera h2 {
  margin: 0;
  font-family: var(--display);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  /* Sin esto, «Le responden» se partía en dos líneas en cuanto la nota de al
     lado crecía, y el guion de acento quedaba colgado sobre una sola palabra.
     El título es corto siempre; quien cede espacio es la nota. */
  white-space: nowrap;
}
/* Guion corto de acento delante del título: firma visual de cada panel. */
.panel-cabecera h2::before {
  content: '';
  display: inline-block;
  width: 14px;
  height: 2px;
  margin-right: 9px;
  vertical-align: middle;
  background: var(--senal);
}

/* En vertical el título y su nota no caben uno al lado del otro: con el título
   sin partir, a la nota le quedaban ciento veinte píxeles y se estrujaba en
   cinco líneas contra el borde. Se deja envolver en vez de apilar a la fuerza:
   donde el título va oculto —los paneles que en móvil se vuelven pestañas—
   apilar dejaba una fila de más y una cabecera hueca. */
@media (max-width: 620px) {
  .panel-cabecera { flex-wrap: wrap; gap: 6px 12px; }
  .panel-cabecera .panel-nota { flex: 1 1 100%; }
}

.panel-nota {
  min-width: 0;
  margin: 0;
  font-size: 11.5px;
  color: var(--texto-tenue);
  letter-spacing: 0.05em;
}
/* Cuando la nota no vive dentro de una `.panel-cabecera` —una vista sin panel
   envolvente, como Monitoreo— necesita su propio espaciado. */
.panel-nota--suelta { margin: 8px 0 16px; }

/* --- Segmentado: componente transversal ------------------------------------
   El control de estado que sustituye a un `<select>` cuando las opciones son
   pocas y se cambia a menudo: un toque en vez de abrir-elegir-cerrar, y el
   estado activo se ve sin interactuar. */
.segmentado {
  display: flex;
  gap: 6px;
  padding: 4px;
  margin-bottom: 4px;
  background: var(--fondo-hundido);
  border-radius: var(--radio-chico);
}
/* Variante compacta: convive con otros filtros en la misma fila, así que no
   se estira a todo el ancho. */
.segmentado--compacto { display: inline-flex; }
.segmentado--compacto .segmentado-opcion { flex: none; padding-left: 14px; padding-right: 14px; }

.segmentado-opcion {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 34px;
  padding: 6px 10px;
  border: 1px solid transparent;
  border-radius: calc(var(--radio-chico) - 2px);
  background: none;
  color: var(--texto-tenue);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.segmentado-opcion b {
  font-family: var(--mono);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: inherit;
}
.segmentado-opcion:hover { color: var(--texto-medio); }
.segmentado-opcion[aria-pressed="true"] {
  background: var(--fondo-elevado);
  border-color: var(--senal);
  color: var(--texto);
  box-shadow: var(--sombra-pieza);
}

.columnas {
  display: grid;
  grid-template-columns: 1.55fr 1fr;
  gap: 22px;
  align-items: start;
}

@media (max-width: 860px) {
  .columnas { grid-template-columns: 1fr; }
}

/* --- Diagrama ------------------------------------------------------------ */

.diagrama-caja {
  position: relative;
  padding: 16px 10px 8px;
  overflow: hidden;
  background:
    radial-gradient(ellipse 55% 75% at 50% 45%, var(--brillo-diagrama), transparent 72%),
    var(--fondo-hundido);
}

/* Barrido lento sobre el lienzo. Muy tenue a propósito: da la sensación de
   instrumento vivo sin convertirse en un elemento que pide atención cada vez
   que pasa, que es lo que cansa de este tipo de efecto. */
.diagrama-caja::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 42%, var(--senal-suave) 50%, transparent 58%);
  opacity: .5;
  animation: barrido 9s ease-in-out infinite;
}
@keyframes barrido {
  0%, 100% { transform: translateX(-60%); }
  50%      { transform: translateX(60%); }
}
@media (prefers-reduced-motion: reduce) {
  .diagrama-caja::after { animation: none; opacity: 0; }
}

.rejilla-linea { stroke: var(--malla-linea-viva); stroke-width: 1; }
.malla-diagrama { pointer-events: none; }

.chapa-alto { stop-color: var(--chapa-alto); }
.chapa-bajo { stop-color: var(--chapa-bajo); }

/* El alto lo fija el guion a partir del viewBox; aquí solo se garantiza que
   nunca desborde el panel. */
#diagrama { display: block; width: 100%; max-width: 100%; }

.arista {
  fill: none;
  stroke: var(--borde-vivo);
  stroke-width: 1.25;
  stroke-linecap: round;
  opacity: .8;
}
/* Cuando una etapa corre, el flujo hacia ella se dibuja moviéndose. Es lo
   que hace visible que la IA está trabajando y no solo esperando. */
.arista-flujo {
  fill: none;
  stroke: var(--senal);
  stroke-width: 1.5;
  stroke-dasharray: 5 9;
  opacity: 0;
  transition: opacity .3s ease;
}
.arista-flujo.corriendo {
  opacity: .9;
  filter: url(#brillo);
  animation: fluir 1.1s linear infinite;
}
@keyframes fluir { to { stroke-dashoffset: -28; } }

/* Paquete que viaja por la arista. Existe solo mientras la etapa destino
   trabaja: el resto del tiempo estorbaría. */
/* La opacidad la conduce la animación SMIL —sube mientras el paquete acelera
   y se apaga al llegar—, así que aquí solo se controla si el paquete existe
   visualmente y cuánto brilla. Poner `opacity` en CSS pisaría la animación. */
.paquete {
  fill: var(--senal);
  transition: filter .3s ease;
}
.paquete:not(.corriendo) { opacity: .18 !important; }
.paquete.corriendo { filter: url(#brillo); }
@media (prefers-reduced-motion: reduce) { .paquete { opacity: 0; } .nodo-orbita { animation: none; } }

/* Núcleo orbital. El vocabulario: un anillo discontinuo que SIEMPRE gira
   —lento en reposo, rápido al procesar— alrededor de un núcleo que emite con
   el color del estado. Nada de cajas: las cajas con conectores se leen como
   un diagrama de base de datos, y esto es un sistema vivo. */
.nodo-orbita {
  fill: none;
  stroke: var(--borde-vivo);
  stroke-width: 1.4;
  transform-box: fill-box;
  transform-origin: center;
  animation: orbitar 40s linear infinite;
  transition: stroke .3s ease;
}
@keyframes orbitar { to { transform: rotate(360deg); } }
.nodo[data-estado="active"] .nodo-orbita {
  stroke: var(--estado-active);
  animation-duration: 2.6s;
}
.nodo[data-estado="success"] .nodo-orbita { stroke: var(--borde-exito); }
.nodo[data-estado="warning"] .nodo-orbita { stroke: var(--borde-aviso); }
.nodo[data-estado="error"]   .nodo-orbita { stroke: var(--estado-error); animation-duration: 6s; }

.nodo-anillo {
  fill: var(--fondo-elevado);
  stroke: var(--borde);
  stroke-width: 1;
}

.nodo-nucleo {
  fill: var(--estado-idle);
  transition: fill .3s ease;
}
.nodo[data-estado="active"]  .nodo-nucleo { fill: var(--estado-active); }
.nodo[data-estado="success"] .nodo-nucleo { fill: var(--estado-success); }
.nodo[data-estado="warning"] .nodo-nucleo { fill: var(--estado-warning); }
.nodo[data-estado="error"]   .nodo-nucleo { fill: var(--estado-error); }

.nodo-indice {
  fill: var(--texto-tenue);
  font-family: var(--mono);
  font-size: 8.5px;
  letter-spacing: .1em;
}
.nodo[data-estado="active"] .nodo-indice { fill: var(--estado-active); }

/* Halo del diodo: el nodo emite luz en vez de estar pintado de color. */
.nodo-halo {
  fill: none;
  stroke: var(--estado-active);
  stroke-width: 2;
  opacity: 0;
}
.nodo[data-estado="active"] .nodo-halo {
  opacity: .9;
  filter: url(#brillo);
  animation: latido 1.4s ease-in-out infinite;
}
@keyframes latido {
  0%, 100% { opacity: .35; stroke-width: 1.5; }
  50%      { opacity: 1;   stroke-width: 3; }
}
.nodo[data-estado="active"]  .nodo-caja { stroke: var(--estado-active); }
.nodo[data-estado="success"] .nodo-caja { stroke: var(--borde-exito); }
.nodo[data-estado="warning"] .nodo-caja { stroke: var(--borde-aviso); }
.nodo[data-estado="error"]   .nodo-caja { stroke: var(--estado-error); }

.nodo-titulo {
  fill: var(--texto);
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 500;
}
.nodo-detalle {
  fill: var(--texto-tenue);
  font-family: var(--sans);
  font-size: 10px;
}
.nodo-ms {
  fill: var(--texto-medio);
  font-family: var(--mono);
  font-size: 9.5px;
  font-variant-numeric: tabular-nums;
}

/* Título centrado bajo el núcleo, en la voz de la marca. */
.nodo-titulo { font-family: var(--display); font-weight: 600; }

.nodo-aura {
  fill: none;
  stroke: var(--estado-active);
  stroke-width: 1;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
}
.nodo[data-estado="active"] .nodo-aura { animation: aura 1.8s ease-out infinite; }
@keyframes aura {
  0%   { opacity: .6; transform: scale(1); }
  100% { opacity: 0;  transform: scale(1.9); }
}
@media (prefers-reduced-motion: reduce) {
  .nodo-aura, .nodo-halo, .arista-flujo.corriendo { animation: none; }
}

.leyenda {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  margin: 0;
  padding: 12px 18px;
  list-style: none;
  border-top: 1px solid var(--borde);
  font-size: 11.5px;
  color: var(--texto-medio);
}
.leyenda li { display: flex; align-items: center; gap: 7px; }

.punto { width: 7px; height: 7px; border-radius: 50%; background: var(--estado-idle); }
.punto[data-estado="active"]  { background: var(--estado-active); }
.punto[data-estado="success"] { background: var(--estado-success); }
.punto[data-estado="warning"] { background: var(--estado-warning); }
.punto[data-estado="error"]   { background: var(--estado-error); }

/* --- Flujo de actividad -------------------------------------------------- */

.flujo {
  margin: 0;
  padding: 6px 0;
  list-style: none;
  max-height: 380px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--borde-vivo) transparent;
}

.flujo-linea {
  display: grid;
  grid-template-columns: 62px 96px 1fr auto;
  gap: 12px;
  align-items: baseline;
  padding: 8px 18px;
  font-size: 12.5px;
  border-left: 2px solid transparent;
  animation: entrar .35s ease both;
}
.flujo-linea + .flujo-linea { border-top: 1px solid var(--linea); }
.flujo-linea[data-estado="active"]  { border-left-color: var(--estado-active); }
.flujo-linea[data-estado="success"] { border-left-color: var(--estado-success); }
.flujo-linea[data-estado="warning"] { border-left-color: var(--estado-warning); }
.flujo-linea[data-estado="error"]   { border-left-color: var(--estado-error); background: var(--tinte-error-suave); }

@keyframes entrar {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

.flujo-hora  { font-family: var(--mono); font-size: 11px; color: var(--texto-tenue); font-variant-numeric: tabular-nums; }
.flujo-nodo  { color: var(--texto); font-weight: 500; }
.flujo-texto { color: var(--texto-medio); overflow-wrap: anywhere; }
.flujo-ms    { font-family: var(--mono); font-size: 11px; color: var(--texto-tenue); font-variant-numeric: tabular-nums; }
.flujo-vacio { padding: 22px 18px; color: var(--texto-tenue); font-size: 13px; }

/* --- Integraciones ------------------------------------------------------- */

.integraciones { margin: 0; padding: 6px 0; list-style: none; }

.integracion {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 18px;
  font-size: 13px;
}
.integracion + .integracion { border-top: 1px solid var(--linea); }
.integracion-nombre { flex: 1; }
.integracion-estado { font-size: 11.5px; color: var(--texto-tenue); letter-spacing: 0.04em; }
.integracion[data-activa="true"] .integracion-estado { color: var(--estado-success); }

.aviso {
  margin: 0;
  padding: 12px 18px;
  border-top: 1px solid var(--borde);
  background: var(--tinte-aviso-suave);
  color: var(--texto-medio);
  font-size: 12.5px;
  line-height: 1.45;
}

/* Respeta a quien pidió menos movimiento: aquí hay mucha animación y para
   algunas personas es un problema real, no una preferencia estética. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .arista-flujo.corriendo { opacity: .85; }
}

/* --- Menú -----------------------------------------------------------------

   Una sola pieza para los dos tamaños: en el teléfono es un cajón que entra
   por la derecha, en escritorio una barra lateral fija. Cambia dónde está,
   no cómo se lee.

   Tres grupos y no una lista de catorce. Con todo seguido había que leer los
   catorce rótulos para encontrar uno, y las pantallas que se miran a diario
   competían con las que se tocan una vez al mes. */

.menu {
  z-index: 5;
  display: flex;
  flex-direction: column;
  padding: 14px 0 12px;
  border-right: 1px solid var(--borde);
  background: var(--fondo-hundido);
  overflow-y: auto;
  scrollbar-width: none;
}
.menu::-webkit-scrollbar { display: none; }

.menu-grupo { padding: 12px 0 0; }
.menu-rotulo {
  margin: 0 18px 5px;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--texto-tenue);
  opacity: .8;
}

.menu a {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  /* 16 y no 18 a la izquierda: los dos píxeles que faltan son el filete de la
     entrada activa, que si no desplazaría la fila al seleccionarla. */
  padding: 9px 18px 9px 16px;
  border-left: 2px solid transparent;
  color: var(--texto-medio);
  text-decoration: none;
  font-size: 13px;
  transition: color .18s ease, background-color .18s ease;
}
.menu a:hover { color: var(--texto); background: var(--fondo-activo); }
/* La sección activa se marca con un filete a la izquierda y un degradado que
   se apaga hacia dentro: el subrayado de pestaña no significa nada cuando la
   navegación es vertical. */
.menu a[aria-current="page"] {
  color: var(--texto);
  border-left-color: var(--senal);
  background: linear-gradient(90deg, var(--senal-suave), transparent);
}

/* --- Escritorio: barra lateral y columna de contenido ----------------------

   El mismo cajón del teléfono, fijo a la izquierda. La rejilla se monta sobre
   el `body` y no con un envoltorio nuevo en el HTML: la cabecera cruza entera
   y por debajo quedan las dos columnas.

   El contenido se limita a 760 px y se centra. Estirar las tarjetas a 1.400 px
   no da más información: da la misma con renglones de ciento veinte caracteres
   que hay que recorrer con la cabeza. */
@media (min-width: 861px) {
  body {
    display: grid;
    grid-template-columns: 250px minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
    grid-template-areas: "cabecera cabecera" "menu main";
  }
  .cabecera { grid-area: cabecera; }
  main { grid-area: main; --ancho-contenido: 760px; }

  .menu {
    grid-area: menu;
    position: sticky;
    top: 0;
    max-height: 100vh;
    /* El sidebar toca el borde físico de la pantalla: en un plegable en
       horizontal ahí puede estar la bisagra o el notch. */
    padding-left: env(safe-area-inset-left);
  }
  /* En escritorio la navegación está siempre a la vista: el botón que la abría
     no tiene nada que abrir. */
  .hamburguesa { display: none; }
}

/* La cuenta, arriba del todo. Antes vivía en la barra superior, donde en un
   teléfono no cabía un correo y se quedaba en una inicial suelta. */
.menu-cuenta {
  flex: none;
  padding: 0 18px 12px;
  border-bottom: 1px solid var(--linea);
}
.menu-cuenta[hidden] { display: none; }
.menu-cuenta-fila { display: flex; align-items: center; gap: 10px; }
.menu-avatar {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--borde-vivo);
  background: var(--fondo-activo);
  color: var(--texto-medio);
  font-family: var(--mono);
  font-size: 11px;
}

/* Al pie, de quién se está hablando. El sistema entero mira a una persona y en
   ninguna pantalla se decía cuál; con dos clientes en el mismo panel eso deja
   de ser un detalle. Va en ámbar tenue: es lo medido, el sujeto del sistema. */
.menu-pie { margin-top: auto; padding: 12px 12px 0; flex: none; }
.menu-persona {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 8px 10px 10px;
  border: 1px solid var(--senal-suave);
  border-radius: var(--radio);
  background: linear-gradient(180deg, var(--senal-suave), transparent);
}
.menu-persona-inicial {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--borde-aviso);
  background: var(--fondo-activo);
  color: var(--senal);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
}
.menu-persona-datos { flex: 1; min-width: 0; }
.menu-persona-datos b {
  display: block;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--texto);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.menu-persona-rotulo {
  display: block;
  margin-top: 2px;
  font-size: 9.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}

/* Qué se está mirando, en la cabecera. Con el menú cerrado la marca es la
   misma en las catorce pantallas y no había nada que dijera dónde estás. */
.cabecera-vista {
  /* Aire antes de la hamburguesa: el rótulo llegaba a tocarla. */
  margin-right: 10px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--texto-tenue);
  white-space: nowrap;
}

.insignia {
  min-width: 18px;
  padding: 1px 6px;
  border-radius: 9px;
  background: var(--senal-suave);
  color: var(--senal);
  font-family: var(--mono);
  font-size: 10.5px;
  text-align: center;
}
.insignia--alerta { background: var(--tinte-error); color: var(--estado-error); }

.vista { display: flex; flex-direction: column; gap: 22px; }
.vista[hidden] { display: none; }

/* --- Filtros ------------------------------------------------------------- */

/* Fila de filtros.
   Era un flex con la etiqueta a la izquierda de cada control: al envolver,
   cada celda medía distinto —«Orden» junto a «Por alcance» ocupa otra cosa
   que «Plataforma» junto a «Todas»— y la segunda línea nunca coincidía con
   la primera. Rejilla de columnas iguales y etiqueta encima: todos los
   controles empiezan y terminan en la misma vertical, envuelvan o no, y la
   estructura es la misma en escritorio y en móvil. */
.filtros {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(172px, 1fr));
  gap: 12px 14px;
  align-items: end;
  padding: 14px 18px;
  border-bottom: 1px solid var(--borde);
}

.filtros label,
.filtros .campo-fecha {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  min-width: 0;
  font-size: 11px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}

.filtro-rotulo {
  font-size: 11px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}

/* Un solo alto para todo lo que se pueda pulsar en la fila: selectores,
   buscador y el disparador de fecha. Sin esto el calendario sobresalía dos
   píxeles y la fila se veía torcida sin que se supiera por qué. */
.filtros select,
.filtros input,
.filtros .fecha-disparador {
  width: 100%;
  height: 36px;
  box-sizing: border-box;
  background: var(--fondo-hundido);
  color: var(--texto);
  border: 1px solid var(--borde-vivo);
  border-radius: var(--radio-chico);
  padding: 0 11px;
  font-family: var(--sans);
  font-size: 13px;
  letter-spacing: 0;
  text-transform: none;
}
.filtros .fecha-disparador { justify-content: space-between; }
.filtros select:focus-visible,
.filtros input:focus-visible { outline: 2px solid var(--senal); outline-offset: 1px; }

/* --- Menciones -------------------------------------------------------------

   Tres capas, de lo que casi nunca se toca a lo que se toca todo el rato:
   ámbito (pestañas anchas, como el resto del panel), periodo y chips de
   primera (segmentado y píldoras), y la hoja de filtros finos —red y
   postura exactas— que se abre a demanda. */


.ambito-opcion {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 11px 4px;
  margin-right: 18px;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--texto-tenue);
  font: inherit;
  font-size: 13.5px;
  white-space: nowrap;
  cursor: pointer;
}
.ambito-opcion b {
  font-family: var(--mono);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: inherit;
}
.ambito-opcion:hover { color: var(--texto-medio); }
.ambito-opcion[aria-selected="true"] {
  border-bottom-color: var(--senal);
  color: var(--texto);
  font-weight: 600;
}

/* Fila única de Menciones: pestañas de ámbito a la izquierda, periodo en
   mono a la derecha, compartiendo el filete inferior. Del mockup. */
.fila-ambitos {
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid var(--linea);
  margin-bottom: 0;
}
.ambitos-tabs { display: flex; }
.ambitos-relleno { flex: 1; }
.periodo-mini { display: flex; align-items: center; gap: 10px; padding: 0 2px; }
.periodo-mini-op {
  padding: 10px 0;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--texto-tenue);
  cursor: pointer;
}
.periodo-mini-op[aria-pressed="true"] { color: var(--senal); }

/* La bandera de vigilancia, en la cabecera, solo cuando Menciones está
   abierta. Ámbar de aviso, como el mockup. */
.cabecera-vigilancia {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 6px;
  background: none;
  border: none;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--estado-warning);
  cursor: pointer;
}
.cabecera-vigilancia[hidden] { display: none; }
.cabecera-vigilancia .insignia-vigilancia { font-weight: 600; }
.segmentado--chico .segmentado-opcion { min-height: 30px; padding: 4px 8px; font-size: 11.5px; }

/* El acceso a vigilancia, compacto: era un botón de texto entero al final de
   la fila de filtros, y aquí compite con mucho menos espacio. */
.boton-vigila {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: none;
  min-height: 34px;
  padding: 0 11px;
  background: none;
  border: 1px solid var(--borde-vivo);
  border-radius: var(--radio-chico);
  color: var(--estado-warning);
  cursor: pointer;
}
.boton-vigila:hover { border-color: var(--borde-aviso); }
.boton-vigila .insignia-vigilancia {
  font-family: var(--mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

.menciones-chips {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}
.chips-desplazables {
  flex: 1;
  min-width: 0;
  display: flex;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
}
.chips-desplazables::-webkit-scrollbar { display: none; }
.chip-filtro {
  flex: none;
  padding: 6px 12px;
  border-radius: 999px;
  background: none;
  border: 1px solid var(--borde-vivo);
  color: var(--texto-tenue);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
}
.chip-filtro:hover { color: var(--texto-medio); }
.chip-filtro[aria-pressed="true"] {
  background: var(--fondo-activo);
  border-color: var(--senal);
  color: var(--texto);
}
.chip-mas {
  flex: none;
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: none;
  border: 1px solid var(--borde-vivo);
  color: var(--texto-tenue);
  font-size: 13px;
  cursor: pointer;
}
.chip-mas:hover { color: var(--texto-medio); border-color: var(--borde-aviso); }

.menciones-contador {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 10px;
}
.menciones-contador .panel-nota { flex: 1; }
.menciones-orden {
  flex: none;
  background: none;
  border: none;
  padding: 0;
  color: var(--texto-medio);
  font: inherit;
  font-size: 11.5px;
  cursor: pointer;
}
.menciones-orden:hover { color: var(--texto); }

.menciones-cargar-mas { display: block; width: 100%; margin-top: 12px; }
.menciones-cargar-mas[hidden] { display: none; }

/* --- Cada mención ----------------------------------------------------------
   Se lee en dos tiempos: quién, cuándo y qué dice —siempre a la vista— y por
   qué se interpretó así —plegado, porque es la prueba, no el titular—. */

.menciones {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.mencion {
  padding: 13px 16px;
  background: var(--fondo-elevado);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  display: flex;
  flex-direction: column;
  gap: 9px;
}
/* El canto en rojo tenue: tóxica o de una cuenta vigilada. Es lo que permite
   escanear la columna sin leer, igual que en Monitoreo. */
.mencion[data-alerta="true"] { border-color: var(--borde-error); }

.mencion-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--texto-tenue);
}
.mencion-red {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--texto-medio);
}
.mencion-red .icono-red { flex: none; }
.mencion-autor { color: var(--texto-medio); }
.mencion-relleno { flex: 1; }
.mencion-fecha { font-variant-numeric: tabular-nums; }

.mencion-texto { margin: 0; font-size: 13px; line-height: 1.55; color: var(--texto); }
.mencion-texto a { color: var(--senal); }
.mencion-texto--resto { white-space: pre-wrap; }
.mencion-vermas {
  align-self: flex-start;
  background: none;
  border: none;
  padding: 0;
  color: var(--ia);
  font: inherit;
  font-size: 11px;
  cursor: pointer;
}
.mencion-vermas:hover { text-decoration: underline; }

/* La portada del vídeo va en su propia fila, pequeña: es la referencia
   visual del origen, no el protagonista de la tarjeta. */
.mencion > .miniatura { width: 128px; aspect-ratio: 16/9; }

.mencion-postura-fila {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.mencion-alcance {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--texto-tenue);
  white-space: nowrap;
}
.mencion-chevron {
  flex: none;
  background: none;
  border: none;
  padding: 0;
  color: var(--texto-tenue);
  font-family: var(--mono);
  font-size: 10.5px;
  cursor: pointer;
}
.mencion-chevron:hover { color: var(--texto-medio); }

.mencion-detalle {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 9px;
  border-top: 1px dashed var(--borde);
}
/* `[hidden]` pierde contra cualquier regla `display` de la hoja: la regla
   compañera va siempre al lado, o el detalle se ve aunque esté plegado. */
.mencion-detalle[hidden] { display: none; }
.mencion-detalle .confianza { font-size: 10.5px; }
.mencion-vector { margin-left: auto; }
.mencion-original { align-self: flex-start; font-size: 11px; }

@media (max-width: 620px) {
  .mencion > .miniatura { width: 100%; }
}

.etiqueta {
  padding: 2px 8px;
  border-radius: 20px;
  border: 1px solid var(--borde-vivo);
  font-size: 10.5px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--texto-medio);
}
.etiqueta--support   { border-color: var(--borde-exito); color: var(--estado-success); }
.etiqueta--oppose    { border-color: var(--borde-error); color: var(--estado-error); }
.etiqueta--mixed     { border-color: var(--borde-aviso); color: var(--estado-warning); }
.etiqueta--toxica    { border-color: var(--borde-error);  color: var(--estado-error); }
/* Dos palabras que no deben partirse: en la fila de metadatos, que ya envuelve,
   la etiqueta baja entera antes que quebrarse por la mitad. */
.etiqueta--pendiente { border-style: dashed; white-space: nowrap; }

.marcos { display: flex; flex-wrap: wrap; gap: 6px; }
.marco {
  padding: 2px 8px;
  border-radius: var(--radio-chico);
  background: var(--senal-suave);
  color: var(--senal);
  font-size: 11px;
}

/* El porqué de la postura, en palabras del modelo. Tenue a propósito: es
   la prueba de la lectura, no el titular -si compitiera visualmente con
   la postura misma, la tarjeta se leería dos veces. */
.mencion-rationale {
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--texto-tenue);
  margin: 0;
}

.alcance { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* --- Monitoreo (Alertas) ---------------------------------------------------

   Se lee por severidad, no por fecha: lo crítico va arriba porque es lo que
   hace falta ver primero, no lo más nuevo. Cada tarjeta lleva su color en el
   borde y en el rótulo del grupo que la contiene, para no repetir una
   etiqueta de severidad en cada una. */

.hallazgos-grupo + .hallazgos-grupo { margin-top: 20px; }
.hallazgos-grupo-rotulo {
  margin: 0 0 9px;
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--texto-medio);
}
.hallazgos-grupo-rotulo--critical,
.hallazgos-grupo-rotulo--high { color: var(--estado-error); }
.hallazgos-grupo-rotulo--medium { color: var(--estado-warning); }
.hallazgos-grupo-rotulo--info { color: var(--texto-tenue); }

.hallazgos-lista { display: flex; flex-direction: column; gap: 10px; }

.hallazgo {
  padding: 14px 16px;
  background: var(--fondo-elevado);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  display: grid;
  gap: 10px;
}
.hallazgo[data-severidad="critical"] {
  border-color: var(--borde-error);
  box-shadow: 0 0 0 1px var(--tinte-error-suave);
}
.hallazgo[data-severidad="high"] { border-color: var(--borde-error); }
.hallazgo[data-severidad="medium"] { border-color: var(--borde-aviso); }

.hallazgo-cabecera { display: flex; align-items: baseline; gap: 10px; justify-content: space-between; }
.hallazgo-titulo { margin: 0; font-size: 14px; font-weight: 600; line-height: 1.4; color: var(--texto); }
.hallazgo[data-severidad="critical"] .hallazgo-titulo { font-size: 15px; }
.hallazgo-fecha {
  flex: none;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--texto-tenue);
  white-space: nowrap;
}
.hallazgo-resumen { margin: 0; font-size: 12.5px; color: var(--texto-medio); line-height: 1.55; }

.hallazgo-accion {
  margin: 0;
  display: flex;
  gap: 9px;
  align-items: flex-start;
  padding: 9px 12px;
  background: var(--senal-suave);
  border: 1px solid var(--borde-aviso);
  border-radius: var(--radio-chico);
}
.hallazgo-accion-flecha { flex: none; color: var(--senal); font-size: 12px; }
.hallazgo-accion p { margin: 0; font-size: 12px; line-height: 1.5; color: var(--texto); }

/* Barra de confianza: la cifra sola se lee como certeza. */
.confianza { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--texto-tenue); }
.confianza-barra { width: 56px; height: 4px; border-radius: 2px; background: var(--fondo-hundido); overflow: hidden; }
/* `display: block`: es un <span>, y en inline el ancho y el alto se ignoran.
   La barra se pintaba siempre vacía. */
.confianza-relleno { display: block; height: 100%; background: var(--senal); }

/* La evidencia, plegada: son las menciones concretas que sostienen el
   resumen, y se piden solo al abrir para no pagar la petición si nadie mira. */
.hallazgo-evidencia { border-top: 1px dashed var(--borde); padding-top: 9px; }
.hallazgo-evidencia > summary {
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  list-style: none;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--texto-medio);
}
.hallazgo-evidencia > summary::-webkit-details-marker { display: none; }
.hallazgo-evidencia > summary::before {
  content: '▸';
  color: var(--texto-tenue);
  transition: transform .15s ease;
}
.hallazgo-evidencia[open] > summary::before { transform: rotate(90deg); }
.hallazgo-evidencia > summary:hover { color: var(--texto); }
.hallazgo-evidencia-cuerpo { margin-top: 8px; display: flex; flex-direction: column; gap: 7px; }
.hallazgo-evidencia-cargando { margin: 0; font-size: 11.5px; color: var(--texto-tenue); }
.hallazgo-evidencia-fila {
  padding: 8px 11px;
  background: var(--fondo-hundido);
  border: 1px solid var(--borde);
  border-radius: var(--radio-chico);
}
.hallazgo-evidencia-meta {
  display: flex;
  gap: 7px;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--texto-tenue);
}
.hallazgo-evidencia-red {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  text-transform: uppercase;
  color: var(--texto-medio);
}
.hallazgo-evidencia-fecha { margin-left: auto; }
.hallazgo-evidencia-texto { margin: 5px 0 0; font-size: 11.5px; line-height: 1.45; color: var(--texto-medio); }
.hallazgo-evidencia-ir {
  align-self: flex-start;
  font-size: 11px;
  color: var(--senal);
  text-decoration: none;
}
.hallazgo-evidencia-ir:hover { text-decoration: underline; }

/* El pie de la tarjeta: la única parte que cambia según el estado. */
.hallazgo-pie { display: flex; align-items: center; gap: 8px; border-top: 1px solid var(--linea); padding-top: 9px; }
.hallazgo-pie-relleno { flex: 1; }
.hallazgo-marcar {
  background: none;
  border: 0;
  padding: 0;
  color: var(--texto-medio);
  font: inherit;
  font-size: 11.5px;
  cursor: pointer;
}
.hallazgo-marcar:hover { color: var(--texto); }
.hallazgo-estado-chip {
  font-size: 11px;
  color: var(--estado-warning);
}
.hallazgo-cierre {
  margin: 0;
  font-size: 11px;
  line-height: 1.5;
  color: var(--texto-tenue);
}
.hallazgo-cierre strong { color: var(--texto); }

/* El campo de nota, en línea. Una frase no necesita un formulario aparte. */
.hallazgo-nota-fila { display: flex; gap: 8px; align-items: center; flex: 1; flex-wrap: wrap; }
.hallazgo-nota-input {
  flex: 1;
  min-width: 160px;
  padding: 8px 11px;
  background: var(--fondo-hundido);
  border: 1px solid var(--borde-vivo);
  border-radius: var(--radio-chico);
  color: var(--texto);
  font: inherit;
  font-size: 11.5px;
}
.hallazgo-nota-input:focus-visible { outline: 2px solid var(--senal); outline-offset: 1px; }
.hallazgo-nota-ok {
  padding: 0 14px;
  height: 34px;
  background: var(--tinte-exito);
  border: 1px solid var(--borde-exito);
  border-radius: var(--radio-chico);
  color: var(--estado-success);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}
.hallazgo-nota-cancelar {
  background: none;
  border: 0;
  padding: 0;
  color: var(--texto-tenue);
  font: inherit;
  font-size: 11px;
  cursor: pointer;
}
.hallazgo-nota-cancelar:hover { color: var(--texto-medio); }

/* --- Series -------------------------------------------------------------- */

/* Una red a la vez: las pestañas lo dejan elegir sin obligar a comparar las
   cuatro apiladas. El neto va dentro de cada una, en su color, para que
   cambiar de canal no sea un salto a ciegas. */
.canales-tabs {
  display: flex;
  gap: 6px;
  margin-bottom: 14px;
  /* Sin scroll: las pestañas reparten el ancho, como el mockup. Cuatro redes
     caben; si un día hay siete, se decide entonces, no se esconde hoy. */
}
.canal-tab {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 9px 4px;
  background: none;
  border: 1px solid var(--borde);
  border-radius: 10px;
  color: var(--texto-tenue);
  font: inherit;
  cursor: pointer;
}
.canal-tab svg { flex: none; }
.canal-tab span { font-size: 12px; }
.canal-tab b {
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--texto-tenue);
}
.canal-tab:hover { border-color: var(--borde-vivo); color: var(--texto-medio); }
/* Activa: fondo elevado y borde vivo, no ámbar. El color solo lo lleva el
   neto de la pestaña elegida; en las demás va apagado, como el mockup. */
.canal-tab[aria-selected="true"] {
  background: var(--fondo-activo);
  border-color: var(--borde-vivo);
  color: var(--texto);
}
.canal-tab[aria-selected="true"] b { color: var(--texto); }
.canal-tab[aria-selected="true"] b[data-tono="alerta"] { color: var(--estado-error); }
.canal-tab[aria-selected="true"] b[data-tono="bien"]   { color: var(--estado-success); }

/* Una columna, no una cuadrícula: en Indicadores cada fila se lee de arriba
   abajo por severidad de un vistazo, y en Redes sociales ya solo se enseña
   una tarjeta de canal a la vez —la que eligió la pestaña—, así que la
   cuadrícula de antes no tenía nada más que repartir. */
.series { display: flex; flex-direction: column; gap: 8px; }
.serie {
  position: relative;
  padding: 18px;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--fondo-elevado);
}
/* Serie con muestra insuficiente: se atenúa entera y se marca el canto. Un
   50% sobre dos menciones no puede tener el mismo peso visual que uno sobre
   doscientas —era el fallo más grave de esta vista—. */
.serie[data-flojo="true"] { background: var(--tinte-aviso-suave); }

/* Padding movido a la fila y al cuerpo: en un `<details>` el padding del
   contenedor entero separaría la cabecera del borde superior tanto plegada
   como abierta, y una lista de siete filas pegadas al borde se lee más densa
   que una con aire solo donde hace falta —dentro de la que está abierta—. */
.serie { padding: 0; overflow: hidden; }

.serie-resumen {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 10px 14px;
  cursor: pointer;
  list-style: none;
}
.serie-resumen::-webkit-details-marker { display: none; }
.serie-resumen:hover { background: var(--fondo-activo); }
.serie-resumen:focus-visible { outline: 2px solid var(--senal); outline-offset: -2px; }

/* El punto: lo único que hace falta mirar para saber si esta fila pide
   atención antes de leer una palabra. Gris cuando no hay nada que decir. */
.serie-punto-fila {
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  background: var(--texto-tenue);
}
.serie-punto-fila[data-juicio="bien"] { background: var(--estado-success); }
.serie-punto-fila[data-juicio="mal"]  { background: var(--estado-error); }

.serie-pregunta {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: 12.5px;
  color: var(--texto);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Plegada, la pregunta se recorta para que la fila quepa en una línea;
   abierta, se suelta entera: el mismo toque que abre la serie es el que
   pide leerla completa. */
.serie[open] .serie-pregunta {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
}

.serie-valor-fila {
  flex: none;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 14px;
  font-weight: 600;
  color: var(--texto);
}
.serie-valor-fila[data-juicio="bien"] { color: var(--estado-success); }
.serie-valor-fila[data-juicio="mal"]  { color: var(--estado-error); }

.serie-chevron {
  flex: none;
  width: 10px;
  color: var(--texto-tenue);
}
.serie-chevron::before { content: '▸'; }
.serie[open] .serie-chevron::before { content: '▾'; }

.serie-cuerpo { padding: 0 14px 16px; }
.serie-nombre-tecnico {
  margin: 0 0 4px;
  font-size: 10px;
  color: var(--texto-tenue);
}

.serie-cabecera { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.serie-nombre { margin: 0; font-size: 12px; letter-spacing: .04em; color: var(--texto-medio); }
.serie-cifra { display: flex; align-items: baseline; gap: 9px; flex: none; }
.serie-valor {
  font-family: var(--mono);
  font-size: 30px;
  font-weight: 500;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 22px var(--senal-suave);
}
/* La variación juzga: en toxicidad subir es malo y en sentimiento es bueno.
   El mismo triángulo verde para todo enseñaría lo contrario de lo que pasa. */
.serie-delta {
  font-family: var(--mono);
  font-size: 11px;
  padding: 2px 7px;
  border-radius: 20px;
  border: 1px solid var(--borde-vivo);
  white-space: nowrap;
}
.serie-delta[data-juicio="bien"] { color: var(--estado-success); border-color: var(--borde-exito); }
.serie-delta[data-juicio="mal"]  { color: var(--estado-error);   border-color: var(--borde-error); }
.serie-delta[data-juicio="neutro"] { color: var(--texto-medio); }

.serie-grafico { display: block; width: 100%; height: 92px; margin-top: 12px; overflow: visible; }

/* Color por naturaleza del indicador, no por decoración. */
.serie-linea { fill: none; stroke-width: 1.6; stroke-linejoin: round; }
.serie-linea--neutro     { stroke: var(--texto-medio); }
.serie-linea--divergente { stroke: var(--estado-success); }
.serie-linea--alarma     { stroke: var(--estado-error); }
.serie-area { stroke: none; }
.serie-area--neutro     { fill: var(--tinte-neutro); }
.serie-area--divergente { fill: var(--tinte-exito); }
.serie-area--alarma     { fill: var(--tinte-error-suave); }
.serie-punto--neutro     { fill: var(--texto); }
.serie-punto--divergente { fill: var(--estado-success); }
.serie-punto--alarma     { fill: var(--estado-error); }

/* Referencias del gráfico: sin una mediana y un cero, una línea que sube no
   dice si está alta o baja PARA ESTA serie. */
.serie-mediana {
  stroke: var(--borde-vivo);
  stroke-width: 1;
  stroke-dasharray: 3 4;
  opacity: .7;
}
.serie-cero { stroke: var(--texto-tenue); stroke-width: 1; opacity: .6; }
.serie-extremo { fill: none; stroke-width: 1.2; }
.serie-extremo--max { stroke: var(--senal); }
.serie-extremo--min { stroke: var(--texto-tenue); }
/* Puntos calculados sobre muestra insuficiente, marcados sobre la línea. */
.serie-flojo { fill: var(--estado-warning); opacity: .85; }
.serie-eje {
  fill: var(--texto-tenue);
  font-family: var(--mono);
  font-size: 7.5px;
  letter-spacing: .04em;
}

/* Fila de datos duros bajo el gráfico. */
.serie-datos {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--linea);
}
.serie-dato { display: flex; flex-direction: column; gap: 2px; }
.serie-dato-et {
  font-family: var(--mono);
  font-size: 8.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}
.serie-dato-v {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--texto);
  font-variant-numeric: tabular-nums;
}

.serie-aviso {
  margin: 10px 0 0;
  padding: 8px 11px;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--estado-warning);
  border: 1px solid var(--borde-aviso);
  border-radius: var(--radio-chico);
  background: var(--tinte-aviso-suave);
}
.serie-pie { margin: 8px 0 0; font-size: 11px; color: var(--texto-tenue); }

/* --- Tabla --------------------------------------------------------------- */

/* La caja ya tenía scroll horizontal, pero la tabla era `width: 100%` y por
   tanto nunca lo usaba: en vez de desbordar, comprimía. El resultado era una
   columna de consultas partiendo URLs a tres letras por línea y filas de
   ciento veinte píxeles de alto. Con un ancho mínimo, la tabla se mantiene
   legible y es la caja la que se desplaza. */
.tabla-caja { overflow-x: auto; }
.tabla { width: 100%; min-width: 860px; border-collapse: collapse; font-size: 13px; }

/* Una línea por celda. La consulta puede ser una URL larga o un booleano de
   tres cláusulas: se recorta y el texto completo queda en el tooltip. */
.tabla td { white-space: nowrap; }
.tabla td .tabla-consulta {
  max-width: 34ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Los botones se separan con margen y no con `display: flex` en la celda:
   un `td` en flex deja de ser celda de tabla y se sale de la rejilla —los
   botones aparecían fuera del panel, a la derecha del borde—. En móvil, donde
   la tabla ya no es tabla sino fichas, sí puede ser flex. */
.tabla-acciones .boton + .boton { margin-left: 8px; }
.tabla th {
  text-align: left;
  padding: 11px 18px;
  font-size: 10.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--texto-tenue);
  font-weight: 500;
  border-bottom: 1px solid var(--borde);
  white-space: nowrap;
}
.tabla td { padding: 12px 18px; border-bottom: 1px solid var(--linea); vertical-align: top; }
.tabla .num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }
.tabla-consulta { color: var(--texto-medio); font-family: var(--mono); font-size: 11.5px; overflow-wrap: anywhere; }
.tabla-error { color: var(--estado-error); font-size: 11.5px; }

/* En vertical una tabla de siete columnas no cabe de ninguna manera, y un
   scroll lateral en móvil esconde la mitad de los datos. Cada fila pasa a ser
   una ficha con sus rótulos, que es como se lee de todos modos en el pulgar. */
@media (max-width: 820px) {
  .tabla { min-width: 0; }
  .tabla thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .tabla, .tabla tbody, .tabla tr, .tabla td { display: block; }
  .tabla tr {
    padding: 14px 18px;
    border-bottom: 1px solid var(--linea);
  }
  .tabla td {
    display: grid;
    grid-template-columns: 92px minmax(0, 1fr);
    gap: 10px;
    align-items: baseline;
    padding: 3px 0;
    border: none;
    white-space: normal;
  }
  .tabla td::before {
    content: attr(data-rotulo);
    font-size: 10.5px;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--texto-tenue);
  }
  /* Todo el contenido de la celda va a la columna del valor. Sin esto, una
     celda con dos hijos —el nombre de la fuente y su «x · search»— empujaba
     el segundo a una fila nueva, bajo el rótulo. */
  .tabla td > * { grid-column: 2; }
  .tabla td .tabla-consulta { max-width: none; white-space: normal; }
  /* Las etiquetas de estado son chips, no barras: sin esto se estiran hasta
     el borde derecho y «OK» queda dentro de una cápsula de 300 px. */
  .tabla td .etiqueta { justify-self: start; }
  .tabla .num { text-align: left; }
  /* Sube la especificidad: `.tabla td { display: grid }` gana por sí solo a
     `.tabla-acciones` y dejaría los dos botones uno encima de otro. */
  .tabla td.tabla-acciones { display: flex; gap: 8px; margin-top: 8px; }
  .tabla td.tabla-acciones .boton + .boton { margin-left: 0; }
  .tabla td.tabla-acciones::before { display: none; }
  .tabla td.tabla-acciones .boton { flex: 1; justify-content: center; }
}

/* --- Ficha de Persona ---------------------------------------------------- */

.ficha { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.campo { padding: 15px 18px; border-top: 1px solid var(--linea); border-right: 1px solid var(--linea); }
.campo-nombre { margin: 0 0 6px; font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--texto-tenue); }
.campo-valor { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--texto); }
.campo-valor--vacio { color: var(--texto-tenue); font-style: italic; }
.campo-lista { display: flex; flex-wrap: wrap; gap: 6px; }

.aviso--fijo { border-top: none; border-bottom: 1px solid var(--borde); }

/* --- Vacíos -------------------------------------------------------------- */

.vacio { padding: 34px 18px; text-align: center; color: var(--texto-tenue); font-size: 13px; line-height: 1.6; }
.vacio b { color: var(--texto-medio); font-weight: 500; }


/* --- Barra de posturas ---------------------------------------------------- */

.barra {
  display: flex;
  height: 8px;
  margin-top: 12px;
  border-radius: 4px;
  overflow: hidden;
  background: var(--fondo-hundido);
}
.barra-tramo { transition: width .3s ease; }
.barra-tramo--support   { background: var(--estado-success); }
.barra-tramo--neutral   { background: var(--estado-idle); }
.barra-tramo--mixed     { background: var(--estado-warning); }
.barra-tramo--unrelated { background: var(--borde-vivo); }
.barra-tramo--oppose    { background: var(--estado-error); }


/* --- Presupuesto ------------------------------------------------------------

   Una barra por categoría, coloreada por el mismo semáforo que los avisos
   de Telegram: verde hasta el 75%, ámbar hasta el 95%, roja de ahí en
   adelante -no hay un cuarto color al tocar el tope porque la barra ya
   está llena, el mensaje de "en pausa" es lo que lo dice-. */

.presupuesto-fila { margin-bottom: 14px; }
.presupuesto-fila:last-child { margin-bottom: 0; }
.presupuesto-cabecera {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  font-size: 12.5px;
}
.presupuesto-nombre { font-weight: 600; }
.presupuesto-cifra { color: var(--texto-tenue); font-variant-numeric: tabular-nums; }
.presupuesto-barra {
  height: 6px;
  margin-top: 4px;
  border-radius: 3px;
  overflow: hidden;
  background: var(--fondo-hundido);
}
.presupuesto-relleno { display: block; height: 100%; transition: width .3s ease; }
.presupuesto-relleno[data-nivel="normal"] { background: var(--estado-success); }
.presupuesto-relleno[data-nivel="alerta"] { background: var(--estado-warning); }
.presupuesto-relleno[data-nivel="riesgo"] { background: var(--estado-error); }
.presupuesto-vital {
  font-size: 10.5px;
  color: var(--texto-tenue);
  margin-top: 2px;
}
.presupuesto-editar {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
}
.presupuesto-editar input {
  width: 72px;
  padding: 3px 6px;
  font-size: 12.5px;
  font-family: var(--mono);
}
.presupuesto-editar .boton { padding: 4px 10px; font-size: 12px; }


/* --- Temas en seguimiento ------------------------------------------------- */

.tema-nuevo { margin-bottom: 14px; }
.tema-nuevo textarea {
  width: 100%;
  padding: 6px 8px;
  font-size: 12.5px;
  font-family: inherit;
  resize: vertical;
}
.tema-nuevo-pie {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  font-size: 12px;
  color: var(--texto-tenue);
}
.tema-nuevo-pie input {
  width: 60px;
  padding: 3px 6px;
  font-size: 12.5px;
  font-family: var(--mono);
}
.tema-nuevo-pie .boton { padding: 4px 10px; font-size: 12px; margin-left: auto; }

.tema-fila {
  padding: 10px 0;
  border-top: 1px solid var(--borde-tenue);
}
.tema-fila[data-estado="cerrado"],
.tema-fila[data-estado="vencido"] { opacity: .6; }
.tema-cabecera {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}
.tema-texto { font-size: 12.5px; font-weight: 600; }
.tema-estado {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--texto-tenue);
  white-space: nowrap;
}
.tema-meta {
  font-size: 10.5px;
  color: var(--texto-tenue);
  margin-top: 2px;
}
/* El análisis viene con saltos de línea desde el servidor y ahí está su
   estructura -riesgo, qué hacer, frase sugerida-: sin `pre-wrap` se
   aplasta en un párrafo y deja de leerse como lo que es. */
.tema-analisis {
  font-size: 11.5px;
  line-height: 1.5;
  margin-top: 6px;
  padding: 6px 8px;
  border-radius: 4px;
  background: var(--fondo-hundido);
  white-space: pre-wrap;
}
.tema-hallazgo {
  display: flex;
  gap: 6px;
  align-items: baseline;
  font-size: 11.5px;
  margin-top: 4px;
}
.tema-hallazgo-origen {
  flex: none;
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: .04em;
  padding: 1px 5px;
  border-radius: 3px;
  background: var(--fondo-hundido);
  color: var(--texto-tenue);
}
/* Lo que le llega a ella directo se distingue de la cobertura de prensa:
   son cosas distintas y el color es lo único que lo dice de un vistazo. */
.tema-hallazgo[data-origen="propia"] .tema-hallazgo-origen,
.tema-hallazgo[data-origen="mencion"] .tema-hallazgo-origen {
  background: var(--estado-warning);
  color: var(--fondo);
}
.tema-fila .boton { margin-top: 8px; padding: 4px 10px; font-size: 12px; }


/* --- Vídeos --------------------------------------------------------------- */

/* Cada aparición es una pieza cerrada, no una fila de una lista.
   Separadas por una línea de un píxel, y con cinco secciones plegables
   dentro que dibujan sus propias líneas, no se distinguía dónde acababa un
   vídeo y empezaba el siguiente: todo parecía la misma retahíla de rótulos.
   Van sobre un fondo hundido y separadas, así que el límite lo marca el aire
   y el contraste en vez de un borde —que es lo que se pidió evitar—. */
/* Las definiciones de `.videos`/`.video` viven junto al resto de la vista,
   más abajo. Aquí hubo una pareja anterior —fondo hundido con padding y
   tarjeta en rejilla— que se pisaba con la del mockup y comprimía las
   tarjetas dentro de un marco que el rediseño no tiene. */
.videos { display: flex; flex-direction: column; gap: 10px; }

/* Dos líneas y corta. Con diecinueve apariciones, un resumen largo por ficha
   convierte el listado en un documento: hay que hacer scroll para ver de qué
   va la siguiente. Dos bastan para decidir si te detienes; el resto está a un
   clic. */
.video-resumen--recorte {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Fila bajo el resumen: la acción a la izquierda, la firma del motor a la
   derecha. */
.video-pie-resumen {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.firma-ia {
  font-family: var(--mono);
  font-size: 8.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ia);
  opacity: .65;
}
/* Doble clase para ganarle a `.ia-marco::after`, que se declara más abajo en
   la hoja: a igual especificidad manda el último, y la firma salía dos veces. */
.ia-marco.ia-marco--sin-firma::after { content: none; }

.video-mas {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12px;
  color: var(--senal);
  cursor: pointer;
}
.video-mas:hover { text-decoration: underline; }

/* --- Secciones plegables de la ficha de vídeo ----------------------------- */

.seccion { border-top: 1px solid var(--linea); }
.seccion > summary {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 9px 0;
  cursor: pointer;
  list-style: none;
  font-size: 12px;
}
.seccion > summary::-webkit-details-marker { display: none; }
.seccion > summary::before {
  content: '▸';
  color: var(--senal);
  font-size: 10px;
}
.seccion[open] > summary::before { content: '▾'; }
.seccion-titulo {
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}
/* La pista va a la derecha y en tono menor: informa del contenido cerrado sin
   competir con el rótulo de la sección. */
.seccion-pista {
  margin-left: auto;
  font-size: 11.5px;
  color: var(--texto-medio);
  text-align: right;
}
.seccion-cuerpo { padding: 4px 0 14px; }

/* Barras de desempeño: la cifra sola invita a leerla como medición. */
/* Seis dimensiones en 3×2. Con `auto-fit` el número de columnas dependía del
   ancho sobrante y una fila podía quedar con un solo elemento colgando. */
.desempeno { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px 20px; }
@media (max-width: 620px) { .desempeno { grid-template-columns: repeat(2, 1fr); } }
.dim { display: grid; gap: 4px; }
.dim-nombre { font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--texto-tenue); }
.dim-fila { display: flex; align-items: center; gap: 8px; }
.dim-barra { flex: 1; height: 4px; border-radius: 2px; background: var(--fondo-hundido); overflow: hidden; }
.dim-relleno { display: block; height: 100%; background: var(--estado-success); }
/* La evasión se lee al revés: más alta es peor. */
.dim[data-invertida="true"] .dim-relleno { background: var(--estado-error); }
.dim-valor { font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums; color: var(--texto); }

.listas { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
@media (max-width: 720px) { .listas { grid-template-columns: 1fr; } }
.lista-titulo { margin: 0 0 6px; font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--texto-tenue); }
.lista { margin: 0; padding-left: 18px; font-size: 13px; line-height: 1.55; color: var(--texto-medio); }
.lista li + li { margin-top: 6px; }
.lista--debil li::marker { color: var(--estado-error); }
.lista--fuerte li::marker { color: var(--estado-success); }

/* Momentos: la cita y su minuto, para poder verificar el juicio en la fuente. */
.momentos { display: grid; gap: 8px; }
.momento {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 12px;
  padding: 10px 12px;
  background: var(--senal-suave);
  border-radius: 0 var(--radio-chico) var(--radio-chico) 0;
}
/* Cian, no ámbar: el minuto lo eligió el modelo al citar. */
.momento-min { font-family: var(--mono); font-size: 12px; color: var(--ia); white-space: nowrap; }
.momento-cita { margin: 0; font-size: 13px; font-style: italic; }
.momento-por-que { margin: 4px 0 0; font-size: 12px; color: var(--texto-tenue); }

/* --- Tema claro -----------------------------------------------------------
 *
 * No es el oscuro invertido. Sobre blanco, el ámbar de señal (#e8b464) no
 * llega al contraste mínimo para texto, así que se oscurece a un ocre; los
 * estados también bajan de luminosidad para poder leerse. Las superficies son
 * papel cálido en vez de blanco puro, que sobre una pantalla grande deslumbra
 * en las mismas sesiones largas para las que se diseñó el modo oscuro.
 *
 * En claro sí hay sombras: sin ellas, sin el contraste del fondo oscuro, las
 * tarjetas se pierden contra la página.
 */

:root[data-tema="claro"] {
  --fondo:            #f2f5f8;
  --fondo-elevado:    #ffffff;
  --fondo-hundido:    #e8edf2;
  --borde:            #dde3ea;
  --borde-vivo:       #c3ccd6;

  --texto:            #14161b;
  --texto-medio:      #565d6a;
  --texto-tenue:      #6b7280;

  /* Ocre: mismo tono que el ámbar del modo oscuro, con luminosidad bajada
     hasta pasar el contraste sobre blanco. */
  --senal:            #9a640a;
  --senal-clara:      #7d5108;
  --fondo-campo:      #e9edf3;
  --sobre-senal:      #ffffff;
  --senal-suave:      rgba(154, 100, 10, 0.10);

  --estado-idle:      #a8aeb9;
  --estado-active:    #9a640a;
  --estado-success:   #1a7a4b;
  --estado-warning:   #96650d;
  --estado-error:     #b0322a;

  --linea:              rgba(20, 22, 27, 0.09);
  --fondo-activo:       #fdf7ec;
  /* Cognición del modelo en claro: el mismo cian bajado a tinta, porque el
     original es luz y sobre crema no contrasta (2,1:1). */
  --ia:               #176e84;
  --ia-suave:         rgba(23, 110, 132, 0.07);
  --ia-borde:         rgba(23, 110, 132, 0.30);
  --ia-brillo:        rgba(23, 110, 132, 0.12);
  --ia-texto:         #3d6b78;
  /* En claro la chapa va al revés: el nodo es más claro arriba y se apoya en
     un gris apenas más oscuro abajo. Copiar los valores del tema oscuro daría
     cajas negras sobre fondo crema. */
  --malla-linea-viva:   rgba(154, 100, 10, 0.075);
  --chapa-alto:         #ffffff;
  --chapa-bajo:         #eef2f6;
  --brillo-cabecera:    rgba(154, 100, 10, 0.045);
  --brillo-diagrama:    rgba(154, 100, 10, 0.05);
  --borde-exito:        rgba(26, 122, 75, 0.45);
  --borde-error:        rgba(176, 50, 42, 0.45);
  --borde-aviso:        rgba(150, 101, 13, 0.45);
  --tinte-exito:        rgba(26, 122, 75, 0.10);
  --tinte-error:        rgba(176, 50, 42, 0.12);
  --tinte-error-suave:  rgba(176, 50, 42, 0.05);
  --tinte-aviso:        rgba(150, 101, 13, 0.12);
  --tinte-aviso-suave:  rgba(150, 101, 13, 0.06);
  --tinte-neutro:       rgba(20, 22, 27, 0.05);
  --sombra:             0 1px 2px rgba(20, 22, 27, 0.05), 0 1px 8px rgba(20, 22, 27, 0.03);
  --sombra-pieza:       0 1px 2px rgba(20, 22, 27, 0.06), 0 6px 16px -10px rgba(20, 22, 27, 0.18);
}

/* Las superficies elevadas necesitan sombra en claro y ninguna en oscuro; la
   variable resuelve las dos sin duplicar reglas. */
.cifra, .panel { box-shadow: var(--sombra); }

/* --- Interruptor de tema ---------------------------------------------------
 *
 * Segmentado en vez de botón con etiqueta: se ven las dos opciones y cuál
 * está activa, sin una palabra compitiendo con el estado en vivo que tiene al
 * lado. El contorno es del mismo peso que el resto de bordes del panel para
 * que no reclame atención: es un ajuste, no una acción.
 */

/* El selector de tema vive ahora en Configuración › Interfaz y usa el
   componente `.segmentado`, así que no necesita estilos propios. */



/* --- Formularios ---------------------------------------------------------- */

.formulario { padding: 18px; border-top: 1px solid var(--borde); display: grid; gap: 16px; }
.form-titulo { margin: 0; font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--texto-tenue); }

.campos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 16px;
  /* Cada campo se ancla arriba de su fila. Sin esto, dos campos vecinos de
     alturas distintas —un textarea largo junto a uno corto— estiraban su
     etiqueta al alto de la fila y el campo bajo quedaba centrado: los
     rótulos alineados y los recuadros a distinta altura. */
  align-items: start;
}
.campo-ancho { grid-column: 1 / -1; }

.formulario label {
  display: grid;
  grid-template-rows: auto auto;
  align-content: start;
  gap: 6px;
  font-size: 11.5px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}
/* `[hidden]` pierde contra el `display: grid` de arriba: sin esto, el campo
   de días se ve aunque el tipo de informe no sea «a medida». */
.formulario label[hidden] { display: none; }

.formulario input,
.formulario select,
.formulario textarea {
  width: 100%;
  padding: 9px 11px;
  background: var(--fondo-hundido);
  color: var(--texto);
  border: 1px solid var(--borde-vivo);
  border-radius: var(--radio-chico);
  font-family: var(--sans);
  font-size: 13.5px;
  letter-spacing: 0;
  text-transform: none;
  resize: vertical;
}
.formulario input:focus-visible,
.formulario select:focus-visible,
.formulario textarea:focus-visible { outline: 2px solid var(--senal); outline-offset: 1px; }

/* La ayuda va bajo el campo y en minúscula: es contexto, no una etiqueta más. */
.ayuda { font-size: 11.5px; letter-spacing: 0; text-transform: none; color: var(--texto-tenue); line-height: 1.45; }
.ayuda b { color: var(--texto-medio); font-weight: 500; }

.boton {
  justify-self: start;
  padding: 9px 18px;
  border: 1px solid var(--senal);
  border-radius: var(--radio-chico);
  background: var(--senal-suave);
  color: var(--senal);
  font-family: var(--sans);
  font-size: 13px;
  cursor: pointer;
  transition: background-color .18s ease;
}
.boton:hover { background: transparent; }
.boton:focus-visible { outline: 2px solid var(--senal); outline-offset: 2px; }
.boton[disabled] { opacity: .5; cursor: progress; }

.boton--fantasma {
  border-color: var(--borde-vivo);
  background: transparent;
  color: var(--texto-medio);
  padding: 5px 10px;
  font-size: 12px;
}
.boton--fantasma:hover { border-color: var(--estado-error); color: var(--estado-error); }

/* «Grabar aquí»: no hereda el rojo al pasar el ratón —ahí `.boton--fantasma`
   significa cancelar— porque empezar a grabar no es una acción destructiva. */
.pauta-entradas { display: flex; gap: 8px; margin-bottom: 14px; }
.pauta-entrada {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 40px;
}
/* El formulario oculto no puede depender solo de [hidden]: tiene display
   propio. La regla de compañía de siempre. */
.formulario[hidden] { display: none; }

.boton--grabar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  width: 100%;
  margin-bottom: 14px;
}
.boton--grabar:hover { border-color: var(--senal); color: var(--senal); }

/* El panel de grabación en curso: se sustituye por el botón al detener, así
   que comparten el mismo hueco en el flujo del formulario. */
.grabacion-panel {
  display: flex;
  flex-direction: column;
  gap: 11px;
  margin-bottom: 14px;
  padding: 12px 13px;
  border: 1px solid var(--borde-error);
  background: var(--tinte-error-suave);
  border-radius: var(--radio);
}
.grabacion-panel[hidden] { display: none; }
.grabacion-fila { display: flex; align-items: center; gap: 9px; }
.grabacion-punto {
  width: 9px;
  height: 9px;
  flex: none;
  border-radius: 50%;
  background: var(--estado-error);
  animation: parpadeo 1.2s ease-in-out infinite;
}
.grabacion-punto[data-pausado="true"] { background: var(--texto-tenue); animation: none; }
@keyframes parpadeo { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
.grabacion-rotulo { flex: 1; margin: 0; font-size: 12px; font-weight: 600; color: var(--texto); }
.grabacion-tiempo {
  font-family: var(--mono);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--texto);
}

/* La respuesta del guardado: los avisos importan tanto como el «guardado». */
.respuesta { padding: 14px 18px; border-top: 1px solid var(--borde); font-size: 13px; }
.respuesta[data-estado="ok"] { background: var(--tinte-exito); }
.respuesta[data-estado="error"] { background: var(--tinte-error-suave); }
.respuesta ul { margin: 8px 0 0; padding-left: 18px; color: var(--texto-medio); line-height: 1.55; }
.respuesta li + li { margin-top: 6px; }

/* --- Reglas de alerta ------------------------------------------------------ */

.regla { padding: 14px 18px; display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.regla + .regla { border-top: 1px solid var(--linea); }
.regla-nombre { font-weight: 500; }
.regla-detalle { flex: 1; font-size: 12px; color: var(--texto-tenue); }

/* --- Desglose de indicadores ---------------------------------------------
   Las bandas de clic son invisibles pero el cursor tiene que decir que se
   puede pulsar: un desglose que nadie descubre es un desglose que no existe. */
.serie-zona {
  fill: transparent;
  cursor: pointer;
}
.serie-zona:hover { fill: var(--senal-suave); }

.desglose {
  margin-top: 0.85rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--borde);
}
.desglose-cabecera {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  margin-bottom: 0.6rem;
  font-size: 0.86rem;
}
.desglose-cabecera > span { color: var(--texto-tenue); }
.desglose-cabecera > .boton { margin-left: auto; }
.desglose-cargando {
  color: var(--texto-tenue);
  font-size: 0.82rem;
  margin: 0.35rem 0;
}
/* El desglose puede traer 60 menciones: se limita el alto para que no empuje
   el resto de las series fuera de la pantalla. */
.desglose .menciones {
  max-height: 26rem;
  overflow-y: auto;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* --- Evaluación de situación ---------------------------------------------
   Es lo primero que se lee. El tono cambia el color del borde izquierdo y no
   el fondo entero: un panel rojo grita antes de que nadie haya leído por qué,
   y este sistema tiene que informar, no alarmar. */
.situacion {
  position: relative;
  background:
    linear-gradient(115deg, var(--ia-suave), transparent 34%),
    var(--fondo-elevado);
  border: 1px solid var(--ia-borde);
  border-radius: 10px;
  padding: 18px 22px;
  margin-bottom: 18px;
  box-shadow: 0 0 34px -18px var(--ia-brillo), inset 0 1px 0 rgba(255, 255, 255, 0.03);
}

/* Firma del motor en la esquina: dice QUIÉN escribió este texto. Es la pieza
   central del lenguaje visual: dato medido no la lleva, juicio del modelo sí. */
.situacion::after {
  content: 'ANÁLISIS · ' attr(data-motor);
  position: absolute;
  top: 10px;
  right: 14px;
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: .16em;
  color: var(--ia);
  opacity: .75;
}

/* Mientras el modelo recalcula, el marco respira en cian. */
.situacion[data-pensando="true"] {
  border-color: var(--ia);
  animation: pensando 1.6s ease-in-out infinite;
}
@keyframes pensando {
  0%, 100% { box-shadow: 0 0 24px -16px var(--ia-brillo); }
  50%      { box-shadow: 0 0 44px -12px var(--ia-brillo); }
}
@media (prefers-reduced-motion: reduce) { .situacion[data-pensando="true"] { animation: none; } }
/* El tono no se marca con una barra de color al costado —el recurso que más
   delata una interfaz generada— sino donde ya se está mirando: el punto que
   precede al titular. */
.situacion-titular::before {
  content: '';
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 9px;
  border-radius: 50%;
  vertical-align: middle;
  background: var(--estado-idle);
}
.situacion[data-tono="tranquilo"] .situacion-titular::before { background: var(--estado-success); }
.situacion[data-tono="atencion"]  .situacion-titular::before { background: var(--estado-warning); }
.situacion[data-tono="riesgo"]    .situacion-titular::before { background: var(--estado-error); }

.situacion-cabecera {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 14px 0 8px;
}
/* Rótulo del bloque: mono, cian y con el rombo. Es la marca de «esto lo
   escribió el modelo» que el sistema usa en todas partes. */
.situacion-rotulo {
  flex: 1;
  margin: 0;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .1em;
  color: var(--ia);
}

/* Carrusel de titulares: el visor recorta y la pista se desplaza en pasos
   de un ancho completo. */
.situacion-visor { overflow: hidden; }
.situacion-pista {
  display: flex;
  transition: transform .25s ease;
}
@media (prefers-reduced-motion: reduce) { .situacion-pista { transition: none; } }

.situacion-titular {
  flex: 0 0 100%;
  box-sizing: border-box;
  font-family: var(--display);
  font-size: 16px;
  font-weight: 700;
  line-height: 1.4;
  margin: 0;
}

/* Puntos de paginación. El activo se alarga en vez de solo cambiar de color:
   así se distingue sin depender de la vista para el color. */
.situacion-puntos {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin-top: 10px;
}
.situacion-puntos[hidden] { display: none; }
.situacion-punto {
  width: 6px;
  height: 6px;
  padding: 0;
  border: none;
  border-radius: 3px;
  background: var(--borde-vivo);
  cursor: pointer;
  transition: width .2s ease, background-color .2s ease;
}
.situacion-punto[aria-current="true"] { width: 16px; background: var(--ia); }
@media (prefers-reduced-motion: reduce) { .situacion-punto { transition: none; } }
.situacion-texto {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.65;
  color: var(--texto-medio);
}

/* --- La evaluación, plegada en vertical -----------------------------------
   En un teléfono, el análisis completo son quince o veinte líneas y los chips
   debajo: al abrir la aplicación no se ve nada más que un muro de texto, y hay
   que arrastrar dos pantallas para llegar a las cifras. Se muestran las
   primeras líneas —que es donde está el titular del titular— y el resto se
   despliega al tocar.

   En escritorio no se pliega: ahí cabe, y esconder texto que se lee de un
   vistazo solo añade un clic. */
@media (max-width: 620px) {
  .situacion[data-plegado="true"] .situacion-texto {
    display: -webkit-box;
    -webkit-line-clamp: 4;
    line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
    /* Se difumina el último renglón en vez de cortarlo en seco: así se ve que
       hay más y no que la frase acabó ahí. */
    -webkit-mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
    mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
  }
  /* Los chips son la evidencia del análisis: mientras está plegado, sobran. */
  .situacion[data-plegado="true"] .chips { display: none; }
}

/* El mando de desplegar. Solo existe en vertical y solo cuando hay texto que
   esconder: en escritorio no se pinta, y con un análisis corto tampoco. */
/* Cian y no ámbar: lo que despliega es el análisis del modelo, y el color
   dice de quién es el texto. */
.situacion-mas {
  display: none;
  align-items: center;
  gap: 6px;
  width: 100%;
  margin-top: 10px;
  padding: 9px 0 2px;
  border: 0;
  border-top: 1px solid var(--linea);
  background: none;
  font: inherit;
  font-size: 12px;
  color: var(--ia);
  text-align: left;
  cursor: pointer;
}
.situacion-destello { flex: none; width: 13px; height: 13px; }
@media (max-width: 620px) {
  .situacion-mas { display: flex; }
}
.situacion-mas::after {
  content: ' ↓';
  display: inline-block;
  transition: transform .15s ease;
}
.situacion[data-plegado="false"] .situacion-mas::after { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .situacion-mas::after { transition: none; }
}

/* --- Resumen: una tarjeta por vista -----------------------------------------

   Sustituye a la rejilla de siete cifras. Cada tarjeta es un enlace entero:
   toda su superficie lleva a la vista, no solo un rótulo «ver más» al fondo.
   Responden a «¿tengo que entrar aquí?» antes de que se entre, así que la
   cifra —lo único que hace falta leer para decidir eso— va grande y a la
   derecha; la frase la explica en una línea, sin obligar a interpretarla. */

.tarjetas-vista {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 14px;
}

.tarjeta-vista {
  display: block;
  background: var(--fondo-elevado);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 14px 16px;
  color: inherit;
  text-decoration: none;
  transition: border-color .15s ease, background-color .15s ease;
}
.tarjeta-vista:hover { border-color: var(--borde-vivo); background: var(--fondo-activo); }
.tarjeta-vista:focus-visible { outline: 2px solid var(--senal); outline-offset: 2px; }
/* Solo dos tonos de borde, y solo cuando hace falta mirar: el resto se queda
   en el borde neutro, que es la lectura correcta para «sin novedad». */
.tarjeta-vista[data-borde="alerta"] { border-color: var(--borde-error); }
.tarjeta-vista[data-borde="aviso"]  { border-color: var(--borde-aviso); }

.tarjeta-vista-cabecera {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.tarjeta-vista-nombre {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--texto-medio);
}
.tarjeta-vista-nombre .icono-menu { opacity: .8; }
.tarjeta-vista-relleno { flex: 1; }
.tarjeta-vista-delta {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--texto-tenue);
  white-space: nowrap;
}
.tarjeta-vista-cifra {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 21px;
  font-weight: 600;
  color: var(--texto);
  white-space: nowrap;
}

.tarjeta-vista-frase {
  margin: 6px 0 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--texto-medio);
}
/* La segunda línea, cuando hay algo más urgente que decir que el titular:
   nunca es más grande que la frase principal, o competiría con ella. */
.tarjeta-vista-extra {
  margin: 5px 0 0;
  font-size: 11px;
  color: var(--texto-tenue);
}
.tarjeta-vista-extra[data-tono="alerta"] { color: var(--estado-error); }
.tarjeta-vista-extra[data-tono="aviso"]  { color: var(--estado-warning); }

.tarjeta-vista-pie {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 9px;
  font-size: 10.5px;
  color: var(--texto-tenue);
}
.tarjeta-vista:hover .tarjeta-vista-pie { color: var(--senal); }
.tarjeta-vista-ir { transition: transform .15s ease; }
.tarjeta-vista:hover .tarjeta-vista-ir { transform: translateX(2px); }

/* La sparkline no se tiñe con el hover de la tarjeta: su color es dato
   —el de la propia serie— y cambiarlo al pasar por encima haría creer que
   significa otra cosa. */
.tarjeta-vista-spark { flex: none; display: block; }
.tarjeta-vista-sparknota {
  flex: none;
  font-size: 9.5px;
  color: var(--texto-tenue);
  white-space: nowrap;
}
.tarjeta-vista:hover .tarjeta-vista-sparknota { color: var(--texto-tenue); }

/* El sistema solo habla cuando algo va mal: en operación normal esta tira no
   existe. Un aviso permanente que dijera «todo bien» sería ruido leído cien
   veces por cada vez que hace falta. */
.aviso-sistema {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  padding: 10px 14px;
  border: 1px solid var(--borde-aviso);
  background: var(--tinte-aviso-suave);
  border-radius: var(--radio-chico);
  color: var(--estado-warning);
}
.aviso-sistema[hidden] { display: none; }
.aviso-sistema p { flex: 1; margin: 0; font-size: 11.5px; }
.aviso-sistema a { font-size: 11px; white-space: nowrap; }

.chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 12px; }
.chip {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 4px 10px;
  border: 1px solid var(--borde-vivo);
  border-radius: 999px;
  font-size: 11.5px;
  background: var(--fondo-hundido);
}
.chip-etiqueta { color: var(--texto-medio); }
.chip-valor { color: var(--texto); font-weight: 600; font-variant-numeric: tabular-nums; }
.chip--riesgo { border-color: var(--borde-error); }
.chip--termino { border-style: dashed; }
.chip--nota { color: var(--texto-tenue); font-style: italic; }

/* --- Informes ------------------------------------------------------------- */
.informe {
  padding: 16px 20px;
  border-bottom: 1px solid var(--borde);
}
.informe-cabecera { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.informe-resumen {
  margin: 8px 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--texto-medio);
}
.informe-cuerpo { margin-top: 12px; font-size: 13.5px; line-height: 1.7; }
.informe-h {
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--senal);
  margin: 18px 0 8px;
}
.informe-p { margin: 0 0 10px; color: var(--texto-medio); }
.informe-lista { margin: 0 0 12px; padding-left: 20px; color: var(--texto-medio); }
.informe-lista li { margin-bottom: 7px; }
.informe-cuerpo strong { color: var(--texto); }

/* --- Voz ------------------------------------------------------------------ */
.audio-item {
  padding: 14px 20px;
  border-bottom: 1px solid var(--borde);
}
.audio-item audio {
  width: 100%;
  max-width: 420px;
  margin-top: 10px;
  height: 34px;
}
.formulario textarea {
  width: 100%;
  font: inherit;
  resize: vertical;
}

/* --- Propuestas de prensa ------------------------------------------------- */
.botonera { display: flex; gap: 10px; flex-wrap: wrap; }
.propuesta {
  padding: 14px 0;
  border-top: 1px solid var(--borde);
}
.propuesta .tabla-consulta { margin: 6px 0 10px; }
#propuestas-prensa { padding: 0 20px 16px; }
#propuestas-prensa details { margin-top: 14px; }
#propuestas-prensa summary { cursor: pointer; }

/* --- Transcripción -------------------------------------------------------
   Cerrada por defecto: lo que se decide mirando la ficha de un vídeo son el
   origen y el análisis. La transcripción es el respaldo para comprobarlos. */
.transcripcion {
  margin-top: 14px;
  border-top: 1px solid var(--borde);
  padding-top: 12px;
}
.transcripcion > summary {
  cursor: pointer;
  display: flex;
  gap: 10px;
  align-items: baseline;
  font-size: 13px;
  color: var(--texto-medio);
  list-style: none;
}
.transcripcion > summary::before {
  content: '▸';
  color: var(--senal);
  transition: transform 0.15s;
}
.transcripcion[open] > summary::before { content: '▾'; }
.transcripcion > summary::-webkit-details-marker { display: none; }
.transcripcion-cifra { color: var(--texto-tenue); font-size: 11.5px; }

.transcripcion-cuerpo {
  margin-top: 12px;
  max-height: 30rem;
  overflow-y: auto;
  padding-right: 10px;
}
.transcripcion-parrafo {
  margin: 0 0 12px;
  font-size: 13px;
  line-height: 1.75;
  color: var(--texto-medio);
}
/* El resaltado señala «aquí pasa algo»; el porqué está en el tooltip. */
.transcripcion-parrafo--clave {
  background: var(--ia-suave);
  padding: 8px 12px;
  border-radius: 6px;
  color: var(--texto);
  cursor: help;
}
.transcripcion-parrafo--clave:focus-visible {
  outline: 2px solid var(--ia);
  outline-offset: 2px;
}
a.transcripcion-marca,
.transcripcion-marca {
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--ia);
  white-space: nowrap;
  text-decoration: none;
}
a.transcripcion-marca:hover { text-decoration: underline; }

/* El cuerpo desplegado de una mención larga —una transcripción— se limita en
   alto y hace scroll dentro: si no, un item de 20.000 caracteres empuja al
   resto del listado fuera de la pantalla. */
.mencion-texto--resto {
  max-height: 22rem;
  overflow-y: auto;
  white-space: pre-wrap;
  padding: 10px 12px;
  background: var(--fondo-hundido);
  border-radius: 6px;
}
.mencion-enlace { font-size: 12px; }

/* --- Bot: lista de chats -------------------------------------------------
   Tres zonas por fila: quién escribe, en qué estado está, y qué se puede
   hacer. Antes era todo un bloque pegado a la izquierda con los botones
   colgando debajo, que dejaba media pantalla vacía y no dejaba comparar dos
   chats de un vistazo. */
.chat {
  display: grid;
  grid-template-columns: minmax(180px, 1.4fr) minmax(160px, 1fr) auto;
  align-items: center;
  gap: 18px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--linea);
}
.chat:last-child { border-bottom: none; }

.chat-quien { display: flex; align-items: center; gap: 11px; min-width: 0; }
/* El punto lleva el estado al borde izquierdo: se escanea la columna sin
   tener que leer la etiqueta de cada fila. */
.chat-punto {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
  background: var(--estado-idle);
  box-shadow: 0 0 0 3px var(--fondo-hundido);
}
.chat[data-autorizado="true"] .chat-punto { background: var(--estado-success); }

.chat-nombre {
  margin: 0;
  font-size: 13.5px;
  color: var(--texto);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chat-id {
  margin: 2px 0 0;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--texto-tenue);
}

.chat-datos { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.chat-meta { font-size: 11.5px; color: var(--texto-tenue); }

.chat-acciones { display: flex; gap: 8px; justify-content: flex-end; }
.chat-acciones .boton { padding: 7px 14px; font-size: 12px; justify-self: auto; }

/* El hilo ocupa la fila completa debajo, no una columna. */
.chat-hilo {
  grid-column: 1 / -1;
  margin-top: 6px;
  max-height: 24rem;
  overflow-y: auto;
  border-top: 1px solid var(--linea);
  padding-top: 12px;
}
.turno {
  padding: 9px 13px;
  border-radius: 8px;
  margin-bottom: 8px;
  font-size: 12.5px;
  line-height: 1.6;
}
.turno--user {
  background: var(--fondo-hundido);
  color: var(--texto-medio);
}
.turno--assistant {
  background: var(--ia-suave);
  color: var(--texto);
}
.turno-texto { margin: 0; white-space: pre-wrap; }
.turno-citas {
  margin: 6px 0 0;
  font-size: 10.5px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}

@media (max-width: 720px) {
  .chat { grid-template-columns: 1fr; gap: 10px; }
  .chat-acciones { justify-content: flex-start; }
}

/* El hilo cuelga de su fila: la sangría dice a quién pertenece cuando hay
   varios chats abiertos a la vez. */
.chat-hilo { padding-left: 19px; }
.turno .informe-p,
.turno .informe-lista { color: inherit; margin-bottom: 8px; }
.turno .informe-lista { padding-left: 18px; }
.turno .informe-h { margin: 10px 0 6px; font-size: 11px; }
.turno > :last-child { margin-bottom: 0; }

/* Término con definición disponible: subrayado punteado discreto. Señala que
   hay algo que preguntar sin gritar; el detalle llega al pasar el ratón. */
.glosado {
  text-decoration: underline dotted var(--borde-vivo);
  text-underline-offset: 3px;
  cursor: help;
}
.glosado:hover,
.glosado:focus-visible {
  text-decoration-color: var(--ia);
  outline: none;
}

/* --- Marco de cognición ---------------------------------------------------
   Todo texto ESCRITO por el modelo lo lleva; lo medido, no. Es la regla
   central del lenguaje: distinguir dato de juicio sin leer nada. */
.ia-marco {
  position: relative;
  padding: 12px 16px;
  border-radius: 8px;
  background: linear-gradient(105deg, var(--ia-suave), transparent 55%);
}
.ia-marco::after {
  content: '◈ ' attr(data-motor);
  position: absolute;
  top: 8px;
  right: 10px;
  font-family: var(--mono);
  font-size: 8.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ia);
  opacity: .65;
  pointer-events: none;
}
/* Dentro del marco, los encabezados del informe hablan la voz del modelo. */
.ia-marco .informe-h { color: var(--ia); }
.ia-marco > :first-child { margin-top: 0; }
.ia-marco > :last-child { margin-bottom: 0; }

/* --- Nota de panel -------------------------------------------------------
   Texto explicativo dentro de un panel. Comparte el sangrado de las filas que
   acompaña, para que no quede flotando contra el borde de la tarjeta. */
.nota-panel {
  margin: 0;
  padding: 14px 20px;
  font-size: 12px;
  line-height: 1.65;
  color: var(--texto-medio);
  background: var(--fondo-hundido);
  border-bottom: 1px solid var(--borde);
}
.nota-panel--pie {
  background: transparent;
  border-bottom: none;
  border-top: 1px solid var(--linea);
  color: var(--texto-tenue);
}
.nota-panel code {
  font-family: var(--mono);
  font-size: 11.5px;
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--senal-suave);
  color: var(--senal);
}

/* --- Candidatos de encuesta ----------------------------------------------- */
.candidato {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 8px 0;
  border-top: 1px solid var(--linea);
}
.candidato .tabla-consulta { overflow-wrap: anywhere; }
.candidato .boton { flex: none; padding: 5px 12px; font-size: 11.5px; }

/* --- Intervenciones de una pauta ------------------------------------------ */
.intervencion { margin-bottom: 14px; }
.intervencion-meta {
  margin: 0 0 4px;
  font-size: 10.5px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}
.intervencion-meta strong { color: var(--senal); }
.intervencion-texto {
  margin: 0;
  font-size: 13px;
  line-height: 1.7;
  color: var(--texto-medio);
}
#lista-reuniones audio { width: 100%; max-width: 420px; margin-top: 10px; height: 34px; }
.formulario input[type="file"] { padding: 8px; font-size: 12px; }

/* --- Miniatura de vídeo ---------------------------------------------------
   Relación 16:9 fija para que la fila no dé un salto cuando carga la imagen,
   y ancho acotado: en el listado de menciones la portada acompaña al texto,
   no lo sustituye. */
/* La portada va al lado del texto, no encima: es la referencia visual del
   origen, y lo que se lee es el análisis.

   No se usa `float` porque tanto `.video` como `.mencion` son contenedores
   grid, y dentro de un grid el float es inerte —se aplicó y no pasó nada, la
   portada seguía apilada arriba—. Se resuelve con el propio grid: una columna
   extra a la derecha que la portada ocupa durante las primeras filas. */
.video:has(> .miniatura),
.mencion:has(> .miniatura) {
  grid-template-columns: minmax(0, 1fr) minmax(200px, 268px);
}
.video:has(> .miniatura) > *,
.mencion:has(> .miniatura) > * {
  grid-column: 1;
}
.video:has(> .miniatura) > .miniatura,
.mencion:has(> .miniatura) > .miniatura {
  grid-column: 2;
  grid-row: 1 / span 3;
}

/* La portada solo acompaña a las tres primeras filas —título, origen y
   resumen—. Todo lo que viene después es el análisis, y dejarlo encerrado en
   la columna estrecha vaciaba media tarjeta: barras de desempeño en dos
   columnas con hueco a la derecha, listas comprimidas y un tercio del ancho
   en blanco desde la mitad de la ficha hacia abajo. A partir de la portada,
   el contenido usa el ancho completo. */
.video:has(> .miniatura) > :nth-child(n + 5),
.mencion:has(> .miniatura) > :nth-child(n + 5) {
  grid-column: 1 / -1;
}

@media (max-width: 720px) {
  /* En vertical no hay dos columnas que repartir: la portada va debajo del
     título, a todo el ancho, y el resto en una sola columna. */
  .video:has(> .miniatura),
  .mencion:has(> .miniatura) { grid-template-columns: minmax(0, 1fr); }
  .video:has(> .miniatura) > .miniatura,
  .mencion:has(> .miniatura) > .miniatura { grid-column: 1; grid-row: auto; }
}

.miniatura {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  align-self: start;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--borde);
  background: var(--fondo-hundido);
  cursor: pointer;
}
.miniatura img,
.miniatura iframe {
  width: 100%;
  height: 100%;
  display: block;
  border: 0;
  object-fit: cover;
}
.miniatura-play {
  position: absolute;
  inset: 0;
  margin: auto;
  border-radius: 50%;
  border: 1px solid var(--senal);
  background: rgba(0, 0, 0, 0.55);
  color: var(--senal);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  transition: transform .15s ease, background-color .15s ease;
}
.miniatura:hover .miniatura-play {
  transform: scale(1.08);
  background: rgba(0, 0, 0, 0.75);
}
/* Al reproducir crece: ahí sí es el contenido principal. */
.miniatura[data-abierto] { cursor: default; }

.miniatura-play { width: 40px; height: 40px; font-size: 13px; }

@media (max-width: 720px) {
  /* En pantalla estrecha no hay sitio para dos columnas: vuelve a apilarse. */
  .video:has(> .miniatura),
  .mencion:has(> .miniatura) { grid-template-columns: 1fr; }
  .video:has(> .miniatura) > .miniatura,
  .mencion:has(> .miniatura) > .miniatura { grid-column: 1; grid-row: auto; }
  .miniatura,
  .miniatura[data-abierto] { width: 100%; max-width: 320px; }
}

/* --- Mediciones de encuesta ------------------------------------------------ */
.medicion-sujeto { color: var(--texto-tenue); }
.medicion-pregunta { color: var(--ia); cursor: help; font-size: 11px; }

/* --- Traza de razonamiento -------------------------------------------------
   Cada nodo escupe una línea de terminal mientras trabaja. Un pipeline que
   solo enciende una luz verde no comunica que hay un motor razonando; esto
   sí. Solo se ve en los nodos activos: inventar actividad en una etapa
   parada sería mentir sobre el estado del sistema. */
/* La burbuja está SIEMPRE visible: el diagrama tiene que leerse como un
   sistema despierto. Lo que cambia con el estado es la intensidad, no la
   presencia. */
.nodo-burbuja {
  opacity: 1;
  transition: opacity .35s ease;
  pointer-events: none;
  overflow: visible;
}

.traza {
  font-family: var(--mono);
  font-size: 7.5px;
  line-height: 1.45;
  letter-spacing: .01em;
  color: var(--ia);
  text-align: center;
  padding: 5px 7px;
  border: 1px solid var(--ia-borde);
  border-radius: 5px;
  background: color-mix(in srgb, var(--fondo-hundido) 88%, transparent);
  backdrop-filter: blur(3px);
  overflow-wrap: anywhere;
  box-shadow: 0 0 18px -8px var(--ia-brillo);
}
/* En reposo la traza baja de intensidad: dice lo que la etapa vigila, no que
   esté procesando. El núcleo del nodo sigue diciendo la verdad del estado. */
.traza[data-reposo="true"] {
  opacity: .5;
  border-color: var(--borde);
  box-shadow: none;
}
.traza[data-reposo="true"]::after { opacity: .4; }

/* Traza real del backend: ámbar, porque es hecho, no ilustración. */
.traza[data-real="true"] {
  color: var(--senal);
  border-color: var(--senal-suave);
}
.nodo[data-estado="error"] .traza {
  color: var(--estado-error);
  border-color: var(--borde-error);
}

/* Entrada de cada línea: aparece desde abajo, como en un log que avanza. */
.traza--entra { animation: traza-entra .32s ease-out; }
@keyframes traza-entra {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Cursor de terminal al final de la línea. */
.traza::after {
  content: '▌';
  margin-left: 2px;
  animation: cursor 1.05s steps(2) infinite;
}
@keyframes cursor { 50% { opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  .traza--entra { animation: none; }
  .traza::after { animation: none; }
}

/* El resumen de facturación y las listas que cuelgan de un formulario iban
   pegadas al borde del panel: el resto del contenido tiene sangrado y estas
   no, así que se leían como texto suelto. */
#lista-audios > .serie-pie,
#lista-reuniones > .serie-pie,
#lista-informes > .serie-pie {
  padding: 12px 20px 0;
  margin: 0;
}
#lista-audios,
#lista-informes,
#lista-reuniones,
#lista-encuestas,
#bot-chats,
#reglas { padding-bottom: 4px; }

/* --- Cierre de alertas ----------------------------------------------------- */
/* El formulario vive en un modal: ya no necesita marco propio ni fondo
   distinto, que ahí dentro solo añadirían una caja sobre otra.

   `.modal-cuerpo` no trae sangrado horizontal —cada contenido pone el suyo,
   porque algunos son bandas a sangre—, así que aquí hay que ponerlo: sin él
   el título citado y el área de texto llegaban pegados a los dos bordes
   mientras la cabecera del modal sí respiraba, y la caja se veía descuadrada.
   Hoy solo lo usa «Mis sesiones»: el cierre de un hallazgo es una nota en
   línea bajo su propia tarjeta, no un modal. */
#generico-cuerpo { padding: 18px 20px 20px; }

/* --- Origen de una mención -------------------------------------------------
   Icono de la red + enlace al posteo. Antes era el nombre en texto y el enlace
   vivía suelto al final del párrafo: poder saltar a la fuente en un clic es lo
   que separa «leí un resumen» de «verifiqué», y cualquier mención que se cite
   en una reunión tiene que ser comprobable en dos segundos. */
.origen {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border: 1px solid var(--borde-vivo);
  border-radius: 20px;
  font-size: 10.5px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--texto-medio);
  text-decoration: none;
  transition: border-color .18s ease, color .18s ease;
}
a.origen:hover,
a.origen:focus-visible {
  border-color: var(--senal);
  color: var(--senal);
  outline: none;
}
.icono-red { flex: none; display: block; }
.origen-flecha { font-size: 9px; opacity: .6; }
a.origen:hover .origen-flecha { opacity: 1; }

/* Tono «aviso»: alto es señal de vigilar, no de daño. La concentración de la
   conversación es el caso: mucha actividad de pocas cuentas hay que mirarla,
   pero no es en sí una mala noticia. */
.serie-linea--aviso { stroke: var(--estado-warning); }
.serie-area--aviso  { fill: var(--tinte-aviso-suave); }
.serie-punto--aviso { fill: var(--estado-warning); }

.serie-detalle {
  margin: 10px 0 0;
  font-size: 11.5px;
  color: var(--texto-medio);
}
.serie-detalle strong { color: var(--texto); font-family: var(--mono); font-size: 11px; }

/* Corte entre los indicadores de conversación y los de canales propios. Ocupa
   la fila completa para que la cuadrícula de percepción quede limpia. */
.series-corte {
  grid-column: 1 / -1;
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  padding: 14px 18px 10px;
  border-top: 1px solid var(--borde);
  background: var(--fondo-hundido);
}
.series-corte-titulo {
  font-family: var(--display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--texto-medio);
}
.series-corte-nota { font-size: 11.5px; color: var(--texto-tenue); }

/* Autenticidad de quien responde, dentro de la tarjeta de cada canal. El
   color sube con la proporción: un signo negativo se lee distinto si un
   tercio de quien lo produce son cuentas con señales. */
.canal-autenticidad {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin: 8px 0 0;
  padding-top: 8px;
  border-top: 1px solid var(--linea);
  font-size: 11.5px;
  color: var(--texto-tenue);
  cursor: help;
}
.canal-aut-valor {
  font-family: var(--mono);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--texto-medio);
}

/* Mención que forma parte de un ataque coordinado. Comparte el rojo de la
   familia hostil, pero con el canto punteado: lo que marca no es el contenido
   del mensaje, es que se repitió. */
.etiqueta--bloque {
  color: var(--estado-error);
  background: var(--tinte-error-suave, transparent);
  border: 1px dashed var(--estado-error);
}

/* --- Leyenda de la barra de posturas ---------------------------------------
   Ocupa la fila entera por encima de las tarjetas de canal: los colores son
   los mismos en las tres y una leyenda por tarjeta pesaría más que las barras
   que explica. */
.leyenda {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 18px;
  padding: 12px 18px;
  border-top: 1px solid var(--linea);
  background: var(--fondo-hundido);
}
.leyenda-titulo {
  font-family: var(--display);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--texto-medio);
}
.leyenda-lista {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.leyenda-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--texto-medio);
}
/* El testigo de color repite exactamente el fondo del tramo: hereda de
   `.barra-tramo--*`, así que si un color cambia, cambia en los dos sitios y no
   pueden desincronizarse. */
.leyenda-color {
  width: 11px;
  height: 11px;
  flex: none;
  border-radius: 3px;
}

/* --- El recuento de cada canal ---------------------------------------------
   Las cifras separadas y con su color en vez de una frase corrida en gris: el
   contraste entre «10 a favor» y «86 en contra» es la lectura entera de la
   tarjeta y antes había que buscarla dentro de una línea de once palabras. */
.canal-recuento {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 14px;
  margin-top: 10px;
  font-size: 11.5px;
  color: var(--texto-tenue);
}
.canal-dato { display: inline-flex; align-items: baseline; gap: 4px; }
.canal-dato b {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.canal-dato--favor  b { color: var(--estado-success); }
.canal-dato--contra b { color: var(--estado-error); }
/* El denominador en tono menor y al final: es el que da sentido a los otros
   dos, pero no es lo que se viene a leer. */
.canal-dato--total { margin-left: auto; color: var(--texto-tenue); }

/* El aviso de muestra corta. Ocupa una línea entera porque su trabajo es
   frenar la lectura: un +1,00 sobre siete respuestas invita a concluir. */
.canal-aviso {
  margin: 10px 0 0;
  padding-top: 8px;
  border-top: 1px solid var(--linea);
  font-size: 11px;
  line-height: 1.5;
  color: var(--estado-warning);
}

/* En la tarjeta de canal la cifra es lo único a la derecha: sin `flex: none`
   el nombre con logo la empujaba fuera cuando el canal se llamaba largo. */
.serie--canal .serie-cifra { flex: none; }
.serie--canal .serie-valor { font-size: 26px; }
.canal-autenticidad[data-nivel="medio"] .canal-aut-valor { color: var(--estado-warning); }
.canal-autenticidad[data-nivel="alto"]  .canal-aut-valor { color: var(--estado-error); }

/* Nombre de canal con su logo. El icono hereda el color del texto para que
   funcione igual en claro y en oscuro sin duplicar reglas. */
.canal-nombre {
  display: flex;
  align-items: center;
  gap: 7px;
}
.canal-nombre .icono-red { flex: none; opacity: .85; }

/* --- Menú móvil -----------------------------------------------------------
   Por debajo de 860 px catorce secciones en una tira horizontal obligaban a
   arrastrar a ciegas: no se veía cuántas había ni dónde estaba uno. Se
   convierte en un panel lateral que entra desde la derecha, que es el lado
   donde está el pulgar. */

.hamburguesa {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 38px;
  height: 34px;
  padding: 0 8px;
  border: 1px solid var(--borde-vivo);
  border-radius: var(--radio-chico);
  background: transparent;
  cursor: pointer;
}
.hamburguesa span {
  display: block;
  height: 1.5px;
  background: var(--texto-medio);
  border-radius: 2px;
  transition: transform .22s ease, opacity .18s ease;
}
/* Las tres barras se convierten en aspa al abrir: el mismo botón cierra. */
.hamburguesa[aria-expanded="true"] span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.hamburguesa[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.hamburguesa[aria-expanded="true"] span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

/* El velo solo existe en móvil y solo cuando el panel está abierto.
   `display: block` a secas pisaba el atributo `hidden` —que es una regla de la
   hoja del navegador y pierde contra cualquier regla de autor—, así que en
   móvil la aplicación quedaba permanentemente tapada por una capa oscura sin
   forma de quitarla. El `:not([hidden])` es lo que devuelve el control al
   atributo. */
.menu-velo { display: none; }

@media (max-width: 860px) {
  .menu-velo:not([hidden]) { display: block; }
}

.menu-velo {
  position: fixed;
  inset: 0;
  z-index: 8;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(2px);
  animation: velo .2s ease;
}
@keyframes velo { from { opacity: 0; } to { opacity: 1; } }

@media (max-width: 860px) {
  .hamburguesa {
    display: flex;
    /* Último elemento de la cabecera. Sin esto quedaba antes del control de
       tema y el botón que abre el menú no era el de la esquina, que es donde
       la mano lo busca. */
    order: 9;
    margin-left: auto;
  }
  /* En móvil la cabecera se reordena: identidad a la izquierda, estado en
     medio, controles a la derecha. */
  .pulso { width: 100%; justify-content: flex-end; gap: 10px; }
  .pulso-ciclo, .motor-detalle { display: none; }

  /* Cabecera fija al desplazar.
     En escritorio el menú se queda pegado arriba y hace de ancla, pero en
     móvil el menú es un cajón lateral, así que al bajar por una lista larga
     —menciones, vídeos— no quedaba nada en pantalla: ni dónde estás, ni el
     botón para cambiar de sección, ni el estado del sistema. Había que subir
     hasta arriba del todo para cualquier cosa.

     `z-index` por debajo del cajón (9) y de su velo (8): la cabecera se queda
     fija, pero cuando se abre el menú el cajón pasa por encima. Al revés, el
     menú aparecería recortado por la cabecera. */
  .cabecera {
    position: sticky;
    top: 0;
    z-index: 6;
    /* Menos aire que en escritorio: fija, cada píxel de alto es contenido que
       ya no se ve. */
    padding-top: 13px;
    padding-bottom: 11px;
    gap: 10px;
    /* Opaca y con desenfoque. El degradado a transparente de escritorio deja
       ver el contenido pasando por debajo, y sobre texto se vuelve ilegible. */
    background: color-mix(in srgb, var(--fondo) 90%, transparent);
    backdrop-filter: blur(16px) saturate(1.3);
    -webkit-backdrop-filter: blur(16px) saturate(1.3);
  }

  /* El isotipo y el rótulo bajan un punto: fijos y a todo lo ancho pesan más
     que en una cabecera que se va al desplazar. */
  .cabecera .sello { width: 34px; height: 34px; margin-top: -5px; }
  .marca { gap: 10px; min-width: 0; }

  /* El nombre del cargo se corta en vez de envolver. Fija, cada línea que se
     parte es contenido que deja de verse; y «PRESIDENTA DEL SENADO» partido
     en dos no aporta nada sobre el mismo texto cortado. */
  .marca-sub {
    font-size: 9.5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .marca > div { min-width: 0; }

  /* La fila de estado en una sola línea. «En vivo» partido en dos y el reloj
     desalineado hacían que la cabecera midiera casi un tercio de la pantalla. */
  .pulso { gap: 8px; flex-wrap: nowrap; }
  .pulso-texto { white-space: nowrap; }
  .motor { padding: 5px 10px; }
  .pulso-sep { display: none; }

  .menu {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: auto;
    z-index: 9;
    width: min(86vw, 330px);
    overflow-x: hidden;
    flex-direction: column;
    justify-content: flex-start;
    gap: 0;
    padding: 74px 0 24px;
    overflow-y: auto;
    overflow-x: hidden;
    border-bottom: none;
    border-left: 1px solid var(--borde);
    background: var(--fondo-elevado);
    box-shadow: -24px 0 60px -30px #000;
    right: -320px;
    transition: right .26s cubic-bezier(.32, .72, 0, 1), visibility .26s;
    visibility: hidden;
  }
  .menu[data-abierto="true"] { right: 0; visibility: visible; }

  /* Bloqueo del scroll de fondo mientras el panel está abierto. Vive aquí y no
     en JS: al pasar a escritorio la regla deja de aplicar sola. */
  /* `position: fixed` y no solo `overflow: hidden`: iOS ignora el segundo
     para el gesto táctil y la página de detrás seguía arrastrándose. El
     desplazamiento se guarda y restaura desde el JS, porque al fijar el body
     la página salta al principio. */
  body.con-menu {
    position: fixed;
    left: 0;
    right: 0;
    width: 100%;
    overflow: hidden;
  }

  .menu a {
    /* Más aire que en escritorio —esto se toca con el pulgar— pero el mismo
       cuerpo: a 15 px las trece entradas no cabían en una pantalla y había que
       arrastrar para llegar a Configuración. */
    padding: 12px 18px 12px 16px;
    font-size: 13.5px;
  }

  .menu a[aria-current="page"] {
    border-left-color: var(--senal);
    background: var(--senal-suave);
  }
  .menu a[aria-current="page"]::after { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .menu { transition: none; }
  .menu-velo { animation: none; }
}

/* --- Diagrama plegable ----------------------------------------------------
   Plegado por defecto en los dos soportes. El diagrama es lo que se enseña, no lo que
   se consulta: ocupa media pantalla y por debajo están las cifras y la
   evaluación de situación, que es a lo que se entra. Se despliega a un clic y
   la tira de puntos conserva lo único que se mira de pasada —si alguna etapa
   corre o falló—. */
#toggle-diagrama {
  display: inline-flex;
  padding: 6px 12px;
  font-size: 12px;
}
.diagrama-resumen { display: none; }

.panel--diagrama[data-colapsado="true"] .diagrama-caja,
.panel--diagrama[data-colapsado="true"] .leyenda { display: none; }

.panel--diagrama[data-colapsado="true"] .diagrama-resumen {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 14px 18px;
  border-top: 1px solid var(--linea);
}

.diagrama-resumen .punto { width: 9px; height: 9px; }
/* El punto de una etapa ejecutando late, igual que en el diagrama. */
.diagrama-resumen .punto[data-estado="active"] {
  box-shadow: 0 0 0 3px var(--senal-suave);
  animation: latido-punto 1.4s ease-in-out infinite;
}
@keyframes latido-punto {
  0%, 100% { box-shadow: 0 0 0 2px var(--senal-suave); }
  50%      { box-shadow: 0 0 0 5px var(--senal-suave); }
}
.diagrama-resumen-texto {
  margin-left: 6px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}

/* La cabecera del panel deja sitio a los mandos sin apretar el título. */
@media (max-width: 860px) {
  .panel--diagrama .panel-cabecera { flex-wrap: wrap; row-gap: 8px; }
}

@media (prefers-reduced-motion: reduce) {
  .diagrama-resumen .punto[data-estado="active"] { animation: none; }
}

.etiqueta--vigilada {
  border-color: var(--estado-error);
  color: var(--estado-error);
  cursor: help;
}

/* --- Hoja (bottom sheet): componente transversal ---------------------------

   Para filtros que se tocan poco: entra desde abajo con las esquinas
   superiores redondeadas, distinto del `.modal` centrado que se usa para
   formularios y fichas. En escritorio, donde no hay «abajo de la pantalla»
   que tenga sentido, se centra como un modal pequeño en vez de pegarse al
   borde inferior de una ventana de 1200 px. */
.hoja {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.hoja[hidden] { display: none; }
.hoja-velo {
  position: absolute;
  inset: 0;
  background: rgba(3, 5, 7, .8);
  animation: velo .2s ease;
}
.hoja-caja {
  position: relative;
  width: 100%;
  max-height: 82vh;
  overflow-y: auto;
  background: var(--fondo-elevado);
  border: 1px solid var(--borde-vivo);
  border-bottom: none;
  border-radius: 16px 16px 0 0;
  padding: 16px;
  box-sizing: border-box;
  animation: hoja-entra .22s cubic-bezier(.32, .72, 0, 1);
}
@keyframes hoja-entra {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}
.hoja-cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}
.hoja-cabecera h3 { margin: 0; font-size: 14px; font-weight: 700; color: var(--texto); }
.hoja-rotulo {
  margin: 0 0 7px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}
.segmentado-libre {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 14px;
}
.segmentado-libre .segmentado-opcion {
  flex: none;
  border-radius: 999px;
  border: 1px solid var(--borde-vivo);
  padding: 6px 12px;
}
.hoja-aplicar { width: 100%; }

@media (min-width: 621px) {
  .hoja-caja {
    width: min(420px, calc(100% - 40px));
    max-height: 86vh;
    border: 1px solid var(--borde-vivo);
    border-radius: 16px;
    margin-bottom: 40px;
  }
  @keyframes hoja-entra { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
}

.modal {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.modal[hidden] { display: none; }
.modal-velo {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(3px);
}
.modal-caja {
  position: relative;
  width: min(760px, 100%);
  max-height: 86vh;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--borde-vivo);
  border-radius: var(--radio);
  background: var(--fondo-elevado);
  box-shadow: 0 40px 90px -40px #000;
  overflow: hidden;
}
.modal-cabecera {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 20px;
  border-bottom: 1px solid var(--borde);
}
.modal-cabecera h2 {
  margin: 0 0 4px;
  font-family: var(--display);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.modal-cuerpo { overflow-y: auto; padding-bottom: 8px; }
/* Mismo motivo que con el cajón: en el teléfono, un modal abierto dejaba
   arrastrar la página de debajo. */
body.con-modal {
  position: fixed;
  left: 0;
  right: 0;
  width: 100%;
  overflow: hidden;
}

.vig-cifras {
  display: flex;
  gap: 26px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--linea);
}
.vig-cifras .serie-dato-v { font-size: 22px; }

.vig-cuenta {
  padding: 16px 20px;
  border-bottom: 1px solid var(--linea);
}
/* Denunciable: acoso o ataque por género, que es lo que una plataforma
   tramita. El resto es desacuerdo y no se marca igual. */
.vig-cuenta[data-denunciable="true"] { background: var(--tinte-error-suave); }
.vig-cuenta .serie-datos { border-top: none; padding-top: 8px; margin-top: 8px; }
.vig-prueba { padding: 8px 0; border-bottom: 1px solid var(--linea); }
.vig-prueba:last-child { border-bottom: none; }

@media (max-width: 620px) {
  .modal { padding: 0; }
  .modal-caja { max-height: 100vh; height: 100%; border-radius: 0; border: none; }
  .vig-cifras { gap: 18px; }
}

/* --- Iconos del menú ------------------------------------------------------ */
.icono-menu { flex: none; opacity: .7; transition: opacity .18s ease; }
.menu a:hover .icono-menu { opacity: 1; }
.menu a[aria-current="page"] .icono-menu { opacity: 1; color: var(--senal); }

/* --- Engranaje de la ficha ------------------------------------------------
   La ficha de la Persona no es una sección que se visite a diario, pero es lo
   que orienta todo el análisis: vive a un clic del nombre del cliente. */
.engranaje {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radio-chico);
  background: transparent;
  color: var(--texto-tenue);
  cursor: pointer;
  transition: color .18s ease, border-color .18s ease, transform .35s ease;
}
.engranaje:hover,
.engranaje:focus-visible {
  color: var(--senal);
  border-color: var(--borde-vivo);
  transform: rotate(45deg);
  outline: none;
}

/* --- Ficha en solo lectura -------------------------------------------------
   El estado por defecto es mirar, no escribir: un campo que se toca sin querer
   al leer cambia cómo se juzga cada texto que entre después. */
.formulario[data-editando="false"] input,
.formulario[data-editando="false"] textarea,
.formulario[data-editando="false"] select {
  border-color: transparent;
  background: var(--fondo-hundido);
  color: var(--texto-medio);
  cursor: default;
}
.formulario[data-editando="false"] input:focus,
.formulario[data-editando="false"] textarea:focus {
  outline: none;
  border-color: var(--borde);
}
/* El botón de guardar no tiene sentido si no se está editando. */
.formulario[data-editando="false"] button[type="submit"] { display: none; }

/* --- Campos de la ficha ----------------------------------------------------
   El modal tiene scroll propio: es preferible un campo alto y legible dentro
   de una caja que se desplaza, a un campo de dos líneas con scroll interno
   donde hay que arrastrar para leer una biografía. El alto exacto lo fija el
   guion según el contenido; esto es el mínimo. */
#persona-cuerpo textarea {
  min-height: 64px;
  line-height: 1.6;
  overflow-y: hidden;
  resize: vertical;
}
/* En solo lectura el campo no debe parecer un cuadro de escritura: se lee
   como el párrafo que es. */
.formulario[data-editando="false"] textarea { resize: none; }

/* La rejilla de la ficha respira: campos largos en una sola columna, cortos
   de a dos o tres. */
#persona-cuerpo .campos { gap: 18px; }

/* La ayuda cuelga del campo sin empujar al vecino: pertenece a la etiqueta,
   no a la rejilla, así que ocupa su tercera fila y no altera la altura de la
   fila de al lado. */
.formulario label > .ayuda { grid-row: 3; margin: 0; }

/* --- Selector de día -------------------------------------------------------
   Calendario propio en vez de `<input type="date">`: el nativo deja elegir
   cualquier fecha del año, y aquí solo tienen sentido las que tienen
   contenido. El punto bajo cada número marca el volumen de ese día, así se
   elige mirando dónde ocurrió algo en vez de probando fechas. */
.campo-fecha { position: relative; }

.fecha-disparador {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 9px 13px;
  border: 1px solid var(--borde-vivo);
  border-radius: var(--radio-chico);
  background: var(--fondo-hundido);
  color: var(--texto);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: border-color .18s ease;
}
.fecha-disparador:hover,
.fecha-disparador[data-abierto="true"] { border-color: var(--senal); }
.fecha-disparador .rotulo-tec { color: var(--texto-tenue); }
.fecha-rotulo { font-variant-numeric: tabular-nums; }
.fecha-flecha { color: var(--texto-tenue); font-size: 10px; }

.fecha-popover {
  position: absolute;
  z-index: 12;
  top: calc(100% + 8px);
  left: 0;
  width: 268px;
  padding: 14px;
  border: 1px solid var(--borde-vivo);
  border-radius: var(--radio);
  background: var(--fondo-elevado);
  box-shadow: 0 24px 60px -30px #000;
  animation: fecha-entra .16s ease;
}
@keyframes fecha-entra {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .fecha-popover { animation: none; } }

.fecha-cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.fecha-mes {
  font-family: var(--display);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.fecha-nav {
  width: 24px;
  height: 24px;
  border: 1px solid transparent;
  border-radius: var(--radio-chico);
  background: transparent;
  color: var(--texto-medio);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.fecha-nav:hover { color: var(--senal); border-color: var(--borde-vivo); }

.fecha-rejilla {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.fecha-dow {
  font-family: var(--mono);
  font-size: 9px;
  text-align: center;
  padding-bottom: 6px;
  color: var(--texto-tenue);
}
.fecha-dia {
  position: relative;
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
  border-radius: var(--radio-chico);
  background: transparent;
  color: var(--texto);
  font-family: var(--mono);
  font-size: 11.5px;
  cursor: pointer;
  transition: background-color .14s ease, border-color .14s ease;
}
/* Un día sin datos no se puede elegir y se ve que no se puede: no hay nada
   que mirar ahí, y dejar pulsarlo produciría una pantalla vacía engañosa. */
.fecha-dia:disabled { color: var(--texto-tenue); opacity: .35; cursor: default; }
.fecha-dia:not(:disabled):hover { background: var(--senal-suave); }
.fecha-dia[data-hoy="true"] { border-color: var(--borde-vivo); }
.fecha-dia[data-elegida="true"] {
  background: var(--senal);
  color: var(--fondo);
  font-weight: 700;
}
.fecha-punto {
  position: absolute;
  bottom: 3px;
  left: 50%;
  transform: translateX(-50%);
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--senal);
}
.fecha-dia[data-elegida="true"] .fecha-punto { background: var(--fondo); opacity: 1 !important; }

.fecha-pie {
  display: flex;
  gap: 8px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--linea);
}
.fecha-pie .boton { flex: 1; justify-content: center; padding: 6px 10px; font-size: 11.5px; }

/* Buscador: es el único campo de la fila donde se escribe, así que ocupa dos
   columnas de la rejilla en vez de pedir un ancho mínimo propio —eso último
   rompía la uniformidad de las columnas y descuadraba toda la hilera. El
   aspecto del control ya lo fija `.filtros input`. */
.campo-buscador { grid-column: span 2; }
.campo-buscador input::placeholder { color: var(--texto-tenue); }

/* Buscador suelto, fuera de la rejilla de `.filtros`: en Vídeos es el primer
   control de la vista, no uno más entre varios. */
.buscador-grande {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 38px;
  margin-bottom: 10px;
  padding: 0 12px;
  background: var(--fondo-hundido);
  border: 1px solid var(--borde-vivo);
  border-radius: var(--radio-chico);
  color: var(--texto-tenue);
}
.buscador-grande:focus-within { border-color: var(--senal); }
/* Tamaño en el CSS y no solo en el atributo del SVG: sin `width`/`height`
   propios, un SVG con `viewBox` se estira al ancho disponible, y una lupa de
   300px tapaba el buscador entero. Ya pasó al añadir el de los chats. */
.buscador-grande svg { flex: none; width: 14px; height: 14px; }
.buscador-grande input {
  flex: 1;
  min-width: 0;
  background: none;
  border: 0;
  outline: none;
  color: var(--texto);
  font: inherit;
  font-size: 13px;
}
.buscador-grande input::placeholder { color: var(--texto-tenue); }

@media (max-width: 620px) {
  .campo-buscador { grid-column: 1 / -1; }
}

/* --- Parámetros de generación de voz --------------------------------------
   Deslizador con los dos extremos rotulados. «Estabilidad 0,5» no le dice
   nada a quien va a locutar un informe; «más expresiva ← → más monótona», sí. */
.parametros-voz {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 16px;
}
.parametro-cabecera {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 6px;
}
/* Cada parámetro es un `<label>`, igual que los demás campos: el rótulo
   hereda la tipografía del formulario en vez de imitarla, así que si mañana
   cambia el estilo de las etiquetas, cambian todas a la vez. */
.parametro { display: block; }
.parametro-nombre { font: inherit; color: inherit; }
.parametro-valor {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--texto);
  font-variant-numeric: tabular-nums;
}

.parametro-rango {
  width: 100%;
  height: 3px;
  appearance: none;
  border-radius: 2px;
  background: var(--borde-vivo);
  cursor: pointer;
}
.parametro-rango::-webkit-slider-thumb {
  appearance: none;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--senal);
  border: 2px solid var(--fondo-elevado);
  box-shadow: 0 0 0 1px var(--senal);
  cursor: grab;
}
.parametro-rango::-moz-range-thumb {
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--senal);
  border: 2px solid var(--fondo-elevado);
  cursor: grab;
}
.parametro-rango:focus-visible { outline: 2px solid var(--senal); outline-offset: 4px; }

.parametro-extremos {
  display: flex;
  justify-content: space-between;
  margin-top: 5px;
  font-size: 9.5px;
  letter-spacing: .02em;
  color: var(--texto-tenue);
}

/* La especificidad importa: `.formulario input { width: 100% }` ganaba a
   `.parametro-interruptor { width: 36px }` y el interruptor se estiraba a
   440 px, con aspecto de barra ámbar. Se sube el selector al mismo nivel. */
/* Interruptor. Es el componente transversal del sistema de diseño, así que
   hay una sola definición y no una por pantalla. La pista se tiñe y la
   bolita se enciende en ámbar; la versión anterior lo hacía al revés
   —pista ámbar sólida, bolita oscura— y encendida se leía como una barra
   de progreso llena más que como un interruptor. */
.formulario .parametro-interruptor,
.parametro-interruptor,
.interruptor {
  appearance: none;
  /* `flex: none` es imprescindible: dentro de la cabecera flexible el
     interruptor se estiraba a todo el ancho y se veía como una barra ámbar. */
  flex: none;
  width: 38px;
  height: 22px;
  border-radius: 11px;
  box-sizing: border-box;
  background: var(--fondo-hundido);
  border: 1px solid var(--borde-vivo);
  position: relative;
  cursor: pointer;
  transition: background-color .2s ease, border-color .2s ease;
}
.parametro-interruptor::after,
.interruptor::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--texto-tenue);
  transition: transform .2s ease, background-color .2s ease;
}
.parametro-interruptor:checked,
.interruptor:checked {
  background: var(--senal-suave);
  border-color: color-mix(in oklab, var(--senal) 50%, transparent);
}
.parametro-interruptor:checked::after,
.interruptor:checked::after { transform: translateX(16px); background: var(--senal); }
.interruptor:focus-visible { outline: 2px solid var(--senal); outline-offset: 2px; }

/* Saldo de generación de voz. El color avisa cuando queda poco; en gris
   cuando el proveedor no deja leer el saldo, para no simular una medición
   que no tenemos. */
.cuota { font-variant-numeric: tabular-nums; cursor: help; }
.cuota strong { color: var(--texto); font-family: var(--mono); }
.cuota[data-nivel="bajo"] strong    { color: var(--estado-warning); }
.cuota[data-nivel="critico"] strong { color: var(--estado-error); }
.cuota[data-nivel="desconocido"]    { color: var(--texto-tenue); font-style: italic; }

/* --- Taller de voz ---------------------------------------------------------
   Texto a la izquierda, ajustes a la derecha y a la misma altura: apilados,
   había que desplazarse para ver el efecto de un control sobre lo que se
   está escribiendo. */
.voz-taller {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(280px, 1fr);
  gap: 22px;
  align-items: stretch;
}
/* Las dos columnas se igualan solas: la de ajustes marca el alto —depende de
   cuántos controles declare el motor— y el área de texto se estira hasta ahí.
   Fijar un alto a mano obliga a corregirlo cada vez que cambia un parámetro. */
.voz-texto { display: grid; grid-template-rows: auto 1fr; gap: 14px; }
/* El selector lleva `.formulario` a propósito. La regla global
   `.formulario label { align-content: start }` —que alinea los campos arriba
   de su fila— tiene más especificidad que una clase suelta, y ganaba: el área
   de texto se quedaba en su alto mínimo y dejaba 240 px de vacío bajo ella
   mientras la columna de ajustes seguía bajando. Aquí sí debe estirarse. */
.formulario .voz-campo-texto {
  display: grid;
  grid-template-rows: auto 1fr;
  gap: 6px;
  align-content: stretch;
}
.voz-campo-texto textarea { height: 100%; min-height: 220px; resize: none; }

.voz-ajustes {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 16px 18px;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--fondo-hundido);
}
/* Los cinco controles caben sin desplazarse: la explicación de cada uno vive
   en su tooltip, no en un párrafo debajo. */
.voz-ajustes .parametros-voz { grid-template-columns: 1fr; gap: 15px; }
.voz-ajustes label { font-size: 10.5px; letter-spacing: .07em; }
.voz-ajustes select { padding: 7px 10px; font-size: 12.5px; }
/* El interruptor comparte fila con su nombre, no ocupa una propia. */
.voz-ajustes .parametro:last-child .parametro-cabecera { margin-bottom: 0; }

@media (max-width: 860px) {
  .voz-taller { grid-template-columns: 1fr; }
  .voz-ajustes { max-height: none; }
  .voz-texto { min-height: 0; }
}

/* Pie del formulario: la ayuda a la izquierda y la acción a la derecha, en
   una fila que cierra el bloque en vez de dejar el botón suelto bajo el
   vacío. */
.voz-pie {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  margin-top: 4px;
  padding-top: 16px;
  border-top: 1px solid var(--linea);
}
.voz-pie .ayuda { margin: 0; max-width: 52ch; }
.voz-pie .boton { flex: none; }

/* --- Historial de audios --------------------------------------------------- */
.audio-cabecera {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 6px;
}
.audio-titulo { font-size: 14px; color: var(--texto); }
.audio-texto {
  margin: 10px 0 0;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--texto-tenue);
}

/* --- Reproductor propio ----------------------------------------------------
   El control nativo cambia de aspecto en cada sistema y no encaja con nada de
   esta interfaz. */
.reproductor {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 10px;
  padding: 9px 13px;
  border: 1px solid var(--borde);
  border-radius: 999px;
  background: var(--fondo-hundido);
  max-width: 460px;
}
.repro-boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  flex: none;
  border: 1px solid var(--senal);
  border-radius: 50%;
  background: var(--senal-suave);
  color: var(--senal);
  cursor: pointer;
  transition: background-color .18s ease;
}
.repro-boton:hover { background: var(--senal); color: var(--fondo); }
.reproductor[data-sonando="true"] .repro-boton {
  background: var(--senal);
  color: var(--fondo);
}

.repro-barra {
  position: relative;
  flex: 1;
  height: 4px;
  border-radius: 2px;
  background: var(--borde-vivo);
  cursor: pointer;
}
/* Zona de clic más alta que la barra: acertarle a 4 px con el ratón es
   imposible y saltar a un punto es lo que más se usa al revisar una toma. */
.repro-barra::before { content: ''; position: absolute; inset: -9px 0; }
.repro-avance {
  height: 100%;
  width: 0;
  border-radius: 2px;
  background: var(--senal);
  transition: width .1s linear;
}
.repro-tiempo {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--texto-tenue);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.repro-descarga {
  display: inline-flex;
  color: var(--texto-tenue);
  transition: color .18s ease;
}
.repro-descarga:hover { color: var(--senal); }

/* Rótulo del grupo de controles. Habla con la misma voz que las etiquetas de
   campo, con una línea que separa el bloque de la selección de voz. */
.grupo-parametros { display: grid; gap: 14px; }
.grupo-titulo {
  display: block;
  padding-top: 12px;
  border-top: 1px solid var(--borde);
  font-size: 10.5px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}

/* --- Mandos del diagrama de operación ------------------------------------- */
/* Actividad y Capacidades eran dos tarjetas al final del panel: se leían como
   contenido y en realidad son instrumentos del pipeline que dibuja el
   diagrama. Aquí van como mandos suyos, cada uno con su lectura a la vista
   para que abrirlos sea una decisión y no un trámite. */
.diagrama-mandos {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.mando {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.mando-cifra {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  padding: 1px 6px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--texto) 8%, transparent);
  color: var(--texto-medio);
}
.mando-cifra[data-tono="bien"]  { color: var(--estado-success); }
.mando-cifra[data-tono="aviso"] { color: var(--estado-warning); }

/* Punto de latido: gris cuando no pasa nada, encendido y pulsando durante
   unos segundos tras cada evento del planificador. */
.mando-pulso {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--texto) 25%, transparent);
  transition: background 180ms ease;
}
.mando-pulso[data-vivo="true"] {
  background: var(--senal);
  animation: mando-latido 1.2s ease-out infinite;
}

@keyframes mando-latido {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--senal) 55%, transparent); }
  100% { box-shadow: 0 0 0 7px transparent; }
}

@media (prefers-reduced-motion: reduce) {
  .mando-pulso[data-vivo="true"] { animation: none; }
}

/* El registro de actividad es una tabla de cuatro columnas: necesita más
   ancho que una ficha de lectura. */
.modal-caja--ancha { width: min(980px, 100%); }

@media (max-width: 720px) {
  /* Tres mandos no caben en una línea de móvil: sin envolver, el tercero
     —«Ocultar diagrama», el rótulo más largo— se salía del panel. Los dos
     medidores comparten la primera fila y el interruptor ocupa la segunda. */
  .diagrama-mandos { margin-left: 0; width: 100%; flex-wrap: wrap; }
  .diagrama-mandos .mando { flex: 1; justify-content: center; }
  .diagrama-mandos #toggle-diagrama { flex: 1 0 100%; justify-content: center; }
}

/* --- Subpestañas de configuración ---------------------------------------- */
/* Fuentes, alertas y bot comparten una entrada de menú y se reparten aquí. No
   son secciones distintas de la aplicación: son tres pantallas del mismo
   trabajo, que es dejar el sistema montado. */
/* Vuelta al hub desde un panel a pantalla completa. */
.volver {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  min-height: 32px;
  padding: 4px 10px;
  margin-bottom: 10px;
  border: 1px solid var(--borde-vivo);
  border-radius: var(--radio-chico);
  color: var(--texto-medio);
  font-size: 11px;
  text-decoration: none;
}
.volver:hover { color: var(--senal); border-color: var(--senal); }

.subpestanas {
  display: flex;
  gap: 4px;
  margin-bottom: 18px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--linea);
  overflow-x: auto;
}
.subpestanas a {
  padding: 7px 14px;
  border-radius: var(--radio-chico);
  font-size: 13px;
  color: var(--texto-medio);
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .15s ease, color .15s ease;
}
.subpestanas a:hover { color: var(--texto); background: var(--fondo-hundido); }
.subpestanas a[aria-current] {
  color: var(--senal);
  background: var(--senal-suave);
}

/* --- Encuestas ------------------------------------------------------------
   Cada entrega trae ficha metodológica, aviso de proyectabilidad, nota y una
   lista de mediciones. Separadas solo por una línea, la lista de una se leía
   como parte de la ficha de la siguiente. Mismo tratamiento que las fichas de
   vídeo: piezas sobre fondo hundido, separadas por aire y contraste. */
/* `#lista-encuestas` tuvo aquí una rejilla con fondo hundido y padding: era
   el contenedor de antes del rediseño y duplicaba a las tarjetas de ahora. */
.encuesta {
  padding: 16px 18px;
  border-bottom: none;
  border-radius: var(--radio);
  background: var(--fondo-elevado);
  box-shadow: var(--sombra-pieza);
}
/* El nombre de la encuestadora y la edición mandan sobre el resto de la
   ficha: es lo que se busca al recorrer la lista. */
.encuesta > .informe-cabecera strong { font-size: 14.5px; }

/* Dos acciones en la cabecera de un panel: van juntas y pegadas a la derecha,
   no repartidas por la fila. */
.botonera--cabecera { margin-left: auto; gap: 8px; }
@media (max-width: 620px) {
  .botonera--cabecera { margin-left: 0; width: 100%; }
  .botonera--cabecera .boton { flex: 1; justify-content: center; }
}

/* --- Paginador ------------------------------------------------------------
   Aparece solo cuando el filtro devuelve más de una página. La cuenta va en
   medio y en cifras: «11–20 de 34» dice a la vez dónde estás y cuánto queda,
   que es lo que hace falta para decidir si merece la pena seguir hojeando. */
.paginador {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 14px 18px;
  border-top: 1px solid var(--linea);
}
.paginador[hidden] { display: none; }
.paginador-cuenta {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--texto-medio);
  font-variant-numeric: tabular-nums;
}
.paginador .boton[disabled] { opacity: .35; cursor: not-allowed; }


/* La aplicación ya no necesita esconderse: `index.html` solo se entrega a
   quien tiene sesión —lo comprueba el proxy contra /api/auth/check— así que
   no hay nada que tapar. La cortina de CSS que había aquí daba una impresión
   de seguridad que no era tal: el marcado ya estaba en el cliente. */

/* --- Acceso ---------------------------------------------------------------
   Cubre la aplicación entera. Nada del sistema se pinta detrás mientras se
   decide si hay sesión: las cifras y los marcos con los que la atacan son el
   producto, y enseñar el esqueleto ya adelanta su forma. */
/* Toda regla `display` de esta hoja lleva su compañera `[hidden]` al lado.
   Sin ella el atributo no hace nada —solo aporta `display: none` desde la
   hoja del navegador, que cualquier regla del documento pisa— y el elemento
   se pinta igual. Aquí eso dejaba los dos velos visibles a la vez y el último
   del marcado tapando al otro: salía la pantalla de cambio de contraseña sin
   haber entrado. Ya había pasado con el velo del menú en móvil. */
/* --- Acceso: estilo app nativa -------------------------------------------
   La pantalla ES la aplicación, no una tarjeta flotando: marca arriba,
   campos rellenos con el rótulo dentro, y el CTA anclado abajo, donde está
   el pulgar. Medidas del mockup, hex a tokens. */
.acceso {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  justify-content: center;
  background:
    radial-gradient(120% 70% at 50% -10%, var(--senal-suave), transparent 60%),
    var(--fondo);
  overflow-y: auto;
}
.acceso[hidden] { display: none; }

/* Mientras no hay sesión, el fondo no se desplaza ni se ve a través. */
body.sin-sesion { overflow: hidden; }

.acceso-caja {
  width: min(400px, 100%);
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  padding: 0 28px;
  box-sizing: border-box;
}
/* En pantalla alta de escritorio el CTA no se va al fondo del monitor: la
   columna se compacta y se centra. Los tokens y las piezas no cambian. */
@media (min-height: 900px) {
  .acceso-caja { min-height: 0; margin: auto 0; padding: 48px 28px 36px; }
  .acceso-abajo { margin-top: 44px; }
}

.acceso-marca {
  margin-top: 72px;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.acceso-sello {
  width: 60px;
  height: 60px;
  color: var(--senal);
  animation: girar 120s linear infinite;
}
@keyframes girar { from { transform: rotate(0); } to { transform: rotate(360deg); } }
.acceso-titulo {
  margin: 6px 0 0;
  text-align: center;
  font-size: 18px;
  letter-spacing: .02em;
}

.acceso-campos {
  margin-top: 44px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Campo relleno con el rótulo dentro. */
.campo-lleno {
  display: block;
  padding: 8px 16px 10px;
  border-radius: 14px;
  background: var(--fondo-campo);
  border: 1px solid transparent;
}
.campo-lleno:focus-within { border-color: var(--borde-vivo); }
.campo-lleno-rotulo { display: block; font-size: 10.5px; color: var(--texto-tenue); }
.campo-lleno input {
  width: 100%;
  box-sizing: border-box;
  padding: 3px 0 0;
  background: none;
  border: none;
  outline: none;
  color: var(--texto);
  font: inherit;
  font-size: 15px;
}
.campo-lleno--clave { display: flex; align-items: center; gap: 10px; }
.campo-lleno-texto { flex: 1; min-width: 0; }
#campo-password[data-error="true"] {
  border-color: color-mix(in oklab, var(--estado-error) 50%, transparent);
}
/* --- Hub de configuración (acordeón) ------------------------------------

   Una fila por parcela del sistema. La nota bajo el nombre dice qué hay
   dentro sin abrirlo, y la insignia dice si hay algo que atender: son las
   dos cosas que evitan abrir las seis secciones a ver cuál se queja. */
.hub { display: flex; flex-direction: column; }
.hub-seccion { border-bottom: 1px solid var(--linea); }
.hub-seccion:last-child { border-bottom: none; }

.hub-fila {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 13px 2px;
  background: none;
  border: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.hub-fila:focus-visible { outline: 2px solid var(--senal); outline-offset: -2px; }

.hub-icono {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  background: var(--fondo-elevado);
  border: 1px solid var(--borde-vivo);
  color: var(--senal);
}
.hub-icono svg { width: 14px; height: 14px; }

.hub-texto { flex: 1; min-width: 0; }
.hub-nombre { display: block; font-size: 13px; font-weight: 600; }
.hub-nota {
  display: block;
  margin-top: 2px;
  font-size: 10.5px;
  color: var(--texto-tenue);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hub-insignia {
  flex: none;
  font-family: var(--mono);
  font-size: 9.5px;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--tinte-error);
  border: 1px solid color-mix(in oklab, var(--estado-error) 45%, transparent);
  color: var(--estado-error);
}
.hub-insignia[data-tono="aviso"] {
  background: var(--tinte-aviso);
  border-color: color-mix(in oklab, var(--estado-warning) 50%, transparent);
  color: var(--estado-warning);
}

.hub-chevron { flex: none; font-family: var(--mono); font-size: 11px; color: var(--texto-tenue); }

/* El cuerpo se alinea bajo el texto de la fila, no bajo el icono: la sangría
   es lo que hace leer el contenido como «de esta sección» y no como otra. */
.hub-cuerpo {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 0 2px 14px 43px;
}
.hub-cuerpo[hidden] { display: none; }
.hub-dato { margin: 0; font-size: 12px; color: var(--texto-medio); }
.hub-dato b { color: var(--texto); font-weight: 600; }
.hub-dato span { color: var(--texto-tenue); }
.hub-rota { margin: 0; font-size: 11.5px; color: var(--estado-error); }
.hub-pie { margin: 0; font-size: 10.5px; color: var(--texto-tenue); }

/* Contadores de Telegram: tres cifras mono en fila, la de pendientes en
   ámbar porque es la única sobre la que hay que hacer algo. */
.hub-cifras { display: flex; gap: 14px; }
.hub-cifra p { margin: 0; }
.hub-cifra-valor { font-family: var(--mono); font-size: 14px; font-weight: 600; color: var(--texto-medio); }
.hub-cifra[data-tono="senal"] .hub-cifra-valor { color: var(--senal); }
.hub-cifra-rotulo { font-size: 9.5px; color: var(--texto-tenue); }

.hub-cola {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 9px 11px;
  border: 1px solid color-mix(in oklab, var(--senal) 35%, transparent);
  background: var(--tinte-aviso-suave);
  border-radius: 9px;
}
.hub-cola-rotulo {
  margin: 0;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: .1em;
  color: var(--senal);
}
.hub-cola-fila { display: flex; align-items: center; gap: 8px; }
.hub-cola-nombre {
  margin: 0;
  flex: 1;
  min-width: 0;
  font-size: 11.5px;
  color: var(--texto-medio);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Regla con interruptor: el nombre es un botón que abre la hoja de edición,
   el interruptor solo enciende y apaga. Separarlos evita que tocar para
   leer acabe desactivando un aviso. */
.hub-regla { display: flex; align-items: center; gap: 10px; }
.hub-regla-abrir {
  flex: 1;
  min-width: 0;
  background: none;
  border: none;
  padding: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.hub-regla-nombre { margin: 0; font-size: 12px; font-weight: 600; }
.hub-regla-detalle { margin: 2px 0 0; font-size: 10.5px; color: var(--texto-tenue); }

/* Chips de elección múltiple: se tocan para encender y apagar. */
.chips-eleccion { display: flex; flex-wrap: wrap; gap: 6px; }
.chip-eleccion {
  padding: 5px 12px;
  min-height: 30px;
  border-radius: 999px;
  border: 1px solid var(--borde-vivo);
  background: none;
  color: var(--texto-tenue);
  font: inherit;
  font-size: 11px;
  cursor: pointer;
}
.chip-eleccion[aria-pressed="true"] {
  background: var(--senal-suave);
  border-color: color-mix(in oklab, var(--senal) 50%, transparent);
  color: var(--senal);
}
.chip-eleccion:hover { border-color: var(--senal); }

.mencion-video {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 6px 0;
  padding: 6px 9px;
  border: 1px solid var(--borde);
  border-radius: var(--radio-chico);
  background: var(--fondo-hundido);
}
.mencion-video svg { width: 16px; height: 16px; flex: none; color: var(--texto-tenue); }
.mencion-video p { margin: 0; font-size: 10.5px; color: var(--texto-tenue); }

.rotulo-hallado {
  margin: 0 0 8px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .1em;
  color: var(--ia);
}

.pub-rotulo-citas {
  margin: 12px 0 6px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--texto-medio);
}

.serie-pista {
  margin: 6px 0 0;
  font-size: 10.5px;
  color: var(--texto-tenue);
}

/* --- Redes sociales: la red seleccionada --------------------------------
   Medidas calcadas del mockup; solo cambian los hex por tokens. */
.red-cabecera {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 12px 0 14px;
  border-bottom: 1px solid var(--linea);
}
.red-nombre { margin: 0; font-size: 16px; font-weight: 700; }
.red-seguidores { margin: 3px 0 0; font-size: 11px; color: var(--texto-tenue); }
.red-balance { text-align: right; }
.red-neto {
  font-family: var(--mono);
  font-size: 26px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.red-neto[data-tono="alerta"] { color: var(--estado-error); }
.red-neto[data-tono="bien"] { color: var(--estado-success); }
.red-neto-sub { font-size: 10.5px; color: var(--texto-tenue); }

.red-veredicto { padding: 16px 0; border-bottom: 1px solid var(--linea); }
.red-veredicto-alto { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.red-veredicto-alto b { font-size: 12px; }
.red-veredicto-muestra { font-size: 11px; color: var(--texto-tenue); }
.red-veredicto-pie { display: flex; gap: 12px; margin-top: 8px; font-size: 11.5px; }
.red-veredicto-pie span:nth-child(1) { color: var(--estado-success); }
.red-veredicto-pie span:nth-child(2) { color: var(--estado-error); }
.red-aviso { margin: 8px 0 0; font-size: 11px; color: var(--estado-warning); }

.red-seccion { display: flex; align-items: baseline; gap: 8px; padding: 20px 0 6px; }
.red-seccion-tic {
  width: 14px;
  height: 3px;
  border-radius: 2px;
  background: var(--senal);
  transform: translateY(-3px);
}
.red-seccion-rotulo { margin: 0; font-size: 13px; font-weight: 700; letter-spacing: .1em; }
.red-seccion-nota { margin: 2px 0 10px; font-size: 11px; color: var(--texto-tenue); }

.pub-estrella {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: 6px;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--senal-suave);
  border: 1px solid color-mix(in oklab, var(--senal) 40%, transparent);
  font-size: 10.5px;
  color: var(--senal);
}

.red-sueltos { margin-top: 18px; }
.red-sueltos > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border: 1px solid var(--borde-vivo);
  border-radius: 10px;
  color: var(--texto-medio);
  font-size: 12px;
  cursor: pointer;
  list-style: none;
}
.red-sueltos > summary::-webkit-details-marker { display: none; }
.red-sueltos-chevron { font-family: var(--mono); color: var(--texto-tenue); }
.red-sueltos[open] .red-sueltos-chevron { transform: rotate(90deg); }
.red-sueltos-cifra { font-family: var(--mono); color: var(--senal); margin-left: auto; }
.red-sueltos[open] > summary { border-radius: 10px 10px 0 0; }
.red-sueltos-cuerpo {
  margin: 0 8px;
  padding: 12px 14px;
  border: 1px solid var(--borde-vivo);
  border-top: none;
  border-radius: 0 0 10px 10px;
}


/* --- Operación ----------------------------------------------------------- */

/* El titular de estado. Tres tonos y no dos: «bien» y «roto» dejaban fuera el
   caso más común —una fuente caída mientras el resto corre—, que no es avería
   ni normalidad, y presentarlo como cualquiera de las dos engaña. */
.estado-general {
  padding: 14px;
  border: 1px solid var(--borde);
  border-radius: 12px;
  background: var(--fondo-elevado);
}
.estado-general-alto { display: flex; align-items: center; gap: 9px; }
.estado-general-punto {
  width: 9px;
  height: 9px;
  flex: none;
  border-radius: 50%;
  background: var(--estado-idle);
}
.estado-general-titular { margin: 0; font-size: 14px; font-weight: 700; }
.estado-general-texto {
  margin: 8px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--texto-medio);
}
.estado-general[data-tono="ok"] { border-color: color-mix(in oklab, var(--estado-success) 40%, var(--borde)); }
.estado-general[data-tono="ok"] .estado-general-punto { background: var(--estado-success); }
.estado-general[data-tono="aviso"] {
  border-color: color-mix(in oklab, var(--estado-warning) 45%, transparent);
  background: var(--tinte-aviso-suave);
}
.estado-general[data-tono="aviso"] .estado-general-punto {
  background: var(--estado-warning);
  animation: latido 2s ease-in-out infinite;
}
.estado-general[data-tono="error"] {
  border-color: color-mix(in oklab, var(--estado-error) 50%, transparent);
  background: var(--tinte-error-suave);
}
.estado-general[data-tono="error"] .estado-general-punto { background: var(--estado-error); }
.estado-general[data-tono="espera"] .estado-general-punto { background: var(--texto-tenue); }
@media (prefers-reduced-motion: reduce) {
  .estado-general[data-tono="aviso"] .estado-general-punto { animation: none; }
}

.rotulo-seccion--suelto { margin: 0; padding-top: 0; border-top: none; }
.rotulo-fila {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 20px 0 8px;
  padding-top: 14px;
  border-top: 1px solid var(--linea);
}
.rotulo-dato { font-size: 10.5px; color: var(--texto-tenue); }
.rotulo-dato[data-tono="ok"] { color: var(--estado-success); }
.rotulo-dato[data-tono="aviso"] { color: var(--estado-warning); }

/* Tira del ciclo: una casilla por etapa. */
.tira { display: flex; gap: 4px; align-items: stretch; }
.tira-etapa { flex: 1; min-width: 0; text-align: center; }
.tira-caja {
  display: grid;
  place-items: center;
  height: 26px;
  border: 1px solid var(--borde);
  border-radius: 8px;
  background: var(--fondo-elevado);
}
.tira-etapa[data-estado="active"] .tira-caja { border-color: var(--senal); }
.tira-etapa[data-estado="error"] .tira-caja { border-color: var(--estado-error); }
.tira-etapa[data-estado="success"] .tira-caja { border-color: color-mix(in oklab, var(--estado-success) 45%, transparent); }
.tira-nombre {
  margin: 6px 0 0;
  font-size: 9.5px;
  line-height: 1.3;
  color: var(--texto-medio);
  overflow: hidden;
  text-overflow: ellipsis;
}
.tira-dato { margin: 1px 0 0; font-family: var(--mono); font-size: 8.5px; color: var(--texto-tenue); }

/* Cronología: hilo vertical con un punto por hito. */
.cronologia {
  list-style: none;
  margin: 0;
  padding: 0 0 0 16px;
  margin-left: 9px;
  border-left: 1px solid var(--borde-vivo);
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.cronologia-vacia { font-size: 11.5px; color: var(--texto-tenue); }
.cronologia-hito { position: relative; }
.cronologia-punto {
  position: absolute;
  left: -21px;
  top: 4px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--estado-idle);
}
.cronologia-hito[data-estado="active"] .cronologia-punto { background: var(--senal); }
.cronologia-hito[data-estado="success"] .cronologia-punto { background: var(--estado-success); }
.cronologia-hito[data-estado="error"] .cronologia-punto { background: var(--estado-error); }
.cronologia-alto { display: flex; align-items: baseline; gap: 8px; }
.cronologia-hora { margin: 0; font-family: var(--mono); font-size: 10px; color: var(--texto-tenue); }
.cronologia-texto { margin: 0; flex: 1; font-size: 12px; color: var(--texto-medio); }
.cronologia-detalle { margin: 4px 0 0; font-size: 10.5px; color: var(--texto-tenue); }

.boton--ancho { width: 100%; justify-content: center; margin-top: 12px; }

/* Fuente que falla: qué es, desde cuándo, por qué y qué hacer. */
.fuente-rota {
  padding: 11px 13px;
  border: 1px solid color-mix(in oklab, var(--estado-warning) 45%, transparent);
  border-radius: 10px;
  background: var(--fondo-elevado);
}
.fuente-rota + .fuente-rota { margin-top: 8px; }
.fuente-rota-alto { display: flex; align-items: center; gap: 8px; }
.fuente-rota-nombre { margin: 0; flex: 1; min-width: 0; font-size: 12px; font-weight: 600; }
.fuente-rota-desde { font-family: var(--mono); font-size: 10px; color: var(--estado-warning); }
.fuente-rota-motivo { margin: 6px 0 0; font-size: 11px; line-height: 1.5; color: var(--texto-medio); }
.fuente-rota-acciones { display: flex; gap: 12px; margin-top: 8px; }

.enlace-accion {
  padding: 0;
  background: none;
  border: none;
  font: inherit;
  font-size: 11px;
  color: var(--senal);
  text-decoration: none;
  cursor: pointer;
}
.enlace-accion:hover { text-decoration: underline; }
.enlace-accion--tenue { color: var(--texto-tenue); }
.enlace-accion[disabled] { color: var(--texto-tenue); cursor: default; text-decoration: none; }

.capacidades { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.capacidad {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 11px;
  border: 1px solid var(--borde);
  border-radius: 9px;
  background: var(--fondo-elevado);
}
.capacidad p { margin: 0; font-size: 11px; color: var(--texto-medio); }
.capacidad[data-activa="false"] p { color: var(--texto-tenue); }

/* --- Vídeos: los promedios del top --------------------------------------
   La rejilla centrada del mockup: cuatro columnas, cifra en mono coloreada
   por bondad y el nombre en versalitas debajo; la escala una sola vez en la
   línea centrada que cierra el bloque. */
/* Con las cuatro dimensiones del mockup era una rejilla; los datos reales
   traen seis y la rejilla partía en dos filas cojas. Carrusel: cuatro a la
   vista y las restantes deslizando, con imán por celda para que el corte
   nunca deje media cifra. */
.vd-promedios {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 25%;
  gap: 0;
  padding: 14px 0 10px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.vd-promedios::-webkit-scrollbar { display: none; }
.vd-prom-puntos { display: flex; justify-content: center; gap: 6px; margin: 2px 0 10px; }
.vd-prom-puntos[hidden] { display: none; }
.vd-prom { text-align: center; scroll-snap-align: start; padding: 0 4px; }
.vd-prom-valor {
  margin: 0;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 17px;
  font-weight: 600;
}
.vd-prom-valor[data-tono="bien"]   { color: var(--estado-success); }
.vd-prom-valor[data-tono="aviso"]  { color: var(--estado-warning); }
.vd-prom-valor[data-tono="alerta"] { color: var(--estado-error); }
.vd-prom-nombre {
  margin: 3px 0 0;
  font-size: 9.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}
.vd-escala {
  margin: 0 0 4px;
  padding-bottom: 12px;
  font-size: 10px;
  color: var(--texto-tenue);
  text-align: center;
  border-bottom: 1px solid var(--borde);
}
.vd-resumen { margin: 0 0 12px; font-size: 11px; color: var(--texto-tenue); }

/* --- Vídeos: la tarjeta de aparición ------------------------------------
   Medidas del mockup; hex a tokens. */
.video {
  background: var(--fondo-elevado);
  border: 1px solid var(--borde);
  border-radius: 12px;
  overflow: hidden;
  /* Hija de una rejilla: sin esto se estira al ancho de su contenido y se
     sale de la pantalla. El mismo fallo ya corregido en Encuestas. */
  min-width: 0;
  max-width: 100%;
}
.video-cab { padding: 12px 14px; cursor: pointer; }
.video-cab:focus-visible { outline: 2px solid var(--senal); outline-offset: -2px; }
.video-fila { display: flex; gap: 12px; }
.video-miniatura {
  position: relative;
  flex: none;
  width: 92px;
  height: 56px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  border: 1px solid var(--borde);
  background: linear-gradient(135deg, var(--fondo-activo), var(--fondo-hundido));
  color: var(--estado-idle);
}
.video-miniatura img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
.video-miniatura svg { width: 20px; height: 20px; }
/* Con portada real, el play de respaldo estorba encima de la imagen. */
.video-miniatura:has(img) svg { display: none; }
/* …y la duración tiene que quedar por encima de la portada. */
.video-dur { z-index: 1; }

/* Tarjeta expandida: la portada ocupa el ancho del contenedor con su play
   encima —aquí sí, porque ahora es un reproductor— y el título baja
   debajo. Lo demás queda donde estaba. */
.video[data-abierto="true"] .video-fila { flex-direction: column; }
.video[data-abierto="true"] .video-miniatura {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
}
.video[data-abierto="true"] .video-miniatura:has(img) svg {
  display: block;
  z-index: 1;
  width: 44px;
  height: 44px;
  padding: 10px;
  box-sizing: content-box;
  border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  color: #fff;
}
.video-miniatura iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: inherit;
}
.video-dur {
  position: absolute;
  bottom: 4px;
  right: 5px;
  padding: 1px 5px;
  border-radius: 4px;
  background: rgba(0, 0, 0, .65);
  font-family: var(--mono);
  font-size: 9px;
  color: var(--texto-medio);
}
.video-textos { min-width: 0; }
.video-titulo {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.video-meta { margin: 5px 0 0; font-family: var(--mono); font-size: 10.5px; color: var(--texto-tenue); }
.video-pendiente { margin: 10px 0 0; font-size: 11.5px; color: var(--estado-warning); }
.video-resumen {
  margin: 10px 0 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--texto-medio);
}
.video-resumen[data-abierto="false"] {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.video-pieza { display: flex; align-items: center; gap: 8px; margin-top: 9px; font-size: 10.5px; }
.video-mejor { font-family: var(--mono); color: var(--estado-success); white-space: nowrap; }
.video-peor { font-family: var(--mono); color: var(--estado-error); white-space: nowrap; }
.video-relleno { flex: 1; }
.video-chevron { font-family: var(--mono); color: var(--texto-tenue); }

.video-analisis {
  border-top: 1px dashed var(--borde);
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.video-analisis[hidden] { display: none; }

.video-dims { display: flex; flex-direction: column; gap: 7px; }
.video-dim { display: flex; align-items: center; gap: 10px; }
.video-dim-nombre { flex: none; width: 76px; font-size: 10.5px; color: var(--texto-medio); }
.video-dim-barra {
  flex: 1;
  height: 5px;
  border-radius: 3px;
  background: var(--linea);
  overflow: hidden;
  display: block;
}
.video-dim-barra span { display: block; height: 100%; }
.video-dim-barra span[data-tono="bien"] { background: var(--estado-success); }
.video-dim-barra span[data-tono="aviso"] { background: var(--estado-warning); }
.video-dim-barra span[data-tono="alerta"] { background: var(--estado-error); }
.video-dim-valor { flex: none; width: 34px; text-align: right; font-family: var(--mono); font-size: 10.5px; }
.video-dim-valor[data-tono="bien"] { color: var(--estado-success); }
.video-dim-valor[data-tono="aviso"] { color: var(--estado-warning); }
.video-dim-valor[data-tono="alerta"] { color: var(--estado-error); }

.video-temas { display: flex; flex-wrap: wrap; gap: 6px; }
.video-tema {
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 10.5px;
  background: var(--ia-suave);
  border: 1px solid var(--ia-borde);
  color: var(--ia);
}

.video-rotulo {
  margin: 0 0 6px;
  font-size: 10px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}
.video-momento { display: flex; gap: 10px; margin-bottom: 8px; }
.video-momento-min {
  flex: none;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--senal);
  text-decoration: none;
}
a.video-momento-min:hover { text-decoration: underline; }
.video-momento-cita { margin: 0; font-size: 11.5px; line-height: 1.45; color: var(--texto-medio); }
.video-momento-porque { margin: 3px 0 0; font-size: 10.5px; line-height: 1.4; color: var(--texto-tenue); }
.video-mas {
  padding: 0;
  background: none;
  border: none;
  font: inherit;
  font-size: 11px;
  color: var(--senal);
  cursor: pointer;
}

.video-tab-visor { overflow: hidden; margin-top: 10px; transition: height .25s ease; }
@media (prefers-reduced-motion: reduce) { .video-tab-visor { transition: none; } }
.video-tab-pista { display: flex; transition: transform .25s ease; }
@media (prefers-reduced-motion: reduce) { .video-tab-pista { transition: none; } }
.video-tab-panel {
  flex: 0 0 100%;
  box-sizing: border-box;
  align-self: flex-start;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.video-item {
  background: var(--fondo-hundido);
  border: 1px solid var(--linea);
  border-radius: 8px;
  padding: 8px 11px;
}
.video-item p { margin: 0; font-size: 11.5px; line-height: 1.5; color: var(--texto-medio); }

.video-confianza { display: flex; align-items: center; gap: 8px; font-size: 10.5px; color: var(--texto-tenue); }
.video-confianza-barra {
  width: 80px;
  height: 4px;
  border-radius: 2px;
  background: var(--linea);
  overflow: hidden;
  display: block;
}
.video-confianza-barra span { display: block; height: 100%; background: var(--ia); }
.video-confianza-cifra { font-family: var(--mono); }
.video-parcial {
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 9.5px;
  background: rgba(138, 127, 74, .18);
  border: 1px solid rgba(138, 127, 74, .5);
  color: #b0a25e;
}

/* Botón primario sólido del rediseño: ámbar relleno, texto oscuro, 700.
   Es la acción principal de un formulario u hoja; el .boton normal (ámbar
   suave) queda para acciones secundarias con peso. Deshabilitado se apaga a
   fondo activo con texto tenue, como el mockup mientras «Generando…». */
.boton--primario {
  background: var(--senal);
  border-color: var(--senal);
  color: var(--sobre-senal);
  font-weight: 700;
}
.boton--primario:hover { background: var(--senal-clara); border-color: var(--senal-clara); color: var(--sobre-senal); }
.boton--primario:disabled {
  background: var(--fondo-activo);
  border-color: var(--fondo-activo);
  color: var(--texto-tenue);
}

/* Botón de la acción que destruye algo. Rojo de contorno y nunca relleno:
   relleno se lee como la acción recomendada, y aquí la recomendada es la
   otra. En la hoja de la grabación va el segundo, no el primero. */
.boton--peligro {
  border-color: color-mix(in oklab, var(--estado-error) 55%, transparent);
  color: var(--estado-error);
}
.boton--peligro:hover {
  border-color: var(--estado-error);
  background: var(--tinte-error-suave);
}

/* Botones de una hoja, apilados y a lo ancho: en el teléfono se responde con
   el pulgar y dos botones estrechos uno al lado del otro se tocan mal. */
.hoja-botones { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.hoja-botones .boton { justify-content: center; min-height: 44px; }

/* La contraseña provisional. Grande, en mono y seleccionable: se va a leer en
   voz alta por teléfono o a copiar, y en ambos casos hay que distinguir un
   cero de una O sin dudar. */
.clave-nueva {
  margin: 0;
  padding: 12px;
  text-align: center;
  border: 1px solid color-mix(in oklab, var(--senal) 45%, transparent);
  background: var(--senal-suave);
  border-radius: var(--radio);
  font-family: var(--mono);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: .06em;
  color: var(--senal);
  user-select: all;
  word-break: break-all;
}

/* Minuto de una intervención: salta a ese tramo de la grabación. */
.intervencion-minuto {
  padding: 1px 7px;
  border: 1px solid var(--borde-vivo);
  border-radius: 999px;
  background: none;
  color: var(--texto-medio);
  font-family: var(--mono);
  font-size: 10.5px;
  cursor: pointer;
}
.intervencion-minuto:hover { border-color: var(--senal); color: var(--senal); }

/* Etiqueta de cosa recién hecha por el modelo. Cian, como todo lo suyo. */
.etiqueta--ia {
  background: var(--ia-suave);
  border-color: var(--ia-borde);
  color: var(--ia);
}

/* --- Informes: contador de días, fases y programados --------------------- */
.paso { display: flex; align-items: center; gap: 10px; }
.paso[hidden] { display: none; }
.paso-rotulo { font-size: 12px; color: var(--texto-medio); }
.paso-mandos {
  display: flex;
  align-items: center;
  border: 1px solid var(--borde-vivo);
  border-radius: 8px;
  overflow: hidden;
}
.paso-boton {
  padding: 7px 13px;
  min-height: 34px;
  background: none;
  border: none;
  color: var(--texto-medio);
  font: inherit;
  font-size: 14px;
  cursor: pointer;
}
.paso-boton:hover { color: var(--senal); }
.paso-valor {
  min-width: 34px;
  text-align: center;
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 600;
}

/* Tarjeta del archivo de informes, del mockup. */
.informe-tarjeta {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 13px 14px;
  background: var(--fondo-elevado);
  border: 1px solid var(--borde);
  border-radius: 12px;
  min-width: 0;
}
.informe-tarjeta + .informe-tarjeta { margin-top: 10px; }
.informe-tarjeta-alto { display: flex; align-items: center; gap: 8px; }
.informe-chip {
  flex: none;
  padding: 2px 9px;
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: .05em;
  background: var(--tinte-neutro);
  border: 1px solid var(--borde-vivo);
  color: var(--texto-medio);
}
.informe-chip[data-tipo="daily"] {
  background: var(--senal-suave);
  border-color: color-mix(in oklab, var(--senal) 45%, transparent);
  color: var(--senal);
}
.informe-chip[data-tipo="weekly"] {
  background: var(--ia-suave);
  border-color: var(--ia-borde);
  color: var(--ia);
}
.informe-chip[data-tipo="monthly"] {
  background: var(--tinte-exito);
  border-color: color-mix(in oklab, var(--estado-success) 45%, transparent);
  color: var(--estado-success);
}
.informe-fecha { flex: 1; font-family: var(--mono); font-size: 10.5px; color: var(--texto-tenue); }
.informe-titular { margin: 0; font-size: 13px; font-weight: 600; line-height: 1.4; }
.informe-teaser {
  margin: 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--texto-medio);
  cursor: pointer;
}
.informe-teaser[data-abierto="false"] {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.informe-mandos { display: flex; gap: 8px; }
.informe-mandos .boton { flex: 1; justify-content: center; }

/* La barra avanza por tiempo, no por progreso real: el backend devuelve el
   informe de una vez. Se acerca al 95% y la respuesta cierra el último tramo. */
.fases { margin-top: 10px; }
.fases[hidden] { display: none; }
.fases-barra {
  height: 4px;
  border-radius: 2px;
  background: var(--linea);
  overflow: hidden;
}
.fases-barra span {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--ia);
  transition: width .5s ease;
}
.fases-texto {
  margin: 7px 0 0;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ia);
}

.rotulo-seccion {
  margin: 16px 0 10px;
  padding-top: 14px;
  border-top: 1px solid var(--linea);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .12em;
  color: var(--texto-tenue);
}

.programado {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--borde-vivo);
  border-radius: 10px;
}
.programado + .programado { margin-top: 8px; }
.programado-texto { flex: 1; min-width: 0; }
.programado-nombre { margin: 0; font-size: 12.5px; font-weight: 600; }
.programado-horario {
  margin: 2px 0 0;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--texto-tenue);
}
.hoja-nota { margin: 0 0 12px; font-size: 11px; color: var(--texto-tenue); }

/* --- Fuentes: la pantalla del mockup 1a ---------------------------------
   Resumen y alta en una fila, lo roto arriba en su caja roja, y una tarjeta
   por fuente con punto de estado, píldora de tipo y tres cifras. */
.fuentes-cabecera { display: flex; align-items: center; gap: 10px; }
.fuentes-resumen { margin: 0; flex: 1; font-size: 11px; line-height: 1.5; color: var(--texto-tenue); }
.fuentes-atencion {
  margin-top: 12px;
  border: 1px solid rgba(226, 104, 95, .45);
  background: rgba(226, 104, 95, .06);
  border-radius: 10px;
  padding: 11px 13px;
}
.fuentes-atencion-rotulo {
  margin: 0 0 8px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .1em;
  color: var(--estado-error);
}
.fuentes-atencion-fila { display: flex; align-items: center; gap: 10px; }
.fuentes-atencion-fila + .fuentes-atencion-fila { margin-top: 9px; }
.fuentes-atencion-textos { flex: 1; min-width: 0; }
.fuentes-atencion-nombre { margin: 0; font-size: 12.5px; font-weight: 600; }
.fuentes-atencion-problema { margin: 2px 0 0; font-size: 11px; color: var(--estado-error); }
.fuentes-atencion-accion {
  flex: none;
  background: none;
  border: 1px solid rgba(226, 104, 95, .5);
  border-radius: 7px;
  padding: 5px 11px;
  color: var(--estado-error);
  font-size: 11px;
  font-family: inherit;
  cursor: pointer;
}
.fuentes-lista { display: flex; flex-direction: column; gap: 9px; margin-top: 14px; }
.fuente {
  background: var(--fondo-elevado);
  border: 1px solid var(--borde);
  border-radius: 12px;
  padding: 12px 14px;
}
.fuente-cab { display: flex; align-items: center; gap: 9px; }
.fuente-punto { flex: none; width: 7px; height: 7px; border-radius: 999px; }
.fuente-punto[data-estado="ok"]       { background: var(--estado-success); }
.fuente-punto[data-estado="aviso"],
.fuente-punto[data-estado="agente"]   { background: var(--estado-warning); }
.fuente-punto[data-estado="rota"]     { background: var(--estado-error); }
.fuente-punto[data-estado="inactiva"] { background: var(--texto-tenue); }
.fuente-nombre {
  margin: 0;
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fuente-tipo {
  flex: none;
  font-family: var(--mono);
  font-size: 9.5px;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--borde);
  color: var(--texto-tenue);
}
.fuente-stats { display: flex; gap: 14px; margin-top: 8px; padding-left: 16px; }
.fuente-stat-valor { margin: 0; font-family: var(--mono); font-size: 12px; font-weight: 600; color: var(--texto-medio); }
.fuente-stat-rotulo { margin: 1px 0 0; font-size: 9.5px; color: var(--texto-tenue); }
.fuente-acciones { display: flex; gap: 12px; justify-content: flex-end; margin-top: 8px; }
.fuente-accion {
  background: none;
  border: none;
  padding: 0;
  font-family: inherit;
  font-size: 11px;
  color: var(--texto-tenue);
  cursor: pointer;
}
.fuente-accion:hover { color: var(--texto); }

/* La foto conjunta: prosa del modelo sobre la última entrega de cada
   encuestadora. Cian de juicio, no ámbar de medición. */
.encuestas-macro { border: 1px solid var(--ia-borde, rgba(111, 211, 232, .35)); cursor: pointer; }
.encuestas-macro[hidden] { display: none; }
.encuestas-macro-rotulo {
  margin: 0 0 6px;
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: .1em;
  color: var(--ia);
}
.encuestas-macro-texto {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--ia-texto);
}
/* Tres líneas y cortar: la prosa completa está a un toque de la tarjeta. */
.encuestas-macro-texto[data-abierto="false"] {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* La botonera de la vista, como en el mockup: dos botones a mitades. */
.enc-acciones { display: flex; gap: 8px; }
.enc-acciones .boton { flex: 1; justify-content: center; }

/* --- Encuestas: una tarjeta por encuestadora ----------------------------

   Agrupadas y no en lista plana: dos entregas seguidas de casas distintas
   invitan a compararlas, y compararlas no es válido. Dentro del grupo sí,
   que es justo lo que hace el delta. */
.grupo-encuesta {
  display: flex;
  flex-direction: column;
  gap: 11px;
  padding: 14px;
  background: var(--fondo-elevado);
  border: 1px solid var(--borde);
  border-radius: 12px;
  /* Imprescindible: la tarjeta es hija de una rejilla y, con el `min-width:
     auto` que traen por defecto los ítems de grid y flex, se estiraba hasta
     el ancho de su contenido —580px dentro de una columna de 333— y las
     cifras quedaban fuera de la pantalla. */
  min-width: 0;
}
.grupo-encuesta + .grupo-encuesta { margin-top: 12px; }
.grupo-encuesta-cabecera { display: flex; align-items: center; gap: 10px; }
.grupo-encuesta-nombre { flex: 1; margin: 0; font-size: 14px; font-weight: 700; }
.grupo-encuesta-cuenta { font-family: var(--mono); font-size: 10px; color: var(--texto-tenue); }

.grupo-encuesta-visor { overflow: hidden; transition: height .25s ease; }
@media (prefers-reduced-motion: reduce) { .grupo-encuesta-visor { transition: none; } }
.grupo-encuesta-pista { display: flex; transition: transform .25s ease; }
@media (prefers-reduced-motion: reduce) { .grupo-encuesta-pista { transition: none; } }
.grupo-encuesta-puntos { display: flex; justify-content: center; gap: 6px; }

/* Cada entrega ocupa el ancho completo del visor. `align-self: flex-start`
   evita que una entrega con tres mediciones estire a las de una sola. */
.entrega {
  flex: 0 0 100%;
  box-sizing: border-box;
  align-self: flex-start;
  display: flex;
  flex-direction: column;
  gap: 11px;
  /* Imprescindible, tercera vez que muerde: hija de flex con `min-width:
     auto`, su mínimo lo fijaba la leyenda en `nowrap` (480px) y la base del
     100% (273px) quedaba en letra muerta — toda la fila desbordaba la
     tarjeta. El `min-width: 0` del nombre no basta: el estirón ocurre un
     nivel más arriba. */
  min-width: 0;
}
.entrega-cabecera { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.entrega-edicion { margin: 0; font-family: var(--mono); font-size: 10.5px; color: var(--texto-tenue); }
.entrega-ficha { margin: 0; font-family: var(--mono); font-size: 10.5px; color: var(--texto-tenue); }
.entrega-nota { margin: 0; font-size: 10px; line-height: 1.5; color: var(--texto-tenue); }

.mediciones { display: flex; flex-direction: column; gap: 8px; }
.medicion-alto { display: flex; align-items: baseline; gap: 8px; }
.medicion-nombre {
  flex: 1;
  min-width: 0;
  font-size: 12px;
  line-height: 1.35;
  color: var(--texto-medio);
  /* Dos líneas y no una recortada: los referentes de una encuesta —«la
     cuenta pública del Presidente…»— no caben en una y cortados dejan la
     barra sin sujeto. La pregunta literal completa sigue en el toque largo. */
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
}
.medicion-delta { font-family: var(--mono); font-size: 10.5px; color: var(--texto-tenue); }
.medicion-delta[data-tono="sube"] { color: var(--estado-success); }
.medicion-delta[data-tono="baja"] { color: var(--estado-error); }
.medicion-valor {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 15px;
  font-weight: 600;
  color: var(--texto);
}
/* La nota escolar chilena se juzga sola: bajo 4, reprobado. */
.medicion-valor[data-tono="bien"]   { color: var(--estado-success); }
.medicion-valor[data-tono="aviso"]  { color: var(--estado-warning); }
.medicion-valor[data-tono="alerta"] { color: var(--estado-error); }
.medicion-barra {
  position: relative;
  height: 4px;
  margin-top: 4px;
  border-radius: 2px;
  background: var(--linea);
  overflow: hidden;
}
.medicion-barra span { display: block; height: 100%; background: var(--senal); }
/* La barra de una nota escolar hereda el juicio de la cifra. */
.medicion-barra span[data-tono="bien"]   { background: var(--estado-success); }
.medicion-barra span[data-tono="aviso"]  { background: var(--estado-warning); }
.medicion-barra span[data-tono="alerta"] { background: var(--estado-error); }
/* La marca del 4: el corte de aprobación sobre la pista. */
.medicion-corte {
  position: absolute;
  top: -1px;
  bottom: -1px;
  width: 2px;
  background: var(--texto-tenue);
  opacity: .7;
}

/* La ficha la escribe el modelo al interpretar el PDF: cian, como todo lo
   que no midió el sistema. */
.entrega-mando {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 0;
  background: none;
  border: none;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ia);
  cursor: pointer;
}
.entrega-chevron { font-size: 11px; }
.entrega-lectura {
  margin: 0;
  font-size: 12px;
  line-height: 1.55;
  color: var(--ia-texto);
}
/* Cerrada muestra dos líneas: bastantes para saber si interesa abrirla. */
.entrega-lectura[data-abierto="false"] {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--texto-tenue);
}
.entrega-lectura[data-abierto="true"] {
  padding-top: 10px;
  border-top: 1px dashed var(--ia-borde);
}

/* Simulacro en curso. Mono y en ámbar apagado: es un estado del sistema que
   hay que poder ver de reojo, no una alarma. */
.simulacro-estado {
  margin: 0;
  font-family: var(--mono);
  font-size: 10px;
  line-height: 1.5;
  color: var(--texto-tenue);
}
.simulacro-estado[data-activo="true"] { color: var(--estado-warning); }


.acceso-ojo {
  flex: none;
  padding: 4px;
  background: none;
  border: none;
  color: var(--texto-tenue);
  cursor: pointer;
}
.acceso-ojo svg { width: 17px; height: 17px; display: block; }
.acceso-ojo[aria-pressed="true"] { color: var(--senal); }

/* Medidor de fuerza de la contraseña nueva. Ámbar/rojo/verde son los mismos
   tres colores de estado que el resto del panel, no una paleta aparte. */
.acceso-fuerza {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 2px;
}
.acceso-fuerza[hidden] { display: none; }
.acceso-fuerza-barra {
  flex: 1;
  height: 3px;
  border-radius: 2px;
  background: var(--fondo-hundido);
  overflow: hidden;
  display: block;
}
.acceso-fuerza-barra span {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--estado-error);
  transition: width .15s ease, background-color .15s ease;
}
.acceso-fuerza-txt {
  font-size: 10px;
  text-transform: none;
  letter-spacing: 0;
  color: var(--texto-tenue);
}

.acceso-error {
  margin: 2px 4px 0;
  font-size: 12px;
  color: var(--estado-error);
}
/* CTA sólido: la única superficie ámbar rellena de la página. */
.cta {
  width: 100%;
  min-height: 48px;
  padding: 15px 0;
  border: none;
  border-radius: 14px;
  background: var(--senal);
  color: var(--sobre-senal);
  font: inherit;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
}
.cta:disabled { opacity: .7; cursor: default; }
.cta--suave {
  min-height: 44px;
  padding: 13px 0;
  border: 1px solid color-mix(in oklab, var(--senal) 55%, transparent);
  background: var(--senal-suave);
  color: var(--senal);
  font-size: 14px;
  font-weight: 600;
}

.acceso-abajo {
  margin-top: auto;
  padding: 24px 0 26px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

/* Pantalla de cambio: formulario corto y centrado. */
.acceso-caja--cambio { justify-content: center; gap: 14px; max-width: 356px; }
.cambio-titulo { margin: 0; font-size: 19px; font-weight: 700; }
.cambio-nota { margin: 0; font-size: 12px; line-height: 1.55; color: var(--texto-medio); }
.cambio-campo { display: block; }
.cambio-rotulo {
  display: block;
  margin-bottom: 6px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}
.cambio-caja {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 8px 0 14px;
  background: var(--fondo-hundido);
  border: 1px solid var(--borde-vivo);
  border-radius: 10px;
}
.cambio-caja:focus-within { border-color: var(--senal); }
.cambio-caja input {
  flex: 1;
  min-width: 0;
  padding: 12px 0;
  background: none;
  border: none;
  outline: none;
  color: var(--texto);
  font: inherit;
  font-size: 14px;
}
.cambio-ayuda {
  display: block;
  margin-top: 7px;
  font-size: 11px;
  line-height: 1.5;
  color: var(--texto-tenue);
}
.acceso-fuerza { margin-top: 7px; }

/* Nota de conexión segura. Tenue a propósito: informa, no tranquiliza a
   gritos. Un sello grande de «SITIO SEGURO» es lo que pinta el phishing. */
.acceso-seguro {
  display: inline-flex;
  align-items: center;
  justify-self: center;
  gap: 8px;
  margin: 0;
  font-size: 12.5px;
  color: var(--texto-medio);
}
.acceso-seguro svg { width: 16px; height: 16px; flex: none; }
.acceso-pie {
  margin: 0;
  text-align: center;
  font-size: 11px;
  color: var(--texto-tenue);
}

/* --- Identidad, dentro del menú -------------------------------------------
   Era una píldora en la barra superior y ahí no cabía un correo: se quedaba en
   una inicial suelta que no decía de quién era la sesión. */

.quien-boton {
  flex: 1;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--texto);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.quien-correo {
  display: block;
  font-size: 12.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* El chevron va con el rol y no con el correo: el correo se corta con
   puntos suspensivos cuando no cabe, y un signo detrás de los puntos queda
   fuera de la caja o desaparece. */
.quien-rol {
  display: block;
  margin: 2px 0 0;
  font-size: 10px;
  color: var(--texto-tenue);
}
.quien-rol::after { content: ' ▸'; }
.quien-boton[aria-expanded="true"] .quien-rol::after { content: ' ▾'; }

.quien-menu {
  display: grid;
  gap: 2px;
  margin-top: 10px;
}
.quien-menu[hidden] { display: none; }
.quien-opcion {
  display: flex;
  align-items: center;
  padding: 8px 10px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--texto-medio);
  font: inherit;
  font-size: 12px;
  text-align: left;
  cursor: pointer;
}
.quien-opcion:hover { background: var(--fondo-activo); color: var(--texto); }
.quien-opcion--salir { color: var(--estado-error); }

/* --- Sesiones abiertas ----------------------------------------------------- */

.sesion-fila {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px;
  padding: 12px 18px;
  font-size: 13px;
}
.sesion-fila + .sesion-fila { border-top: 1px solid var(--linea); }
.sesion-quien { color: var(--texto); font-weight: 500; }
.sesion-ip { font-family: var(--mono); font-size: 12px; color: var(--texto-medio); }
.sesion-cuando { color: var(--texto-tenue); font-size: 12px; }
.sesion-agente {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--texto-tenue);
  font-size: 11.5px;
}

/* --- Portada de entrada ----------------------------------------------------
   Se muestra solo cuando la aplicación se abre instalada, no en el navegador.

   El encargo era que diera cuenta del nivel de seguridad «de manera elegante
   pero no obvia». Por eso no hay candados ni escudos: lo que dice que esto es
   cerrado es la secuencia —canal cifrado, identidad, sesión— escrita en
   monoespaciada, en gris, tachándose sola como una comprobación que ya estaba
   hecha antes de que llegaras. Un icono de seguridad tranquiliza a quien no
   sabe; una comprobación explícita informa a quien sí. */
.portada {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  grid-template-rows: 1fr auto;
  place-items: center;
  padding: 40px 24px 32px;
  background: var(--fondo);
  /* La salida es lenta y sin escala: un desvanecimiento tranquilo se lee como
     un sistema que estaba listo, y un rebote como una animación de carga. */
  transition: opacity .5s ease .1s, visibility 0s linear .6s;
}
.portada[hidden] { display: none; }
.portada[data-fuera="true"] { opacity: 0; visibility: hidden; pointer-events: none; }

.portada-centro { display: grid; place-items: center; height: 100%; }

/* Solo el icono, girando despacio. Toca en cualquier parte para continuar. */
.portada { cursor: pointer; }
.portada-sello {
  width: 96px;
  height: 96px;
  color: var(--senal);
  animation: girar 120s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .portada-sello, .acceso-sello { animation: none; }
}

/* El sello de la cabecera. `currentColor` en el SVG y el color aquí: en claro
   y en oscuro es el mismo fichero. */

/* --- Rótulo de la marca ----------------------------------------------------
   La romana del logotipo, en los tres sitios donde aparece el nombre:
   cabecera, caja de acceso y portada. El resto de la interfaz sigue en
   grotesca; esto es lo único que es marca y no dato.

   Va sin negrita —la romana ya tiene el contraste que la grotesca conseguía
   engordando— y con el interletrado ligeramente abierto, que es lo que le da
   el aire de placa y no de titular. */
.cabecera h1,
.acceso-titulo {
  font-family: 'Cortex Logotipo', 'Public Sans', system-ui, sans-serif;
  /* Bruno Ace trae un solo peso y ya es ancha de por sí: forzar negrita la
     emborrona y añadir interletrado la desarma. */
  font-weight: 400;
  /* Caja mixta, no versales: en mayúsculas la romana se lee como cabecera de
     periódico y desaparece el contraste de astiles y remates que es lo que
     hace juego con los puntos del logotipo. */
  text-transform: none;
  letter-spacing: 0;
}

/* «CORTEX» en versales dentro del rótulo. La distinción la hace la caja
   tipográfica y el interletrado, no un cambio de peso: engordar además la
   segunda palabra la separaría de la primera en vez de componerla con ella. */
.marca-cortex { color: var(--senal); }

.cabecera h1 { font-size: 21px; }


@media (max-width: 620px) {
  .cabecera h1 { font-size: 17px; }
}

/* La cifra de audiencia lleva «~» cuando la plataforma solo publica un número
   redondeado. El signo llama la atención; la palabra al pie dice qué es, y el
   porqué queda en el tooltip para no repetir la misma frase en cada tarjeta. */
.cifra-aprox {
  color: var(--senal);
  border-bottom: 1px dotted var(--borde-vivo);
  cursor: help;
}

@media (max-width: 560px) {
  /* Las cifras largas con «~» —«~45.800»— no caben a 27 px y rompían la
     tarjeta. El número sigue siendo lo primero que se lee, solo que ajustado
     al ancho real de una columna de móvil. */
  .cifra-valor { font-size: 24px; letter-spacing: -0.01em; }
  .canal-nombre { white-space: nowrap; }
  /* Todas las tarjetas de una fila con el mismo alto: el pie de una puede
     ocupar dos líneas y el de la vecina una, y con altos distintos la rejilla
     se lee como si algo estuviera mal alineado. */
  .cifras > .cifra { align-content: start; }
}

/* --- Tirar para refrescar -------------------------------------------------- */

/* El contenido se desplaza hacia abajo y deja ver el indicador en el hueco.
   `main` y no el documento: así la cabecera fija no se mueve. */
main {
  transition: transform .28s cubic-bezier(.2, .8, .2, 1);
}
/* `will-change` SOLO mientras se arrastra, no en reposo.

   Permanente crea un bloque contenedor para todo descendiente `position:
   fixed`, y las hojas y los modales viven dentro de `main`: con la página
   desplazada dejaban de anclarse al viewport y se abrían fuera de la
   pantalla. Se veía como «la hoja no aparece», y solo si habías bajado
   antes —por eso pasó desapercibido—.

   Aquí el aviso al navegador no aporta nada en reposo: la capa se necesita
   durante el gesto, y durante el gesto hay `transform` de verdad, que ya la
   crea. */
main.arrastrando { transition: none; will-change: transform; }

.tiron {
  position: fixed;
  /* Justo bajo la cabecera; el JS mide su alto y lo pone aquí. */
  top: var(--tiron-arriba, 0px);
  left: 0;
  right: 0;
  z-index: 7;
  height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  overflow: hidden;
  pointer-events: none;
  /* Opaco arriba: aunque quede solapado un píxel con la cabecera, no se
     transparenta el texto de debajo. */
  /* Sin fondo propio: el hueco que deja el contenido al bajar ya es el fondo
     de la página, y una capa más ahí solo añadiría un borde que no existe. */
  transition: height .28s cubic-bezier(.2, .8, .2, 1);
}
/* Mientras el dedo arrastra NO hay transición: el indicador tiene que ir
   pegado al dedo. Con ella activa llegaba un cuarto de segundo tarde a cada
   movimiento y el gesto se sentía pegajoso, que fue justo lo que se notó. */
.tiron[data-arrastrando="true"] { transition: none; }

.tiron-marca { flex: none; transform: rotate(-90deg); }
/* El aro empieza arriba, como un reloj, y no a las tres. */
.tiron-pista { stroke: var(--borde-vivo); opacity: .5; }
.tiron-avance {
  stroke: var(--senal);
  /* Sin transición: el aro tiene que seguir al dedo igual que la altura. */
  transition: stroke .18s ease;
}
.tiron[data-listo="true"] .tiron-avance { stroke: var(--senal); }
.tiron[data-girando="true"] .tiron-marca {
  opacity: 1;
  animation: tiron-giro .7s linear infinite;
}
/* Al terminar, el aro se completa en verde: el gesto tiene un final visible y
   no solo una desaparición. */
.tiron[data-hecho="true"] .tiron-marca { animation: none; }
.tiron[data-hecho="true"] .tiron-avance { stroke: var(--estado-success); }

.tiron-texto {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}
.tiron[data-hecho="true"] .tiron-texto { color: var(--estado-success); }

@keyframes tiron-giro { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .tiron-marca { animation: none; }
}

/* `none` y no `contain`: `contain` solo impide que el rebote se propague al
   contenedor de arriba, pero deja que la propia página rebote. Con eso, tirar
   arrastraba la cabecera —fija y todo— y el indicador acababa por encima de
   ella. Con `none` la cabecera se queda quieta y el aro aparece justo debajo,
   que es donde se le busca.

   En los dos ejes: la goma elástica horizontal de iOS permitía arrastrar el
   lienzo entero hacia un lado y asomaba lo que vive fuera del viewport —el
   cajón del menú, el fondo desnudo—. `overflow-x: clip` remata: nada se
   pinta ni se desplaza más allá del borde. `clip` y no `hidden`, porque
   `hidden` en el body crea un contexto de scroll horizontal propio y el
   gesto seguiría moviéndolo. */
html, body { overscroll-behavior: none; overflow-x: clip; }

/* La barra de desplazamiento del documento no existe donde se navega con el
   dedo: una app nativa no la enseña y aquí delataba que esto es una página.
   Solo con puntero grueso: en escritorio la barra es informativa y quitarla
   sería esconder el mapa. Los desplazables internos ya la ocultan uno a uno. */
@media (pointer: coarse) {
  html { scrollbar-width: none; }
  html::-webkit-scrollbar,
  body::-webkit-scrollbar { display: none; }
}

/* El selector de tema NO se oculta en móvil: baja al cajón.
   Ocultarlo dejaba atrapado a quien hubiera tocado un botón alguna vez —la
   preferencia guardada seguía mandando sobre el sistema y no había forma de
   borrarla—. Con la opción «seguir al sistema» dentro del cajón, la cabecera
   queda limpia y la elección sigue siendo reversible. */
.cajon-ajustes { justify-content: space-between; flex-wrap: nowrap; }
.cajon-ajustes .tema { flex: none; }
.cajon-rotulo {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}

/* --- Estado y tema repartidos al cajón (móvil) -----------------------------
   Lo que en escritorio vive en la cabecera baja aquí. La cuenta y la Persona
   ya están en el cajón por marcado; esto es solo el estado del sistema y el
   control de tema, que no caben en 375 px de barra. */
.cajon-cabecera {
  display: grid;
  gap: 2px;
  /* `minmax(0, 1fr)` y no el `auto` implícito: sin esto, un hijo ancho —el
     nombre del cargo, la fila del motor— estira la rejilla más allá del cajón
     y el contenido se sale por la derecha en vez de ajustarse. */
  grid-template-columns: minmax(0, 1fr);
  margin: 0 0 10px;
  border-bottom: 1px solid var(--linea);
}

.cajon-bloque {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 9px;
  padding: 13px 16px;
  min-width: 0;
}
/* Todo lo que entra aquí tiene que poder encogerse. Por defecto un elemento
   flex no baja de su contenido, y basta un correo largo o el cargo de la
   Persona para empujar el cajón entero. */
.cajon-bloque > * { min-width: 0; max-width: 100%; }
.cajon-bloque + .cajon-bloque { border-top: 1px solid var(--linea); }

/* Estado del sistema. En el cajón hay ancho de sobra, así que vuelve a
   mostrarse lo que la cabecera móvil escondía: el detalle del motor y la
   cuenta atrás del próximo ciclo. */
.cajon-estado { gap: 8px 10px; }
/* El chip del motor puede encogerse y cortar su detalle antes que desbordar. */
.cajon-estado .motor { min-width: 0; overflow: hidden; }
.cajon-estado .motor-detalle { overflow: hidden; text-overflow: ellipsis; }
.cajon-estado .pulso-ciclo { white-space: nowrap; }
.cajon-estado .motor { padding: 5px 11px; }
.cajon-estado .pulso-ciclo,
.cajon-estado .motor-detalle { display: inline; }
.cajon-estado .pulso-texto,
.cajon-estado .pulso-ciclo {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--texto-medio);
}

@media (max-width: 860px) {
  /* En la cabecera solo queda lo que identifica el producto. */
  .cabecera { padding-top: 14px; padding-bottom: 14px; }
  /* `width: auto` -en vez del 100% de más arriba- para que no ocupe una fila
     entera de aire, pero pegada a la derecha: la cabecera envuelve, y una
     fila con un solo elemento y `space-between` lo alinea a la IZQUIERDA.
     Sin este margen la hamburguesa quedaba junto al rótulo de la vista, a
     media pantalla, en vez de en la esquina donde la mano la busca.
     Comprobado en Android y reproducido a 375 px. */
  .pulso { width: auto; gap: 0; margin-left: auto; }
}

/* --- Zonas seguras de iOS --------------------------------------------------
   Con `viewport-fit=cover` la página llega a los bordes físicos del teléfono,
   que es lo que hace desaparecer la franja negra bajo la isla dinámica: el
   fondo del tema ocupa también esa zona. A cambio, apartar el contenido de la
   isla, del notch y del indicador inferior pasa a ser cosa nuestra.

   Se cubren los cuatro lados y no solo el superior: **en apaisado el notch se
   va a un lateral**, y ahí lo que se come es el margen izquierdo o el derecho.
   Con el teléfono girado, sin esto, la primera columna de las tarjetas queda
   debajo del recorte. */

/* Fondo del tema hasta el borde físico, por debajo de todo lo demás. */
html { background: var(--fondo); }

.cabecera {
  padding-top: calc(22px + env(safe-area-inset-top));
  padding-left: calc(var(--margen-alineado) + env(safe-area-inset-left));
  padding-right: calc(var(--margen-alineado) + env(safe-area-inset-right));
}

main {
  padding-bottom: calc(48px + env(safe-area-inset-bottom));
  padding-left: calc(var(--margen-lateral) + env(safe-area-inset-left));
  padding-right: calc(var(--margen-lateral) + env(safe-area-inset-right));
}

/* Los velos que cubren toda la pantalla: acceso, portada y modales. */
.acceso {
  padding-top: calc(24px + env(safe-area-inset-top));
  padding-bottom: calc(24px + env(safe-area-inset-bottom));
}
.portada {
  padding-top: calc(40px + env(safe-area-inset-top));
  padding-bottom: calc(32px + env(safe-area-inset-bottom));
}
.modal {
  padding-top: calc(24px + env(safe-area-inset-top));
  padding-bottom: calc(24px + env(safe-area-inset-bottom));
}

@media (max-width: 860px) {
  .cabecera { padding-top: calc(13px + env(safe-area-inset-top)); }

  /* El cajón nace en `top: 0` y llega a `bottom: 0`, así que se le mete por
     dentro todo el recuadro seguro: arriba la isla, abajo el indicador y a la
     derecha el borde, que es de donde entra. */
  .menu {
    padding-top: calc(14px + env(safe-area-inset-top));
    padding-bottom: calc(20px + env(safe-area-inset-bottom));
    padding-right: calc(0px + env(safe-area-inset-right));
  }

  /* En pantalla completa el modal ocupa todo: sus propios bordes son los del
     teléfono y su cabecera queda bajo la isla si no se aparta. */
  .modal-caja { padding-top: env(safe-area-inset-top); }
}

/* --- Cajón: qué se desplaza y qué no --------------------------------------- */

/* El envoltorio es la parte que se desplaza: la cuenta se queda arriba y la
   Persona al pie, que es lo que se viene a mirar cuando se abre el menú. */
.menu-secciones {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.menu-version {
  margin: 0;
  padding: 12px 16px 4px;
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--texto-tenue);
  opacity: .5;
}
.menu-version[hidden] { display: none; }

@media (max-width: 860px) {
  /* El cajón es una columna: cabecera fija, secciones desplazables y versión
     al pie. Antes se desplazaba el cajón entero y con él se iban de la vista
     la cuenta y el estado del sistema, que son justo lo que se viene a mirar. */
  .menu {
    display: flex;
    flex-direction: column;
    overflow-y: hidden;
    /* Corta el encadenado: al llegar al final de la lista, el gesto dejaba de
       mover el cajón y empezaba a arrastrar la página de debajo. */
    overscroll-behavior: contain;
  }

  .cajon-cabecera { flex: none; margin-bottom: 0; }

  /* Solo esto se desplaza. */
  .menu-secciones {
    display: block;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding-top: 8px;
  }

  .menu-version { flex: none; padding-bottom: 8px; }
}

/* --- Pestañas de columnas (móvil) ------------------------------------------
   Solo existen en móvil, donde las dos columnas se apilarían. La barra se
   inyecta desde el JS y desaparece al ensanchar. */
.pestanas {
  display: flex;
  gap: 4px;
  padding: 4px;
  border-radius: var(--radio-chico);
  background: var(--fondo-hundido);
}

.pestana {
  flex: 1;
  min-width: 0;
  padding: 10px 12px;
  border: 0;
  border-radius: calc(var(--radio-chico) - 2px);
  background: transparent;
  color: var(--texto-medio);
  font: inherit;
  font-size: 13px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}
.pestana[aria-selected="true"] {
  background: var(--fondo-elevado);
  color: var(--texto);
  box-shadow: var(--sombra-pieza);
}

/* La pestaña activa ya dice de qué panel se trata: repetirlo en el título de
   dentro gasta una línea de las pocas que hay en un teléfono. */
@media (max-width: 860px) {
  .columnas .panel > .panel-cabecera > h2 { display: none; }
}

/* --- La destacada del día ---------------------------------------------------
   Tiene que leerse como «esto es lo destacado» antes de leer una palabra. De
   ahí el acento en el canto, la marca con punto y el número grande: es la
   única pieza de la vista que responde a «¿qué funcionó?», y compite con dos
   listas largas por la atención. */
.destacada {
  position: relative;
  overflow: hidden;
  background:
    linear-gradient(100deg, var(--senal-suave), transparent 45%),
    var(--fondo-elevado);
}
/* Franja en el canto izquierdo. Es lo que la distingue de un panel más sin
   añadirle un borde alrededor. */
.destacada::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--senal);
}

.destacada-cabecera {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 12px;
  padding: 15px 18px 0;
}

.destacada-marca {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--senal);
}
.destacada-punto {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--senal);
  box-shadow: 0 0 0 3px var(--senal-suave);
}

.destacada-cuando { font-size: 11.5px; color: var(--texto-tenue); }
/* Cuando no es de hoy se avisa en color de aviso, no en gris: una pieza de
   hace meses presentada como la del día lleva a decidir sobre lo que se cree
   reciente. */
.destacada-cuando--vieja { color: var(--estado-warning); }

/* La tarjeta entera en columna para que el cuerpo pueda estirarse: en una fila
   de dos, la rejilla las iguala de alto y sin esto el sobrante quedaba como un
   hueco muerto debajo del texto corto. */
.destacada { display: flex; flex-direction: column; }
.destacada-cuerpo {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 20px;
  align-items: stretch;
  padding: 14px 18px 18px;
  flex: 1;
}

.destacada-cifra {
  display: grid;
  justify-items: start;
  /* `align-content: start` porque la columna se estira con el cuerpo: sin
     esto la rejilla repartía el sobrante entre las tres filas y el rótulo
     «interacciones» acababa flotando a cien píxeles de su número. */
  align-content: start;
  gap: 2px;
  min-width: 118px;
}
.destacada-numero {
  font-family: var(--mono);
  font-size: 34px;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--senal);
}
.destacada-unidad {
  font-size: 10.5px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}
/* Las vistas son el denominador, no el titular: mismo bloque, medio tono. */
.destacada-vistas {
  margin-top: 5px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--texto-medio);
}

/* El texto arriba y la procedencia abajo, separados por el sobrante. Es lo que
   convierte el hueco de la tarjeta corta en margen entre dos cosas en vez de
   en un vacío al final. */
.destacada-pieza {
  display: grid;
  grid-template-rows: auto 1fr;
  gap: 10px;
  min-width: 0;
}

/* Recorte por LÍNEAS y no por caracteres: 320 caracteres de un texto con
   emojis y saltos ocupan el doble de alto que 320 de un párrafo corrido, y las
   dos tarjetas quedaban de altos distintos. Con líneas, ambas cortan en el
   mismo sitio pase lo que pase con el contenido. */
.destacada-texto {
  display: -webkit-box;
  -webkit-line-clamp: 6;
  line-clamp: 6;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Que el texto venga cortado de origen se dice con el aviso del pie y nada
   más. Se probó marcar además el canto del párrafo con una línea discontinua:
   con el contraste de `--linea` no se distinguía, y subirlo habría metido un
   segundo elemento gráfico compitiendo con un aviso que ya es explícito. */

.destacada-pie {
  display: grid;
  gap: 6px;
  align-content: end;
  min-width: 0;
}
.destacada-recorte {
  display: flex;
  align-items: baseline;
  gap: 5px;
  margin: 0;
  font-size: 11px;
  line-height: 1.45;
  color: var(--texto-tenue);
}
/* Ámbar no: el ámbar de esta interfaz significa «esto lo contó el sistema» y
   aquí lo que se dice es justo lo contrario, que falta información. El aviso
   se queda en el gris de las notas, con el signo como única señal. */
.destacada-recorte-icono { flex: none; color: var(--estado-warning); }

@media (max-width: 620px) {
  /* En vertical la cifra pasa arriba, en una línea con su unidad: en dos
     columnas estrechas no cabía ninguna de las dos. */
  .destacada-cuerpo { grid-template-columns: minmax(0, 1fr); gap: 14px; }
  .destacada-cifra { grid-auto-flow: column; align-items: baseline; gap: 8px; min-width: 0; }
  .destacada-numero { font-size: 28px; }
  .destacada-vistas { margin-top: 0; }
}

/* --- Cabecera de un bloque que no vive dentro de un panel -----------------
   Mismo peso tipográfico y mismo guion de acento que `.panel-cabecera`, pero
   sin la caja ni la línea inferior: el bloque que titula son tarjetas sueltas
   sobre el fondo, no un panel. */
.seccion-cabecera {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 14px;
  margin-bottom: 12px;
}
.seccion-cabecera h2 {
  margin: 0;
  font-family: var(--display);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.seccion-cabecera h2::before {
  content: '';
  display: inline-block;
  width: 14px;
  height: 2px;
  margin-right: 9px;
  vertical-align: middle;
  background: var(--senal);
}
.seccion-cabecera .panel-nota { min-width: 0; }
@media (max-width: 620px) {
  .seccion-cabecera .panel-nota { flex: 1 1 100%; }
}

/* Las publicaciones con más interacción, una por red, en rejilla.

   Estas tarjetas SÍ se igualan de alto. Hubo un tiempo en que no —con textos
   de largo muy distinto, la corta se estiraba y dejaba un vacío al final— pero
   eso se resolvió anclando el pie al fondo: el sobrante lo ocupa algo que
   sirve, de dónde salió y cuándo. Lo que quedó fue el `align-items: start` de
   entonces, y con él tres tarjetas a tres alturas distintas y los pies
   flotando cada uno a su nivel. */
.destacadas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  /* `stretch` y no `start`. Con `start` cada tarjeta tomaba su altura de
     contenido, así que en una fila de tres quedaban a tres alturas distintas y
     los pies —«ver original», la fecha— flotaban cada uno a su nivel. El
     interior ya estaba preparado para estirarse (la tarjeta es una columna, el
     cuerpo lleva `flex: 1` y el pie va anclado al fondo), pero nada de eso
     actuaba mientras la rejilla no las igualara primero. */
  align-items: stretch;
  gap: 14px;
}

/* El enlace al original, sin repetir la red: la cabecera ya la nombra. */
.destacada-enlace {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--texto-medio);
  text-decoration: none;
  border-bottom: 1px solid var(--linea);
}
.destacada-enlace:hover { color: var(--senal); border-bottom-color: var(--senal); }

/* --- Rejillas con un número impar de tarjetas ------------------------------
   En dos columnas, una cantidad impar deja la última sola y a media anchura,
   con un hueco al lado que se lee como si faltara algo. La última pasa a
   ocupar la fila entera: deja de ser media tarjeta huérfana y se convierte en
   el cierre del bloque.

   `:last-child:nth-child(odd)` es la forma de decir «es la última Y hay un
   número impar»: si fueran pares, la última sería par y la regla no aplica.

   Con una salvedad que costó un rato ver: `nth-child` cuenta posiciones en el
   marcado, no celdas en la rejilla. La tarjeta de ataques coordinados ya ocupa
   la fila entera por su cuenta, así que consume una posición pero deja de
   contar como media celda, y el cálculo se desplaza en uno: con siete tarjetas
   —seis normales, que llenan tres filas exactas— la última salía estirada sin
   hueco que rellenar. Se distingue con `:has()` si la rejilla lleva una tarjeta
   a lo ancho, y en ese caso se busca la paridad contraria. */
@media (max-width: 980px) {
  .cifras:not(:has(.cifra--ataque)) > .cifra:last-child:nth-child(odd),
  .cifras:has(.cifra--ataque) > .cifra:last-child:nth-child(even),
  .destacadas > .destacada:last-child:nth-child(odd) { grid-column: 1 / -1; }
}
@media (max-width: 620px) {
  .desempeno > .dim:last-child:nth-child(odd) { grid-column: 1 / -1; }
}

/* --- Contraste de las pestañas --------------------------------------------
   En tema oscuro, `--fondo-elevado` sobre `--fondo-hundido` son dos negros a
   ocho puntos de luminancia: la pestaña activa no se distinguía de la otra de
   un vistazo. Se añade el acento de la marca —franja inferior y color de
   texto—, que no depende del contraste entre dos fondos casi iguales. */
.pestana[aria-selected="true"] {
  background: var(--fondo-elevado);
  color: var(--texto);
  box-shadow: inset 0 -2px 0 var(--senal), var(--sombra-pieza);
  font-weight: 500;
}
.pestana[aria-selected="false"] { color: var(--texto-tenue); }
.pestana[aria-selected="false"]:hover { color: var(--texto-medio); }

/* --- Por qué funcionó ------------------------------------------------------ */

/* La tarjeta entera es el objetivo: un «ver más» en una esquina se descubre
   tarde y esta pieza invita a preguntarse el porqué. */
.destacada { cursor: pointer; transition: border-color .15s ease, transform .12s ease; }
.destacada:hover { transform: translateY(-1px); }
.destacada:focus-visible { outline: 2px solid var(--senal); outline-offset: 2px; }

.porque-titular {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px;
  padding: 18px 20px;
  border-bottom: 1px solid var(--linea);
}
.porque-multiplo {
  font-family: var(--mono);
  font-size: 40px;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--senal);
}
.porque-explica { flex: 1; min-width: 200px; font-size: 13px; line-height: 1.55; color: var(--texto-medio); }

.porque-hechos { display: grid; }
.porque-fila {
  display: grid;
  grid-template-columns: 128px auto 1fr;
  gap: 12px;
  align-items: baseline;
  padding: 11px 20px;
  font-size: 13px;
}
.porque-fila + .porque-fila { border-top: 1px solid var(--linea); }
.porque-rotulo {
  font-size: 10.5px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}
.porque-valor { font-family: var(--mono); color: var(--texto); font-variant-numeric: tabular-nums; }
.porque-nota { font-size: 12px; color: var(--texto-tenue); }

.porque-texto { padding: 16px 20px 20px; border-top: 1px solid var(--linea); }
.porque-enlace {
  display: inline-block;
  margin-top: 10px;
  font-size: 12.5px;
  color: var(--senal);
}

@media (max-width: 620px) {
  /* Tres columnas no caben: rótulo arriba, valor y nota debajo. */
  .porque-fila { grid-template-columns: minmax(0, 1fr); gap: 3px; }
  .porque-multiplo { font-size: 34px; }
}

/* --- Modales como paneles deslizantes en móvil -----------------------------
   En un teléfono, una caja centrada con velo alrededor es un patrón de
   escritorio: deja franjas muertas arriba y abajo y el pulgar tiene que subir
   hasta el centro. El panel que sube desde abajo llega a la mano, aprovecha
   todo el ancho y es el gesto que la gente ya conoce del sistema operativo.

   Es el MISMO marcado: solo cambia dónde se ancla y cómo entra. No hay una
   segunda implementación que mantener. */
@media (max-width: 860px) {
  .modal { padding: 0; align-items: flex-end; }

  .modal-caja {
    width: 100%;
    max-width: none;
    max-height: 88vh;
    border-radius: var(--radio) var(--radio) 0 0;
    /* Entra deslizando. `transform` y no `top`: se anima en la GPU y no
       provoca recálculo de diseño en cada fotograma. */
    transform: translateY(100%);
    transition: transform .26s cubic-bezier(.2, .8, .2, 1);
    padding-bottom: env(safe-area-inset-bottom);
  }
  .modal:not([hidden]) .modal-caja { transform: translateY(0); }

  /* Asa de arrastre. No es decorativa: es la señal de que esto se cierra
     hacia abajo, antes de buscar el botón de cerrar. */
  .modal-caja::before {
    content: '';
    display: block;
    width: 36px;
    height: 4px;
    margin: 8px auto 0;
    border-radius: 2px;
    background: var(--borde-vivo);
  }

  @media (prefers-reduced-motion: reduce) {
    .modal-caja { transition: none; }
  }
}

/* La tarjeta de vigilancia abre su registro: se anuncia como pulsable.

   El cursor y el realce al pasar por encima no existen en un teléfono, así que
   por sí solos no anuncian nada a la mitad de quienes la miran. Lo que la
   anuncia es la línea de acción de abajo, escrita con palabras. */
.cifra--accion {
  cursor: pointer;
  /* La acción se ancla al pie aunque las tarjetas vecinas sean más altas: en
     una fila de cuatro, un «Toca para revisar» flotando a media altura se lee
     como un pie de la cifra de al lado. */
  display: flex;
  flex-direction: column;
  transition: transform .12s ease, border-color .12s ease;
}
.cifra--accion .cifra-pie { margin-bottom: auto; }
.cifra--accion:hover { transform: translateY(-1px); border-color: var(--senal); }
.cifra--accion:focus-visible { outline: 2px solid var(--senal); outline-offset: 2px; }

/* El icono junto al rótulo. Va en la misma línea y con el mismo tono tenue:
   identifica de qué habla la tarjeta sin competir con la cifra. */
.cifra-etiqueta--icono { display: inline-flex; align-items: center; gap: 6px; }
.icono-cifra { flex: none; opacity: .85; }

.cifra-accion {
  display: flex;
  align-items: center;
  gap: 5px;
  margin: 12px 0 0;
  padding-top: 9px;
  border-top: 1px solid var(--linea);
  font-size: 11.5px;
  color: var(--texto-medio);
}
.cifra-accion-verbo { color: var(--senal); font-weight: 500; }
/* La flecha se desplaza al pasar por encima: confirma que lleva a otro sitio
   y no que despliega algo aquí mismo. */
.cifra-accion-flecha {
  margin-left: auto;
  color: var(--senal);
  transition: transform .12s ease;
}
.cifra--accion:hover .cifra-accion-flecha { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) {
  .cifra--accion, .cifra-accion-flecha { transition: none; }
  .cifra--accion:hover { transform: none; }
  .cifra--accion:hover .cifra-accion-flecha { transform: none; }
}

/* Audiencia: cuatro tarjetas en una sola fila en escritorio.
   Con la rejilla general de tres columnas, la cuarta caía sola a una segunda
   fila y volvía el hueco que acabábamos de quitar. */
#vp-audiencia { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1100px) { #vp-audiencia { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px)  { #vp-audiencia { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.porque-lectura { margin: 0 20px 20px; padding: 14px 16px; border-radius: var(--radio-chico); }
.porque-lectura .lista-titulo { margin-top: 0; }
/* Lo replicable es lo único que cambia lo que se hace mañana: se separa del
   párrafo para que no se pierda dentro de la interpretación. */
.porque-replicable {
  margin: 12px 0 0;
  padding-top: 10px;
  border-top: 1px solid var(--linea);
  font-size: 13px;
  line-height: 1.6;
  color: var(--texto-medio);
}
.porque-replicable b { color: var(--texto); }

/* --- Dónde está el respaldo -------------------------------------------------

   Dos barras, una encima de otra, con la MISMA paleta: arriba cuánta gente
   opina qué, abajo qué opinión tiene detrás a más gente. Comparar dos
   proporciones se hace mirando; con dos porcentajes en texto habría que leer
   los dos y restarlos mentalmente.

   La de respaldo va más fina y con menos contraste a propósito. La lectura
   principal sigue siendo el recuento —que es la que tiene muestra completa— y
   esta es la que matiza; darles el mismo peso visual sugeriría que son
   intercambiables, y no lo son. */
.respaldo { margin-top: 14px; }

.respaldo-rotulo {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--texto-tenue);
}
.respaldo-rotulo b {
  color: var(--texto-medio);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: .04em;
}

.barra--respaldo { height: 5px; margin-top: 6px; opacity: .82; }

.respaldo-nota {
  margin: 8px 0 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--texto-medio);
}
/* Solo se pinta cuando el respaldo empeora la lectura del recuento. Que
   mejore también se dice, pero en gris: una buena noticia no necesita
   llamar la atención igual que una mala. */
.respaldo-nota[data-sentido="peor"] { color: var(--estado-error); }

/* --- La frase que prende ----------------------------------------------------

   Es texto de una persona, no una medición, así que se cita en vez de
   presentarse como dato. El filo de color a la izquierda lleva la postura, que
   es la misma información que el color de la barra y por eso el mismo color.

   Sin cian: no lo escribió el modelo, lo escribió alguien. Que la postura sea
   un juicio del modelo se dice con la etiqueta del pie, que ya la lleva. */
.resonante {
  margin: 12px 0 0;
  padding: 9px 0 9px 11px;
  border-left: 2px solid var(--borde-vivo);
  background: linear-gradient(90deg, var(--tinte-neutro), transparent 70%);
  border-radius: 0 var(--radio-chico) var(--radio-chico) 0;
}
.resonante[data-postura="oppose"]  { border-left-color: var(--estado-error); }
.resonante[data-postura="support"] { border-left-color: var(--estado-success); }
.resonante[data-postura="mixed"]   { border-left-color: var(--estado-warning); }

.resonante-texto {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--texto);
  /* Tres líneas: es una cita, no el comentario entero. Quien quiera el resto
     lo tiene en la lista de respuestas de más abajo. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.resonante-pie {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  margin: 7px 0 0;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--texto-tenue);
}
.resonante-pie b {
  color: var(--texto-medio);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

/* ===========================================================================
   SUS PUBLICACIONES
   ===========================================================================

   Responde a «qué funcionó de lo último que hice», y se usa para escanear: se
   recorre la lista buscando lo que se salió de lo normal y solo entonces se
   entra. Un vistazo tiene que dar el 80 %.

   Seis filas y ni una más:

     1. De dónde y cuándo · el rendimiento comparado, a la derecha
     2. Lo que escribió, a dos líneas
     3. Las cifras, con las interacciones al frente
     4. Cómo se recibió: veredicto, barra y tamaño de la muestra
     5. Lo que entendió el modelo, en chips
     6. El porqué y los comentarios, plegados

   La regla que sostiene la pieza entera: **ámbar es lo que el sistema contó,
   cian lo que el modelo interpretó**, y no se mezclan nunca. Si algo se pinta
   de cian, es un juicio de una máquina y tiene que poder saberse sin leerlo. */

.periodos { display: flex; gap: 8px; margin: 0 0 16px; flex-wrap: wrap; }
.periodo {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  /* 44 píxeles de alto: esto se toca con el pulgar, en el teléfono y entre
     reuniones. */
  min-height: 44px;
  padding: 0 16px;
  border-radius: 999px;
  border: 1px solid var(--borde-vivo);
  background: none;
  color: var(--texto-medio);
  font-family: var(--sans);
  font-size: 14px;
  cursor: pointer;
  transition: border-color .15s, color .15s, background .15s;
}
.periodo b {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--texto-tenue);
}
.periodo:hover:not(:disabled) { border-color: var(--senal); color: var(--texto); }
.periodo:focus-visible { outline: 2px solid var(--senal); outline-offset: 2px; }
.periodo[aria-pressed="true"] {
  background: var(--senal-suave);
  border-color: var(--senal);
  color: var(--texto);
  font-weight: 600;
}
.periodo[aria-pressed="true"] b { color: var(--senal); }
/* Un periodo vacío se apaga, no se esconde: que exista y no tenga nada es
   información —«esta semana no publicó»— y ocultarlo lo convierte en duda. */
.periodo:disabled { opacity: .4; cursor: default; }

.publicaciones { display: flex; flex-direction: column; gap: 16px; }

.publicacion {
  background: var(--fondo-elevado);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 18px;
  display: flex;
  flex-direction: column;
  /* Aire entre bloques. Con 12 px las seis filas se leían como un párrafo
     apretado y había que buscar dónde acababa una cosa y empezaba otra. */
  gap: 16px;
  box-shadow: var(--sombra-pieza);
}

/* --- Fila 1: de dónde, cuándo y cuánto rindió ---------------------------- */
.pub-cabecera {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
.pub-origen { min-width: 0; }
.pub-origen-linea {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  color: var(--texto-medio);
}
.pub-origen svg { flex: none; }
/* Nombre de red y fecha no se parten: en un teléfono estrecho «07-ago,» y
   «14:32» acababan en líneas distintas y la cabecera se leía como una lista.
   Si no caben juntos, la fecha baja entera. */
.pub-red {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  white-space: nowrap;
}
.pub-fecha {
  font-family: var(--mono);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  color: var(--texto-tenue);
  white-space: nowrap;
}
/* Distinguible pero sin protagonismo: la fijada lleva meses acumulando y su
   cifra no compite con las de esta semana. */
.pub-fijada {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 6px;
  padding: 2px 8px;
  border: 1px solid var(--borde-vivo);
  border-radius: 20px;
  font-size: 10.5px;
  color: var(--texto-medio);
}

/* El rendimiento comparado: el indicador más importante de la tarjeta. Destaca
   por posición y color, no por tamaño de presencia —lo medido manda sobre lo
   calculado— y siempre lleva su palabra al lado. */
.pub-rendimiento {
  flex: none;
  max-width: 160px;
  text-align: right;
}
.pub-multiplo {
  display: block;
  font-family: var(--mono);
  font-size: 24px;
  font-weight: 600;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--texto);
}
/* Color solo en los extremos: marcar un 5 % de diferencia lo volvería ruido. */
.pub-multiplo[data-tono="bien"]  { color: var(--estado-success); }
.pub-multiplo[data-tono="flojo"] { color: var(--estado-error); }
/* El «=» es un signo y no una cifra: a 24 px y en negrita son dos barras
   gruesas en la esquina y se lee como un botón de menú, no como un dato. */
.pub-multiplo[data-simbolo="igual"] {
  font-size: 22px;
  font-weight: 500;
  /* Y en gris: «igual que siempre» es justo lo que no tiene que llamar la
     atención mientras se recorre la columna buscando lo que se salió. */
  color: var(--texto-medio);
}
.pub-multiplo-sub {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  color: var(--texto-medio);
  white-space: nowrap;
}

/* Los estados sin múltiplo son de primera clase, no huecos: de 40
   publicaciones solo 9 son medibles. Cada uno explica por qué a la vista, no
   en un tooltip: en el teléfono no hay tooltip. */
.pub-espera-fila {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  color: var(--texto-medio);
}
.pub-espera-txt {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}
.pub-espera-desc {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  line-height: 1.35;
  color: var(--texto-tenue);
}
/* Ámbar solo mientras el sistema sigue trabajando; gris cuando el dato no va a
   llegar nunca. */
.pub-rendimiento--espera[data-curso="true"] .pub-espera-fila { color: var(--senal); }
.pub-rendimiento--espera[data-curso="true"] .pub-espera-txt  { color: var(--senal); }

/* El indicador de «sigue en marcha»: tres puntos en ola que se funden con una
   antena —recolectando— y unas barras —calculando—. Una etiqueta quieta que
   diga «sin comparación» se lee como error; esto dice que aún no toca. Solo
   aparece cuando de verdad habrá respuesta más tarde: animar una espera que no
   termina sería mentir con movimiento. */
.vigila-escena {
  position: relative;
  display: inline-block;
  width: 14px;
  height: 14px;
  flex: none;
}
.vigila-fase {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  animation: vigila-turno 6s ease-in-out infinite;
}
.vigila-puntos  { animation-delay: 0s; }
.vigila-antena  { animation-delay: 2s; }
.vigila-calculo { animation-delay: 4s; }

@keyframes vigila-turno {
  0%, 2%    { opacity: 0; }
  8%, 27%   { opacity: 1; }
  33%, 100% { opacity: 0; }
}
.vigila-puntos i {
  width: 3px; height: 3px; margin: 0 .5px;
  border-radius: 50%;
  background: currentColor;
  animation: vigila-ola 1.4s ease-in-out infinite;
}
.vigila-puntos i:nth-child(2) { animation-delay: .18s; }
.vigila-puntos i:nth-child(3) { animation-delay: .36s; }
@keyframes vigila-ola {
  0%, 60%, 100% { transform: translateY(0); opacity: .45; }
  30%           { transform: translateY(-3px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .vigila-fase { animation: none; opacity: 0; }
  .vigila-puntos { opacity: 1; }
  .vigila-puntos i { animation: none; opacity: .7; }
}

/* --- Fila 2: lo que escribió --------------------------------------------- */
.pub-texto {
  margin: 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--texto);
  /* Dos líneas: sirve para reconocer de qué publicación se habla, no para
     leerla. El caption completo va de 87 a 1.358 caracteres. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.pub-texto[data-abierto="true"] { display: block; }
.pub-vertexto {
  background: none;
  border: 0;
  margin: 0;
  padding: 6px 0 0;
  cursor: pointer;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--texto-medio);
}
.pub-vertexto:hover { color: var(--senal); }
.pub-vertexto:focus-visible { outline: 2px solid var(--senal); outline-offset: 2px; }

/* --- Fila 3: las cifras -------------------------------------------------- */
.pub-cifras {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 14px;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
/* La cifra dominante, y la única en ámbar: es lo que el sistema contó. No
   incluye las visualizaciones —ver algo al pasar no es interactuar—. */
.pub-interacciones {
  font-size: 15px;
  font-weight: 600;
  color: var(--senal);
}
.pub-interacciones-rot { font-size: 10.5px; font-weight: 400; color: var(--texto-medio); }
.pub-dato { font-size: 11.5px; color: var(--texto-medio); }
.pub-dato-rot { color: var(--texto-tenue); }
/* Un dato ausente no es un cero: «sin cifras» y «cero interacciones» son cosas
   distintas y no pueden verse igual. */
.pub-sin-cifras {
  margin: 0;
  padding: 8px 10px;
  border: 1px dashed var(--borde-vivo);
  border-radius: var(--radio-chico);
  font-size: 12px;
  line-height: 1.45;
  color: var(--texto-tenue);
}

/* --- Fila 4: cómo se recibió, medido ------------------------------------- */
.pub-veredicto {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  /* Envuelve entero o no envuelve: en el teléfono «rechazo dominante» se
     partía a la mitad y las dos piezas se leían como una lista de tres cosas.
     Si no caben en la misma línea, la muestra baja completa a la siguiente. */
  flex-wrap: wrap;
  gap: 2px 10px;
  margin-bottom: 9px;
}
.pub-veredicto-txt {
  font-size: 13px;
  font-weight: 600;
  color: var(--texto-medio);
  white-space: nowrap;
}
.pub-veredicto-txt[data-tono="favor"]  { color: var(--estado-success); }
.pub-veredicto-txt[data-tono="contra"] { color: var(--estado-error); }
/* Ninguna cifra sin su muestra. */
.pub-veredicto-muestra {
  font-family: var(--mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--texto-tenue);
  white-space: nowrap;
}
.pub-reaccion .barra--pub { height: 6px; margin: 0; border-radius: 3px; }
.pub-muestra-corta {
  margin: 4px 0 0;
  font-size: 11px;
  color: var(--senal);
}
.pub-sin-reaccion {
  margin: 0;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .03em;
  color: var(--texto-tenue);
}

/* --- Fila 5: lo que entendió el modelo ----------------------------------- */
.pub-chips { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.pub-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 20px;
  border: 1px solid var(--borde-vivo);
  font-size: 11.5px;
  color: var(--texto-medio);
}
.pub-chip--ia {
  border-color: var(--ia-borde);
  background: var(--ia-suave);
  color: var(--ia);
  font-weight: 600;
}
/* Que el desacuerdo apunte a ella es el dato más accionable de la vista: es el
   único chip a pleno contraste. */
.pub-chip--ia[data-alerta="true"] { border-color: var(--ia); color: var(--texto); }
.rombo-ia {
  width: 6px;
  height: 6px;
  flex: none;
  transform: rotate(45deg);
  background: var(--ia);
}

/* --- Fila 6: el porqué y la prueba, plegados ----------------------------- */
.pub-detalle {
  border: 1px solid var(--ia-borde);
  border-radius: var(--radio);
  background: var(--ia-suave);
}
.pub-detalle > summary {
  display: block;
  min-height: 44px;
  padding: 13px 16px;
  cursor: pointer;
  list-style: none;
  transition: background .15s, border-color .15s;
}
.pub-detalle > summary::-webkit-details-marker { display: none; }
.pub-detalle > summary:hover { background: var(--ia-brillo); }
.pub-detalle > summary:focus-visible { outline: 2px solid var(--ia); outline-offset: 2px; }
.pub-detalle-fila {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.pub-detalle-rotulo {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  color: var(--ia);
}
.pub-detalle-flecha {
  display: inline-block;
  font-size: 12px;
  color: var(--ia);
  transition: transform .15s;
}
.pub-detalle[open] .pub-detalle-flecha { transform: rotate(90deg); }
/* El arranque del resumen, solo plegado: dice si vale la pena abrir sin
   obligar a leer un párrafo por publicación. */
.pub-teaser {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: 7px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--texto-medio);
}
.pub-detalle[open] .pub-teaser { display: none; }

.pub-detalle-cuerpo {
  display: flex;
  flex-direction: column;
  gap: 16px;
  /* Aire para separar el cuerpo de la cabecera del panel, que comparten fondo. */
  padding: 12px 16px 16px;
}
/* La lectura del modelo va suelta: ni caja propia ni rótulo propio. El panel
   que la contiene ya es cian y su cabecera ya dice qué es, así que una tarjeta
   dentro de otra idéntica —o un segundo rótulo dos renglones más abajo— era
   anunciar dos veces lo mismo. Todo lo que hay aquí dentro lo escribió el
   modelo, y el color lo dice sin gastar una línea. */
.pub-lectura-texto { margin: 0; font-size: 13px; line-height: 1.65; color: var(--texto); }
/* La referencia, en palabras y sin la cifra técnica: «mediana» no aparece en
   la interfaz en ningún sitio. */
.pub-referencia { margin: 0; font-size: 12px; color: var(--texto-medio); }

.pub-comentarios {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
/* Son la prueba de lo que dice la lectura, y por eso llevan el color de su
   postura en el canto: se puede comprobar de un vistazo que la barra de arriba
   no se lo inventó. */
.pub-com {
  border-left: 2px solid var(--estado-idle);
  padding: 2px 0 2px 12px;
}
.pub-com[data-postura="support"] { border-left-color: var(--estado-success); }
.pub-com[data-postura="oppose"]  { border-left-color: var(--estado-error); }
.pub-com[data-postura="mixed"]   { border-left-color: var(--estado-warning); }
.pub-com-texto {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--texto);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.pub-com-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 7px;
  font-family: var(--mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--texto-tenue);
}
.pub-com-postura { text-transform: uppercase; letter-spacing: .06em; }
.pub-com[data-postura="support"] .pub-com-postura { color: var(--estado-success); }
.pub-com[data-postura="oppose"]  .pub-com-postura { color: var(--estado-error); }
.pub-com[data-postura="mixed"]   .pub-com-postura { color: var(--estado-warning); }

/* Ámbar y sin subrayado, como el resto de los enlaces del panel: con el azul
   del navegador parecía un enlace de un correo pegado dentro de la tarjeta. */
.pub-original {
  font-family: var(--mono);
  font-size: 12px;
  align-self: flex-start;
  color: var(--senal);
  text-decoration: none;
}
.pub-original:hover { text-decoration: underline; }
.pub-original:focus-visible { outline: 2px solid var(--senal); outline-offset: 2px; }

@media (max-width: 620px) {
  .publicacion { padding: 16px; }
  /* Los tres tramos en una sola fila también en pantalla estrecha: partidos en
     dos filas, el selector pesa más que la primera tarjeta. */
  .periodo { padding: 0 13px; }
  .pub-rendimiento { max-width: 150px; }
  .pub-multiplo { font-size: 22px; }
}
