/* Paneltone — hoja de estilos única.
   Un solo vocabulario para todo el panel: tokens (color, espacio, tipo), el
   armazón (rail, cabecera, contenido) y los componentes que usan las vistas.
   Tema oscuro por defecto; el claro con <html data-theme="light"> (botón de
   tema, se recuerda en localStorage). */

/* ---------------------------------------------------------------- Tipografías
   IBM Plex, servida desde el propio panel (assets/fonts). Sans para el texto,
   Mono para lo que es dato técnico: rutas, dominios, versiones, tamaños. */
@font-face {
  font-family: 'Plex Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(../fonts/plex-sans.woff2) format('woff2');
}
@font-face {
  font-family: 'Plex Sans';
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url(../fonts/plex-sans-italic.woff2) format('woff2');
}
@font-face {
  font-family: 'Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../fonts/plex-mono-400.woff2) format('woff2');
}
@font-face {
  font-family: 'Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(../fonts/plex-mono-500.woff2) format('woff2');
}

/* --------------------------------------------------------------------- Tokens */
:root {
  color-scheme: dark;

  /* Superficies: grafito cálido, no azul-negro. */
  --bg: #141311;
  --bg-2: #1b1a17;
  --bg-3: #232119;
  --bg-4: #2b2921;
  --line: #2f2c26;
  --line-2: #3d3931;
  --text: #ece7dc;
  --text-2: #c9c3b7;
  --muted: #9a9388;

  /* Acento: lo que se puede pulsar. */
  --accent: #6aa3ff;
  --accent-2: #8ab8ff;
  --accent-ink: #0f1a2e;
  --accent-soft: rgba(106, 163, 255, .14);
  --focus: rgba(106, 163, 255, .38);

  /* Semáforo. */
  --ok: #3fb950;
  --ok-soft: rgba(63, 185, 80, .14);
  --warn: #e3a12e;
  --warn-soft: rgba(227, 161, 46, .14);
  --danger: #f0605a;
  --danger-soft: rgba(240, 96, 90, .14);
  --info: var(--accent);
  --info-soft: var(--accent-soft);
  --ok-text: var(--ok);
  --danger-2: #d3463f;
  --ok-fill: var(--ok); --warn-fill: var(--warn); --danger-fill: var(--danger);

  /* La marca: la corteza del panettone. Solo en la marca y el acceso. */
  --crust: #d69a55;

  /* Espacio, radios, sombras. */
  --s-1: 4px; --s-2: 8px; --s-3: 12px; --s-4: 16px; --s-5: 24px; --s-6: 32px;
  --r-sm: 6px; --r-md: 10px; --r-lg: 14px;
  --radius: var(--r-md);
  --shadow: 0 12px 32px rgba(0, 0, 0, .45), 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-sm: 0 4px 14px rgba(0, 0, 0, .35);

  /* Tipo. */
  --font: 'Plex Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --mono: 'Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --fs-xs: 12px; --fs-sm: 13px; --fs: 14px; --fs-md: 15px; --fs-lg: 17px; --fs-xl: 21px;

  --rail-w: 232px;
  --content-pad: var(--s-5);
}
:root[data-theme="light"] {
  color-scheme: light;
  --bg: #f2f1ee;
  --bg-2: #ffffff;
  --bg-3: #f7f6f3;
  --bg-4: #edebe6;
  --line: #e2dfd8;
  --line-2: #cfcbc2;
  --text: #1f1d1a;
  --text-2: #423f39;
  --muted: #6b665d;
  --accent: #2a63d4;
  --accent-2: #1f52b8;
  --accent-ink: #ffffff;
  --accent-soft: rgba(42, 99, 212, .11);
  --focus: rgba(42, 99, 212, .3);
  --ok: #1a7f37;
  --ok-soft: rgba(26, 127, 55, .12);
  --warn: #9a6700;
  --warn-soft: rgba(154, 103, 0, .12);
  --danger: #cf222e;
  --danger-soft: rgba(207, 34, 46, .1);
  --danger-2: #a40e26;
  --crust: #b7823f;
  --ok-fill: #2da44e; --warn-fill: #e0a020; --danger-fill: #e5484d;
  --shadow: 0 12px 32px rgba(30, 25, 15, .16), 0 1px 2px rgba(30, 25, 15, .12);
  --shadow-sm: 0 4px 14px rgba(30, 25, 15, .12);
}

/* ----------------------------------------------------------------------- Base */
* { box-sizing: border-box; }
/* `hidden` oculta SIEMPRE. Sin esto, cualquier regla con display (label es
   block, .row es flex…) le gana al estilo del navegador y lo «oculto» se ve:
   pasaba en el alta de reglas de Bots, con el campo CIDR a la vista en una
   regla de user-agent. */
[hidden] { display: none !important; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--fs)/1.5 var(--font);
  font-feature-settings: 'tnum' 0;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.3; }
h1 { font-size: var(--fs-xl); letter-spacing: -.01em; }
h2 { font-size: var(--fs-lg); }
h3 { font-size: var(--fs-md); }
h4 { font-size: var(--fs); }
p { margin: 0 0 var(--s-3); }
p:last-child { margin-bottom: 0; }
a { color: var(--accent); }
a:hover { color: var(--accent-2); }
code, .mono { font-family: var(--mono); font-size: .92em; }
b, strong { font-weight: 600; }
hr { border: 0; border-top: 1px solid var(--line); margin: var(--s-4) 0; }
::selection { background: var(--accent-soft); }

