/* Capa mínima sobre el tema Tabler. Solo estilos que Tabler no cubre:
   la gráfica de barras del historial de disco. */

.dh-chart {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 130px;
}
.dh-bar {
  flex: 1;
  min-width: 4px;
  height: 100%;
  display: flex;
  align-items: flex-end;
  background: var(--tblr-border-color, rgba(255, 255, 255, 0.05));
  border-radius: 4px 4px 0 0;
  overflow: hidden;
}
.dh-fill {
  display: block;
  width: 100%;
  min-height: 2px;
  border-radius: 4px 4px 0 0;
  background: linear-gradient(to top, var(--tblr-green, #2fb344), #4ade80);
}
.dh-axis {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  margin-top: 8px;
}

/* Layout compacto: todos los paneles visibles en 1920x1080 sin scroll de página.
   Cada lista con mucho contenido hace scroll DENTRO de su cuadro. */
/* overflow-x: la tabla de consultas ya no lleva .table-responsive (rompía el thead
   sticky), así que el propio panel absorbe el scroll horizontal si hiciera falta. */
.panel-scroll { max-height: 258px; overflow-y: auto; overflow-x: auto; }
.dh-chart { height: 110px; }
/* Métricas compactas */
#cards .card-body { padding: 12px 16px; }
/* Tablas más densas dentro de los cuadros */
.card-table td { padding-top: .4rem; padding-bottom: .4rem; }
body, .page { overflow-x: hidden; }

/* Cuadros del mismo nivel = mismo alto: la columna estira la card a la más alta del
   renglón; el contenido (panel-scroll / table-responsive con max-height) hace scroll si
   excede. Aplica a Recursos (3), Máquinas+Endpoints, Servicios+IP, Disco+Deploys. */
.row-cards > [class*="col-"] > .card { height: 100%; }
.row-cards > [class*="col-"] > .card > .panel-scroll { flex: 1 1 auto; min-height: 0; }

/* Deja ver el color de fondo del <thead> (cada tabla un color distinto): las celdas th de
   Tabler traen su propio background que lo tapaba. Solo afecta a los thead con style inline. */
.card-table thead[style] th { background-color: transparent !important; }

/* Historial de IP: un scroll DIFERENTE por máquina. El cuadro se reparte en bloques
   (uno por máquina); el nombre queda fijo y SOLO la tabla de esa máquina hace scroll.
   Así mivps y vpsolaya2 se desplazan de forma independiente sin arrastrarse entre sí. */
#iphistory-body { display: flex; flex-direction: column; gap: .75rem; overflow: hidden; flex: 1 1 auto; min-height: 0; }
.iph-machine { display: flex; flex-direction: column; flex: 1 1 0; min-height: 0; }
.iph-machine > .iph-scroll { flex: 1 1 0; min-height: 0; overflow-y: auto; }
/* Encabezado de la tabla pegado arriba mientras se hace scroll dentro del bloque. Le
   devolvemos un fondo opaco al <th> (la regla de arriba lo dejaba transparente) para que
   las filas que pasan por detrás no se traslucan sobre el encabezado fijo. */
.iph-machine .iph-scroll thead th {
  position: sticky; top: 0; z-index: 1;
  background-color: hsl(275, 40%, 20%) !important;
}

/* ===== Base de conocimiento: botones flotantes + modal =====
   Tabler no trae dock flotante, así que lo montamos aquí. z-index por debajo del
   .modal (1055) y del .modal-backdrop (1050) de Bootstrap para que no se encimen. */
/* Encabezado inmóvil de las tablas con scroll interno (Consultas a scrapers). El sticky
   debe ir en los TH (un sticky en thead no funciona) y con fondo opaco para que las filas
   no se transparenten al pasar por debajo. */
.sticky-head th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: hsl(210, 50%, 18%);
}

/* Encabezados inmóviles del resto de tablas con scroll (cada una conserva su color).
   OJO: el sticky solo funciona si la tabla cuelga DIRECTO del contenedor que scrollea
   (un .table-responsive intermedio crea su propio contexto y lo rompe). */
#servicios-list thead th { position: sticky; top: 0; z-index: 1; background-color: hsl(150, 45%, 15%) !important; }
#sordera-list thead th { position: sticky; top: 0; z-index: 1; background-color: hsl(0, 45%, 18%) !important; }
#solicitudes-list thead th { position: sticky; top: 0; z-index: 1; background-color: hsl(265, 40%, 20%) !important; }
#diskhistory-body thead th { position: sticky; top: 0; z-index: 1; background-color: hsl(30, 50%, 18%) !important; }

/* Badge de efectividad del panel de consultas: fondo distintivo por umbral. */
.efect-badge {
  display: inline-block;
  margin-left: .35rem;
  padding: .1rem .55rem;
  border-radius: 999px;
  font-weight: 700;
  color: #fff;
}
.efect-ok   { background: #047857; }
.efect-warn { background: #b45309; }
.efect-bad  { background: #b91c1c; }

.kb-dock {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 1040;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: .5rem;
}
.kb-fab {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-width: 9.5rem;
  padding: .5rem .9rem;
  border-radius: 999px;
  /* Fondo distintivo de la KB central: gradiente esmeralda→cian, distinto del
     violeta→rosa del botón de Solicitudes (esquina opuesta). */
  background: linear-gradient(135deg, #047857, #0e7490);
  color: #ecfeff;
  border: 1px solid rgba(110, 231, 183, .45);
  box-shadow: 0 6px 18px rgba(4, 120, 87, .45);
  font-weight: 600;
  white-space: nowrap;
}
.kb-fab:hover { background: linear-gradient(135deg, #059669, #0891b2); color: #ffffff; }
.kb-fab .status-dot { flex: none; }
.kb-fab-text { flex: 1 1 auto; text-align: left; }

/* ===== Modal: tamaño, paleta propia y estructura de pestañas =====
   El monitor usa --tblr-body-bg #111827 y tarjetas #1f2937 (gris neutro). El modal
   estrena su propia paleta azul-índigo, más clara, con borde visible y sombra marcada:
   así se lee como una CAPA por encima del dashboard y no se confunde con el fondo. */
/* La misma paleta la comparte el cuadro emergente de información volátil (#kbv-modal),
   que es una capa por encima: si estrenara colores propios parecerían dos productos.
   Y también el de Solicitudes a Claude Code (#sc-modal): son cuadros hermanos, no
   productos distintos; lo único propio de aquel es su botón flotante. */
#kb-modal,
#kbv-modal,
#sc-modal {
  --kb-bg: #1b2540;        /* fondo del cuadro */
  --kb-bg-alt: #222f52;    /* cabecera y barra de pestañas */
  --kb-card: #26345c;      /* tarjetas y tablas dentro del modal */
  --kb-thead: #2c3b68;     /* encabezados de tabla (pegados arriba) */
  --kb-borde: #46599a;
  --kb-texto: #e9edf7;
  --kb-texto-2: #a7b3cd;   /* secundario, con más contraste que el de Tabler */
  --kb-acento: #6f8ff0;
}
/* Ocupa la mayor parte de la pantalla, con un tope razonable en monitores anchos. */
.kb-dialog { width: 92vw; max-width: 1680px; margin: auto; }
.kb-content {
  height: 90vh;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background-color: var(--kb-bg);
  color: var(--kb-texto);
  border: 1px solid var(--kb-borde);
  border-radius: 10px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, .75);
}
/* Fondo del backdrop más opaco: refuerza la sensación de capa superior. */
#kb-backdrop.modal-backdrop,
#kbv-backdrop.modal-backdrop,
#sc-backdrop.modal-backdrop { background-color: #05070d; opacity: .72; }

.kb-header {
  flex: 0 0 auto;
  background-color: var(--kb-bg-alt);
  border-bottom: 1px solid var(--kb-borde);
}
#kb-modal .modal-title, #kbv-modal .modal-title, #sc-modal .modal-title { color: #fff; }
#kb-modal .text-secondary, #kbv-modal .text-secondary, #sc-modal .text-secondary { color: var(--kb-texto-2) !important; }
#kb-modal .subheader, #kbv-modal .subheader, #sc-modal .subheader { color: var(--kb-texto-2); }
#kb-modal .card,
#kbv-modal .card,
#sc-modal .card { background-color: var(--kb-card); border-color: rgba(120, 150, 220, .22); }
#kb-modal .btn,
#kbv-modal .btn,
#sc-modal .btn {
  background-color: #2b3a63; border-color: var(--kb-borde); color: var(--kb-texto);
}
#kb-modal .btn:hover:not(:disabled),
#kbv-modal .btn:hover:not(:disabled),
#sc-modal .btn:hover:not(:disabled) { background-color: #35477a; color: #fff; }
#kb-modal .btn:disabled, #kbv-modal .btn:disabled, #sc-modal .btn:disabled { opacity: .45; }
#kb-modal .form-control,
#sc-modal .form-control,
#sc-modal .form-select {
  background-color: #16203a; border-color: var(--kb-borde); color: var(--kb-texto);
}
#kb-modal .form-control::placeholder,
#sc-modal .form-control::placeholder { color: #8494b5; }

/* Pestañas a mano (sin el JS de Tabler): solo cambian qué panel se muestra. */
.kb-tabs {
  flex: 0 0 auto;
  display: flex;
  gap: .25rem;
  padding: 0 .75rem;
  background-color: var(--kb-bg-alt);
  border-bottom: 1px solid var(--kb-borde);
}
.kb-tab {
  appearance: none;
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--kb-texto-2);
  padding: .5rem .9rem;
  font-weight: 500;
  cursor: pointer;
}
.kb-tab:hover { color: #fff; }
.kb-tab.active {
  color: #fff;
  border-bottom-color: var(--kb-acento);
  background-color: rgba(111, 143, 240, .14);
}

/* Totales de la instancia (vehículos / personas). Franja fija entre las pestañas y el
   cuerpo: se ve igual en las TRES pestañas, con dos cuadros del mismo ancho y alto, y
   nunca se encima con el buscador de las tablas (va por encima de .kb-body, no dentro). */
.kb-totales {
  flex: 0 0 auto;
  display: flex;
  gap: .5rem;
  padding: .75rem .75rem 0;
}
.kb-totales:empty { display: none; }
.kb-total {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: .6rem;
  padding: .45rem .85rem;
  background-color: var(--kb-card);
  border: 1px solid rgba(120, 150, 220, .22);
  border-radius: 8px;
}
.kb-total-label { flex: 0 0 auto; }
.kb-total-valor {
  font-size: 1.75rem;
  line-height: 1.15;
  font-weight: 600;
  color: #fff;
}
/* El pie se pega a la derecha y se recorta si no cabe: el número grande manda. */
.kb-total-sub {
  margin-left: auto;
  text-align: right;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Historial diario: alto acotado con scroll propio y encabezado pegado arriba (mismo
   patrón que el log de consultas). Con una sola fila el cuadro queda igual de compacto. */
.kb-hist-scroll { max-height: 260px; overflow-y: auto; }
.kb-hist-scroll thead th {
  position: sticky; top: 0; z-index: 1;
  background-color: var(--kb-thead) !important;
}

/* El cuerpo no hace scroll: lo hace cada panel por dentro (cuadros uniformes, nada encimado). */
.kb-body { flex: 1 1 auto; min-height: 0; overflow: hidden; padding: .75rem; }
.kb-pane { height: 100%; display: flex; flex-direction: column; min-height: 0; }
.kb-pane-scroll { display: block; overflow-y: auto; overflow-x: hidden; }

/* Vehículos / Personas: buscador arriba, tabla con scroll propio, paginador abajo. */
.kb-toolbar { flex: 0 0 auto; display: flex; align-items: center; gap: .5rem; margin-bottom: .5rem; }
.kb-buscador { max-width: 24rem; }
.kb-tabla-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;                 /* la tabla nunca desborda el modal */
  background-color: var(--kb-card);
  border: 1px solid rgba(120, 150, 220, .22);
  border-radius: 8px;
}
.kb-pager { flex: 0 0 auto; display: flex; align-items: center; gap: .5rem; padding-top: .5rem; }
.kb-tabla { margin-bottom: 0; white-space: nowrap; }
.kb-tabla thead th {
  position: sticky; top: 0; z-index: 1;
  background-color: var(--kb-thead) !important;
  color: var(--kb-texto);
}
.kb-tabla td { color: var(--kb-texto); }
.kb-tabla .kb-nulo { color: #7c89a6; }

/* Efectividad: el dato principal del modal, en grande y sin competencia visual. */
.kb-efectividad { font-size: 2.6rem; line-height: 1.1; font-weight: 600; }

/* Log de consultas: alto fijo con scroll propio y encabezado pegado arriba. La regla
   de arriba deja transparentes los thead con style inline, así que le devolvemos un
   fondo opaco para que las filas no se traslucen por detrás del encabezado. */
.kb-log-scroll { max-height: 300px; overflow-y: auto; }
.kb-log-scroll thead th {
  position: sticky; top: 0; z-index: 1;
  background-color: var(--kb-thead, hsl(210, 45%, 16%)) !important;
}

/* ===== Cuadro emergente: información volátil de un vehículo (#kbv-modal) =====
   Segunda capa POR ENCIMA del modal de la base. Va más estrecho y más bajo a propósito:
   así se ven los bordes del cuadro de abajo y se entiende que es un detalle, no otra
   pantalla. Tabler reserva 1050/1055 para modal y backdrop; aquí subimos a 1075/1080
   para quedar por encima del modal de la base sin taparlo del todo. */
#kbv-modal { z-index: 1080; }
#kbv-backdrop.modal-backdrop { z-index: 1075; }
.kbv-dialog { width: 74vw; max-width: 1100px; margin: auto; }
/* Va después de .kb-content, así que su alto manda sobre el de aquel. A diferencia del
   modal de la base (alto fijo), este se ajusta a lo que hay: un vehículo sin información
   volátil no abre un cuadro medio vacío de pantalla completa. */
.kbv-content { height: auto; max-height: 82vh; min-height: 16rem; }

/* El botón de la columna "Volátil": discreto, del alto de una fila, sin ensanchar la tabla. */
.kbv-btn { padding: .05rem .5rem; font-size: .75rem; line-height: 1.5; }

/* Franja de frescura: los mismos cuadros que los totales pero en columna. El valor es una
   fecha con hora, no un número redondo: en fila se partía en tres líneas y el pie se
   recortaba. Apilados, los tres cuadros quedan del mismo alto y todo el texto cabe. */
.kbv-meta .kb-total { flex-direction: column; align-items: flex-start; gap: .05rem; padding: .4rem .8rem; }
.kbv-meta .kb-total-valor { font-size: 1.05rem; line-height: 1.3; }
.kbv-meta .kb-total-sub { margin-left: 0; text-align: left; max-width: 100%; }

/* Secciones del cuerpo (volátil actual / historial). */
.kbv-seccion { margin-bottom: .9rem; }
.kbv-seccion:last-child { margin-bottom: 0; }
.kbv-seccion-titulo {
  display: flex; align-items: baseline; gap: .5rem;
  margin: 0 0 .45rem;
  font-size: .75rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .05em;
  color: var(--kb-texto-2);
}

/* Rejilla de bloques: todas las tarjetas del mismo ancho y, en cada fila, del mismo alto.
   `auto-fill` con mínimo fijo evita tarjetas huérfanas de doble ancho en pantallas raras. */
.kbv-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(21rem, 1fr)); gap: .6rem; }
.kbv-card {
  background-color: var(--kb-card);
  border: 1px solid rgba(120, 150, 220, .22);
  border-radius: 8px;
  overflow: hidden;               /* nada se sale del cuadro */
  min-width: 0;
  display: flex; flex-direction: column;
}
.kbv-card-head {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: .5rem;
  padding: .35rem .65rem;
  background-color: var(--kb-thead);
  border-bottom: 1px solid rgba(120, 150, 220, .22);
  font-weight: 600; font-size: .875rem;
  color: var(--kb-texto);
}
.kbv-card-body { flex: 1 1 auto; padding: .5rem .65rem; min-width: 0; }
/* Un bloque con VARIOS registros se pinta como tabla y necesita el doble de ancho: en una
   sola columna se cortarían las últimas columnas de la tabla. */
.kbv-card-ancho { grid-column: span 2; }

/* Resumen humano del bloque (vencimiento, estado…) antes del detalle completo. */
.kbv-chips { display: flex; flex-wrap: wrap; gap: .3rem; margin-bottom: .45rem; }

/* Pares clave/valor en dos columnas: la clave se ajusta a su texto y el valor ocupa el
   resto. `overflow-wrap` parte los valores largos (VIN, resoluciones) en vez de
   desbordar la tarjeta. */
.kbv-dl {
  display: grid;
  grid-template-columns: minmax(6rem, max-content) 1fr;
  gap: .18rem .7rem;
  margin: 0;
  font-size: .8125rem;
}
.kbv-dt { color: var(--kb-texto-2); min-width: 0; overflow-wrap: anywhere; }
.kbv-dd { margin: 0; color: var(--kb-texto); min-width: 0; overflow-wrap: anywhere; }
.kbv-nulo { color: #7c89a6; }

/* Una lista de registros (varios SOAT, varias RTM) se pinta como tabla compacta con
   scroll horizontal propio: la tarjeta nunca se ensancha ni empuja a las vecinas. */
.kbv-tabla-scroll {
  overflow-x: auto;
  border: 1px solid rgba(120, 150, 220, .18);
  border-radius: 6px;
}
.kbv-tabla { margin-bottom: 0; white-space: nowrap; font-size: .8125rem; }
.kbv-tabla thead th { background-color: var(--kb-thead) !important; color: var(--kb-texto); }
.kbv-tabla td { color: var(--kb-texto); }
.kbv-sub { margin-top: .4rem; }
.kbv-sub-titulo { font-size: .75rem; color: var(--kb-texto-2); margin-bottom: .15rem; }

/* Bloques sin registros: una sola línea con etiquetas, en vez de 10 tarjetas vacías. */
.kbv-vacios { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem; font-size: .8125rem; }

/* Historial de versiones: una fila plegable por versión. Cerrado ocupa una línea. */
.kbv-version { border: 1px solid rgba(120, 150, 220, .22); border-radius: 8px; overflow: hidden; margin-bottom: .4rem; }
.kbv-version:last-child { margin-bottom: 0; }
.kbv-version-head {
  width: 100%;
  display: flex; align-items: center; gap: .6rem;
  padding: .4rem .65rem;
  background-color: var(--kb-thead);
  border: 0; text-align: left;
  color: var(--kb-texto); font-size: .875rem;
  cursor: pointer;
}
.kbv-version-head:hover { background-color: #35477a; }
.kbv-version-flecha { flex: 0 0 auto; width: 1rem; color: var(--kb-texto-2); }
.kbv-version-fecha { flex: 0 0 auto; font-weight: 600; }
.kbv-version-sub { margin-left: auto; text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--kb-texto-2); font-size: .8125rem; }
.kbv-version-body { padding: .55rem; background-color: var(--kb-card); }

/* Aviso discreto (historial aún sin datos, endpoint no publicado todavía). */
.kbv-aviso {
  padding: .5rem .65rem;
  border: 1px dashed rgba(120, 150, 220, .35);
  border-radius: 8px;
  color: var(--kb-texto-2);
  font-size: .8125rem;
}

/* En móvil los botones son más chicos y el contenido gana aire abajo para que el
   dock no tape la última tarjeta. */
@media (max-width: 575.98px) {
  .kb-dock { right: .5rem; bottom: .5rem; gap: .35rem; }
  .kb-fab { min-width: 0; padding: .35rem .7rem; font-size: .8125rem; }
  .page-body { padding-bottom: 6rem; }
}

/* En pantallas chicas el modal aprovecha casi todo el alto y el buscador ocupa su fila. */
@media (max-width: 767.98px) {
  .kb-dialog { width: 98vw; }
  .kb-content { height: 94vh; max-height: 94vh; }
  .kb-toolbar { flex-wrap: wrap; }
  .kb-buscador { max-width: none; flex: 1 1 100%; }
  .kb-tab { padding: .5rem .6rem; font-size: .875rem; }
  /* Los dos totales se apilan: en una fila el número grande no cabría con su pie. */
  .kb-totales { flex-wrap: wrap; gap: .35rem; padding: .5rem .5rem 0; }
  .kb-total { flex: 1 1 100%; }
  .kb-total-valor { font-size: 1.4rem; }
  /* El cuadro emergente pasa a ocupar casi toda la pantalla y sus tarjetas a una columna. */
  .kbv-dialog { width: 98vw; }
  .kbv-content { height: 92vh; max-height: 92vh; }
  .kbv-grid { grid-template-columns: 1fr; }
  /* Con una sola columna, un "span 2" crearía una columna fantasma fuera del cuadro. */
  .kbv-card-ancho { grid-column: auto; }
  .kbv-meta .kb-total-valor { font-size: 1rem; }
}

/* ===== Solicitudes a Claude Code: botón flotante + modal =====
   El dock de la base de conocimiento (.kb-dock) ocupa la esquina de ABAJO a la derecha;
   este vive ARRIBA a la derecha, que estaba libre, y no se cruzan nunca.
   z-index 1040, el mismo del otro dock: por debajo del .modal-backdrop (1050) y del
   .modal (1055) de Bootstrap, y del cuadro volátil (1075/1080), para que cualquier
   cuadro abierto lo tape en vez de flotar encima. */
.sc-dock {
  position: fixed;
  top: 1rem;
  right: 1rem;
  z-index: 1040;
}

/* A diferencia de los .kb-fab (píldora gris, sobria), este tiene que LLAMAR la atención:
   es el acceso a lo que está pendiente. Gradiente vivo, sombra marcada y un pulso suave. */
.sc-fab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .55rem 1.05rem;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, .28);
  background: linear-gradient(100deg, #6d28d9 0%, #8b5cf6 45%, #ec4899 100%);
  color: #fff;
  font-weight: 600;
  letter-spacing: .01em;
  white-space: nowrap;
  cursor: pointer;
  animation: sc-pulso 2.6s ease-out infinite;
}
.sc-fab:hover {
  color: #fff;
  filter: brightness(1.12);
  animation-play-state: paused; /* al apuntarlo deja de latir: ya tiene la atención */
}
.sc-fab-emoji { font-size: 1.05rem; line-height: 1; }

/* El pulso es un halo que se expande y se desvanece; la sombra base no se toca para que
   el botón no "salte" de profundidad en cada ciclo. */
@keyframes sc-pulso {
  0%   { box-shadow: 0 10px 26px rgba(0, 0, 0, .5), 0 0 0 0 rgba(168, 85, 247, .55); }
  70%  { box-shadow: 0 10px 26px rgba(0, 0, 0, .5), 0 0 0 .7rem rgba(168, 85, 247, 0); }
  100% { box-shadow: 0 10px 26px rgba(0, 0, 0, .5), 0 0 0 0 rgba(168, 85, 247, 0); }
}
/* Quien pide menos movimiento se queda con el botón quieto, pero igual de visible. */
@media (prefers-reduced-motion: reduce) {
  .sc-fab { animation: none; box-shadow: 0 10px 26px rgba(0, 0, 0, .5); }
}

/* Contador de pendientes, en la esquina del botón. app.js lo oculta cuando es 0: un
   círculo rojo con un cero sería una alarma falsa. */
.sc-fab-badge {
  position: absolute;
  top: -.4rem;
  right: -.35rem;
  min-width: 1.35rem;
  padding: 0 .35rem;
  border-radius: 999px;
  background: #e11d48;
  border: 2px solid #111827;              /* recorta el badge contra el fondo del dashboard */
  color: #fff;
  font-size: .75rem;
  font-weight: 700;
  line-height: 1.25rem;
  text-align: center;
}

/* --- Modal --- */
/* Más estrecho que el de la base de conocimiento: es una lista de texto, no tablas. */
.sc-dialog { width: 82vw; max-width: 1080px; margin: auto; }
.sc-content { height: 88vh; max-height: 88vh; }

/* Formulario de alta: franja fija arriba del cuerpo, para que no se pierda al hacer
   scroll de la lista. */
.sc-form {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: .5rem;
  padding: .6rem .75rem;
  background-color: var(--kb-bg-alt);
  border-bottom: 1px solid var(--kb-borde);
}
.sc-form-proyecto { flex: 0 0 15rem; max-width: 100%; }
.sc-form-texto { flex: 1 1 22rem; min-width: 0; resize: vertical; }

/* Aviso (error de escritura, token rechazado…). Vacío no ocupa nada. */
.sc-aviso {
  flex: 1 1 100%;
  padding: .35rem .6rem;
  border-radius: 6px;
  background-color: rgba(225, 29, 72, .16);
  border: 1px solid rgba(225, 29, 72, .45);
  color: #ffc9d5;
  font-size: .8125rem;
}
.sc-aviso:empty { display: none; }

/* --- Lista agrupada por proyecto --- */
.sc-grupo { margin-bottom: .9rem; }
.sc-grupo:last-child { margin-bottom: 0; }
/* El nombre del proyecto queda pegado arriba mientras se recorre su grupo: con muchas
   solicitudes uno pierde de vista de qué proyecto está leyendo. */
.sc-grupo-head {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: baseline;
  gap: .5rem;
  padding: .35rem .6rem;
  background-color: var(--kb-thead);
  border: 1px solid rgba(120, 150, 220, .22);
  border-radius: 8px 8px 0 0;
}
.sc-grupo-nombre { font-weight: 600; color: #fff; }
.sc-grupo-cuerpo {
  border: 1px solid rgba(120, 150, 220, .22);
  border-top: 0;
  border-radius: 0 0 8px 8px;
  overflow: hidden;
}

/* Una solicitud. La barra de color de la izquierda dice el estado de un vistazo. */
.sc-item {
  display: flex;
  flex-direction: column;
  gap: .3rem;
  padding: .5rem .65rem;
  background-color: var(--kb-card);
  border-top: 1px solid rgba(120, 150, 220, .16);
  border-left: 3px solid transparent;
}
.sc-grupo-cuerpo > .sc-item:first-child { border-top: 0; }
.sc-item-pendiente { border-left-color: #f59e0b; }
.sc-item-en_progreso { border-left-color: #3b82f6; }
.sc-item-hecho { border-left-color: #2fb344; }
.sc-item-descartado { border-left-color: #6b7280; opacity: .68; }

.sc-item-head { display: flex; align-items: center; flex-wrap: wrap; gap: .45rem; }
.sc-item-fecha { color: var(--kb-texto-2); font-size: .8125rem; white-space: nowrap; }
.sc-item-acciones { margin-left: auto; display: flex; align-items: center; gap: .35rem; }
.sc-estado-select { width: auto; padding: .1rem 1.6rem .1rem .5rem; font-size: .8125rem; }
.sc-borrar { padding: .05rem .5rem; font-size: .75rem; line-height: 1.5; }
.sc-item-texto { color: var(--kb-texto); overflow-wrap: anywhere; }

/* Avances de Claude Code: hilo indentado bajo la solicitud, del más nuevo al más viejo. */
.sc-avances { margin: .15rem 0 0; padding: .3rem 0 0 .7rem; border-left: 2px solid rgba(120, 150, 220, .3); }
.sc-avance { display: flex; gap: .5rem; font-size: .8125rem; padding: .1rem 0; }
.sc-avance-hora { flex: 0 0 auto; color: var(--kb-texto-2); white-space: nowrap; }
.sc-avance-texto { min-width: 0; color: var(--kb-texto); overflow-wrap: anywhere; }
.sc-sin-avances { font-size: .8125rem; color: #7c89a6; }

@media (max-width: 767.98px) {
  /* Arriba a la derecha en móvil el botón compite con menos cosas, pero se achica. */
  .sc-dock { top: .5rem; right: .5rem; }
  .sc-fab { padding: .4rem .75rem; font-size: .8125rem; }
  .sc-dialog { width: 98vw; }
  .sc-content { height: 94vh; max-height: 94vh; }
  /* Cada campo del formulario ocupa su propia fila: en una sola no cabrían. */
  .sc-form-proyecto, .sc-form-texto { flex: 1 1 100%; }
}

/* ===== Franja de sesiones WAHA (cabecera, encima de las máquinas) =====
   Color PROPIO: azul índigo, para no confundirse con el verde→cian del dock de la KB ni
   con el violeta→rosa del botón de Solicitudes. Los chips son píldoras oscuras encima de
   la franja; el color del estado va en el punto y en el badge, nunca en la franja, para
   que un número caído se vea de un vistazo contra el fondo. */
.waha-franja {
  margin-bottom: .5rem;
  padding: .55rem .85rem;
  border-radius: .5rem;
  border: 1px solid hsl(222, 70%, 55%);
  border-left-width: .35rem;
  background: linear-gradient(90deg, hsl(228, 55%, 20%), hsl(216, 55%, 24%));
  box-shadow: 0 4px 14px rgba(20, 40, 110, .35);
}
/* Reserva a la derecha para el botón flotante de Solicitudes (fixed, arriba a la derecha):
   sin esto el último chip quedaba debajo del botón. */
@media (min-width: 768px) { .waha-franja { padding-right: 15rem; } }
.waha-franja-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .35rem .75rem;
  margin-bottom: .4rem;
}
.waha-franja-titulo {
  font-weight: 700;
  color: #dbe4ff;
  letter-spacing: .01em;
  white-space: nowrap;
}
.waha-franja-resumen { font-size: .8125rem; color: #aebbe6; }
.waha-franja-resumen .badge { vertical-align: middle; }
.waha-chips {
  display: flex;
  flex-wrap: wrap;                 /* en móvil los chips se envuelven */
  gap: .4rem;
}
.waha-chip {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  max-width: 100%;
  padding: .3rem .7rem;
  border-radius: 999px;
  border: 1px solid rgba(160, 180, 240, .35);
  background: rgba(8, 14, 34, .6);
  color: #e6ecff;
  font-size: .8125rem;
  line-height: 1.2;
  white-space: nowrap;
}
.waha-chip .status-dot { flex: none; }
.waha-chip-etiqueta { font-weight: 600; }
.waha-chip-numero { font-variant-numeric: tabular-nums; color: #c3cff5; }
.waha-chip-hace { color: #8f9fd0; font-size: .75rem; }
/* Un número distinto al esperado o una sesión caída: el borde del chip lo grita. */
.waha-chip-otro { border-color: #f43f5e; box-shadow: 0 0 0 2px rgba(244, 63, 94, .35); }
.waha-chip-caida { border-color: rgba(239, 68, 68, .7); }
@media (max-width: 575.98px) {
  .waha-franja { padding: .5rem .6rem; }
  .waha-chip { font-size: .75rem; padding: .25rem .55rem; gap: .35rem; }
}

/* Consultas a scrapers en tiempo real (13-oct-2026): chip EN VIVO + resaltado de filas nuevas. */
.scraper-live { font-size: 11px; font-weight: 600; letter-spacing: .04em; padding: 2px 8px; border-radius: 999px; margin-left: 10px; vertical-align: middle; white-space: nowrap; }
.scraper-live::before { content: ""; display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 5px; vertical-align: 1px; background: currentColor; }
.scraper-live.on { color: #16a34a; background: rgba(22,163,74,.12); }
.scraper-live.on::before { animation: scraper-pulso 1.6s ease-in-out infinite; }
.scraper-live.off { color: #d97706; background: rgba(217,119,6,.12); }
@keyframes scraper-pulso { 0%,100% { opacity: 1; } 50% { opacity: .25; } }
#scraperhistory-list tr.fila-nueva > td { animation: scraper-fila-nueva 4s ease-out; }
@keyframes scraper-fila-nueva { 0% { background-color: rgba(34,197,94,.35); } 100% { background-color: transparent; } }

/* ===== Tablas COMPACTAS (16-oct-2026): «Consultas a scrapers» y «Actividad de los PDV»
   comparten fila a 50/50, así que no pueden pedir scroll horizontal. Layout fijo con los
   anchos del <colgroup>, una línea por celda y elipsis; el valor completo va en el title. */
.tabla-compacta { table-layout: fixed; width: 100%; font-size: .78rem; }
.tabla-compacta th, .tabla-compacta td {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  padding-left: .35rem; padding-right: .35rem;
}
.tabla-compacta th { font-size: .66rem; }
.tabla-compacta .badge {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; vertical-align: middle;
  font-size: .68rem; padding: .2em .45em;
}
.tabla-compacta a { display: inline; }
#scraperhistory-list, #actpdv-list { overflow-x: hidden; }
/* Encabezado de la tarjeta: la insignia de efectividad es larga y a media pantalla debe
   poder bajar de renglón en vez de empujar el título. */
.card-header-wrap { flex-wrap: wrap; gap: .25rem .5rem; }
.card-header-wrap .card-actions { margin-left: auto; min-width: 0; }
#actpdv-list .sticky-head th { background: hsl(28, 45%, 18%); }