/* Utilidades: lo que antes eran estilos inline repetidos por las vistas. */
.muted { color: var(--muted); }
.small { font-size: var(--fs-sm); }
.xs { font-size: var(--fs-xs); }
.text-warn { color: var(--warn); }
.text-danger { color: var(--danger); }
.text-ok { color: var(--ok); }
.num, .tabular { font-variant-numeric: tabular-nums; }
.right { text-align: right; }
.center { text-align: center; }
.nowrap { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prewrap { white-space: pre-wrap; overflow-wrap: anywhere; }
.break { overflow-wrap: anywhere; word-break: break-word; }
.grow { flex: 1; min-width: 0; }
.row { display: flex; gap: var(--s-2); align-items: center; }
.row--wrap { flex-wrap: wrap; }
.row--start { align-items: flex-start; }
.row--end { justify-content: flex-end; }
.row--between { justify-content: space-between; }
.row--gap-lg { gap: var(--s-3); }
.stack { display: flex; flex-direction: column; gap: var(--s-2); }
.stack--lg { gap: var(--s-4); }
.mt-0 { margin-top: 0 !important; }
.mt-1 { margin-top: var(--s-1); }
.mt-2 { margin-top: var(--s-2); }
.mt-3 { margin-top: var(--s-3); }
.mt-4 { margin-top: var(--s-4); }
.mt-5 { margin-top: var(--s-5); }
.mb-0 { margin-bottom: 0 !important; }
.mb-1 { margin-bottom: var(--s-1); }
.mb-2 { margin-bottom: var(--s-2); }
.mb-3 { margin-bottom: var(--s-3); }
.mb-4 { margin-bottom: var(--s-4); }
.ml-2 { margin-left: var(--s-2); }
.m-0 { margin: 0 !important; }
.w-auto { width: auto !important; }
.w-full { width: 100% !important; }
.w-num { width: 8rem !important; }   /* un número corto junto a una elección (MB, peticiones) */
.block-h { margin-top: var(--s-5); }
.hidden { display: none !important; }

/* ------------------------------------------------------------ Carga y estados */
.loading { display: grid; place-items: center; height: 100vh; }
.spinner {
  width: 26px; height: 26px; flex: none;
  border: 3px solid var(--line-2); border-top-color: var(--accent);
  border-radius: 50%; animation: spin .8s linear infinite;
}
.spinner--sm { width: 14px; height: 14px; border-width: 2px; display: inline-block; vertical-align: -2px; margin-right: 6px; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Mientras llega algo: mismo aspecto en todas las vistas (ui.js cargando()). */
.cargando { display: flex; align-items: center; gap: var(--s-2); color: var(--muted); padding: var(--s-4) 0; }
.cargando .spinner { width: 16px; height: 16px; border-width: 2px; }

/* Vacío: una frase y, si procede, qué hacer. */
.empty {
  color: var(--muted); padding: var(--s-6) var(--s-4); text-align: center;
  border: 1px dashed var(--line-2); border-radius: var(--r-md); margin: 0;
}
.empty--sm { padding: var(--s-4); }
.empty__action { margin-top: var(--s-3); }
td .empty, .tbl .empty { border: 0; padding: var(--s-4); }

/* Error de pantalla: siempre con el mismo rojo y la misma caja. */
.error-box {
  color: var(--danger); background: var(--danger-soft);
  border: 1px solid transparent; border-left: 3px solid var(--danger);
  padding: var(--s-3) var(--s-4); border-radius: var(--r-sm); margin: 0;
}
.result__error { color: var(--danger); background: var(--danger-soft); border-left: 3px solid var(--danger); padding: var(--s-3) var(--s-4); border-radius: var(--r-sm); }
.dash-card__err { color: var(--danger); background: var(--danger-soft); border-left: 3px solid var(--danger); padding: var(--s-2) var(--s-3); border-radius: var(--r-sm); font-size: var(--fs-sm); }

/* Avisos no bloqueantes. */
.alert { border-radius: var(--r-sm); padding: var(--s-3) var(--s-4); font-size: var(--fs-sm); margin-bottom: var(--s-4); border: 1px solid transparent; border-left-width: 3px; color: var(--text); }
.alert--warn { background: var(--warn-soft); border-left-color: var(--warn); }
.alert--danger { background: var(--danger-soft); border-left-color: var(--danger); }
.alert--info { background: var(--info-soft); border-left-color: var(--accent); }
.alert--ok { background: var(--ok-soft); border-left-color: var(--ok); }
.alert strong { font-weight: 600; }

/* ------------------------------------------------------------------ Armazón */
.app { display: grid; grid-template-columns: var(--rail-w) minmax(0, 1fr); height: 100vh; }
.rail {
  background: var(--bg-2); border-right: 1px solid var(--line);
  display: flex; flex-direction: column; padding: var(--s-3) var(--s-3) var(--s-3);
  overflow: auto;
}
.rail__head { display: flex; align-items: center; justify-content: space-between; }
.rail__toggle { display: none; font: inherit; font-size: 20px; line-height: 1; cursor: pointer; background: transparent; border: 1px solid var(--line); border-radius: var(--r-sm); color: var(--text); padding: 6px 10px; }
.brand {
  display: flex; align-items: center; gap: 10px; font-weight: 600; font-size: var(--fs-md);
  padding: 6px 8px 14px; letter-spacing: -.01em; color: var(--text); text-decoration: none;
}
.brand__logo { width: 26px; height: 26px; border-radius: 7px; display: inline-block; flex: none; }
.brand__name { line-height: 1.1; }
.brand__tag { display: block; font-size: var(--fs-xs); font-weight: 400; color: var(--muted); margin-top: 2px; }
.rail__nav { display: flex; flex-direction: column; gap: 1px; flex: 1; }
/* Administración va abajo del todo, separada: es el panel, no la flota. */
.navlink--foot { margin-top: auto; }
.navlink--foot::before { content: ""; display: block; border-top: 1px solid var(--line); margin: 0 -8px 8px; }
.navlink--foot.active::before { border-top-color: var(--line); }
/* Solo el primero de abajo empuja y lleva la raya: con dos (Agentes y Administración)
   el hueco se repartía y Agentes quedaba flotando a media altura. */
.navlink--foot ~ .navlink--foot { margin-top: 0; }
.navlink--foot ~ .navlink--foot:not(.active)::before { display: none; }
.rail__section { margin: var(--s-4) 8px var(--s-1); font-size: var(--fs-xs); font-weight: 600; color: var(--muted); }
.navlink {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; border-radius: var(--r-sm);
  color: var(--text-2); text-decoration: none; font-weight: 500; font-size: var(--fs);
  position: relative;
  transition: background .12s, color .12s;
}
.navlink:hover { background: var(--bg-3); color: var(--text); }
.navlink.active { background: var(--accent-soft); color: var(--text); font-weight: 600; }
.navlink.active::before {
  content: ''; position: absolute; left: 0; top: 7px; bottom: 7px; width: 3px;
  border-radius: 0 3px 3px 0; background: var(--accent);
}
.rail__foot { margin-top: auto; padding-top: var(--s-3); display: flex; flex-direction: column; gap: var(--s-2); }
.rail__actions { display: flex; gap: var(--s-2); }
.rail__actions .btn { flex: 1; }
.userchip { display: flex; align-items: center; gap: 10px; padding: 8px; background: var(--bg-3); border: 1px solid var(--line); border-radius: var(--r-md); min-width: 0; }
.userchip__name { font-weight: 600; font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.userchip__role { color: var(--muted); font-size: var(--fs-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.avatar { width: 32px; height: 32px; flex: none; border-radius: 50%; background: var(--accent); color: var(--accent-ink); display: grid; place-items: center; font-weight: 600; font-size: var(--fs-sm); }

.main { display: flex; flex-direction: column; overflow: hidden; min-width: 0; }
.topbar {
  flex: none; display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-4) var(--content-pad); min-height: 64px;
  border-bottom: 1px solid var(--line); background: var(--bg-2);
}
.topbar h1 { font-size: var(--fs-xl); }
.topbar__sub { color: var(--muted); font-size: var(--fs-sm); margin-top: 1px; }
.topbar .row { flex-wrap: wrap; justify-content: flex-end; gap: var(--s-2); }
.topbar select, .topbar .input, .topbar input[type=text], .topbar input[type=search] { width: auto; min-width: 170px; max-width: 280px; }
.content { padding: var(--content-pad); overflow: auto; min-width: 0; }

/* ----------------------------------------------------------------- Botones */
.btn {
  font: inherit; font-size: var(--fs); font-weight: 500; line-height: 1.25;
  cursor: pointer; border: 1px solid var(--line-2);
  background: var(--bg-3); color: var(--text); padding: 7px 12px;
  border-radius: var(--r-sm); white-space: nowrap;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  transition: background .12s, border-color .12s, color .12s, opacity .12s;
}
.btn:hover { border-color: var(--accent); background: var(--bg-4); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .5; cursor: default; pointer-events: none; }
.btn--primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }
.btn--primary:hover { background: var(--accent-2); border-color: var(--accent-2); }
.btn--danger { background: var(--danger); border-color: var(--danger); color: #fff; font-weight: 600; }
.btn--danger:hover { background: var(--danger-2); border-color: var(--danger-2); }
/* El secundario del panel (Editar, Cancelar, Detalle…): sin relleno, pero con
   borde. Un botón tiene que verse como un botón y no como texto suelto. */
.btn--ghost { background: transparent; border-color: var(--line-2); color: var(--text-2); }
.btn--ghost:hover { background: var(--bg-3); border-color: var(--accent); color: var(--text); }
/* Sin borde solo el cromo: cerrar un modal, plegar el centro de tareas. No es
   una acción de la pantalla, así que no compite con las que sí lo son. */
.btn--bare { background: transparent; border-color: transparent; color: var(--text-2); }
.btn--bare:hover { background: var(--bg-3); border-color: var(--line-2); color: var(--text); }
.btn--sm { padding: 3px 8px; font-size: var(--fs-xs); border-radius: 5px; }
.btn--icon { padding: 6px 8px; }
.btn .spinner--sm { margin-right: 0; }

.btn:focus-visible, .navlink:focus-visible, .tab:focus-visible,
.rail__toggle:focus-visible, .chip--sel:focus-visible, a:focus-visible, .sec__head:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}

/* ---------------------------------------------------------------- Formularios */
.input, input[type=text], input[type=password], input[type=email], input[type=number],
input[type=search], input[type=date], input[type=time], input[type=url], select, textarea {
  font: inherit; font-size: var(--fs); width: 100%; padding: 7px 10px;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--line-2); border-radius: var(--r-sm);
  transition: border-color .12s, box-shadow .12s;
}
:root[data-theme="light"] .input, :root[data-theme="light"] input:not([type=checkbox]):not([type=radio]),
:root[data-theme="light"] select, :root[data-theme="light"] textarea { background: var(--bg-2); }
select { cursor: pointer; }
textarea { line-height: 1.45; resize: vertical; min-height: 84px; }
textarea.mono, .textarea--mono, .input.mono { font-family: var(--mono); font-size: var(--fs-sm); }
.input:focus, input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--focus);
}
input::placeholder, textarea::placeholder { color: var(--muted); opacity: .8; }
input[type=checkbox], input[type=radio] { accent-color: var(--accent); width: 15px; height: 15px; margin: 0; flex: none; }
label { display: block; font-size: var(--fs-sm); color: var(--muted); font-weight: 500; margin-bottom: 4px; }
label input, label select, label textarea { margin-top: 4px; }
label > input[type=checkbox], label > input[type=radio] { margin-top: 0; }
.check, .bk-check { display: flex; align-items: center; gap: 8px; color: var(--text); font-size: var(--fs); cursor: pointer; font-weight: 400; margin-bottom: 0; }
.check--top, .bk-check { align-items: flex-start; }
.check--top input, .bk-check input { margin-top: 3px; }
.check input { width: auto; margin: 0; }
.help { font-size: var(--fs-xs); color: var(--muted); margin: 3px 0 0; }
.help--indent { margin-left: 23px; }

.form { display: flex; flex-direction: column; gap: var(--s-4); max-width: 520px; }
.form--wide { max-width: none; }
.form__row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--s-3); }
.form__actions { margin-top: var(--s-1); display: flex; gap: var(--s-2); }
.fieldset { border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-3) var(--s-4); display: flex; flex-direction: column; gap: var(--s-3); }
.fieldset__title { font-weight: 600; font-size: var(--fs-sm); }

/* Barra de filtros / herramientas: una sola, en todas las vistas. */
.filters, .toolbar {
  display: flex; gap: var(--s-2) var(--s-3); align-items: center; margin-bottom: var(--s-4); flex-wrap: wrap;
}
.filters .input, .toolbar .input, .filters select, .toolbar select,
.filters input[type=search], .toolbar input[type=search], .filters input[type=text], .toolbar input[type=text] {
  width: auto; min-width: 190px;
}
.toolbar .check { white-space: nowrap; }
.toolbar__sp { flex: 1; }
/* Con etiquetas encima de los campos, lo que se alinea es el borde inferior. */
/* Barra de selección: sale sola cuando hay filas marcadas. Se distingue del
   resto de barras porque no es un filtro, es una acción sobre lo elegido. */
.toolbar--sel {
  background: var(--bg-2); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: var(--s-2) var(--s-3);
}
.toolbar--end { align-items: flex-end; }
.toolbar--end label { margin-bottom: 0; }
.toolbar--end .check { padding-bottom: 8px; }
.toolbar label:not(.check) { margin-bottom: 0; }

/* ------------------------------------------------------------------ Tablas */
.tbl-wrap { width: 100%; max-width: 100%; overflow-x: auto; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg-2); }
.tbl-wrap .tbl { border: 0; border-radius: 0; }
/* Anchos por contenido: con doce columnas, el reparto a partes iguales de
   `fixed` partía los dominios letra a letra. `.tbl--fixed` para quien lo necesite. */
.tbl { width: 100%; table-layout: auto; border-collapse: collapse; background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--r-md); font-size: var(--fs-sm); }
.tbl--fixed { table-layout: fixed; }
.tbl th, .tbl td { text-align: left; padding: 8px 12px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.tbl th {
  background: var(--bg-3); font-size: var(--fs-xs); font-weight: 600; color: var(--muted);
  position: sticky; top: 0; z-index: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tbl tr:last-child td { border-bottom: none; }
.tbl tbody tr:hover td { background: var(--bg-3); }
.tbl td.num, .tbl th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tbl td { font-variant-numeric: tabular-nums; }
.tbl tr.is-alert td { background: var(--danger-soft); }
.tbl tr.is-alert td:first-child { box-shadow: inset 3px 0 0 var(--danger); }
.tbl tbody tr.is-alert:hover td { background: rgba(240, 96, 90, .2); }
.tbl tr.is-warn td:first-child { box-shadow: inset 3px 0 0 var(--warn); }
.tbl tr.is-ok td:first-child { box-shadow: inset 3px 0 0 var(--ok); }
.tbl tr.is-muted td { color: var(--muted); }
.tbl tr.is-click { cursor: pointer; }
/* break-word y no anywhere: así la columna se dimensiona al dominio entero y
   solo parte una ruta larguísima cuando de verdad no cabe. */
.tbl code { overflow-wrap: break-word; }
.tbl td > .badge { vertical-align: middle; }
/* Tablas vivas (tablas.js): cabeceras que ordenan y filtro rápido encima. */
.tbl th.th--viva { cursor: pointer; user-select: none; }
.tbl th.th--viva:hover { color: var(--text); }
.tbl th.th--viva[aria-sort] { color: var(--text); }
.th__flecha { font-size: .85em; }
.tbl-viva__barra { display: flex; justify-content: flex-end; align-items: center; gap: var(--s-2); margin: 0 0 var(--s-2); }
.tbl-viva__buscar { max-width: 220px; padding-top: 5px; padding-bottom: 5px; font-size: var(--fs-sm); }
.tbl tr[hidden] { display: none; }
.tbl td[colspan] { overflow: visible; white-space: normal; }
.th--sort { cursor: pointer; user-select: none; }
.th--sort:hover { color: var(--text); }
.tbl-group td { font-weight: 600; padding-top: var(--s-3); background: var(--bg-3); color: var(--text-2); font-size: var(--fs-xs); }
.cell-clip { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* En una celda, max-width no cuenta para el reparto; con max-width:0 la
   columna deja de exigir el texto entero y el ellipsis hace su trabajo. */
.tbl td.cell-clip { max-width: 0; min-width: 14rem; }
.col-xs { width: 2.2rem; }
/* Celda de casilla (seleccionFilas): toda ella marca y desmarca. */
.col-check { cursor: pointer; }
.col-sm { width: 5rem; }
.col-md { width: 7rem; }
.col-lg { width: 10rem; }
.col-xl { width: 13rem; }
/* Columna de la casilla de selección: lo justo para la casilla. */
.col-check { width: 2.2rem; text-align: center; }
.col-sev { width: 5.2rem; }
.col-when { width: 6.5rem; }
.col-state { width: 7rem; }
.col-actions { width: 11rem; }
.tbl:has(td.row-actions) thead th:last-child { width: 14rem; min-width: 9rem; }
.row-actions { display: flex; gap: 4px; justify-content: flex-end; flex-wrap: wrap; }
/* En una tabla la celda de acciones sigue siendo una celda (nada de flex, que
   la saca de la fila); los botones se alinean a la derecha y saltan de línea
   si son muchos. */
td.row-actions { display: table-cell; text-align: right; line-height: 2; }
td.row-actions .btn + .btn { margin-left: 4px; }
/* Si la tabla no cabe y se desplaza de lado, las acciones se quedan a la vista
   pegadas a la derecha. El fondo tiene que ser opaco: los tonos de fila
   (is-alert, hover) son translúcidos y se vería pasar la tabla por debajo. */
.tbl-wrap td.row-actions, .tbl-wrap .tbl:has(td.row-actions) thead th:last-child { position: sticky; right: 0; }
.tbl-wrap .tbl:has(td.row-actions) thead th:last-child { z-index: 2; }
.tbl-wrap td.row-actions { background: var(--bg-2); box-shadow: inset 1px 0 0 var(--line); }
.tbl-wrap .tbl tbody tr:hover td.row-actions { background: var(--bg-3); }
.tbl-wrap .tbl tr.is-alert td.row-actions { background: linear-gradient(var(--danger-soft), var(--danger-soft)), var(--bg-2); }
.tbl-wrap .tbl tbody tr.is-alert:hover td.row-actions { background: linear-gradient(rgba(240, 96, 90, .2), rgba(240, 96, 90, .2)), var(--bg-2); }
.row-actions .btn { padding: 3px 8px; font-size: var(--fs-xs); border-radius: 5px; }
/* Dentro de una fila, un botón rojo lleno por línea es un semáforo en rojo
   permanente: se pinta sin relleno (pero con borde, que sigue siendo un
   botón) y se enciende al pasar por encima. */
.row-actions .btn--danger { background: transparent; border-color: var(--line-2); color: var(--danger); font-weight: 500; }
.row-actions .btn--danger:hover { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); }
.pager { display: flex; gap: var(--s-3); align-items: center; justify-content: center; margin-top: var(--s-4); }

/* ------------------------------------------------------------------ Tarjetas */
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--s-4); }
.card { background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-4) 18px; }
.card--flat { background: transparent; }
.card__head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--s-3); margin-bottom: var(--s-2); }
.card__head h2, .card__head h3 { font-size: var(--fs-md); }
.card__title { font-weight: 600; font-size: var(--fs-md); }
.card__sub { color: var(--muted); font-size: var(--fs-sm); }
.card-stack { margin-bottom: var(--s-4); }
.card.is-ok { box-shadow: inset 3px 0 0 var(--ok); }
.card.is-warn { box-shadow: inset 3px 0 0 var(--warn); }
.card.is-danger { box-shadow: inset 3px 0 0 var(--danger); }
.card.is-info { box-shadow: inset 3px 0 0 var(--info); }
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--s-2); }
.chips:first-child { margin-top: 0; }
.chips--filter { margin: var(--s-3) 0 var(--s-1); }
.chips--inline { display: inline-flex; align-items: center; margin-top: 0; }
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--bg-3); border: 1px solid var(--line-2); border-radius: 999px;
  padding: 2px 10px; font-size: var(--fs-xs); font-weight: 500; color: var(--text-2); line-height: 1.5;
}
.chip--sel { cursor: pointer; user-select: none; }
a.chip { text-decoration: none; }   /* un chip que es enlace (a otra pestaña) se ve como los demás */
.chip--sel:hover { border-color: var(--accent); color: var(--text); }
.chip--sel.is-on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

/* Cifras clave (antes .bk-stats / bk-stat). */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: var(--s-3); }
.stat { padding: var(--s-3) var(--s-4); background: var(--bg-3); border: 1px solid var(--line); border-radius: var(--r-md); min-width: 0; }
.stat__label { color: var(--muted); font-size: var(--fs-xs); font-weight: 500; }
.stat__val { font-weight: 600; font-size: var(--fs-lg); font-variant-numeric: tabular-nums; margin-top: 2px; overflow-wrap: anywhere; }
.stat__val--danger { color: var(--danger); }
.stat__val--warn { color: var(--warn); }
.stat__val--ok { color: var(--ok); }
.stat__hint { color: var(--muted); font-size: var(--fs-xs); margin-top: 2px; }
.bk-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: var(--s-3); }
.bk-stat { padding: var(--s-3) var(--s-4); background: var(--bg-3); border: 1px solid var(--line); border-radius: var(--r-md); min-width: 0; }
.bk-stat__val { font-weight: 600; font-size: var(--fs-lg); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.bk-stat__val--danger { color: var(--danger); }
.bk-stat__val--warn { color: var(--warn); }

/* Lista clave: valor. */
.kv { display: grid; grid-template-columns: minmax(110px, max-content) 1fr; gap: 4px var(--s-3); margin: var(--s-1) 0; align-items: baseline; }
.kv b, .kv__k { color: var(--muted); font-weight: 500; font-size: var(--fs-sm); }
.kv code { overflow-wrap: anywhere; }
.kvs { display: flex; flex-direction: column; gap: 2px; }
/* Dos columnas (o las que quepan) de clave: valor: la cabecera de una ficha. */
.kvs--cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); column-gap: var(--s-5); }

/* --------------------------------------------- Bloques y secciones plegables */
/* Título de bloque dentro de una vista: un solo aspecto para h2/h3/h4. */
.h-block {
  display: flex; align-items: center; gap: var(--s-2);
  font-size: var(--fs-md); font-weight: 600; margin: var(--s-5) 0 var(--s-3);
  padding-bottom: 6px; border-bottom: 1px solid var(--line);
}
.h-block:first-child { margin-top: 0; }
.h-block .chip, .h-block .badge { font-weight: 500; }
.h-block__hint { color: var(--muted); font-weight: 400; font-size: var(--fs-sm); }
.h-block__sp { flex: 1; }
.h-sub { font-size: var(--fs); font-weight: 600; margin: var(--s-4) 0 var(--s-2); }
.h-sub:first-child { margin-top: 0; }
.bk-h { font-size: var(--fs-md); font-weight: 600; margin: var(--s-5) 0 var(--s-3); padding-bottom: 6px; border-bottom: 1px solid var(--line); }

/* Bloque de pantalla: título de bloque y contenido; sin flecha ni chips. */
.bloque { margin-top: var(--s-5); }
.bloque:first-child, .tabs + .bloque { margin-top: 0; }
.bloque > .h-block { margin-top: 0; }

.sec { margin-top: var(--s-5); }
.sec__head {
  display: flex; align-items: center; gap: var(--s-2); width: 100%;
  padding: 6px 0; background: none; border: 0; border-bottom: 1px solid var(--line);
  color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.sec__head:hover .sec__title { color: var(--accent); }
.sec__arrow { width: 1em; flex: none; color: var(--muted); font-size: var(--fs-xs); }
.sec__title { margin: 0; font-size: var(--fs-md); }
.sec__body { padding-top: var(--s-3); }
/* Plegable suelto (dentro de un modal, o agrupando resultados): misma flecha,
   menos peso; el título es texto normal y no una sección de la pantalla. */
.sec--inline { margin-top: var(--s-3); }
.form > .sec--inline { margin-top: 0; }   /* el hueco lo pone ya el gap del formulario */
.sec--inline .sec__title { font-size: var(--fs); font-weight: 600; }
.sec--inline .sec__body { padding-top: var(--s-2); }

/* ----------------------------------------------------------------- Estados */
.badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 8px; border-radius: 999px; font-size: var(--fs-xs); font-weight: 500;
  background: var(--bg-3); border: 1px solid var(--line-2); color: var(--text-2);
  white-space: nowrap; line-height: 1.5; vertical-align: middle;
}
.badge--ok { background: var(--ok-soft); color: var(--ok); border-color: transparent; }
.badge--warn { background: var(--warn-soft); color: var(--warn); border-color: transparent; }
.badge--danger { background: var(--danger-soft); color: var(--danger); border-color: transparent; }
.badge--info { background: var(--info-soft); color: var(--accent); border-color: transparent; }
.badge--gap { margin: 0 6px; }
.badge--sm { padding: 0 6px; font-size: 11px; }

.dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; flex: none; background: var(--muted); }
.dot--idle { background: var(--muted); animation: pulse 1.2s ease-in-out infinite; }
.dot--ok { background: var(--ok); box-shadow: 0 0 0 3px var(--ok-soft); }
.dot--warn { background: var(--warn); box-shadow: 0 0 0 3px var(--warn-soft); }
.dot--err { background: var(--danger); box-shadow: 0 0 0 3px var(--danger-soft); }
@keyframes pulse { 50% { opacity: .3; } }

.meters { display: flex; flex-direction: column; gap: var(--s-3); }
.meter { min-width: 0; }
.meter__top { display: flex; justify-content: space-between; gap: var(--s-2); font-size: var(--fs-sm); margin-bottom: 4px; align-items: center; }
.meter__label { color: var(--muted); font-weight: 500; }
.meter__val { font-variant-numeric: tabular-nums; color: var(--text-2); font-size: var(--fs-xs); text-align: right; }
.meter__bar { height: 6px; background: var(--bg-4); border-radius: 3px; overflow: hidden; }
.meter__fill { height: 100%; border-radius: 3px; transition: width .4s ease; background: var(--accent); }
.meter__fill--ok { background: var(--ok-fill); }
.meter__fill--warn { background: var(--warn-fill); }
.meter__fill--danger { background: var(--danger-fill); }

/* Histograma: barras verticales (peticiones por hora, por día). La altura de
   cada barra es el único valor calculado (height:${pct}%); el color, como los
   medidores: acento, o el semáforo si la barra marca algo. */
.histo { background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-3) 18px var(--s-2); margin-bottom: var(--s-4); }
.histo__bars { display: flex; align-items: flex-end; gap: 3px; height: 96px; }
.histo__col { flex: 1; min-width: 0; height: 100%; display: flex; align-items: flex-end; }
.histo__bar { width: 100%; min-height: 1px; background: var(--accent); border-radius: 2px 2px 0 0; }
.histo__bar--warn { background: var(--warn-fill); }
.histo__bar--danger { background: var(--danger-fill); }
.histo__bar--muted { background: var(--bg-4); }
.histo__bar--ok { background: var(--ok-fill); }
.histo--mini { background: none; border: 0; border-radius: 0; padding: 0; margin: 0; }
.histo--mini .histo__bars { height: 24px; gap: 1px; background: var(--bg-4); border-radius: 3px; overflow: hidden; }
.histo--mini .histo__bar { border-radius: 0; }
.histo__axis { display: flex; gap: 3px; margin-top: 4px; }
.histo__axis span { flex: 1; min-width: 0; text-align: center; font-size: var(--fs-xs); color: var(--muted); font-variant-numeric: tabular-nums; overflow: hidden; white-space: nowrap; }

/* Franjas: cuándo trabaja cada servidor sobre un eje de horas común (Copias → Tiempos). */
.franjas { display: flex; flex-direction: column; gap: var(--s-2); background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-3) 18px; margin-bottom: var(--s-3); }
.franja { display: grid; grid-template-columns: 90px 1fr 250px; gap: var(--s-3); align-items: center; font-size: var(--fs-sm); }
.franja__nombre { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.franja__pista { position: relative; height: 14px; background: var(--bg-4); border-radius: 3px; }
.franja__peor, .franja__normal { position: absolute; top: 0; bottom: 0; border-radius: 3px; }
.franja__peor { background: var(--accent); opacity: .3; }
.franja__normal { background: var(--accent); }
.franja__dato { font-variant-numeric: tabular-nums; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.franja--eje .franja__pista { background: none; height: 16px; }
.franja--eje .franja__pista span { position: absolute; transform: translateX(-50%); font-size: var(--fs-xs); color: var(--muted); font-variant-numeric: tabular-nums; }
@media (max-width: 800px) { .franja { grid-template-columns: 70px 1fr; } .franja__dato { grid-column: 2; } }

/* Bloques preformateados: uno solo. */
.pre, pre.pre, .result__raw, .bk-log, .bk-patterns {
  font-family: var(--mono); font-size: var(--fs-xs); line-height: 1.5;
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: var(--s-3); overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere;
  max-height: 400px; margin: 0; color: var(--text-2);
}
.pre--tall { max-height: 60vh; }
.pre--short { max-height: 24vh; }
.bk-log { max-height: 50vh; }
.bk-patterns { max-height: 30vh; }
.bk-diff-add { color: var(--ok); }
.bk-diff-del { color: var(--danger); }
.bk-diff-hunk { color: var(--accent); }

/* ---------------------------------------------------------------- Pestañas */
.tabs { display: flex; gap: 2px; flex-wrap: wrap; margin: calc(-1 * var(--s-2)) 0 var(--s-4); border-bottom: 1px solid var(--line); }
.tab {
  font: inherit; font-size: var(--fs); cursor: pointer; background: transparent; border: 0;
  border-bottom: 2px solid transparent; color: var(--muted);
  padding: 8px 12px; margin-bottom: -1px; font-weight: 500; border-radius: var(--r-sm) var(--r-sm) 0 0;
  transition: color .12s, background .12s;
}
.tab:hover { color: var(--text); background: var(--bg-3); }
.tab.is-on { color: var(--text); border-bottom-color: var(--accent); font-weight: 600; }
.tab > .badge { margin-left: 6px; vertical-align: 1px; }

.result { margin-top: var(--s-4); }

/* ---------------------------------------------------------------- Inicio */
.dash-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: var(--s-4); }
.dash-card { background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-4) 18px; }
.dash-card__head { display: flex; align-items: flex-start; gap: 10px; margin-bottom: var(--s-3); }
.dash-card__head > .dot { margin-top: 7px; }
.dash-card__name { font-weight: 600; color: inherit; text-decoration: none; font-size: var(--fs-md); }
a.dash-card__name:hover { color: var(--accent); }
.dash-card__body { min-width: 0; }
.dash-card__wd { margin-top: var(--s-1); display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.dash-card__wd a { text-decoration: none; }

/* Recursos: reparto de consumo por sitio (barras 24 h, vista de aislamiento) */
.usebars { background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-3) 18px; margin: var(--s-3) 0 var(--s-4); }
.usebars__head { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; margin-bottom: var(--s-2); }
.usebars__title { font-weight: 600; margin-right: 6px; }
.usebars__head .muted { margin-left: auto; }
.usebars__row { display: grid; grid-template-columns: minmax(150px, 230px) 1fr minmax(120px, max-content); gap: var(--s-3); align-items: center; padding: 4px 6px; border-radius: var(--r-sm); cursor: pointer; }
.usebars__row:hover { background: var(--bg-3); }
.usebars__row--rest { cursor: default; }
.usebars__row--rest .meter__fill { background: var(--muted); opacity: .5; }
.usebars__dom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-sm); font-family: var(--mono); }
.usebars__row--rest .usebars__dom { color: var(--muted); font-family: var(--font); }
.usebars__val { font-variant-numeric: tabular-nums; font-size: var(--fs-xs); color: var(--muted); text-align: right; white-space: nowrap; }

/* Permisos */
.permlist { display: flex; flex-direction: column; gap: var(--s-3); max-height: 50vh; overflow: auto; }
.permgroup__title { font-size: var(--fs-xs); font-weight: 600; color: var(--muted); margin-bottom: 4px; }
.permgroup .check { padding: 3px 0; }

/* ----------------------------------------------------------------- Acceso */
.login { display: grid; place-items: center; height: 100vh; padding: 20px; position: relative; }
.login__theme { position: absolute; top: 16px; right: 16px; }
.login__form {
  background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 30px 32px 32px; width: 100%; max-width: 380px; box-shadow: var(--shadow);
  display: flex; flex-direction: column; gap: var(--s-4); position: relative; overflow: hidden;
}
.login__form::before { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 3px; background: linear-gradient(90deg, var(--crust), var(--accent)); }
.login__title { display: flex; align-items: center; gap: 10px; font-size: 22px; font-weight: 600; }
.login__title .brand__logo { width: 34px; height: 34px; border-radius: 9px; }
.login__sub { color: var(--muted); margin: -10px 0 4px; font-size: var(--fs-sm); }
.login__form .btn--primary { padding: 9px 14px; margin-top: var(--s-1); }

/* ----------------------------------------------------------------- Modal */
.modal__overlay { position: fixed; inset: 0; background: rgba(8, 7, 5, .55); display: grid; place-items: center; padding: 20px; z-index: 50; backdrop-filter: blur(2px); }
.modal {
  background: var(--bg-2); border: 1px solid var(--line-2); border-radius: var(--r-lg);
  width: 100%; max-width: 540px; box-shadow: var(--shadow); max-height: 90vh; display: flex; flex-direction: column;
}
.modal--lg { max-width: 820px; }
.modal--xl { max-width: 1100px; }
.modal:focus { outline: none; }
.modal:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.modal__head { display: flex; justify-content: space-between; align-items: center; gap: var(--s-3); padding: var(--s-4) 20px; border-bottom: 1px solid var(--line); }
.modal__head h3 { font-size: var(--fs-md); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.modal__body { padding: 20px; overflow: auto; }
.modal__foot { display: flex; justify-content: flex-end; gap: var(--s-2); padding: var(--s-3) 20px; border-top: 1px solid var(--line); flex-wrap: wrap; }
.modal__foot .row-actions { justify-content: flex-end; }
.confirm-text { margin: 0; }

/* ----------------------------------------------------------------- Toasts */
.toasts { position: fixed; right: 20px; bottom: calc(20px + var(--taskdock-h, 0px)); display: flex; flex-direction: column; gap: var(--s-2); z-index: 100; }
.toast {
  background: var(--bg-2); border: 1px solid var(--line-2); border-left: 3px solid var(--accent);
  border-radius: var(--r-sm); padding: 10px 14px; box-shadow: var(--shadow-sm); max-width: 380px;
  font-size: var(--fs-sm); transition: opacity .25s, transform .25s;
}
.toast--ok { border-left-color: var(--ok); }
.toast--error { border-left-color: var(--danger); }
.toast--info { border-left-color: var(--accent); }
.toast--warn { border-left-color: var(--warn); }

/* --------------------------------------------------------- Módulo de copias */
.bk-lockrow { display: grid; grid-template-columns: 210px 1fr; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--line); }
.bk-lockrow:last-child { border-bottom: 0; }
@media (max-width: 560px) { .bk-lockrow { grid-template-columns: 1fr; gap: 2px; } }
.bk-crumb, .crumb { margin: var(--s-1) 0 var(--s-3); font-size: var(--fs-sm); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.bk-crumb a, .crumb a { color: var(--accent); text-decoration: none; }
.bk-tables { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 6px; max-height: 40vh; overflow: auto; border: 1px solid var(--line); border-radius: var(--r-sm); padding: 10px; }
.bk-table-item { display: flex; align-items: center; gap: 6px; font-size: var(--fs-sm); cursor: pointer; font-family: var(--mono); }
.bk-danger { color: var(--danger); }
.bk-legacy { font-size: var(--fs-sm); margin: 3px 0; word-break: break-all; }
.bk-legacy code { font-size: .95em; }
.bk-times { display: flex; flex-direction: column; gap: 6px; margin: 6px 0; }
.bk-days { display: flex; gap: 6px; flex-wrap: wrap; margin: 6px 0; }
.bk-day { display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px; border: 1px solid var(--line-2); border-radius: 999px; cursor: pointer; font-size: var(--fs-sm); color: var(--text); }
.bk-day:has(input:checked) { background: var(--accent-soft); border-color: var(--accent); }
.bk-exc { margin: 6px 0; }
.bk-exc input[type="date"] { width: 150px; }
.bk-patterns-edit { width: 100%; font-family: var(--mono); font-size: var(--fs-sm); resize: vertical; }
.file-ico { display: inline-block; width: 1.2em; color: var(--muted); text-align: center; }

/* Botonera de exportación (PDF/Excel/CSV) sobre una tabla de resultados. */
.export { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; margin: 0 0 var(--s-2); }
.export .muted { font-size: var(--fs-xs); }

/* ---------------------------------------------------------- Centro de tareas */
.taskdock {
  position: fixed; right: 20px; bottom: 20px; width: 400px; max-width: calc(100vw - 40px);
  background: var(--bg-2); border: 1px solid var(--line-2); border-radius: var(--r-md);
  box-shadow: var(--shadow); z-index: 40; overflow: hidden;
}
.taskdock__head { display: flex; align-items: center; gap: 6px; padding: 8px 10px; border-bottom: 1px solid var(--line); background: var(--bg-3); }
.taskdock__title { font-weight: 600; font-size: var(--fs-sm); }
.taskdock__sp { flex: 1; }
.taskdock__body { max-height: 45vh; overflow: auto; }
.taskdock__item { padding: 8px 10px; border-bottom: 1px solid var(--line); font-size: var(--fs-sm); }
.taskdock__item:last-child { border-bottom: 0; }
.taskdock__row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; row-gap: 4px; }
.taskdock__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 180px; }
.taskdock__step { margin-top: 4px; }
.taskbar { height: 4px; background: var(--bg-4); border-radius: 2px; margin-top: 6px; overflow: hidden; }
.taskbar__fill { height: 100%; background: var(--accent); transition: width .3s; }

/* ------------------------------------------------------------- Responsive */
@media (max-width: 800px) {
  :root { --content-pad: 12px; }
  .app { grid-template-columns: 1fr; grid-template-rows: auto 1fr; height: 100dvh; }
  .rail { border-right: none; border-bottom: 1px solid var(--line); padding: 8px 12px; overflow: visible; }
  .rail__toggle { display: block; }
  .brand { padding: 4px; }
  .rail__nav, .rail__foot { display: none; }
  .rail--open .rail__nav { display: flex; padding: 4px 0 8px; }
  .rail--open .rail__foot { display: flex; margin: 0; padding: 0 0 8px; }
  .navlink--foot { margin-top: 8px; }
  .topbar { flex-wrap: wrap; gap: 8px; padding: 12px var(--content-pad); min-height: 0; }
  .topbar h1 { font-size: var(--fs-lg); }
  /* Título en su línea; las acciones debajo, alineadas a la izquierda. */
  .topbar > .grow { flex-basis: 100%; }
  .topbar .row { justify-content: flex-start; }
  .content { padding: 14px var(--content-pad); }
  .content .row, .topbar .row { flex-wrap: wrap; }
  .tbl { min-width: 640px; }
  .tbl th { position: static; }
  .dash-grid { grid-template-columns: 1fr; }
  .toasts { left: 12px; right: 12px; bottom: calc(12px + var(--taskdock-h, 0px)); }
  .toast { max-width: none; }
  .modal--lg, .modal--xl { max-width: none; }
  .taskdock { right: 10px; left: 10px; width: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .spinner, .dot--idle { animation: none; }
  .meter__fill, .toast, .btn, .navlink, .tab, .taskbar__fill { transition: none; }
}

/* Iconos SVG en línea (ui.js icon()). */
.ico { display: inline-flex; align-items: center; vertical-align: -3px; line-height: 0; flex: none; }
.ico svg { display: block; }
.btn .ico { vertical-align: 0; }

/* Buscador con sugerencias (ui.js buscador()): la lista flota bajo el campo. */
.buscador { position: relative; }
.buscador__lista {
  position: absolute; z-index: 20; left: 0; right: 0; top: calc(100% + 2px);
  background: var(--bg-2); border: 1px solid var(--line-2); border-radius: var(--r-sm);
  max-height: 280px; overflow: auto; padding: 4px;
}
.buscador__op {
  display: block; width: 100%; text-align: left; padding: 6px 8px; border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--text); font: inherit; font-size: var(--fs-sm); cursor: pointer;
}
.buscador__op:hover, .buscador__op.is-on { background: var(--bg-3); }
.buscador__nada { padding: 6px 8px; color: var(--muted); font-size: var(--fs-sm); }

/* Hilo de un caso (Incidencias): una tarjeta por mensaje, el filo dice de quién
   es (cliente en azul, nuestro en verde) y la nota interna va en ámbar entera
   para que no se confunda nunca con lo que ve el cliente. */
.hilo { display: flex; flex-direction: column; gap: var(--s-3); }
.msg { padding: var(--s-3) var(--s-4); }
.msg--nota { background: var(--warn-soft); }
.msg__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px var(--s-2); margin-bottom: var(--s-2); }
.msg__fecha { margin-left: auto; }
.msg__cuerpo { white-space: pre-wrap; overflow-wrap: anywhere; font-size: var(--fs); }
.msg__pie { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); margin-top: var(--s-2); }
.msg__sis { color: var(--muted); font-size: var(--fs-xs); padding: 0 var(--s-4); }
/* El original de un correo (HTML no fiable): iframe con sandbox y sin red. */
.original { display: block; width: 100%; height: 62vh; border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff; }

/* Adjuntar ficheros a un mensaje (ui.js adjuntador()). */
.adjuntos { display: flex; flex-direction: column; gap: var(--s-2); padding: var(--s-2); border: 1px dashed var(--line-2); border-radius: var(--r-sm); }
.adjuntos.is-drop { border-color: var(--accent); background: var(--accent-soft); }
.adjuntos__lista { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.adjuntos__lista:empty { display: none; }
.adjunto { display: inline-flex; align-items: center; gap: 6px; padding: 3px 4px 3px 6px; border: 1px solid var(--line-2); border-radius: var(--r-sm); background: var(--bg-3); font-size: var(--fs-xs); max-width: 280px; }
.adjunto img { height: 32px; width: auto; max-width: 56px; object-fit: cover; border-radius: 3px; }
.adjunto__nombre { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* Imágenes adjuntas en el hilo: miniatura que se abre en grande. */
.msg__imgs { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-2); }
.msg__img { display: block; padding: 0; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--bg-3); cursor: zoom-in; overflow: hidden; }
.msg__img img { display: block; height: 120px; width: auto; max-width: 240px; object-fit: cover; }
.img-grande { display: block; max-width: 100%; max-height: 75vh; margin: 0 auto; }

/* Tablero (kanban) de Incidencias: una columna por etapa abierta, tarjetas que se
   arrastran entre columnas. Las columnas son marco, sin relleno; las tarjetas, .card. */
.kanban { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(270px, 1fr); gap: var(--s-3); align-items: start; overflow-x: auto; padding-bottom: var(--s-2); }
.kanban--estrecho { grid-auto-columns: minmax(210px, 1fr); }   /* Tareas: cinco columnas que caben en una pantalla normal */
.kanban__col { border: 1px solid var(--line); border-radius: var(--r-md); min-width: 0; }
.kanban__col.is-sobre { border-color: var(--accent); background: var(--accent-soft); }
.kanban__head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); padding: var(--s-2) var(--s-3); font-size: var(--fs-sm); font-weight: 600; border-bottom: 1px solid var(--line); }
.kanban__body { display: flex; flex-direction: column; gap: var(--s-2); padding: var(--s-2); min-height: 72px; }
.kanban__vacio { padding: var(--s-2); text-align: center; }
.kcard { display: flex; flex-direction: column; gap: 4px; padding: var(--s-2) var(--s-3); cursor: pointer; font-size: var(--fs-sm); }
.kcard[hidden], .toolbar [hidden] { display: none; }
.kcard[draggable="true"] { cursor: grab; }
.kcard:hover { border-color: var(--line-2); }
.kcard.is-arrastrando { opacity: .45; }
.kcard__top { display: flex; align-items: center; gap: 6px; }
.kcard__titulo { color: var(--text); font-size: var(--fs); font-weight: 500; line-height: 1.35; overflow-wrap: anywhere; }
.kcard__linea { display: flex; flex-wrap: wrap; gap: 4px 8px; color: var(--text-2); }
.kcard__linea code { font-size: var(--fs-xs); }
.kcard__pie { display: flex; flex-wrap: wrap; gap: 2px 10px; color: var(--muted); font-size: var(--fs-xs); }

/* Tareas (GTD): listas de tareas, captura y calendario. Una fila es casilla,
   estrella de Foco, título con su línea de datos y acciones a la derecha. */
.gtd-lista { list-style: none; margin: 0; padding: 0; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg-2); }
.gtd-lista + .gtd-lista { margin-top: var(--s-3); }
.gtd-fila { display: flex; align-items: flex-start; gap: var(--s-2); padding: var(--s-2) var(--s-3); border-top: 1px solid var(--line); border-left: 3px solid transparent; }
.gtd-fila:first-child { border-top: 0; border-top-left-radius: var(--r-md); border-top-right-radius: var(--r-md); }
.gtd-fila:last-child { border-bottom-left-radius: var(--r-md); border-bottom-right-radius: var(--r-md); }
.gtd-fila:hover { background: var(--bg-3); }
.gtd-fila.is-alert { border-left-color: var(--danger); }
.gtd-fila.is-warn { border-left-color: var(--warn); }
.gtd-fila.is-sobre { box-shadow: inset 0 2px 0 var(--accent); }
.gtd-fila.is-arrastrando { opacity: .45; }
.gtd-fila[draggable="true"] { cursor: grab; }
.gtd-fila.is-prevista .gtd-fila__titulo { color: var(--muted); }
.gtd-fila__cuerpo { flex: 1; min-width: 0; cursor: pointer; color: inherit; text-decoration: none; }
.gtd-fila__cuerpo:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.gtd-fila__titulo { color: var(--text); line-height: 1.4; overflow-wrap: anywhere; }
.gtd-fila__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 10px; margin-top: 2px; color: var(--muted); font-size: var(--fs-xs); }
.gtd-fila__meta:empty { display: none; }
.gtd-fila__meta .chip { padding: 0 7px; }
.gtd-fila .row-actions { align-self: center; }
.gtd-check { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; margin-top: 1px; padding: 0;
  border: 1.5px solid var(--line-2); border-radius: 5px; background: transparent; color: transparent; cursor: pointer; }
.gtd-check:hover { border-color: var(--ok); color: var(--ok); }
.gtd-check:focus-visible, .gtd-foco:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.is-hecha > .gtd-check { background: var(--ok); border-color: var(--ok); color: #fff; }
.is-hecha .gtd-fila__titulo { color: var(--muted); text-decoration: line-through; }
.gtd-foco { flex: none; display: inline-flex; padding: 0; margin-top: 1px; border: 0; background: transparent; color: var(--line-2); cursor: pointer; }
.gtd-foco:hover { color: var(--accent); }
.gtd-foco.is-on { color: var(--accent); }
.gtd-foco.is-on svg { fill: currentColor; }
.gtd-tipo { flex: none; color: var(--muted); margin-top: 1px; }
.gtd-hora { flex: none; width: 76px; padding-top: 1px; color: var(--text-2); font-size: var(--fs-xs); }
.gtd-entrada { margin-bottom: var(--s-4); }
.gtd-previa { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-height: 22px; margin-top: 6px; font-size: var(--fs-xs); }
.gtd-capturadas { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; color: var(--text-2); font-size: var(--fs-sm); }
.gtd-capturadas li .ico { color: var(--ok); }
.gtd-capturadas li.is-error { color: var(--danger); text-decoration: line-through; }
.gtd-notas { white-space: pre-wrap; color: var(--text-2); margin: 0 0 var(--s-4); }
kbd { font-family: var(--mono); font-size: var(--fs-xs); padding: 1px 6px; border: 1px solid var(--line-2); border-bottom-width: 2px; border-radius: 4px; background: var(--bg-3); }

/* Calendario de Tareas: un mes en rejilla (lunes primero). Las entradas son botones:
   eventos con fondo de acento suave, fechas límite con filo ámbar (rojo si pasó),
   lo que empieza ese día en neutro y las vueltas previstas de una repetición punteadas. */
.cal__titulo { font-size: var(--fs-md); font-weight: 600; }
.cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); border-top: 1px solid var(--line); border-left: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; background: var(--bg-2); }
.cal__cab { padding: 6px 8px; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); background: var(--bg-3); color: var(--muted); font-size: var(--fs-xs); font-weight: 600; }
.cal__dia { display: flex; flex-direction: column; gap: 2px; min-width: 0; min-height: 104px; padding: 4px 4px 6px; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); cursor: copy; }
.cal__dia.is-fuera { background: var(--bg); }
.cal__dia.is-fuera .cal__num { color: var(--muted); }
.cal__num { align-self: flex-start; min-width: 22px; padding: 1px 6px; border-radius: 999px; font-size: var(--fs-xs); font-weight: 600; text-align: center; font-variant-numeric: tabular-nums; }
.cal__dia.is-hoy .cal__num { background: var(--accent); color: var(--accent-ink); }
.cal__ev { display: flex; align-items: center; gap: 4px; width: 100%; min-width: 0; padding: 1px 6px; border: 1px solid transparent; border-radius: 4px;
  background: var(--bg-3); color: var(--text-2); font: inherit; font-size: var(--fs-xs); text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; }
.cal__ev:hover { border-color: var(--line-2); color: var(--text); }
.cal__ev .ico { flex: none; }
.cal__ev--evento { background: var(--accent-soft); color: var(--text); }
.cal__ev--vence { border-left: 3px solid var(--warn); }
.cal__ev--vencida { border-left-color: var(--danger); }
.cal__ev--prevista { background: transparent; border: 1px dashed var(--line-2); color: var(--muted); }
.cal__mas { padding: 0 6px; color: var(--muted); font-size: var(--fs-xs); }
@media (max-width: 800px) {
  .cal__dia { min-height: 64px; padding: 2px; }
  .cal__ev { padding: 0 3px; }
  .gtd-fila { flex-wrap: wrap; }
  .gtd-fila .row-actions { width: 100%; justify-content: flex-start; padding-left: 52px; }
}

/* Inicio: una cifra que lleva a su lista (la tarjeta entera es el enlace). */
.stat-link { display: block; color: inherit; text-decoration: none; }
.stat-link:hover .stat { border-color: var(--line-2); }
.stat-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--r-md); }

/* Ficha de una incidencia: en ancho, el hilo a la izquierda y un lateral fijo a la derecha con lo
   que se usa siempre (datos, acciones y lo que ha hecho el agente). En estrecho, una columna con el
   lateral primero (va antes en el HTML). */
.ficha__cuerpo { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-5); }
.ficha__lado > .bloque:first-child, .ficha__principal > .bloque:first-child .h-block { margin-top: 0; }
@media (min-width: 1200px) {
  .ficha__cuerpo { grid-template-columns: minmax(0, 1.7fr) minmax(340px, 1fr); grid-template-areas: "principal lado"; align-items: start; }
  .ficha__principal { grid-area: principal; min-width: 0; }
  .ficha__lado { grid-area: lado; position: sticky; top: 0; max-height: calc(100vh - 150px); overflow-y: auto; padding-right: 2px; }
  .ficha__lado .kvs--cols { grid-template-columns: minmax(0, 1fr); }
}
.ficha__lado .row-acciones { margin-top: var(--s-3); }
/* Lo que ha hecho el agente: resumen y borrador, legibles sin ir al hilo. */
.agente-res { padding: var(--s-3) var(--s-4); }
.agente-res__borrador { margin-top: var(--s-3); padding-top: var(--s-3); border-top: 1px solid var(--line); }
/* Textos largos del hilo: unas 10 líneas y «Ver entero». */
.msg__cuerpo--corto { max-height: calc(1.5em * 10); overflow: hidden; }
.msg__mas { margin-top: var(--s-1); }
.msg__cuerpo--resumido { max-height: calc(1.5em * 3); overflow: hidden; }
.ficha__lado > .row:first-child { margin-top: 0; }
