/* Herramienta interna: densidad de información y contraste por encima de la estética. */

:root {
  /* Hace que los controles nativos (selector de fecha, iconos, autofill) sigan el
     tema del sistema en vez de renderizarse siempre en claro. */
  color-scheme: light dark;

  --bg: #f6f7f9;
  --panel: #ffffff;
  --border: #d8dce2;
  --border-strong: #b5bcc6;
  --text: #16191d;
  --muted: #61686f;
  /* The app's standard blue (Monkeyjobs). Every blue fill —header, primary button,
     chart series— starts from it; `--brand-strong` is its hover/border shade. */
  --brand: #017fc3;
  --brand-strong: #01679e;
  --accent: var(--brand);
  --accent-soft: #e5f2fa;

  --ok: #1a7f45;
  /* El verde como TEXTO sobre fondos verdes claros: más oscuro para pasar de 4,5:1. */
  --ok-texto: color-mix(in srgb, var(--ok) 80%, var(--text));
  --warn: #a35c00;
  --warn-bg: #fdf3e2;
  /* El resaltador amarillo («Bugs reportados»: la palabra «bug» en títulos y etiquetas) */
  --resaltador: #ffec80;
  --resaltador-texto: #1a1f24;
  --danger: #b3261e;
  --danger-bg: #fdecea;
  --info: #4a3fb5;
  --info-bg: #eeecfb;
  --neutral-bg: #f0f1f3;
  --esqueleto-brillo: rgba(255, 255, 255, 0.75);

  /* Azul de cabecera: vivo y el MISMO en claro y en oscuro. No sigue al tema porque
     es una franja de color con texto blanco encima, no un elemento que tenga que
     mimetizarse con el fondo. */
  --header-azul: var(--brand);
  --header-azul-borde: var(--brand-strong);

  --radius: 6px;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;

  /* Alto de la cabecera pegada (las dos barras). Es solo el valor de arranque: lo
     mantiene al día el ResizeObserver de `AppRoot`. Lo usa la columna izquierda para
     saber dónde pegarse y cuánto puede medir. */
  --topbar-h: 88px;
}

/* The theme. `<html data-theme>` holds the RESOLVED one —`light` or `dark`—, set before
   the first paint by the inline script in index.html and kept by AppRoot: the user's
   choice in «Ajustes» (light, dark or follow the system) is turned into one of the two
   there, so the dark tokens live in this single block and not twice. Presenting forces
   light (see `html[data-presentacion]`), hence the `:not()`. */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"]:not([data-presentacion]) {
  color-scheme: dark;
  --bg: #16181c;
  --panel: #1e2126;
  --border: #333941;
  --border-strong: #4a525c;
  --text: #e6e8ea;
  --muted: #9aa2ab;
  /* The same blue, lightened to read on a dark surface (validated against the chart types) */
  --accent: #2a9ddf;
  --accent-soft: #10283a;

  --ok: #5cc98a;
  --ok-texto: var(--ok);
  --warn: #e0a458;
  --warn-bg: #33280f;
  --resaltador: #6b5a0f;
  --resaltador-texto: #fff8d6;
  --danger: #f2857c;
  --danger-bg: #3a1c1a;
  --info: #a79df5;
  --info-bg: #23204a;
  --neutral-bg: #24272c;
  --esqueleto-brillo: rgba(255, 255, 255, 0.06);
}

* { box-sizing: border-box; }

/* Sin el rebote elástico de macOS al tirar de la página hacia arriba: dejaba ver una franja
   en blanco encima de la cabecera fija, como si la app se descolgara. Cada caja que se
   desplaza sigue haciéndolo dentro de sí. */
html { overscroll-behavior-y: none; }

body {
  margin: 0;
  font: 13px/1.45 system-ui, -apple-system, "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--text);
}

button, input, select, textarea { font: inherit; color: inherit; }

/* ---------------------------------------------------------------- layout */

/* La cabecera y la barra de modo se pegan JUNTAS: si solo se pegara la primera, al
   bajar desaparecería la segunda y con ella la única señal de qué modo corre. */
.topbar-stack { position: sticky; top: 0; z-index: 20; }

.topbar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 16px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}
.topbar h1 { font-size: 15px; margin: 0; font-weight: 600; }
/* The logo beside the app's name. Its own blue square with rounded corners: it keeps
   its colours on the light bar and on the blue one of the tools alike. */
.marca-app { display: inline-flex; align-items: center; gap: 9px; white-space: nowrap; }

/* «Apariencia» and «Marca de la cabecera» in Ajustes: three equal buttons in a row, the
   chosen one in the brand blue. The two share the shape on purpose —they are the same
   gesture, one row of mutually exclusive choices— and keep their own names so each says
   what it picks. */
.tema-opciones { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
/* La marca tiene CUATRO opciones: en fila se quedarían sin sitio para su etiqueta, así
   que se reparten en dos columnas y se apilan solas en una ventana estrecha. */
.marca-opciones { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 6px; }
.tema-opcion, .marca-opcion {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 36px; border-radius: 8px; font-size: 13px; color: var(--text);
}
.tema-opcion .mdi, .marca-opcion .mdi { font-size: 16px; color: var(--muted); }
.tema-opcion.activa, .marca-opcion.activa { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.tema-opcion.activa .mdi, .marca-opcion.activa .mdi { color: var(--accent); }

/* La marca: el selector de imagen, la vista previa y los dos botones de abajo.
   El `<input type="file">` del navegador no se puede peinar, así que se esconde y lo
   dispara el botón de al lado (igual que en el adjunto del runbook). */
.marca-ajuste input[type="file"] { display: none; }
.marca-archivo { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; min-width: 0; }
.marca-archivo .hint { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* El previo imita la barra de verdad: mismo fondo, mismo borde abajo y las mismas
   clases de la marca (`.marca-app`, `.marca-logo`), para que no puedan separarse. */
.marca-previo { display: flex; flex-direction: column; gap: 4px; margin-top: 2px; }
.marca-previo-barra {
  display: flex; align-items: center;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel);
  overflow: hidden;
}
/* El color va DICHO, no heredado, y con el segundo selector por delante de
   `body[data-bar="solid"] .topbar h1`: el modal de Ajustes cuelga del propio `.topbar`,
   así que en un ambiente de barra sólida esa regla pintaba este título de blanco sobre
   blanco y el previo se veía vacío. */
.marca-previo-barra h1,
body[data-bar="solid"] .topbar .marca-previo-barra h1 {
  font-size: 15px; margin: 0; font-weight: 600; min-width: 0; color: var(--text);
}
/* Un nombre largo cede con puntos suspensivos en vez de empujar la caja */
.marca-previo-barra .marca-app { overflow: hidden; text-overflow: ellipsis; display: flex; }
.marca-acciones { display: flex; align-items: center; gap: 8px; margin-top: 4px; flex-wrap: wrap; }
.marca-acciones .spacer { flex: 1; }
/* Alto fijo y ancho libre: el logo de la app es cuadrado, pero el que sube un usuario
   puede ser apaisado y forzarlo a un cuadrado lo dejaría aplastado. `contain` por si
   acaso, y un tope de ancho para que un logo muy largo no se coma la barra. */
.marca-logo { width: auto; height: 26px; max-width: 140px; object-fit: contain; border-radius: 6px; flex: none; display: block; }
/* El monograma: lo que firma la cabecera mientras no exista el archivo del logo del
   producto (hoy el de Cielum). Mismo sitio, mismo tamaño y mismo aire que la imagen, para
   que el día que el archivo aparezca la barra no dé un salto. El dibujo se repite en
   `dominio/marcaProducto.js` para lo que pinta el servidor y en el icono de la pestaña. */
.marca-monograma {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 26px; height: 26px; border-radius: 6px;
  background: var(--brand); background-image: linear-gradient(135deg, var(--brand) 0%, #015d8f 100%);
  color: #fff; font-size: 10px; font-weight: 800; letter-spacing: .02em;
  box-shadow: 0 0 0 2px #fff;
}
/* The logo always wears a white ring: it keeps its edge on every bar colour (the tools'
   blue is the logo's own) and gives it the same look everywhere */
.marca-logo { box-shadow: 0 0 0 2px #fff; }
.topbar .spacer, .subbar .spacer { flex: 1; }

/* Modo a la izquierda, plataformas a la derecha: se lee como una frase —qué corrida
   es, contra qué APIs va— sin abrir ningún desplegable. */
.subbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 16px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}

.chip {
  padding: 4px 11px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}
.chip:hover:not(:disabled):not(.locked) { color: var(--text); border-color: var(--accent); }
.chip.active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}
/* `locked` NO es `disabled`: en comparación las dos plataformas participan de verdad,
   así que se ven encendidas; lo único que no se puede es elegirlas. */
.chip.locked { cursor: default; }
.chip:disabled { opacity: 0.55; cursor: not-allowed; }

.layout {
  display: grid;
  grid-template-columns: minmax(360px, 460px) 1fr;
  gap: 14px;
  padding: 14px 16px 40px;
  align-items: start;
}
@media (max-width: 900px) { .layout { grid-template-columns: 1fr; } }

.col { display: flex; flex-direction: column; gap: 12px; min-width: 0; }

/* La columna de configuración se pega bajo la cabecera y scrollea SOLA.
 *
 * Con las cinco secciones abiertas es mucho más alta que la de resultados, así que el
 * scroll de la página la usaba a ella de referencia: para llegar al final del formulario
 * había que arrastrar toda la pantalla, y los resultados —que ya no crecían— se iban
 * hacia arriba. Con su propio scroll, cada columna se mueve por su cuenta.
 *
 * `--topbar-h` la mide `AppRoot` con un ResizeObserver: las dos barras de la cabecera
 * se parten en varias líneas al estrechar la ventana, así que cablear su altura
 * dejaría la columna descuadrada justo cuando hay menos sitio. */
.layout > .col-config {
  position: sticky;
  top: var(--topbar-h);
  /* 54px = el padding vertical de `.layout` (14 arriba + 40 abajo). Descontarlo entero
     es lo que hace que, con la columna de resultados corta, la página NO scrollee: si
     sobran píxeles, vuelve la barra de la ventana que se venía a quitar. */
  max-height: calc(100vh - var(--topbar-h) - 54px);
  overflow-y: auto;
  /* Reserva el hueco de la barra de scroll: sin esto, abrir una sección que provoque
     desbordamiento encoge las tarjetas unos píxeles de golpe. */
  scrollbar-gutter: stable;
}

/* En una sola columna no hay nada al lado que justifique el scroll aparte: vuelve a
   ser una página normal. */
@media (max-width: 900px) {
  .layout > .col-config {
    position: static;
    max-height: none;
    overflow: visible;
  }
}

.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.card > header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
  border-bottom: 1px solid var(--border);
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.card > header .spacer { flex: 1; }
.card > .body { padding: 12px; display: flex; flex-direction: column; gap: 10px; }
.card.collapsible > header { cursor: pointer; user-select: none; }
.card.collapsible > header:hover { color: var(--text); }
.caret { display: inline-block; width: 10px; color: var(--muted); }

/* ------------------------------------------------------- color por entorno
 *
 * `data-env` solo existe cuando el entorno tiene color (producción no lo tiene: se
 * queda con el aspecto neutro y su badge rojo). Así "sin tinte" y "tinte transparente"
 * no se confunden, y nada se desplaza al cambiar de entorno.
 *
 * La franja va con `box-shadow: inset` y no con un borde: no ocupa espacio, así que no
 * mueve el contenido al cambiar de entorno. */

/* An environment paints its bars SOLID, like a tool (`body[data-bar="solid"]`, further
   down): white text on its colour. Pale tints of it read as dull in both themes.
   The fill is the environment's colour deepened a little: the green of Development and
   the orange of Localhost are so light that white text on them fell to 2:1 and could
   not be read; 15% towards black keeps them vivid and legible. A tool keeps its exact
   colour (the app's blue already carries white text). */
body[data-env] { --bar-fill: color-mix(in oklch, var(--env) 85%, black); }
body[data-herramienta] { --bar-fill: var(--env); }

/* The cards carry a light touch of it in their headers, in OKLCH so it stays clean */
:root { --env-tint-card: 14%; }
:root[data-theme="dark"]:not([data-presentacion]) { --env-tint-card: 22%; }
body[data-env] .card > header {
  background: color-mix(in oklch, var(--env) var(--env-tint-card), var(--panel));
}
body[data-env] .caret { color: var(--env); }

/* La tabla y el paginador ocupan todo el ancho de la tarjeta, sin el padding del cuerpo. */
.card > .body > .table-wrap,
.card > .body > .pager { margin: 0 -12px; }
.card > .body > .table-wrap:last-child { margin-bottom: -12px; }

/* ---------------------------------------------------------------- forms */

.field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.field > label { font-size: 11px; color: var(--muted); font-weight: 600; }

/* Cabecera de un bloque: etiqueta a la izquierda, acción pegada a la derecha. */
.field-head { display: flex; align-items: center; gap: 8px; min-height: 20px; }
.field-head .spacer { flex: 1; }
.label-danger { color: var(--danger); }

/* Separa visualmente un bloque del anterior dentro de la misma tarjeta. */
.field.divided { border-top: 1px solid var(--border); padding-top: 12px; margin-top: 4px; }

/* `fieldset` se usa solo para deshabilitar en bloque durante una corrida. */
fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
fieldset.col { display: flex; flex-direction: column; gap: 12px; }
fieldset[disabled] { opacity: 0.75; }

/* `fieldset[disabled]` solo inhabilita controles de formulario: el dropzone es un div
   con un @click, así que hay que apagarlo aparte. Las cabeceras plegables siguen vivas. */
fieldset[disabled] .dropzone { pointer-events: none; }
.row { display: flex; gap: 8px; align-items: flex-end; flex-wrap: wrap; }
.row > .field { flex: 1; min-width: 110px; }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.grid3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }

/* Por exclusión, no por lista de tipos: un `<input>` sin atributo `type` (o uno
   nuevo como `date`) no casa con `input[type="text"]` y se quedaría sin estilo.
 *
 * `.swal2-input` queda fuera a propósito: los campos de un diálogo no son campos de
 * un formulario de la app. Este selector tiene especificidad (0,3,1) por los tres
 * `:not()`, así que su `width:100%` le ganaba a `body .swal2-input` (0,1,1) y el
 * input del diálogo se salía del popup por sus propios márgenes laterales. */
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(.swal2-input),
select,
textarea {
  width: 100%;
  padding: 6px 8px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
input:disabled, select:disabled, textarea:disabled, button:disabled { opacity: 0.55; cursor: not-allowed; }
input::placeholder, textarea::placeholder { color: var(--muted); }

/* Los textos largos crecen a lo alto y nunca a lo ancho: ensanchar rompería la columna. */
textarea { resize: vertical; min-height: 64px; line-height: 1.45; }

/* Safari/Chrome pintan el autofill con un fondo amarillo propio que ignora `background`. */
input:-webkit-autofill,
input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text);
  -webkit-box-shadow: 0 0 0 100px var(--panel) inset;
}

.check { display: flex; align-items: center; gap: 6px; font-size: 12px; }
.check input { width: auto; }

/* `a.btn`: a signed download (`data-signed-path`) must be a link, and it looks like a button */
button, a.btn {
  padding: 6px 12px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--panel);
  cursor: pointer;
}
a.btn { color: inherit; text-decoration: none; }
button:hover:not(:disabled), a.btn:hover { border-color: var(--accent); }
button.primary { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
button.danger { color: var(--danger); border-color: var(--danger); }
button.link { border: 0; background: none; color: var(--accent); padding: 2px 4px; text-decoration: underline; }
button.big { padding: 10px; width: 100%; font-size: 14px; }

/* Enlace con aspecto de botón (ej. «Descargar avance» en el panel de progreso). */
.btn-link {
  display: inline-flex;
  align-items: center;
  padding: 6px 12px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  text-decoration: none;
  cursor: pointer;
}
.btn-link:hover { border-color: var(--accent); color: var(--accent); }

/* -------------------------------------------------------------- tokens
   Los botones que insertan un token en la plantilla de ruta del ZIP. Antes eran
   enlaces pegados unos a otros y no se veía dónde acababa un encabezado y empezaba
   el siguiente. Ahora son pastillas, y las dos primeras van destacadas: son las que
   apuntan a los selects y aguantan que el próximo Excel traiga otros encabezados. */

.tokens { display: flex; flex-direction: column; gap: 6px; margin-top: 2px; }
/* El rótulo a un lado y las pastillas en su propia caja: así las que se desbordan
   siguen alineadas con las de la primera línea, en vez de arrancar bajo el rótulo. */
.tokens-fila { display: flex; gap: 6px; align-items: baseline; }
.tokens-lista { display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; }
/* Ancho fijo para que las dos filas de pastillas empiecen a la misma altura: con el
   rótulo al ancho de su texto, «Insertar» y «Columnas» las dejaban desalineadas. */
.tokens-cap { flex: 0 0 auto; min-width: 62px; font-size: 11px; color: var(--muted); line-height: 1.9; }
.token {
  max-width: 100%;
  padding: 3px 10px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.6;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.token:hover { color: var(--accent); border-color: var(--accent); }
.token.destacado {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

.hint { font-size: 11px; color: var(--muted); }
/* Una pista que, además de explicar, señala un error del campo de al lado. */
.hint.danger { color: var(--danger); }
.mono { font-family: var(--mono); font-size: 11px; }

/* ------------------------------------------------------------- dropdown
   Menú propio para el selector de entorno: el popup del <select> nativo de macOS
   alinea la opción marcada con el control y escondía las primeras opciones tras un
   chevron de scroll. Este abre siempre hacia abajo, con todas a la vista. */

.dropdown { position: relative; }
.dropdown-toggle { display: inline-flex; align-items: center; gap: 7px; }
.dropdown-menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  min-width: max(100%, 160px);
  display: flex;
  flex-direction: column;
  padding: 4px;
  background: var(--panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.22);
  z-index: 30;
}
.dropdown-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border: 0;
  border-radius: 4px;
  background: none;
  text-align: left;
  white-space: nowrap;
}
.dropdown-item:hover { background: var(--accent-soft); }
/* El menú dejó de ser solo entornos: ahora agrupa «Ambientes» y «Herramientas», y sin
   un rótulo y una línea de por medio las dos listas se leían como una sola. */
.dropdown-group {
  padding: 6px 10px 3px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.dropdown-sep { height: 1px; margin: 4px 6px; background: var(--border-strong); }
.dropdown-item .tick { width: 12px; flex: 0 0 auto; color: var(--accent); }
.env-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }

/* ------------------------------------------------------------------ docs
   El visor de documentación: una lista larga que se recorre buscando, así que cada
   ticket es una fila compacta y solo el abierto muestra sus archivos. */

/* A todo el ancho: la tabla de documentación trae diez columnas y encajonarla en la
   anchura de una tarjeta obligaba a desplazarse en horizontal para nada. */
/* Con una herramienta abierta, su tarjeta ocupa el alto que quede.
 *
 * `.layout` alinea sus columnas arriba (`align-items: start`), que es lo que quiere la
 * pantalla de trabajo: dos columnas de alto distinto no deben estirarse. Aquí solo hay
 * una tarjeta y es la pantalla entera, así que dejarla acabar donde acabe su contenido
 * era un socavón gris debajo — visible en Estadísticas, que es más corta que la tabla.
 *
 * Los 54px son el padding vertical de `.layout` (14 arriba + 40 abajo), el mismo cálculo
 * que ya usa la columna de configuración para no provocar barra de página. */
.layout-ancho {
  grid-template-columns: minmax(0, 1fr);
  /* Alto DEFINIDO, no mínimo. Con `min-height` la tarjeta podía crecer, y como el número
     de filas sale del alto de la tabla y la tabla estiraba la tarjeta, el cálculo se
     perseguía a sí mismo: más filas, más alto, más filas. Fijándolo, la única variable
     es cuántas filas caben. */
  height: calc(100vh - var(--topbar-h));
  align-items: stretch;
}
/* Y la cadena hasta la tabla, para que sea ELLA la que se estire: así su alto es el
   sitio disponible —de donde salen las filas que caben y su desplazamiento propio— en
   vez de tener que deducirlo restándole cosas a la ventana. `min-height: 0` en cada
   eslabón porque, sin él, un hijo flexible no encoge por debajo de su contenido y la
   tabla empujaría la tarjeta fuera de la pantalla. */
/* `.col` también: por defecto un elemento de grid o de flex vale `min-height: auto`, que
   significa «no encojas por debajo de tu contenido». Con la columna sin esto, la tabla
   la empujaba por debajo del alto de la pantalla y todo lo demás daba igual. */
.layout-ancho > .col { min-height: 0; }
.layout-ancho > .col > .card { flex: 1; display: flex; flex-direction: column; min-height: 0; }
/* El cuerpo se desplaza por dentro cuando su contenido no cabe —Estadísticas en una
   pantalla baja—, para que nunca aparezca la barra de la página. En la vista de la lista
   no llega a usarse: ahí lo que se desplaza es la tabla. */
.layout-ancho > .col > .card > .cuerpo-docs { flex: 1; min-height: 0; overflow-y: auto; }
/* LA PANTALLA ocupa toda la caja, ella sola.
   Es la regla que impide que lo de abajo le coma sitio a la tabla: los filtros, las
   cifras, la tabla y su pie viven aquí dentro con `min-height: 100%`, así que el hueco
   que reparte el flex es el mismo haya o no avisos debajo. Ya pasó una vez —al estrenar
   los avisos, «Automático» se quedó en seis filas y la tabla se vio aplastada—, y pasará
   otra vez con el siguiente añadido si esto desaparece. Lo que se añada debajo va FUERA
   de `.pantalla-docs`, debajo del pliegue, y se alcanza desplazando. */
.layout-ancho .cuerpo-docs > .pantalla-docs {
  display: flex; flex-direction: column; gap: 14px;
  min-height: 100%;
  /* The cards on top keep a margin from the box's edge, as in Horas de gestión */
  padding-top: 16px; box-sizing: border-box;
}
.layout-ancho .pantalla-docs > .tabla-scroll { flex: 1; min-height: 0; }
/* The pagination bar right under the totals row: without the screen's 14px gap and its own
   top padding (the scroll box's horizontal bar already separates them) */
.layout-ancho .pantalla-docs > .paginacion-barra { margin-top: -14px; padding-top: 4px; }

/* La cabecera del visor no es la de una tarjeta más: es el título de la pantalla, y
   con el estilo de sección se perdía entre los rótulos de las columnas. */
/* Con `.card >` delante para ganar a la regla general de las cabeceras de tarjeta:
   sin eso, el borde de acento se lo comía el gris de `.card > header`. */
.card > header.header-fuerte {
  padding: 14px 16px;
  /* Azul lleno: la cabecera de la pantalla tiene que distinguirse de un vistazo del
     resto de la tarjeta, y un tinte suave no la separaba de nada. */
  background: var(--header-azul);
  border-bottom: 2px solid var(--header-azul-borde);
  border-radius: var(--radius) var(--radius) 0 0;
  /* Aire de verdad por debajo: pegada a los filtros, la franja azul parecía parte de
     ellos en vez de la cabecera de la pantalla. */
  margin-bottom: 18px;
  color: #fff;
}
.header-fuerte h2 {
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  color: #fff;
}
.header-fuerte .hint { color: rgba(255, 255, 255, 0.85); }
/* El botón, en blanco sobre el azul: con sus colores de siempre desaparecía. */
.header-fuerte .btn {
  border-color: rgba(255, 255, 255, 0.65);
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
}
.header-fuerte .btn:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.22);
  border-color: #fff;
}

/* Un botón con su borde y su texto, no un icono suelto: el engranaje a secas se leía
   como decoración y no invitaba a pulsarlo. */
.btn-icono { display: inline-flex; align-items: center; gap: 6px; }

.paginacion { display: flex; align-items: center; gap: 8px; padding-top: 8px; }
.paginacion .spacer { flex: 1; }
.paginacion-tam { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--muted); }
.paginacion-tam select { width: auto; }
.paginacion .btn-link:disabled { opacity: 0.4; cursor: default; }

/* La tabla se desplaza DENTRO de su caja: si desbordara la página, la cabecera y el
   buscador se irían con ella. */
/* Se desplaza en los dos ejes: en horizontal cuando no caben las columnas, y en
   vertical cuando la paginación fija (15, 100, «Todos») hace la lista más larga que la
   pantalla. El alto máximo lo pone `DocsTablePanel` al medir, porque depende de dónde quede
   la tabla; aquí solo se declara que puede desplazarse. */
.tabla-scroll { overflow: auto; }
.tabla-docs { width: 100%; border-collapse: collapse; font-size: 12px; }
/* 5 px de aire lateral y no 8: con quince columnas eso son unos noventa píxeles, que es
   lo que faltaba para que la tabla entrara entera en una pantalla de 1440 sin quitarle
   ninguna columna. Presentando se vuelve a 12, que es donde sí sobra sitio. */
.tabla-docs th, .tabla-docs td { padding: 6px 5px; border-bottom: 1px solid var(--border); text-align: left; }
/* The header is pinned to the top ABOVE the rows: without a z-index, anything positioned in
   a row (the type and status chips carry `position: relative` for their tooltip, the pinned
   Acciones cell) was painted over it while scrolling. Rows' Acciones cells are at 2. */
.tabla-docs thead th {
  position: sticky;
  top: 0;
  z-index: 4;
  background: var(--panel);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}
.tabla-docs .th-grupo { text-align: center; border-bottom: 1px solid var(--border-strong); }
/* The phases' row is pinned right UNDER the group's row, not at 0 (`--fila-grupo`: its
   height, measured by DocsTablePanel.js) */
.tabla-docs thead tr + tr th { top: var(--fila-grupo, 27px); }
/* DevOps Backend, DevOps Frontend and Jira repeat «Asignado a» · Estado under them: a thin rule
   before each group says where one ends and the next begins (useColumnGroups) */
.tabla-docs .th-grupo-asignacion-interna,
.tabla-docs .th-grupo-devops-backend,
.tabla-docs .th-grupo-devops-frontend,
.tabla-docs .th-grupo-jira,
.tabla-docs .th-grupo-desarrollo { border-left: 1px solid var(--border); }
/* Each group says where its data comes from with its brand's icon and colour (26-10-2026) */
.tabla-docs .th-grupo-icono { margin-right: 5px; font-size: 14px; vertical-align: -1px; }
.tabla-docs .th-grupo-icono.icono-devops { color: #0078d4; }
.tabla-docs .th-grupo-icono.icono-jira { color: #2684ff; }
.tabla-docs .th-grupo-icono.icono-desarrollo { color: var(--accent); }
/* «Desarrollo» (02-11-2026): the group's header is centred, so its «Proyectos locales» chip sits under the title */
.tabla-docs .th-grupo-desarrollo .dr-proyectos-chip { margin: 4px auto 0; }
/* «Asignación interna» is the app's own: the brand colour */
.tabla-docs .th-grupo-icono.icono-asignacion-interna { color: var(--brand); }

/* ------------------------------------------------------------------ presentación
   El visor de documentación proyectado en una reunión.

   Va sobre `html[data-presentacion]` y no sobre una clase del panel porque tiene que
   alcanzar cosas que están FUERA de él —la barra superior de la app— y a los controles
   nativos, que solo obedecen a `color-scheme` en la raíz. */

/* El tema claro, a la fuerza. No es capricho: un proyector lava los oscuros y una
   tabla de cifras grises sobre negro no se lee desde el fondo de la sala. Se repiten
   los valores de `:root` en vez de heredarlos: el bloque oscuro (`:root[data-theme="dark"]`)
   se apaga con su `:not([data-presentacion])`, y esto deja el claro por encima. */
html[data-presentacion] {
  color-scheme: light;

  /* Claro, pero NO blanco. Una tarjeta a #ffffff proyectada es una lámpara: deslumbra,
     y una hora de reunión mirándola cansa. Un roto apagado da el mismo contraste con el
     texto —que es lo que hace falta para leer desde el fondo— sin el brillo. */
  --bg: #e6ebef;
  --panel: #f2f4f6;
  --border: #d3d9df;
  --border-strong: #b0b8c0;
  --text: #1a1f24;
  --muted: #5a636b;
  /* El azul de los detalles (la flecha de la columna ordenada) sale del mismo tono que
     la cabecera, oscurecido lo justo para que se lea sobre el claro. */
  --accent: var(--brand);
  --accent-soft: #e5f2fa;

  --ok: #1a7f45;
  /* El verde como TEXTO sobre fondos verdes claros: más oscuro para pasar de 4,5:1. */
  --ok-texto: color-mix(in srgb, var(--ok) 80%, var(--text));
  --warn: #a35c00;
  --warn-bg: #fdf3e2;
  /* El resaltador amarillo («Bugs reportados»: la palabra «bug» en títulos y etiquetas) */
  --resaltador: #ffec80;
  --resaltador-texto: #1a1f24;
  --danger: #b3261e;
  --danger-bg: #fdecea;
  --info: #4a3fb5;
  --info-bg: #eeecfb;
  --neutral-bg: #f0f1f3;

  /* Sin barra superior no hay nada a lo que pegarse ni de lo que descontar alto. */
  --topbar-h: 0px;

  /* La cabecera de la presentación tiene su propio color. */
  --header-azul: var(--brand);
  --header-azul-borde: var(--brand-strong);
}

/* La cabecera de la app entera. En presentación lo que se enseña es la tabla, no en
   qué herramienta está el que la enseña. */
html[data-presentacion] .topbar-stack { display: none; }

/* La letra, que es lo que convierte «pantalla limpia» en «presentación». Se aplica a la
   tabla y a su pie; el resto de la pantalla se queda como está, que ni los filtros ni
   la cabecera son lo que la sala está leyendo. `--docs-letra` la pone `DocsTablePanel`. */
html[data-presentacion] .tabla-docs { font-size: var(--docs-letra, 16px); }
/* El ticket y la fecha van en `.mono`, que fija 11px: con la letra grande se quedaban
   igual de pequeños mientras el título crecía. Aquí el tamaño pasa a ser relativo al de
   la tabla —`em`, no píxeles— y un pelo menor, que una monoespaciada al mismo tamaño se
   ve más grande que el texto normal. */
html[data-presentacion] .tabla-docs .mono { font-size: 0.92em; }
html[data-presentacion] .tabla-docs thead th { font-size: calc(var(--docs-letra, 16px) * 0.72); }
/* Aire arriba y abajo, que es lo que hace legible una fila proyectada. A los lados
   también, ahora que solo quedan dos columnas y no hay nada que se pueda salir. */
html[data-presentacion] .tabla-docs th,
html[data-presentacion] .tabla-docs td { padding: 10px 12px; }
html[data-presentacion] .paginacion { font-size: calc(var(--docs-letra, 16px) * 0.85); }
/* Sin las columnas de fechas ni de horas, un título largo ya no puede empujar nada
   fuera de la pantalla: se le quita el recorte y se lee entero, que es de lo que va la
   presentación. */
html[data-presentacion] .tabla-docs .col-titulo { max-width: none; white-space: normal; }
/* Presenting, the title is read whole and at the presentation size */
html[data-presentacion] .tabla-docs .col-titulo .titulo-texto { display: block; -webkit-line-clamp: unset; line-clamp: unset; font-size: inherit; }
/* Y con solo dos columnas el navegador se reparte el ancho a medias, dejando un hueco
   entre el ticket y su título que parece un error de maquetación. Al ticket se le da lo
   justo que ocupa y el título se queda con todo lo demás. */
/* Only the first header row: the second starts with a sub-column of a group, not with the ticket */
html[data-presentacion] .tabla-docs thead tr:first-child th:first-child,
html[data-presentacion] .tabla-docs tbody td:first-child { width: 1%; white-space: nowrap; }

/* La tabla ocupa el alto que haya.
 *
 * Sin esto, la tarjeta terminaba donde terminaban las filas: con seis resultados dejaba
 * dos tercios de pantalla en gris. Se encadena el alto desde `.layout` hasta el cuerpo
 * —cada eslabón con `min-height: 0`, o un hijo que desborda estira al padre en vez de
 * desplazarse él— y es la zona de la tabla la que crece, así que el pie con la
 * paginación queda abajo del todo y no flotando a media pantalla. */
html[data-presentacion] .layout { height: 100vh; align-items: stretch; padding-bottom: 16px; }
html[data-presentacion] .layout > .col { min-height: 0; }
html[data-presentacion] .card { display: flex; flex-direction: column; flex: 1; min-height: 0; }
html[data-presentacion] .cuerpo-docs { flex: 1; min-height: 0; }
html[data-presentacion] .tabla-scroll { flex: 1; min-height: 0; overflow-y: auto; }

/* «Buscar» baja al final. Se hace con `order` y no moviendo el marcado porque fuera de
   la presentación su sitio es arriba, con los demás filtros: reordenar el DOM obligaría
   a mantener dos versiones de lo mismo. Queda debajo de la tabla y de su pie, que es
   donde menos estorba: presentando se usa a ratos, y arriba se llevaba la primera
   mirada de la sala. */
html[data-presentacion] .tabla-scroll { order: 1; }
html[data-presentacion] .paginacion { order: 2; }
html[data-presentacion] .filtros { order: 3; }
/* Y los avisos, primero: si algo falló hay que verlo antes que nada. */
html[data-presentacion] .cuerpo-docs > .alert,
html[data-presentacion] .cuerpo-docs > .hint { order: 0; }

/* Presentando, el visor es la diapositiva entera: sin margen ni esquinas redondeadas,
   que el documento es lo que se viene a leer y cada píxel cuenta. */
html[data-presentacion] .backdrop { padding: 0; }
html[data-presentacion] .modal.modal-visor {
  width: 100vw;
  max-width: 100vw;
  height: 100vh;
  border: 0;
  border-radius: 0;
}

/* La fila que se puede pulsar lo tiene que decir antes de pulsarla. */
.tabla-docs tbody tr.fila-pulsable { cursor: pointer; }

/* Los dos botones del tamaño de letra, juntos como un solo control. */
.letra-presentacion { display: inline-flex; gap: 4px; }

/* Los controles de la cabecera del visor. El `.spacer` empuja el título a un lado y
   deja el zoom y el cerrar juntos al otro. */
.modal-header { gap: 10px; }
.modal-header .spacer { flex: 1; }

/* El zoom, como un control y no como una etiqueta con un desplegable al lado: una caja
   con su borde, la lupa dentro y el `select` sin el suyo, para que se lean como una sola
   pieza. La lupa en vez de la palabra «Zoom» porque el valor —«150%», «Ajustar»— ya dice
   de qué va, y así ocupa lo que tiene que ocupar. */
.zoom-visor {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 30px;
  padding: 0 8px 0 9px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--panel);
  color: var(--muted);
}
.zoom-visor:hover { border-color: var(--accent); color: var(--text); }
.zoom-visor:focus-within { outline: 2px solid var(--accent); outline-offset: -1px; }
.zoom-visor .mdi { font-size: 16px; line-height: 1; }
.zoom-visor select {
  height: 100%;
  padding: 0 2px;
  border: 0;
  background: none;
  color: var(--text);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
.zoom-visor select:focus { outline: none; }

/* Y «Cerrar» a la misma altura, que si no la cabecera parece dos barras superpuestas. */
.modal-header .btn-icono { height: 30px; padding: 0 12px; font-size: 12px; }
.modal-header .btn-icono .mdi { font-size: 15px; line-height: 1; }
/* The viewer's «Descargar» is a link: no underline, centred like the buttons around it */
.modal-header a.btn-icono { display: inline-flex; align-items: center; gap: 4px; text-decoration: none; border: 1px solid var(--border-strong); }

/* La cabecera que ordena es un botón de verdad —se llega con el tabulador y responde al
   Enter—, pero tiene que seguir pareciendo la cabecera: hereda tipo, tamaño y color, y
   solo se distingue al pasar por encima. El `th` ya trae su relleno, así que el botón va
   sin el suyo para que el texto no se descoloque respecto a las columnas que no ordenan. */
.tabla-docs .th-orden {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  cursor: pointer;
}
.tabla-docs .th-orden:hover { color: var(--text); }
.tabla-docs .th-orden:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
/* La flecha de «se puede ordenar por aquí» se insinúa; la de la columna activa se ve.
   Ocupan lo mismo en los dos casos, para que la cabecera no baile al cambiar de columna. */
.tabla-docs .th-orden .mdi { font-size: 13px; line-height: 1; opacity: 0.28; }
.tabla-docs th[aria-sort="ascending"] .th-orden,
.tabla-docs th[aria-sort="descending"] .th-orden { color: var(--text); }
.tabla-docs th[aria-sort="ascending"] .th-orden .mdi,
.tabla-docs th[aria-sort="descending"] .th-orden .mdi { opacity: 1; color: var(--accent); }
/* En las columnas de números el texto va a la derecha, y su botón también: si no, el
   título quedaba pegado a la izquierda y las cifras a la derecha, sin relación visible. */
.tabla-docs th.num .th-orden { justify-content: flex-end; }
/* The estimation hours, centred under their header. Only these: `.num` is also used by
   the Sistema tables that share this stylesheet, and there right-aligned is right. */
.tabla-docs td.horas,
.tabla-docs th.horas { text-align: center; }
.tabla-docs .num { text-align: right; white-space: nowrap; }
.tabla-docs td.total { font-weight: 600; color: var(--text); }
/* Totals of the filtered tickets: pinned to the bottom of the scroll box like the header
   to the top, so the sum stays in view while scrolling a long list. */
.tabla-docs tfoot td {
  position: sticky;
  bottom: 0;
  /* Above the rows, as the header (see `.tabla-docs thead th`) */
  z-index: 4;
  background: var(--panel);
  border-top: 1px solid var(--border-strong);
  border-bottom: 0;
  font-weight: 600;
  color: var(--text);
}
/* With few rows the totals must still sit at the bottom of the box: the table fills the
   scroll box and the filler row (percentage height) takes the spare space, so the data
   rows keep their natural height. With many rows the filler collapses to nothing and the
   sticky footer takes over. */
.layout-ancho .pantalla-docs > .tabla-scroll > .tabla-docs { height: 100%; }
.tabla-docs tbody tr.fila-relleno { height: 100%; }
.tabla-docs tbody tr.fila-relleno td { padding: 0; border: 0; }
.tabla-docs tbody tr.fila-relleno:hover { background: none; }
.tabla-docs tfoot .totales-etiqueta { text-align: right; font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.tabla-docs tfoot .totales-etiqueta .hint { text-transform: none; letter-spacing: 0; font-weight: 400; }
/* The hours of the documents table at the size of its dates, title and type chips
   (10 px). Only there and only in the working view: the management-hours table shares
   `.tabla-docs` and keeps its size, and presenting keeps the presentation size. */
html:not([data-presentacion]) .tabla-docs:not(.tabla-gestion) td.horas { font-size: 10px; }
.tabla-docs tbody tr:hover { background: var(--accent-soft); }
/* El título se recorta con puntos suspensivos. Iba por posición —`nth-child(2)`— y al
   añadir la columna de la casilla dejó de apuntar al título para apuntar al ticket, que
   nunca es largo: el título volvió a estirar la tabla sin que se notara por qué. Ahora va
   por su nombre, que no se mueve cuando cambian las columnas. */
/* 240 y no 420: con catorce columnas la tabla mide 1744 px y a 1440 no cabía, así que el
   título cedió el ancho que le sobraba. No se pierde nada —el completo sigue en el
   tooltip de la celda— y presentando se libera, que es donde hay sitio y se lee entero. */
/* 165 y no 240: con la columna de Factura, la tabla pedía 1465 px en una caja de 1374.
   El título es la columna que más ancho suelta sin perder nada —el completo sigue en el
   tooltip de la celda— y es lo único que deja ver la factura sin desplazar. Presentando
   se libera, que es donde hay sitio y se lee entero. */
/* 24-10-2026 (decided by the owner): wider again, 260 px. The table already scrolls sideways
   since the DevOps Backend / Frontend / Jira groups, and a title in 165 px said almost nothing */
.tabla-docs .col-titulo { min-width: 240px; max-width: 260px; overflow: hidden; }
/* The title on up to two lines, at the same size as the two-line dates next to it: one
   line cut most titles after three or four words. The full title stays in the tooltip. */
.tabla-docs .col-titulo .titulo-texto {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  white-space: normal;
  font-size: 10px;
  line-height: 1.35;
}
/* La celda de acciones es una CELDA NORMAL, no una caja flexible.
   Desde que las fichas de Tipo van apiladas, una fila puede medir el doble que su vecina,
   y un `td` convertido en `display: flex` se queda con SU alto y se pega arriba: los
   botones aparecían diez píxeles por encima del texto de su propia fila y la tabla se
   leía como una escalera. Siendo celda, el centrado vertical de la tabla los coloca sin
   que haya que pedírselo. La separación entre botones pasa de `gap` —que solo entiende
   una caja flexible— a un margen entre hermanos. */
.tabla-docs .acciones { white-space: nowrap; }
/* The actions cell: see and download, and the ⋮ menu pushed to the right */
.acciones-fila { display: flex; align-items: center; gap: 4px; }
.acciones-fila .acciones-mas { margin-left: auto; }
.btn-ver.acciones-mas.abierto { border-color: var(--accent); color: var(--accent); }
/* The ⋮ menu: one row per action, icon and title; fixed at the button, above the table */
.menu-acciones {
  position: fixed; z-index: 60; min-width: 220px; padding: 4px 0;
  display: flex; flex-direction: column;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
}
.menu-acciones-item {
  display: flex; align-items: center; gap: 10px; height: 36px; padding: 0 14px;
  border: 0; background: transparent; color: var(--text); font-size: 13px; text-align: left;
  white-space: nowrap; cursor: pointer;
}
.menu-acciones-item:hover, .menu-acciones-item:focus-visible { background: var(--neutral-bg); outline: none; }
.menu-acciones-item .mdi { font-size: 18px; line-height: 1; color: var(--muted); }
.menu-acciones-item.con-datos .mdi { color: var(--ok); }
/* An action that already holds something: a light green fill, the same tone as the ⋮ button */
.menu-acciones-item.con-datos { background: color-mix(in srgb, var(--ok) 10%, var(--panel)); }
.menu-acciones-item.con-datos:hover,
.menu-acciones-item.con-datos:focus-visible { background: color-mix(in srgb, var(--ok) 18%, var(--panel)); }
.menu-acciones-item.con-datos + .menu-acciones-item.con-datos { border-top: 1px solid var(--panel); }
.tabla-docs .acciones .btn-ver + .btn-ver { margin-left: 8px; }
.tabla-docs .col-check { width: 34px; text-align: center; padding-right: 0; }

/* Tipo: plain for the areas, a tinted chip for estimations. Under the new DOCS rules a
   ticket can show up twice — its requirement and its estimation — and the second row
   has to stand out at a glance, not after reading the column. */
.tabla-docs .col-tipo { white-space: nowrap; }
/* The total is right-aligned and the creation date left-aligned, so with the hours now
   next to the title the two met with just the cell padding between them and read as one
   number. Some air separates the estimation block from the dates. */
.tabla-docs .col-fecha { padding-left: 10px; }
/* Creación y modificado: el día arriba y la hora debajo (fechaHora separa con \n). */
.tabla-docs .two-line-date { white-space: pre-line; line-height: 1.35; font-size: 10px; }
/* Presenting, the letters grow and the date column is squeezed: `pre-line` let the date
   break at its hyphens ("2026-09-" / "25"). `pre` keeps the one break between date and
   time and never splits the date itself; the column widens to fit it. */
html[data-presentacion] .tabla-docs .two-line-date { white-space: pre; }
/* A tinted chip per type, in the table and in the filter.
   Every colour comes from a theme variable through `--c`, so one rule serves the dark
   theme and the light one of the presentation, and `color-mix` builds the fill from the
   same colour as the text — no second palette to keep in step. */
.tipo-doc {
  --c: var(--muted);
  display: inline-block;
  /* All the same width, so the column reads as one block and not as a ragged edge.
     `min-width` and not `width`: a type longer than the widest one today must grow
     rather than spill out of its chip. */
  min-width: 88px;
  text-align: center;
  padding: 1px 8px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--c) 26%, transparent);
  color: var(--c);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}
.tipo-tl { --c: var(--accent); }
.tipo-devops { --c: var(--ok); }
.tipo-estimacion { --c: var(--info); }
.tipo-neutro { --c: var(--muted); }

/* El filtro: con la forma de un `select` —mismo alto, mismo borde, misma flecha— y los
   chips dentro de su menú, pulsables y con selección múltiple. Sin pulsar quedan en
   contorno; pulsados se rellenan con su color, que es el de su columna. */
/* El mismo control sirve para TIPO y para ESTADO: son la misma pregunta hecha dos veces
   («qué es» y «en qué va»), y dos mandos distintos para lo mismo solo dan trabajo al que
   mira. Cada campo conserva su clase propia porque el clic fuera cierra por selector: si
   compartieran clase, abrir uno dejaría el otro abierto encima. */
.campo-tipos, .campo-estados { position: relative; min-width: 0; }
.campo-tipos .select-tipos,
.campo-estados .select-tipos {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  min-width: 120px;
  padding: 6px 8px 6px 10px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  cursor: pointer;
}
.campo-tipos .select-tipos.abierto,
.campo-estados .select-tipos.abierto { border-color: var(--accent); }
.campo-tipos .select-tipos .mdi,
.campo-estados .select-tipos .mdi { font-size: 18px; line-height: 1; color: var(--muted); }
.menu-tipos {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 30;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-width: 100%;
  margin-top: 4px;
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.28);
}
/* UNA FICHA PULSABLE, donde sea que esté.
   El aspecto NO cuelga de `.menu-tipos`. Colgaba, y por eso los cuatro botones de estado
   del modal de relación —que son estas mismas fichas fuera de ese menú— salían como
   botones grises del navegador, todos idénticos y sin que `activo` cambiara un píxel:
   se podía elegir un estado, pero no se veía, que para quien lo usa es lo mismo que no
   poder. Lo específico del menú se queda abajo; esto vale para todos. */
.chip-tipo {
  /* `--c` NO se declara aquí a propósito: lo pone la clase del tipo (`.tipo-tl`…) o la
     de la paleta (`.paleta-warn`…), y declararlo aquí ganaría por especificidad y
     pintaría todas las fichas en gris. El valor por defecto va en el `var()`, para la
     ficha «Todos», la de «Sin estado» y cualquier otra sin color propio. */
  padding: 4px 10px;
  border: 1px solid color-mix(in srgb, var(--c, var(--muted)) 60%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--c, var(--muted)) 12%, transparent);
  color: var(--c, var(--muted));
  font-size: 11px;
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
  cursor: pointer;
}
.chip-tipo:hover {
  border-color: var(--c, var(--muted));
  background: color-mix(in srgb, var(--c, var(--muted)) 24%, transparent);
}
/* Pulsada: relleno macizo con el color del tipo y el texto del fondo de la app. Sirve
   para los dos temas — en oscuro los colores son pasteles claros y el texto cae oscuro,
   en claro son saturados y el texto cae blanco — y deja el «puesto/no puesto» a la
   vista, que con un tinte al 20% había que fijarse para distinguirlo. */
.chip-tipo.activo {
  background: var(--c, var(--muted));
  border-color: var(--c, var(--muted));
  color: var(--panel);
}

/* Y lo que solo vale dentro del menú de tipos: todas del mismo ancho, en su rejilla. */
.menu-tipos .chip-tipo { min-width: 104px; text-align: center; flex: 0 0 auto; }
.menu-tipos .chip-todos { --c: var(--text); }
/* «Sin estado» no es un estado del catálogo y no tiene color propio: va en gris, que es
   justo lo que dice —nadie lo ha clasificado todavía—. */
.menu-tipos .chip-sin-estado { --c: var(--muted); }

/* The status select inside the table's Estado column: the chip itself is the control,
   with a caret, and it opens the same chip menu as the filter. The menu is fixed (its
   coordinates come from the button) so the table's scroll box does not clip it. */
.celda-estado { display: inline-block; }
.select-estado {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 2px 2px 2px 4px; border: 1px solid transparent; border-radius: 6px;
  background: transparent; color: var(--muted); cursor: pointer;
}
.select-estado:hover, .select-estado.abierto { border-color: var(--border-strong); background: var(--neutral-bg); }
.select-estado:disabled { cursor: progress; opacity: 0.7; }
.select-estado .mdi { font-size: 16px; line-height: 1; }
.select-estado .sin-estado { font-size: 10px; color: var(--muted); padding: 0 4px; }
/* With a status the whole control is the chip: the status colour fills it edge to edge,
   caret included, and the chip inside loses its own fill so there is one shape only */
.select-estado.con-estado {
  gap: 0; padding: 0 4px 0 0; border: 0; border-radius: 999px;
  background: var(--c-solid, #61686f); color: var(--c-ink, #fff);
}
.select-estado.con-estado:hover,
.select-estado.con-estado.abierto {
  background: color-mix(in oklch, var(--c-solid, #61686f) 88%, white);
}
.select-estado.con-estado .ficha-estado { background: transparent; padding-right: 2px; }
/* Every status chip the same width, whatever its name, so the column reads as one block:
   the name centred in the space left of the caret */
.select-estado.con-estado { min-width: 124px; justify-content: space-between; }
.select-estado.con-estado .ficha-estado { flex: 1; min-width: 0; text-align: center; }
.select-estado.con-estado .mdi { color: var(--c-ink, #fff); }
.menu-tipos.menu-estado {
  position: fixed; top: auto; left: auto; margin: 0; min-width: 0; width: 140px;
  flex-direction: column; flex-wrap: nowrap;
  /* Its `max-height` is the room left on screen (DocsTablePanel.js): it scrolls, never gets cut */
  overflow-y: auto; overscroll-behavior: contain;
}
.menu-estado .chip-tipo { flex: none; }
.menu-estado .chip-tipo { min-width: 0; width: 100%; }

/* The dash of an old document whose analysis is folded into Backend: dotted underline
   so it reads as "there is an explanation here", which the tooltip gives. */
.tabla-docs td.horas-combinadas { text-decoration: underline dotted; text-underline-offset: 3px; cursor: help; }

/* The description under the title, only in the presentation. Two lines and not one:
   at presentation size one line keeps barely the first words of a 400-character text,
   and two already tell what the ticket is about. The whole of it is in the tooltip. */
.descripcion-doc {
  margin-top: 3px;
  font-size: 0.78em;
  line-height: 1.35;
  color: var(--muted);
  white-space: normal;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.tabla-docs .col-check input { margin: 0; cursor: pointer; }
/* La fila marcada se distingue del simple hover: una es una elección y el otro solo
   dice dónde está el ratón. */
.tabla-docs tbody tr.marcada { background: var(--accent-soft); }

/* «FIJAR TICKETS ARRIBA» (23-10-2026). La chincheta va en la celda de la casilla, detrás de ella,
   para no quitarle ancho a la columna Ticket (86 px, ya justa con «DevOps-6005» y el robot): la
   celda de la casilla crece 18 px solo cuando la cuenta puede fijar. En reposo con `--muted` sin
   transparencia (más de 3:1 en claro y en oscuro); fijada, con el azul de la app. El blanco del
   clic mide 24 px —el icono 14— y los márgenes negativos impiden que la fila crezca por él. Todo
   con los tokens del tema, así que el modo oscuro viene con ellos. */
.tabla-docs .col-check.con-fijar { width: 52px; white-space: nowrap; }
.btn-fijar {
  display: inline-flex; align-items: center; justify-content: center; vertical-align: middle;
  width: 24px; height: 24px; margin: -5px -4px -5px 0; padding: 5px; border: 0; border-radius: 4px;
  background: transparent; color: var(--muted); cursor: pointer;
}
.btn-fijar .mdi { font-size: 14px; line-height: 1; }
.btn-fijar:hover { color: var(--accent); background: var(--neutral-bg); }
.btn-fijar:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; }
.btn-fijar.activo { color: var(--accent); }
.btn-fijar[aria-busy="true"] { cursor: progress; }
/* La fila fijada: un filo fino a la izquierda y un fondo apenas tintado (menos que la marcada,
   que es una elección de ahora; esto es un orden que se queda). La marcada y el hover mandan. */
.tabla-docs tbody tr.fijada > td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
.tabla-docs tbody tr.fijada:not(.marcada):not(:hover) { background: color-mix(in srgb, var(--accent-soft) 45%, var(--panel)); }
/* Y la raya que separa los fijados del resto, detrás del último de la página */
.tabla-docs tbody tr.cierra-fijados > td { border-bottom: 1px solid var(--border-strong); }

/* Botón cuadrado, solo icono: en una tabla de diez columnas, dos enlaces de texto por
   fila robaban ancho y ruido a lo que de verdad se lee. */
.btn-ver {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
}
.btn-ver:hover { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.btn-ver .mdi { font-size: 16px; line-height: 1; }

/* Tooltip propio para los botones que son solo icono.
   El del navegador tarda casi un segundo en salir y a veces no sale: en una fila con
   cuatro iconos idénticos en tamaño, eso deja al usuario adivinando cuál es cuál.
   Va a la IZQUIERDA porque la columna de acciones es la última y una burbuja hacia
   arriba la recortaría la caja con scroll de la tabla. */
.con-tooltip { position: relative; }
.con-tooltip::after {
  content: attr(data-tooltip);
  position: absolute;
  right: calc(100% + 6px);
  top: 50%;
  transform: translateY(-50%);
  padding: 3px 8px;
  border-radius: 4px;
  background: var(--text);
  color: var(--panel);
  font-size: 11px;
  line-height: 1.5;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.1s ease 0.15s, visibility 0s linear 0.15s;
  z-index: 5;
}
.con-tooltip:hover::after,
.con-tooltip:focus-visible::after { opacity: 1; visibility: visible; }
/* To the right instead: for what sits near the left edge (the Tipo column's chips) */
.con-tooltip.tooltip-derecha::after { right: auto; left: calc(100% + 6px); z-index: 20; font-weight: 500; }
/* An empty tooltip shows nothing */
.con-tooltip[data-tooltip=""]::after { display: none; }

/* El relato de la sincronización: un paso por línea, con su marca. */
.pasos { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.pasos li { display: flex; align-items: baseline; gap: 8px; font-size: 12px; }
.pasos li .mdi { flex: 0 0 auto; color: var(--muted); }
.pasos li.paso-ok .mdi { color: var(--ok); }
.pasos li.paso-conflicto .mdi, .pasos li.paso-error .mdi { color: var(--warn); }

.conflicto { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border: 1px solid var(--border-strong); border-radius: var(--radius); }
.conflicto .mdi { color: var(--warn); font-size: 16px; }
.conflicto-ruta { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Las dos opciones de descarga: tarjetas grandes, no una lista de enlaces. Se elige
   entre ellas de un vistazo y cada una dice qué se lleva. */
.opcion {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  color: var(--text);
  text-decoration: none;
  cursor: pointer;
}
.opcion:hover { border-color: var(--accent); background: var(--accent-soft); }
.opcion > .mdi:first-child { font-size: 26px; color: var(--accent); line-height: 1; }
.opcion > .mdi:last-child { font-size: 18px; color: var(--muted); margin-left: auto; }
.opcion-texto { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.opcion.inhabilitada { opacity: 0.5; cursor: not-allowed; pointer-events: none; }

/* Las flechas de la paginación como iconos, del tamaño del texto que acompañan. */
.btn-pag {
  border: 0;
  background: none;
  color: var(--muted);
  padding: 2px 4px;
  border-radius: 4px;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.btn-pag:hover:not(:disabled) { color: var(--accent); background: var(--accent-soft); }
.btn-pag:disabled { opacity: 0.35; cursor: default; }

/* ------------------------------------------------------------------ visor */

/* Ancho de verdad: un documento con tablas de seis columnas no se lee en una columna
   estrecha, y el visor es lo que se viene a mirar. */
/* Con `.modal.` delante para ganarle a `.modal { max-width: 460px }`, que se declara
   después: si no, el visor salía del ancho de un diálogo pequeño. */
.modal.modal-visor { max-width: min(1720px, 97vw); width: 97vw; display: flex; flex-direction: column; height: 94vh; }
.visor { display: flex; min-height: 0; flex: 1 1 auto; position: relative; }

/* Cmd/Ctrl + F del visor: arriba a la derecha del documento, fuera de su zoom. Las coincidencias
   se pintan con la API de resaltado (`::highlight`), sin tocar el marcado del Word; en el texto de
   CodeMirror, con sus propias marcas. */
.visor-busqueda {
  position: absolute;
  top: 10px;
  right: 24px;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 6px 4px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--muted);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
}
.visor-busqueda-caja {
  display: inline-flex;
  align-items: center;
  gap: 1px;
  padding-right: 3px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg);
}
.visor-busqueda-caja:focus-within { border-color: var(--accent); }
.visor-busqueda-caja.con-error { border-color: var(--danger); }
.visor-busqueda input {
  width: 200px;
  height: 28px;
  padding: 0 6px;
  border: 0;
  background: none;
  color: var(--text);
}
.visor-busqueda input:focus { outline: none; }
/* Los interruptores Aa, ab y .* de VS Code: encendidos, con el borde y el fondo del acento */
.visor-busqueda-opcion {
  min-width: 24px;
  height: 22px;
  padding: 0 4px;
  border: 1px solid transparent;
  border-radius: 3px;
  background: none;
  color: var(--muted);
  font: 600 12px/1 var(--mono);
  cursor: pointer;
}
.visor-busqueda-opcion:hover { background: var(--neutral-bg); color: var(--text); }
.visor-busqueda-opcion[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); color: var(--text); }
.visor-busqueda-opcion.opcion-palabra { text-decoration: underline; text-underline-offset: 2px; }
.visor-busqueda-contador.con-error { color: var(--danger); }
.visor-busqueda-contador { min-width: 72px; font-size: 12px; text-align: right; white-space: nowrap; }
.visor-busqueda .btn-ver:disabled { opacity: 0.4; cursor: default; }
::highlight(visor-busqueda) { background-color: var(--resaltador); color: var(--resaltador-texto); }
::highlight(visor-busqueda-actual) { background-color: #f59e0b; color: #1f2937; }
.CodeMirror .cm-visor-busqueda { background-color: var(--resaltador); color: var(--resaltador-texto); }
.CodeMirror .cm-visor-busqueda-actual { background-color: #f59e0b; color: #1f2937; }
@media (max-width: 640px) {
  .visor-busqueda { left: 8px; right: 8px; }
  .visor-busqueda-caja { flex: 1 1 auto; min-width: 0; }
  .visor-busqueda input { width: auto; flex: 1 1 auto; min-width: 0; }
}
.visor-lista {
  flex: 0 0 270px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px;
  border-right: 1px solid var(--border);
  overflow-y: auto;
}
/* Árbol de archivos: carpeta y contenido, con el sangrado marcando de quién cuelga
   cada cosa. Una lista plana no dejaba ver qué evidencia iba con qué subcarpeta. */
.visor-archivo,
.visor-carpeta {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  border: 0;
  border-radius: 4px;
  background: none;
  text-align: left;
  cursor: pointer;
  width: 100%;
}
.visor-archivo:hover,
.visor-carpeta:hover { background: var(--accent-soft); }
.visor-archivo.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.visor-carpeta { color: var(--muted); font-weight: 600; }
.visor-carpeta .mdi:first-child { font-size: 13px; width: 12px; }
.visor-archivo .mdi,
.visor-carpeta .mdi { flex: 0 0 auto; font-size: 14px; line-height: 1; }
.visor-nombre { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }

.visor-cuerpo { flex: 1 1 auto; min-width: 0; overflow: auto; padding: 14px 16px; background: var(--neutral-bg); }
.visor-marco { width: 100%; height: 100%; min-height: 70vh; border: 0; background: #fff; }

/* El documento que pinta `docx-preview` viene con sus propios estilos y su hoja de
   papel; aquí solo se centra y se le da fondo, sin tocarle nada por dentro. */
.visor-word { display: flex; justify-content: center; }
.visor-word .docx-wrapper { background: transparent; padding: 0; }
.visor-word .docx { box-shadow: 0 1px 6px rgba(0, 0, 0, 0.25); margin-bottom: 14px; }
/* Los saltos de línea del documento se respetan. Word guarda algunas listas dentro de
   una celda como un solo texto con saltos, y en HTML esos saltos se colapsan a un
   espacio: la lista salía en un párrafo corrido. */
.visor-word .docx p { white-space: pre-wrap; }

/* --------------------------------------------------------- hojas y código */

/* Alto en medidas concretas y no en porcentajes: dentro de un contenedor que además
   hace scroll, un `height: 100%` no tiene contra qué resolverse y el visor salía
   aplastado. El modal mide 94vh, menos su cabecera, su pie y el aire de los lados. */
.visor-hoja,
.visor-codigo { height: calc(94vh - 170px); min-height: 320px; display: flex; flex-direction: column; }

.hoja-tabla { flex: 1 1 auto; min-height: 0; overflow: auto; background: var(--panel); border: 1px solid var(--border-strong); border-radius: var(--radius); }
.rejilla { border-collapse: separate; border-spacing: 0; font-size: 12px; width: max-content; min-width: 100%; }
.rejilla td, .rejilla th { border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: 3px 8px; white-space: pre-wrap; vertical-align: top; max-width: 420px; }
/* Las cabeceras de columna y de fila se quedan a la vista, como en una hoja de cálculo. */
.rejilla thead th { position: sticky; top: 0; z-index: 2; background: var(--neutral-bg); color: var(--muted); font-weight: 600; text-align: center; min-width: 64px; }
.rejilla .fila-num { position: sticky; left: 0; z-index: 1; background: var(--neutral-bg); color: var(--muted); font-weight: 500; text-align: right; min-width: 42px; }
.rejilla .esquina { position: sticky; left: 0; z-index: 3; min-width: 42px; }
.rejilla tbody tr:hover td { background: var(--accent-soft); }

.hoja-pie { display: flex; align-items: center; gap: 10px; padding-top: 8px; }
.hoja-pie .spacer { flex: 1; }
.hoja-pestanas { display: flex; flex-wrap: wrap; gap: 4px; }
.hoja-pestana {
  padding: 4px 10px;
  border: 1px solid var(--border-strong);
  border-radius: 4px 4px 0 0;
  background: transparent;
  color: var(--muted);
  font-size: 11px;
  cursor: pointer;
}
.hoja-pestana:hover { color: var(--text); }
.hoja-pestana.active { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 600; }

.visor-codigo .CodeMirror { flex: 1 1 auto; height: auto; min-height: 0; }
.visor-imagen { max-width: 100%; }
.visor-imagen.sin-tope { max-width: none; }
.visor-texto { white-space: pre-wrap; font-family: var(--mono); font-size: 11px; margin: 0; }

/* El documento convertido: se lee, no se maqueta. */
.visor-doc { font-size: 13px; line-height: 1.55; }
.visor-doc h2 { font-size: 16px; margin: 18px 0 6px; }
.visor-doc h3 { font-size: 14px; margin: 14px 0 5px; }
.visor-doc h4 { font-size: 13px; margin: 12px 0 4px; color: var(--muted); }
.visor-doc p { margin: 0 0 8px; }
.visor-doc p.lista { padding-left: 14px; }
.visor-doc img { max-width: 100%; border: 1px solid var(--border); border-radius: 4px; margin: 6px 0; }
.visor-doc table { width: 100%; border-collapse: collapse; margin: 8px 0 14px; font-size: 12px; }
.visor-doc th, .visor-doc td { border: 1px solid var(--border); padding: 5px 7px; text-align: left; vertical-align: top; }
.visor-doc thead th { background: var(--neutral-bg); font-weight: 600; }
/* `>` y no descendiente: el .docx trae su propio <footer> —el pie del documento, con el
   «Proyecto P2H | TL-…»— y no es el pie del modal. Ahora que este solo lleva la ruta,
   además, se alinea a la izquierda en vez de quedar colgando a la derecha. */
.modal-visor > footer { align-items: center; justify-content: flex-start; }
.modal-visor > footer .spacer { flex: 1; }
/* «Abrir»: a la altura del pie, no a la de los botones de la cabecera. */
.modal-visor > footer .btn-abrir { height: 26px; padding: 0 10px; font-size: 11px; }
.modal-visor > footer .btn-abrir .mdi { font-size: 14px; line-height: 1; }
/* El botón de copiar: delante de la ruta, del tamaño del pie y no del de la tabla, y
   solo a la vista cuando el ratón está en el pie.
   Se esconde con `visibility` y no con `display`, para que conserve su hueco: con
   `display: none` la ruta daba un salto de 24px cada vez que el ratón entraba y salía.
   El foco también lo enseña, o con el teclado sería un botón invisible. */
.modal-visor > footer .btn-copiar-ruta {
  width: 24px;
  height: 24px;
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.12s ease;
}
.modal-visor > footer .btn-copiar-ruta .mdi { font-size: 14px; }
.modal-visor > footer:hover .btn-copiar-ruta,
.modal-visor > footer .btn-copiar-ruta:focus-visible { visibility: visible; opacity: 1; }
/* El tooltip, ARRIBA y no a la izquierda. El de la tabla sale a la izquierda porque sus
   botones viven pegados al borde derecho; este vive pegado al izquierdo, así que por ahí
   se salía del modal y se leía cortado («…uta del archivo»). */
.modal-visor > footer .btn-copiar-ruta::after {
  right: auto;
  left: 0;
  top: auto;
  bottom: calc(100% + 6px);
  transform: none;
}
/* Las horas del documento, en el pie del visor: la etiqueta pequeña y tenue, el número
   con el color del texto, y el total destacado, como en la tabla. */
.horas-visor { display: flex; align-items: baseline; gap: 14px; white-space: nowrap; }
.hora-fase { display: inline-flex; align-items: baseline; gap: 5px; }
.hora-etiqueta { font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.hora-valor { font-size: 13px; color: var(--text); font-variant-numeric: tabular-nums; }
.hora-total .hora-valor { font-weight: 700; }
.hora-valor.horas-combinadas { text-decoration: underline dotted; text-underline-offset: 3px; cursor: help; }
/* Y por lo mismo, el encabezado y el pie del documento no llevan nada del encabezado ni del pie
   de un modal (`.modal header`, `.modal footer`): son contenido del Word, no controles de la app.
   El `display: flex` de `.modal footer` ponía sus dos renglones uno al lado del otro y a la
   derecha, en vez de centrados y uno debajo del otro como en Word. */
.modal .visor-word header,
.modal .visor-word footer {
  display: block;
  gap: 0;
  justify-content: normal;
  flex: none;
  padding: 0;
  border: 0;
  font-weight: inherit;
}

/* El contenido de la tarjeta, separado de sus bordes y de la cabecera. */
.cuerpo-docs { display: flex; flex-direction: column; gap: 14px; padding: 0 16px 16px; }

/* Los filtros en una fila que se parte cuando no cabe: el buscador manda y se lleva
   el espacio sobrante, los demás se quedan en su ancho. */
.filtros { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }
.filtros .field { min-width: 0; }
.filtros .campo-buscar { flex: 1 1 260px; }
.filtros .acciones-filtro { display: flex; flex-direction: row; align-items: center; gap: 8px; }

.fila-buscar { display: flex; gap: 8px; align-items: center; }
.fila-buscar input { flex: 1 1 auto; min-width: 0; }
.fila-ruta { display: flex; gap: 8px; align-items: center; }
.fila-ruta input { flex: 1 1 auto; min-width: 0; }

.doc-ticket { border-top: 1px solid var(--border); }
.doc-cabecera {
  display: flex;
  align-items: baseline;
  gap: 10px;
  width: 100%;
  padding: 7px 4px;
  border: 0;
  background: none;
  text-align: left;
}
.doc-cabecera:hover { background: var(--accent-soft); }
.doc-id { flex: 0 0 92px; color: var(--accent); font-weight: 600; }
.doc-titulo { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.doc-cuerpo { display: flex; flex-direction: column; gap: 6px; padding: 4px 4px 12px 96px; }
.doc-archivo { display: flex; align-items: center; gap: 10px; }
.doc-nombre { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.explorador { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; padding: 8px; border: 1px solid var(--border-strong); border-radius: var(--radius); }
.explorador-ruta { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.explorador-lista { display: flex; flex-direction: column; max-height: 220px; overflow-y: auto; }
.explorador-item { padding: 4px 6px; border: 0; border-radius: 4px; background: none; text-align: left; white-space: nowrap; }
.explorador-item:hover { background: var(--accent-soft); }

/* ---------------------------------------------------------------- badges */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}
.badge.prod { background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger); }
.badge.ok { background: var(--neutral-bg); color: var(--ok); }
.badge.off { background: var(--neutral-bg); color: var(--muted); }

.v-COINCIDE { background: var(--neutral-bg); color: var(--ok); }
.v-NO_ENCONTRADA { background: var(--neutral-bg); color: var(--muted); }
.v-DIFIERE { background: var(--warn-bg); color: var(--warn); }
.v-SOLO_CMS, .v-SOLO_P2H { background: var(--info-bg); color: var(--info); }
.v-ERROR, .v-ERROR_PARCIAL { background: var(--danger-bg); color: var(--danger); }

/* ---------------------------------------------------------------- alerts */

.alert { padding: 8px 10px; border-radius: 4px; font-size: 12px; border: 1px solid; }
.alert.warn { background: var(--warn-bg); color: var(--warn); border-color: var(--warn); }
.alert.danger { background: var(--danger-bg); color: var(--danger); border-color: var(--danger); }
.alert.info { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }
.alert.success { background: color-mix(in srgb, var(--ok) 12%, var(--panel)); color: var(--ok); border-color: var(--ok); }

/* ---------------------------------------------------------------- progress */

.bar { height: 8px; background: var(--neutral-bg); border-radius: 999px; overflow: hidden; }
.bar > span { display: block; height: 100%; background: var(--accent); transition: width 0.3s; }

/* Barra del lote actual: más fina y tenue, para no competir con la del total. */
.bar.thin { height: 4px; }
.bar.thin > span { background: var(--muted); }

.counters { display: flex; flex-wrap: wrap; gap: 6px; }
.counter {
  background: var(--neutral-bg);
  border-radius: 4px;
  padding: 5px 9px;
  min-width: 74px;
}
.counter b { display: block; font-size: 15px; font-variant-numeric: tabular-nums; }
.counter span { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.03em; }
.counter.bad b { color: var(--danger); }
.counter.mismatch b { color: var(--warn); }

/* ---------------------------------------------------------------- table */

.table-wrap { overflow-x: auto; border-top: 1px solid var(--border); }
table { border-collapse: collapse; width: 100%; font-size: 12px; }
th, td { padding: 5px 8px; text-align: left; border-bottom: 1px solid var(--border); white-space: nowrap; }
th { background: var(--neutral-bg); font-size: 10px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); position: sticky; top: 0; }
/* Inside a MODAL a header sticks only within its own scroll box. Otherwise the scrolling
   ancestor is the modal's body, and the header of a table halfway down stayed glued to its
   top, painted over the cards scrolling under it (the references modal) */
.modal th { position: static; }
.modal .tabla-scroll th, .modal .table-wrap th { position: sticky; top: 0; z-index: 1; }
tbody tr:hover { background: var(--accent-soft); }
td.num { font-variant-numeric: tabular-nums; }
td.motivo { white-space: normal; min-width: 260px; color: var(--muted); }

.pager { display: flex; align-items: center; gap: 8px; padding: 8px 12px; }

/* ---------------------------------------------------------------- modal */

.backdrop {
  position: fixed; inset: 0; background: rgba(0, 0, 0, 0.45);
  display: flex; align-items: center; justify-content: center; z-index: 50; padding: 16px;
}
/* El body/footer pueden ser hijos directos o venir dentro del <form> de una pestaña
   (Ajustes → Usuario): por eso descendiente y no `>`. */
/* Columna con alto ACOTADO: la cabecera y el pie se quedan fijos y el cuerpo es lo
   único que scrollea. Sin esto, un modal largo —el árbol de permisos son ochenta filas—
   crecía más que la pantalla y se llevaba los botones de Guardar fuera de la vista,
   obligando a scrollear la página entera para encontrarlos. */
.modal {
  background: var(--panel); border-radius: 8px; width: 100%; max-width: 460px;
  border: 1px solid var(--border);
  display: flex; flex-direction: column;
  max-height: calc(100vh - 64px);
}
.modal header { padding: 12px 14px; border-bottom: 1px solid var(--border); font-weight: 600; flex: none; }
.modal .body {
  padding: 14px; display: flex; flex-direction: column; gap: 10px;
  /* `min-height: 0` es lo que deja encoger a un hijo de flex por debajo de su contenido;
     sin él, el cuerpo se niega a scrollear y empuja al contenedor. */
  overflow-y: auto; min-height: 0;
}
.modal footer { padding: 12px 14px; border-top: 1px solid var(--border); display: flex; gap: 8px; justify-content: flex-end; flex: none; }
/* A modal whose body and footer live inside a <form>: the form takes the modal's place in the
   column, so the BODY scrolls and the footer stays in view (without this a long form spilled
   below the modal and its buttons went out of sight — the user form, 15-10-2026) */
.modal > form { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.modal > form > .body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
/* A save error shown right above the footer, outside the scrolling body, so it is seen
   whatever part of the form was on screen when the button was pressed */
.modal .modal-aviso { flex: none; margin: 0 14px 12px; }
/* The installation's version, pushed to the left of the Settings footer */
.modal footer .app-version { margin-right: auto; align-self: center; color: var(--muted); font-size: 12px; }
.modal.modal-wide { max-width: 640px; }
.modal.modal-xl { max-width: 820px; } /* el editor de mapeos necesita aire */

/* --------------------------------------------------------------- codemirror
   Editor del tab «Mapeo de Respuesta» (CodeMirror 5, vendorizado). Se tematiza con
   las variables de la app para que siga el modo claro/oscuro sin un theme extra. */
.cm-host .CodeMirror {
  height: 340px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
}
.cm-host .CodeMirror-gutters { background: var(--neutral-bg); border-right: 1px solid var(--border); }
.cm-host .CodeMirror-linenumber { color: var(--muted); }
.cm-host .CodeMirror-cursor { border-left: 1px solid var(--text); }
.cm-host .CodeMirror-selected { background: var(--accent-soft); }
.cm-host .CodeMirror-focused .CodeMirror-selected { background: var(--accent-soft); }
.cm-host .cm-string { color: var(--ok); }
.cm-host .cm-number, .cm-host .cm-atom { color: var(--info); }
.cm-host .cm-property { color: var(--accent); }
/* Solo lectura (v1): se nota a simple vista que no es editable. */
.cm-host .CodeMirror-readonly, .cm-host .CodeMirror[class*="nocursor"] { opacity: 0.8; }

.tabs.profile-tabs { padding: 0; border-bottom: 1px solid var(--border); }
.tab.tab-add { color: var(--accent); }
.profile-meta { min-height: 16px; }

/* Botón de pegar flotando sobre el editor, sin robarle espacio. */
.cm-wrap { position: relative; }
.cm-paste {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 5;
  display: inline-flex;
  align-items: center;
  padding: 5px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--panel);
  color: var(--muted);
  cursor: pointer;
}
.cm-paste:hover { color: var(--accent); border-color: var(--accent); }

/* Encabezado con la X de cierre alineada a la derecha del título. */
.modal-header { display: flex; align-items: center; justify-content: space-between; }
/* The modals' «×»: a 32 px target with a 24 px cross, easy to hit; a soft square on hover */
.modal-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 8px;
  background: none;
  padding: 0;
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  color: var(--muted);
  transition: background .15s, color .15s;
}
.modal-close .mdi { font-size: 20px; }
.modal-close:hover { color: var(--text); background: color-mix(in srgb, currentColor 10%, transparent); }

/* Pestañas del modal de Ajustes. */
.tabs { display: flex; gap: 2px; padding: 0 14px; border-bottom: 1px solid var(--border); }
.tab {
  padding: 9px 14px;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  background: none;
  color: var(--muted);
}
.tab:hover:not(:disabled) { color: var(--text); border-color: var(--border-strong); }
.tab.active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }

/* Subtítulos de sección dentro de una pestaña («Información general», …). */
.settings-subtitle {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 4px;
}
/* Tarjeta del usuario logueado (Ajustes → Usuario). */
.user-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--neutral-bg);
}
.user-avatar {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  font-size: 17px;
  letter-spacing: 0.03em;
  flex: 0 0 auto;
}
.user-name { font-size: 15px; font-weight: 600; }
.user-handle { font-size: 12px; color: var(--muted); }
.user-details { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.user-detail {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 9px 11px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  min-width: 0;
}
.user-detail svg { color: var(--muted); margin-top: 2px; flex: 0 0 auto; }
.user-detail > div { min-width: 0; overflow-wrap: anywhere; }

button.with-icon { display: inline-flex; align-items: center; gap: 6px; }

/* Chip de "qué configuración está aplicada" en el panel Ejecutar. */
.config-chip { display: flex; align-items: center; gap: 6px; }
.config-chip svg { color: var(--muted); flex: 0 0 auto; }
.config-dirty { color: var(--warn); }

/* Contraseña con ojo: el botón vive DENTRO del input, sin robarle ancho al texto. */
.pass-field { position: relative; }
.pass-field input { padding-right: 32px; }
.pass-toggle {
  position: absolute;
  right: 3px;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  border: 0;
  background: none;
  padding: 2px 6px;
  line-height: 1;
  cursor: pointer;
  color: var(--muted);
}
.pass-toggle:hover { color: var(--text); }
.pass-toggle svg { display: block; }

/* ---------------------------------------------------------------- toasts */

.toasts { position: fixed; right: 14px; bottom: 14px; display: flex; flex-direction: column; gap: 8px; z-index: 60; max-width: 380px; }
.toast { display: flex; align-items: flex-start; gap: 8px; padding: 9px 12px; border-radius: 5px; font-size: 12px; border: 1px solid; box-shadow: 0 3px 12px rgba(0, 0, 0, 0.16); background: var(--panel); }
.toast.error { border-color: var(--danger); color: var(--danger); }
.toast.info { border-color: var(--accent); color: var(--accent); }
/* `warn` ya se usaba sin regla y salía con el borde por defecto: un aviso que no se
   distingue de una confirmación es un aviso que nadie lee. */
.toast.warn { border-color: var(--warn); color: var(--warn); }
.toast-enlace { color: inherit; font-weight: 600; text-decoration: underline; }
/* El cuerpo del aviso: texto plano, o un botón/enlace cuando lleva a algún sitio (02-11-2026).
   Un aviso clicable se nota: cursor, subrayado punteado que se vuelve sólido al pasar, y «→». */
.toast-cuerpo { flex: 1; min-width: 0; margin: 0; padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: left; line-height: 1.4; overflow-wrap: anywhere; }
.toast-con-destino .toast-cuerpo { cursor: pointer; text-decoration: underline dotted; text-underline-offset: 3px; }
.toast-con-destino .toast-cuerpo:hover, .toast-con-destino .toast-cuerpo:focus-visible { text-decoration-style: solid; }
.toast-con-destino .toast-cuerpo:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; border-radius: 3px; }
.toast-flecha { margin-left: 5px; font-weight: 600; }
/* El × solo cierra, nunca navega */
.toast-cerrar { flex: none; margin: -2px -4px 0 0; padding: 0 4px; border: 0; background: none; color: inherit; font: inherit; font-size: 15px; line-height: 1; opacity: 0.65; cursor: pointer; border-radius: 3px; }
.toast-cerrar:hover, .toast-cerrar:focus-visible { opacity: 1; }

/* ---------------------------------------------------------------- sweetalert2 */

/* SweetAlert2 expone sus propias variables CSS, así que se tematiza apuntándolas a las
   de la app en vez de sobrescribir sus clases con `!important`.
 *
 * Se declaran en `body` y NO en `:root`: SweetAlert las define en su propio `:root`
 * (`--swal2-background: white`) y su hoja de estilos se inyecta DESPUÉS de esta, así
 * que con la misma especificidad ganaría la suya. Como el popup se monta dentro de
 * `body`, este es un ancestro más cercano y sus valores prevalecen sin depender del
 * orden de carga. */
body {
  --swal2-background: var(--panel);
  --swal2-color: var(--text);
  --swal2-border: 1px solid var(--border);
  --swal2-border-radius: 8px;
  --swal2-backdrop: rgba(0, 0, 0, 0.55);
  --swal2-width: 28rem;

  --swal2-input-background: var(--panel);
  --swal2-input-border: 1px solid var(--border-strong);
  --swal2-input-border-radius: 4px;
  --swal2-input-box-shadow: none;
  --swal2-input-focus-box-shadow: none;
  --swal2-input-focus-border: 1px solid var(--accent);

  --swal2-validation-message-background: var(--danger-bg);
  --swal2-validation-message-color: var(--danger);
  --swal2-actions-width: 100%;
  --swal2-actions-justify-content: flex-end;
  --swal2-actions-padding: 0 1.5rem 1.25rem;
  --swal2-footer-background: var(--panel);
  --swal2-footer-color: var(--muted);
  --swal2-footer-border-color: var(--border);
}

/* `body .x` (0,1,1) gana a `.x` (0,1,0) aunque su CSS se cargue después.
   El objetivo es que el diálogo parezca un `.modal` más de la app: título a la
   izquierda con borde inferior, cuerpo denso alineado a la izquierda y una fila de
   acciones separada por borde superior — nada del centrado gigante por defecto. */
body .swal2-popup { font: inherit; padding: 0; text-align: left; }
body .swal2-title {
  font-size: 14px;
  font-weight: 600;
  text-align: left;
  justify-content: flex-start;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
body .swal2-html-container {
  font-size: 13px;
  color: var(--muted);
  text-align: left;
  margin: 0;
  padding: 12px 14px 0;
}
/* `body .swal2-popup .swal2-input` (0,2,1) y no `body .swal2-input` (0,1,1): SweetAlert
   trae `div:where(.swal2-container) .swal2-input { padding: 0 .75em; height: 2.625em }`,
   que empata en especificidad y gana por orden de carga. Con el ancho pasa lo mismo:
   `width:auto` deja que el input se estire dentro de la rejilla del popup respetando
   sus márgenes, que es justo lo que evita que se salga. */
body .swal2-popup .swal2-input {
  color: var(--text);
  margin: 10px 14px 0;
  width: auto;
  height: auto;
  font-size: 13px;
  padding: 6px 8px;
}
body .swal2-icon { display: none !important; } /* el título ya dice qué pasa; el icono gigante no aporta */
body .swal2-actions {
  gap: 8px;
  margin: 12px 0 0;
  padding: 12px 14px;
  border-top: 1px solid var(--border);
}
body .swal2-validation-message { margin: 10px 14px 0; font-size: 12px; justify-content: flex-start; }

/* Botón de confirmación de una acción de riesgo: rojo sólido, no el azul de acción normal. */
button.danger-solid {
  padding: 6px 12px;
  border: 1px solid var(--danger);
  border-radius: 4px;
  background: var(--danger);
  color: #fff;
  font-weight: 600;
  cursor: pointer;
}

.dropzone {
  border: 2px dashed var(--border-strong);
  border-radius: var(--radius);
  padding: 18px;
  text-align: center;
  cursor: pointer;
  color: var(--muted);
}
.dropzone.over { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }

.cond-row { display: grid; grid-template-columns: 1fr 1.2fr 1fr auto; gap: 6px; align-items: center; }
/* Condicional de salida: campo · tipo (fijo/columna) · operador · valor · ✕ */
.cond-row-out { display: grid; grid-template-columns: 1.3fr 0.9fr 1.1fr 1fr auto; gap: 6px; align-items: center; margin-top: 6px; }

/* Separa los bloques Entrada / Salida dentro del mismo expandible de Condicionales. */
.section-divider { border: 0; border-top: 1px solid var(--border); margin: 14px 0 2px; }

/* Mapeos: un bloque por cada { column, active, values } */
.mapping { border: 1px solid var(--border); border-radius: var(--radius); margin-top: 8px; }
.mapping-head {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 8px;
  align-items: center;
  padding: 7px 9px;
  background: var(--neutral-bg);
  border-bottom: 1px solid var(--border);
  border-radius: var(--radius) var(--radius) 0 0;
}
.mapping-head .check { white-space: nowrap; }
.mapping-body { padding: 9px; display: flex; flex-direction: column; gap: 6px; }
.mapping-body.off { opacity: 0.45; }
.map-row { display: grid; grid-template-columns: 90px 1fr auto; gap: 6px; align-items: center; }

/* Cita de la agenda: una tarjeta pulsable que abre su módulo en MP.
   Es un `button` y no un `div` con `@click` para que llegue por teclado y se anuncie
   como lo que es: una acción. */
.cita {
  display: flex;
  align-items: baseline;
  gap: 10px;
  width: 100%;
  text-align: left;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel);
}
.cita:hover:not(:disabled) { border-color: var(--accent); background: var(--accent-soft); }
.cita:disabled { opacity: 0.6; cursor: default; }
.cita-hora {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: 12px;
  white-space: nowrap;
  color: var(--accent);
}
.cita-datos { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.cita-paciente { font-size: 13px; overflow: hidden; text-overflow: ellipsis; }

/* Fila de acciones de un formulario embebido en una tarjeta (no en un modal): separada
   del último campo y pegada a la derecha, como el pie de los diálogos. */
.form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 14px;
}

/* Pares a comparar: [#n] [campo P2H] vs [campo CMS] [quitar] */
.vs-head, .vs-row {
  display: grid;
  grid-template-columns: 28px 1fr 22px 1fr auto;
  gap: 6px;
  align-items: center;
}
.vs-head {
  margin-top: 8px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
}
.vs-row { margin-top: 6px; }
/* Par que su configuración no puede evaluar: se ve, pero se ve que no cuenta. */
.vs-row.off { opacity: 0.45; }
.vs-n { font-size: 11px; color: var(--muted); text-align: center; }
.vs-sep { font-size: 11px; color: var(--muted); text-align: center; }

/* Columnas de salida: [título en el Excel] [key de la respuesta] [quitar] */
.col-row { display: grid; grid-template-columns: 1fr 1.1fr auto; gap: 6px; align-items: center; margin-top: 6px; }
.col-row input.dupe { border-color: var(--danger); }

/* «Generar órdenes» → estudios de la cita abierta en MP. */
.mp-cita {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 24px;
  margin-bottom: 10px;
}
.mp-cita > div { display: flex; flex-direction: column; gap: 2px; }


/* Sugerencias del catálogo de diagnósticos de MP: una lista pulsable bajo el campo. */
.sugerencias {
  display: flex;
  flex-direction: column;
  max-height: 220px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 4px;
}
.sugerencias > button {
  display: flex;
  gap: 10px;
  align-items: baseline;
  text-align: left;
  border: 0;
  border-radius: 0;
  background: transparent;
  padding: 6px 8px;
  font-size: 12px;
}
.sugerencias > button:hover { background: var(--accent-soft); }
.sugerencias > button + button { border-top: 1px solid var(--border); }
.sugerencias .mono { min-width: 74px; color: var(--muted); }

/* Selector de tipo dentro de una tarjeta (órdenes de laboratorio/imagen/procedimiento). */
.subbar-inline { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 4px; }

/* El estudio ocupa lo que haya; la cantidad, lo justo. */
.fila-estudio { display: flex; gap: 10px; align-items: flex-start; }
.fila-estudio > .field:first-child { flex: 1; min-width: 0; }

/* Un bloque que todavía está trayendo lo suyo: la barra avanza sola para que se note
   que la app trabaja, y el texto dice EN QUÉ, que es lo que quita la ansiedad. */
.cargando {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  color: var(--muted);
  padding: 2px 0;
}
.cargando-barra {
  flex: 0 0 90px;
  height: 4px;
  border-radius: 999px;
  background: var(--neutral-bg);
  overflow: hidden;
  position: relative;
}
.cargando-barra::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 40%;
  border-radius: inherit;
  background: var(--accent);
  animation: cargando-va 1.1s ease-in-out infinite;
}
@keyframes cargando-va {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(250%); }
}
/* Quien prefiere no ver animaciones ve una barra quieta, no una barra rota. */
@media (prefers-reduced-motion: reduce) {
  .cargando-barra::after { animation: none; width: 100%; opacity: 0.5; }
}

/* ── Herramienta «Sistema» ─────────────────────────────────────────────────────
   Menú lateral fijo y cuerpo con su propio scroll: las secciones son listas que
   crecen (usuarios, corridas) y sin esto el menú se iba hacia arriba al bajar.

   Alto dinámico, como en Documentación, pero por otro camino: allí se calcula CUÁNTAS
   filas caben porque la tabla es lo único que hay y se pagina; aquí la sección mezcla
   fichas y tablas —y un dashboard no se pagina—, así que la tarjeta ocupa la pantalla
   y lo que sobra se desplaza dentro. El 134px es donde empieza el cuerpo (barra
   superior más cabecera de la tarjeta) y los 12 restantes son el aire de abajo. */
/* El alto sale de lo que miden las barras, no de un número a mano: `--topbar-h` la mide
   `AppRoot` con un ResizeObserver, así que cuadra aunque las barras se partan en dos líneas.
   Va en la TARJETA y con `border-box` (15-10-2026): puesto en `.sistema`, el borde de la
   tarjeta sumaba 2px a la página, y eso bastaba para que el documento entero hiciera scroll
   y la cabecera fija se moviera. */
.card-sistema {
  display: flex; box-sizing: border-box;
  height: calc(100vh - var(--topbar-h));
  min-height: 320px;
}
.sistema {
  display: flex; align-items: stretch;
  flex: 1; min-height: 0; min-width: 0;
}

/* The side column holds the menu and, pinned at its foot, the app version (AppVersionFooter `menu`) */
.sistema-lateral {
  display: flex; flex-direction: column;
  width: 190px; flex: none; min-height: 0;
  border-right: 1px solid var(--border);
}
.sistema-menu {
  display: flex; flex-direction: column; gap: 2px;
  flex: 1; padding: 12px 8px;
  /* Con varias ramas abiertas el menú es más alto que la pantalla: se desplaza solo, en vez
     de alargar la página */
  overflow-y: auto; min-height: 0;
}
.sistema-opcion {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; border: 1px solid transparent; border-radius: 6px;
  background: none; color: var(--muted); font-size: 13px; text-align: left; cursor: pointer;
}
.sistema-opcion:hover { color: var(--text); background: var(--accent-soft); }
.sistema-opcion.activa {
  color: var(--accent); background: var(--accent-soft); border-color: var(--accent);
  font-weight: 600;
}
.sistema-opcion .mdi { font-size: 18px; line-height: 1; }
/* The menu is a tree: each depth (`--nivel`) indents one step, and a branch
   (Parametrización, Documentación) unfolds its entries with the chevron. */
.sistema-opcion { padding-left: calc(10px + var(--nivel, 0) * 16px); }
.sistema-rama .sistema-chevron { margin-left: auto; font-size: 16px; }

/* Parametrización: the catalog entry modal */
.modal.modal-catalogo { width: 100%; max-width: 720px; }
.modal.modal-equipo { max-width: 640px; }
/* The team's header brand, under its name and order (BrandSettings) */
.modal-equipo .equipo-marca { border-top: 1px solid var(--border); padding-top: 14px; }

/* Azure DevOps: the token of an account (Administración → Usuarios) and the attach modal */
.modal.modal-devops { width: 100%; max-width: 560px; }
.devops-status {
  display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--neutral-bg);
}
.devops-status > .mdi { font-size: 22px; line-height: 1; color: var(--muted); }
.devops-status.connected > .mdi { color: var(--ok, #1a7f45); }
.devops-status strong { display: block; }
.btn-ver.devops-connected .mdi { color: var(--brand); }
/* «Integraciones» of an account (account menu and Administración → Usuarios): one section per
   integration (Azure DevOps, Jira), each with its own save and remove; none is required */
.integracion-seccion { border: 1px solid var(--border); border-radius: var(--radius); padding: 12px; }
.integracion-titulo { margin: 0 0 10px; font-size: 14px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.integracion-cuerpo { display: flex; flex-direction: column; gap: 10px; }
.integracion-acciones { display: flex; align-items: center; gap: 8px; }
.integracion-acciones .spacer { flex: 1; }
.devops-status.aviso { border-color: var(--warn); background: var(--warn-bg); }
.devops-status.aviso > .mdi { color: var(--warn); }
.devops-status .hint { display: block; }
/* Jira's secondary way in (the e-mail + API token), folded under «Conectar con Atlassian» */
.integracion-alternativa { border-top: 1px dashed var(--border); padding-top: 8px; }
.integracion-alternativa > summary { cursor: pointer; font-size: 13px; color: var(--muted); }
.integracion-alternativa[open] > summary { margin-bottom: 8px; }
/* «Integraciones» in two columns (23-10-2026): on the left each integration with its state dot,
   on the right the chosen one; on a narrow screen the left column goes on top as tabs */
.modal.modal-integraciones { max-width: 980px; width: 100%; }
.modal-integraciones .integraciones-cuerpo { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 0; padding: 0; min-height: 460px; }
.integraciones-nav { display: grid; align-content: start; gap: 4px; padding: 12px; border-right: 1px solid var(--border); background: var(--neutral-bg); }
.integraciones-item {
  display: grid; grid-template-columns: 26px minmax(0, 1fr) auto; gap: 8px; align-items: center; text-align: left;
  padding: 10px; border: 0; border-radius: var(--radius); background: transparent; color: inherit; cursor: pointer; font: inherit;
}
.integraciones-item:hover { background: color-mix(in srgb, var(--brand) 8%, transparent); }
.integraciones-item.activo { background: color-mix(in srgb, var(--brand) 16%, transparent); }
.integraciones-item > .mdi { font-size: 20px; color: var(--muted); }
.integraciones-item.activo > .mdi { color: var(--brand); }
.integraciones-item-texto { display: grid; min-width: 0; }
.integraciones-item-texto > span { font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.integraciones-punto { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); }
.integraciones-punto.ok { background: var(--ok); }
.integraciones-punto.warn { background: var(--warn); }
.integraciones-panel { padding: 16px 20px; display: grid; gap: 14px; align-content: start; min-width: 0; }
.integraciones-panel .integracion-seccion { border: 0; padding: 0; }
.integraciones-panel .integracion-titulo { font-size: 17px; }
.integraciones-pie { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.integracion-estado { align-items: center; }
.integracion-estado-texto { flex: 1; min-width: 0; }
.integracion-estado-acciones { display: inline-flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
/* «Tokens personales»: the form, the token shown once and its table */
.tokens-form { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 10px; align-items: end; padding: 12px; border: 1px dashed var(--border); border-radius: var(--radius); }
.tokens-form .field { margin: 0; display: grid; gap: 4px; font-size: 12px; color: var(--muted); }
.tokens-seg { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
.tokens-seg > button { padding: 7px 10px; font: inherit; font-size: 12px; border: 0; border-right: 1px solid var(--border); background: transparent; color: var(--text, inherit); cursor: pointer; }
.tokens-seg > button:last-child { border-right: 0; }
.tokens-seg > button.activo { background: var(--brand); color: #fff; }
.tokens-nuevo { display: grid; gap: 8px; padding: 12px; border: 1px solid var(--ok); border-radius: var(--radius); background: color-mix(in srgb, var(--ok) 8%, var(--panel)); }
.tokens-nuevo > b .mdi { color: var(--ok); }
.tokens-copiar { display: flex; gap: 8px; align-items: center; min-width: 0; }
.tokens-copiar > code { flex: 1; min-width: 0; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tokens-copiar > .btn { flex: none; white-space: nowrap; }
.tabla-tokens-personales .col-acciones { white-space: nowrap; text-align: right; }
.tabla-tokens-personales .chip-estado-correo { white-space: nowrap; }
.tabla-tokens-personales .chip-estado-correo.err { color: var(--danger); background: color-mix(in srgb, var(--danger) 12%, transparent); }
@media (max-width: 720px) {
  .modal-integraciones .integraciones-cuerpo { grid-template-columns: minmax(0, 1fr); min-height: 0; }
  .integraciones-nav { display: flex; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--border); padding: 8px; }
  .integraciones-item { flex: none; grid-template-columns: 22px auto auto; }
  .integraciones-item-texto > span { display: none; }
  .integraciones-panel { padding: 14px; }
  .tokens-form { grid-template-columns: minmax(0, 1fr); }
  .integracion-estado { flex-wrap: wrap; }
}
.modal.modal-devops-attach { max-width: 720px; }
/* The attach modal's file explorer: one row per folder or file, indented by its level */
.devops-explorer {
  max-height: 300px; overflow-y: auto; padding: 4px 0;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel);
}
.devops-explorer > .hint { padding: 8px 12px; }
.devops-explorer-row {
  display: flex; align-items: center; gap: 6px; padding: 4px 10px 4px calc(10px + var(--level, 0) * 18px);
  font-size: 13px; cursor: pointer; min-width: 0;
}
.devops-explorer-row:hover { background: var(--neutral-bg); }
.devops-explorer-row .mdi { font-size: 16px; line-height: 1; color: var(--muted); }
.devops-explorer-row.folder > .mdi-folder-outline,
.devops-explorer-row.folder > .mdi-folder-open-outline { color: var(--brand); }
.devops-explorer-toggle { display: inline-flex; width: 18px; padding: 0; border: 0; background: transparent; cursor: pointer; }
.devops-explorer-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.devops-explorer-row input[type="checkbox"] { margin: 0; }
.chip.refs-devops-state { margin-left: 6px; font-size: 11px; cursor: help; }
.chip.refs-devops-state.sin-acceso { color: var(--muted); border-style: dashed; }
.devops-state-row { display: flex; gap: 8px; align-items: center; }
.devops-state-row select, .devops-state-row .person-picker { flex: 1; min-width: 0; }
.devops-wi-title { display: block; margin-top: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.devops-history-box { max-height: 200px; overflow-y: auto; border: 1px solid var(--border); border-radius: var(--radius); }
.devops-history-box .tabla-docs { width: 100%; font-size: 12px; }
.devops-history-box .nowrap { white-space: nowrap; }
.devops-history-file { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chip.devops-sent-ok { color: var(--ok); border-color: var(--ok); }
.chip.devops-sent-failed { color: var(--danger); border-color: var(--danger); cursor: help; }
.chip.devops-sent-skipped { color: var(--muted); border-color: var(--border-strong); border-style: dashed; cursor: help; }
.devops-sent { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
.btn-link.peligro { color: var(--danger); }
.btn-link.peligro:hover { border-color: var(--danger); }
/* Row 3 of the catalog form: Tipo (or the inventory value) and Orden side by side */
.catalogo-fila { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: end; }
.catalogo-fila .switch-seg { display: flex; }
.catalogo-fila .switch-seg button { flex: 1; }
.modal-catalogo .elegidos { margin-bottom: 6px; }
/* The preview: centred in its own soft panel, the chip as the filter paints it and, for
   a status, as the Estado column's selector */
.catalogo-preview {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 16px; border: 1px dashed var(--border-strong); border-radius: 10px;
  background: var(--neutral-bg);
}
.catalogo-preview-titulo { font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.catalogo-preview-muestras { display: flex; align-items: center; justify-content: center; gap: 14px; flex-wrap: wrap; }
.catalogo-preview-chip { font-size: 12px; padding: 5px 14px; min-width: 120px; }
.catalogo-preview-select { pointer-events: none; }
@media (max-width: 640px) { .catalogo-fila { grid-template-columns: 1fr; } }

/* Parametrización → Parámetros: a header that says what the section holds, the search
   on its own line, and an empty state instead of a bare table */
.param-encabezado { display: flex; align-items: center; gap: 12px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.param-encabezado-icono {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 40px; height: 40px; border-radius: 10px; background: var(--accent-soft); color: var(--accent); font-size: 22px;
}
.param-encabezado-texto { flex: 1; min-width: 0; }
.param-encabezado-texto h2 { margin: 0; font-size: 16px; font-weight: 600; color: var(--text); }
.param-encabezado-texto p { margin: 2px 0 0; }
.param-nuevo { flex: none; white-space: nowrap; }
.param-barra { align-items: center; gap: 12px; flex-wrap: wrap; row-gap: 10px; }
/* «Exportar a Excel» (components/ExportExcelButton.js): last in a history's filter bar, to the right */
.param-barra > .exportar-excel { margin-left: auto; flex: none; white-space: nowrap; }
.exportar-excel .mdi-microsoft-excel { color: var(--ok); }
.param-buscar {
  display: flex; align-items: center; gap: 6px; flex: 0 1 420px; min-width: 0;
  padding: 0 10px; border: 1px solid var(--border-strong); border-radius: 8px; background: var(--panel);
}
.param-buscar .mdi { color: var(--muted); font-size: 18px; }
/* The same `:not()` chain as the global input rule (specificity 0,3,1): without it that
   rule won and the field drew its own border and focus outline inside the box */
.param-buscar > input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(.swal2-input) {
  flex: 1; width: auto; min-width: 0; border: 0; border-radius: 0; outline: 0; background: transparent; padding: 8px 0;
}
.param-buscar > input:focus { outline: 0; }
.param-buscar:focus-within { border-color: var(--accent); }
.param-conteo { white-space: nowrap; }
.param-vacio {
  display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 48px 16px;
  border: 1px dashed var(--border-strong); border-radius: 10px; color: var(--text); text-align: center;
}
.param-vacio .mdi { font-size: 34px; color: var(--muted); }
.parametro-valor-celda { max-width: 420px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.modal.modal-parametro { width: 100%; max-width: 640px; }
.parametro-fila { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
/* Administración → Permisos: the read-only catalog, scrolling inside the screen's height */
.sistema-pantalla > .permisos-lista { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; }
.permiso.permiso-catalogo { cursor: default; }
.permiso-quien { margin-left: auto; display: inline-flex; align-items: center; gap: 10px; flex: none; }
.permiso-quien .chips { justify-content: flex-end; }
.permiso-usuarios { display: inline-flex; align-items: center; gap: 2px; font-size: 12px; color: var(--muted); min-width: 36px; justify-content: flex-end; }

/* Sistema → Históricos → Correos electrónicos */
.historico-filtro { width: auto; flex: none; padding: 7px 8px; border-radius: 8px; }
/* A free-text filter (e.g. «Ticket») grows and shrinks with the bar like a field, not the inputs' 100% */
.param-barra > input.historico-filtro { width: auto; flex: 1 1 10ch; min-width: 10ch; max-width: 22ch; }
.historico-fecha { white-space: nowrap; }
.historico-asunto { max-width: 360px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.historico-error { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 2px; }
/* Sistema → Históricos → Tickets and → DevOps: more filters, so the bar wraps; the ticket
   chip opens its detail; a non-person «Quién» (cron, CI, sync) is a chip; details unfold */
.historico-barra { flex-wrap: wrap; }
.historico-barra .param-buscar { flex: 1 1 280px; }
.historico-work-item { width: 120px; }
.chip-ticket.historico-ticket { cursor: pointer; font: inherit; font-size: 11px; color: var(--text); justify-self: start; }
.chip-ticket.historico-ticket:hover, .chip-ticket.historico-ticket:focus-visible { border-color: var(--accent); color: var(--accent); }
.historico-quien { white-space: nowrap; }
.historico-sistema { color: var(--text); }
.historico-resumen { min-width: 220px; max-width: 520px; white-space: normal; }
.historico-ver-detalle { display: inline-flex; align-items: center; gap: 2px; margin-left: 6px; font-size: 12px; }
.historico-detalle {
  display: grid; grid-template-columns: max-content 1fr; gap: 2px 10px; margin: 6px 0 0; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--bg); font-size: 12px;
}
.historico-detalle dt { color: var(--muted); font-weight: 600; }
.historico-detalle dd { margin: 0; color: var(--text); word-break: break-word; }
.historico-detalle dd.sin-etiqueta { grid-column: 1 / -1; }
.historico-work-item-enlace { white-space: nowrap; font-variant-numeric: tabular-nums; }
@media (max-width: 640px) {
  .historico-barra > .historico-filtro { flex: 1 1 140px; }
  .historico-resumen { min-width: 180px; }
}
/* Sistema → Históricos → WhatsApp: el mensaje de un envío, en su propio modal */
.modal-whatsapp-mensaje { max-width: 920px; width: 100%; }
/* The person a number belongs to, and the message's first lines (boceto historico-whatsapp) */
.whatsapp-persona .celda-doble > b { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.whatsapp-persona-sin { background: var(--chip-bg, rgba(127,127,127,.18)); color: var(--muted); }
.whatsapp-previa {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  max-width: 320px; color: var(--muted); font-size: 12.5px; line-height: 1.4;
}
/* The detail: the facts on the left, the phone on the right */
.whatsapp-detalle { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 22px; align-items: start; }
.whatsapp-ficha { display: grid; grid-template-columns: 110px minmax(0, 1fr); gap: 10px 8px; margin: 0; font-size: 13px; align-items: center; }
.whatsapp-ficha dt { color: var(--muted); font-weight: 600; }
.whatsapp-ficha dd { margin: 0; min-width: 0; word-break: break-word; }
.whatsapp-ficha dd.sin-etiqueta { grid-column: 1 / -1; }
.whatsapp-ficha-error { color: var(--danger); background: var(--danger-bg); border: 1px solid var(--danger); border-radius: 8px; padding: 8px 10px; font-size: 12.5px; }
/* WhatsApp's own dark look, the same in both themes: it is a picture of the phone */
.whatsapp-telefono { background: #0b141a; border-radius: 14px; padding: 14px; display: grid; gap: 6px; align-content: start; color: #e9edef; }
.whatsapp-chat-cabecera { display: flex; gap: 10px; align-items: center; font-size: 13px; padding: 2px 2px 10px; border-bottom: 1px solid #1f2c33; margin-bottom: 6px; }
.whatsapp-chat-cabecera .celda-doble > span { color: #8696a0; font-size: 11px; }
.whatsapp-chat-avatar { width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; background: #017fc3; color: #fff; flex: none; }
.whatsapp-burbuja { background: #1f2c33; border-radius: 0 10px 10px 10px; padding: 8px 10px 6px; font-size: 13.5px; line-height: 1.4; min-width: 0; }
.whatsapp-texto { overflow-wrap: anywhere; }
.whatsapp-documento { background: #18242b; border-radius: 6px; padding: 8px; display: flex; gap: 8px; align-items: center; margin-bottom: 8px; font-size: 12px; min-width: 0; }
.whatsapp-documento > .mdi { color: #2b7de9; font-size: 26px; }
.whatsapp-documento .celda-doble > b { overflow-wrap: anywhere; }
.whatsapp-documento .celda-doble > span { color: #8696a0; }
.whatsapp-encabezado { font-weight: 600; margin-bottom: 6px; }
.whatsapp-hora { text-align: right; color: #8696a0; font-size: 10.5px; margin-top: 4px; }
.whatsapp-botones { display: grid; gap: 4px; }
.whatsapp-boton { background: #1f2c33; color: #53bdeb; border-radius: 8px; padding: 9px; text-align: center; font-size: 13.5px; display: flex; gap: 6px; justify-content: center; align-items: center; }
.whatsapp-sin-mensaje { color: #8696a0; font-size: 12.5px; margin: 8px 2px; }
@media (max-width: 860px) { .whatsapp-detalle { grid-template-columns: 1fr; } }
.chip-estado-correo {
  display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 600;
  border: 1px solid currentColor;
}
.chip-estado-correo.sent { color: var(--accent); background: var(--accent-soft); }
.chip-estado-correo.failed { color: var(--danger, #c0392b); background: transparent; }
.chip-estado-correo.ok { color: var(--accent); background: var(--accent-soft); }
.chip-estado-correo.neutral { color: var(--muted, #61686f); background: transparent; }
.chip-estado-correo.skipped { color: var(--muted, #61686f); background: transparent; border-style: dashed; }
/* A header with its own action (Sincronizaciones → «Sincronizar ahora»): the button goes right */
.param-encabezado > .btn { margin-left: auto; flex: none; white-space: nowrap; }

/* A «Lista de correos» value: an input with «Agregar», and the addresses as removable pills */
.lista-correos { display: flex; flex-direction: column; gap: 8px; }
.lista-correos-agregar { display: flex; gap: 8px; align-items: stretch; }
.lista-correos-agregar > input { flex: 1; min-width: 0; }
.lista-correos-agregar > .btn { flex: none; white-space: nowrap; }
.lista-correos-error { color: var(--danger, #c0392b); }
.lista-correos .chip.correo {
  display: inline-flex; align-items: center; gap: 6px; cursor: default;
  font-family: var(--mono, Menlo, Consolas, monospace); font-size: 12px;
}
.lista-correos .chip-quitar {
  border: 0; background: none; padding: 0 2px; line-height: 1; font-size: 15px;
  color: var(--muted); cursor: pointer;
}
.lista-correos .chip-quitar:hover { color: var(--danger, #c0392b); }
.parametro-nombre { display: block; padding: 6px 0; }
.switch-parametro { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }
.modal-parametro textarea { width: 100%; }
/* The JSON value (CodeMirror, `JsonEditor.js`): its colours come from `.cm-host`; the height
   follows the text between ~12 and ~18 lines, then scrolls. */
.modal.modal-parametro.modal-json { max-width: 760px; }
.parametro-json .json-editor .CodeMirror { height: auto; }
.parametro-json .json-editor .CodeMirror-scroll { min-height: 216px; max-height: 324px; }
.parametro-json .json-editor-fallback { min-height: 216px; resize: vertical; font-family: var(--mono); font-size: 12px; }
.parametro-json-pie { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.parametro-json-pie .hint { flex: 1; }
.parametro-json-error { color: var(--danger, #c0392b); }
.btn-link.parametro-json-formatear { padding: 3px 8px; font-size: 12px; gap: 4px; }
/* WHATSAPP_TEMPLATES / CRON_SCHEDULES: one line per entry (state, key, description) under the editor */
/* A cron's header: what it does (its CRON_SCHEDULES description) and the «Apagado» notice */
.param-encabezado-texto p.cron-descripcion { margin: 4px 0 0; font-size: 13px; color: var(--text); }
.cron-apagado { color: var(--danger, #c0392b); }
@media (max-width: 640px) { .parametro-fila { grid-template-columns: 1fr; } }

/* The two colour pickers (fill and text) side by side; stacked on a narrow screen */
.catalogo-colores-fila { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.catalogo-colores-fila .color-picker { max-width: none; }
@media (max-width: 640px) { .catalogo-colores-fila { grid-template-columns: 1fr; } }
.catalogo-colores { display: flex; flex-wrap: wrap; gap: 6px; }
/* The catalog chips look like Documentation's filter chips (`.chip-tipo`: solid fill,
   white text, a ring around the picked one), all the same width like in its menu */
.chip-catalogo { display: inline-block; min-width: 104px; text-align: center; }

/* The colour picker (`ColorPicker.js`), shaped like Vuetify's `v-color-picker
   hide-inputs`: the saturation/value square over the hue, then swatch + hue bar */
.color-picker { display: flex; flex-direction: column; gap: 12px; width: 100%; max-width: 320px; }
/* The hue fill is set inline; the two gradients sit over it: white to the left, black below */
.color-picker-square { position: relative; height: 150px; border-radius: 6px; cursor: crosshair; touch-action: none; }
.color-picker-square::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
}
.color-picker-square::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(to top, #000, rgba(0, 0, 0, 0));
}
.color-picker-dot {
  position: absolute; z-index: 1; width: 14px; height: 14px; margin: -7px 0 0 -7px;
  border: 2px solid #fff; border-radius: 50%; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35);
  pointer-events: none;
}
.color-picker-controls { display: flex; align-items: center; gap: 12px; }
.color-picker-bars { flex: 1; display: flex; flex-direction: column; gap: 14px; }
/* The checkerboard behind whatever can be transparent, so the transparency shows */
.color-picker-checker {
  background-color: #fff;
  background-image:
    linear-gradient(45deg, #ccc 25%, transparent 25%), linear-gradient(-45deg, #ccc 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #ccc 75%), linear-gradient(-45deg, transparent 75%, #ccc 75%);
  background-size: 8px 8px;
  background-position: 0 0, 0 4px, 4px -4px, -4px 0;
}
.color-picker-swatch {
  position: relative; flex: none; width: 32px; height: 32px; border-radius: 50%; overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
}
.color-picker-swatch > span { position: absolute; inset: 0; }
.color-picker-hue,
.color-picker-alpha {
  position: relative; height: 10px; border-radius: 999px; cursor: pointer; touch-action: none;
}
.color-picker-hue { background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00); }
.color-picker-alpha-fill { position: absolute; inset: 0; border-radius: inherit; }
.color-picker-alpha:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.color-picker-thumb {
  position: absolute; top: 50%; width: 14px; height: 14px; margin: -7px 0 0 -7px;
  border: 2px solid #fff; border-radius: 50%; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35);
  pointer-events: none;
}
.color-picker-square:focus-visible, .color-picker-hue:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.sistema-cuerpo {
  flex: 1; min-width: 0; padding: 14px 16px;
  display: flex; flex-direction: column; gap: 12px;
  overflow-y: auto;
}
/* A Sistema screen with a table (Usuarios) fills the body's height and the table takes
   what is left, like the documentation viewer: the table box is stretched by the layout,
   so its height is the room «Automático» measures (`useFitRows.js`), the rows stay at the
   top with the filler row taking the rest, and the pager sits at the bottom. */
.sistema-cuerpo > .sistema-pantalla { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 12px; }
.sistema-pantalla > .tabla-scroll { flex: 1; min-height: 0; }
.sistema-pantalla > .tabla-scroll > .tabla-docs { height: 100%; }
.sistema-pantalla > .paginacion { padding-top: 0; }
/* Parametrización → Documentación → Reglas (modules/docsRules): the text, or its editor, takes the
   whole height of the panel; monospaced, and the long lines wrap instead of scrolling sideways */
.reglas-docs-meta { margin: 0; display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.reglas-docs-texto {
  flex: 1; min-height: 0; overflow: auto; margin: 0; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: 6px; background: var(--neutral-bg);
  font-family: var(--mono); font-size: 12.5px; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; color: var(--text);
}
.reglas-docs-editor { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 10px; }
.reglas-docs-area {
  flex: 1; min-height: 240px; width: 100%; resize: none; padding: 12px 14px;
  font-family: var(--mono); font-size: 12.5px; line-height: 1.5; tab-size: 2;
}
.reglas-docs-pie { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.reglas-docs-nota { flex: 1; min-width: 240px; }
.reglas-docs-pie > .acciones { display: flex; gap: 8px; }
/* Horas de gestión fills the box the same way: its screen is exactly the body's height (not
   `min-height`, which would let the table push it down), the module takes what is left and
   its table the rest of that, with the filler row stretching and the pager at the bottom. */
.layout-ancho .cuerpo-docs > .pantalla-gestion { height: 100%; min-height: 0; padding-top: 16px; box-sizing: border-box; }
/* Its skeleton: the board's cards with the real ones' gap, and the table with ITS columns
   (Fecha, Tipo, Desde, Hasta, Horas, Ticket(s), Persona, Asunto, Registrado por, actions) */
.esqueleto-tarjetas.esqueleto-tarjetas-gestion { grid-template-columns: repeat(3, minmax(0, 1fr)); margin-bottom: 10px; }
.gestion-modulo > .esqueleto-tabla-gestion { flex: 1; min-height: 0; overflow: hidden; }
.esqueleto-tabla-gestion .esqueleto-fila {
  grid-template-columns: 0.9fr 1fr 0.5fr 0.5fr 0.4fr 0.8fr 1fr 2.6fr 1.6fr 64px;
}
.esqueleto-acciones { display: inline-flex; gap: 6px; justify-content: flex-end; }
.esqueleto-acciones .esqueleto-check { width: 26px; height: 26px; border-radius: 6px; }
.pantalla-gestion > .gestion-modulo { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.gestion-modulo > .tabla-scroll { flex: 1; min-height: 0; }
.gestion-modulo > .tabla-scroll > .tabla-docs { height: 100%; }
@media (max-width: 900px) {
  .layout-ancho .cuerpo-docs > .pantalla-gestion { height: auto; }
  .gestion-modulo > .tabla-scroll { flex: 0 0 auto; min-height: 240px; max-height: 70vh; }
  .gestion-modulo > .tabla-scroll > .tabla-docs { height: auto; }
  .esqueleto-tabla-gestion .esqueleto-fila { grid-template-columns: 1fr 1fr 0.6fr 0.6fr; }
  .esqueleto-tarjetas.esqueleto-tarjetas-gestion { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* La cabecera se queda a la vista al desplazar: una tabla larga sin encabezado obliga
   a subir para recordar qué columna era cuál. */
.sistema-cuerpo .tabla-docs thead th { position: sticky; top: 0; z-index: 1; }
.sistema-titulo {
  margin: 6px 0 0; font-size: 12px; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--muted);
}
/* El contador que dice cuántas se ven de cuántas hay: es un dato, no parte del título,
   así que no se lleva las mayúsculas ni la negrita. */
.sistema-titulo .hint {
  margin-left: 8px; text-transform: none; letter-spacing: 0; font-weight: 400;
}

/* Las cifras del Dashboard. `auto-fit` y no un número de columnas fijo: la app se usa
   tanto a pantalla completa como en media ventana junto al navegador de MP. */
.metricas { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; }
.metrica {
  display: flex; flex-direction: column; gap: 2px;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel);
}
.metrica-num { font-size: 26px; font-weight: 600; line-height: 1.1; color: var(--text); }
.metrica-eti { font-size: 12px; color: var(--text); }
.metrica-pie { font-size: 11px; color: var(--muted); }

/* ------------------------------------------------------------- System dashboard
   Chart colors as tokens, with their own dark steps (not an automatic flip). Single
   series use series-1; the run statuses use the fixed status palette, always next to
   their label in the legend and the tooltip. */
:root {
  --viz-series-1: #2a78d6;
  --viz-good: #0ca30c;
  --viz-warning: #fab219;
  --viz-critical: #d03b3b;
  --viz-neutral: #898781;
  --viz-grid: #e1e0d9;
  --viz-axis-text: #898781;
  /* Ticket types: the colors of their chips in Documentation. "Otro" is a mid gray,
     picked with the palette validator so it stays apart from the DevOps green next to it. */
  --viz-type-tl: var(--accent);
  --viz-type-devops: var(--ok);
  --viz-type-otro: #8a9199;
  --viz-type-estimacion: var(--info);
}
:root[data-theme="dark"]:not([data-presentacion]) {
  --viz-series-1: #3987e5;
  --viz-grid: #2c2c2a;
  --viz-type-otro: #6b737c;
}

.dash { display: flex; flex-direction: column; gap: 14px; }

.dash-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }
.dash-tile {
  display: flex; flex-direction: column; gap: 4px;
  padding: 14px 16px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel);
}
.dash-tile-label { font-size: 12px; color: var(--muted); }
.dash-tile-value { font-size: 30px; font-weight: 600; line-height: 1.1; color: var(--text); }
.dash-tile-foot { font-size: 11px; color: var(--muted); }

.dash-card {
  display: flex; flex-direction: column; gap: 10px; min-width: 0;
  padding: 14px 16px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel);
}
.dash-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.dash-card-title { margin: 0; font-size: 13px; font-weight: 600; color: var(--text); }
.dash-card-sub { margin: 2px 0 0; font-size: 11px; color: var(--muted); }

/* One series per row: the keys stack instead of running side by side. */
.dash-legend { display: flex; flex-direction: column; gap: 4px; margin: 0; padding: 0; list-style: none; font-size: 11px; color: var(--muted); }
.dash-legend li { display: inline-flex; align-items: center; gap: 6px; }
.dash-legend strong { color: var(--text); font-weight: 600; }
.dash-key { display: inline-block; width: 10px; height: 10px; border-radius: 3px; flex: none; }

/* The weekly chart: an SVG drawn in pixels at the card's measured width, so its text
   stays at 10 px however wide the card is. */
.dash-chart { position: relative; width: 100%; }
.dash-chart svg { display: block; overflow: visible; }
.dash-grid line { stroke: var(--viz-grid); stroke-width: 1; shape-rendering: crispEdges; }
.dash-grid text,
.dash-axis-label { font-size: 10px; fill: var(--viz-axis-text); font-variant-numeric: tabular-nums; }
.dash-cap { font-size: 10px; font-weight: 600; fill: var(--text); }
.dash-mark { transition: opacity 0.12s; }
.dash-mark.dim { opacity: 0.35; }
.dash-hit { fill: transparent; cursor: default; outline: none; }

.dash-tooltip {
  position: absolute; top: 0; transform: translateX(12px); pointer-events: none; z-index: 2;
  min-width: 170px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--panel); box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18); font-size: 11px; color: var(--text);
}
.dash-tooltip.flip { transform: translateX(calc(-100% - 12px)); }
.dash-tooltip-title { margin-bottom: 6px; font-weight: 600; }
.dash-tooltip-row { display: grid; grid-template-columns: 10px 1fr auto; align-items: center; gap: 8px; padding: 1px 0; color: var(--muted); }
.dash-tooltip-row strong { color: var(--text); font-variant-numeric: tabular-nums; }
.dash-tooltip-row.total { margin-top: 4px; padding-top: 5px; border-top: 1px solid var(--border); color: var(--text); }

/* Breakdowns: horizontal bars, one series, value at the tip. */
.dash-grid-3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; }
.dash-grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 12px; }
/* The three parts of the dashboard (users, documentation, runs), each under its heading */
.dash-section { display: flex; flex-direction: column; gap: 12px; }
.dash-section + .dash-section { margin-top: 10px; padding-top: 16px; border-top: 1px solid var(--border); }
.dash-section-title { margin: 0; }
/* Users: the two indicators and the roles card side by side */
.dash-users { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }
.dash-users .dash-users-roles { grid-column: span 2; }
@media (max-width: 720px) { .dash-users .dash-users-roles { grid-column: auto; } }
.dash-bars { display: flex; flex-direction: column; gap: 9px; margin: 0; padding: 0; list-style: none; }
.dash-bars li { display: grid; grid-template-columns: minmax(90px, 38%) 1fr; align-items: center; gap: 10px; font-size: 12px; }
.dash-bar-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.dash-bar-track { display: flex; align-items: center; gap: 8px; min-width: 0; }
.dash-bar {
  display: block; height: 10px; min-width: 2px; flex: none;
  background: var(--viz-series-1); border-radius: 0 4px 4px 0; /* square at the baseline */
  /* Room for the value at the tip, up to "5.643,85" */
  max-width: calc(100% - 72px);
}
.dash-bar-value { font-size: 11px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.dash-bars li:hover .dash-bar { filter: brightness(1.12); }

/* System status: one line of facts with state dots. */
.dash-status-row { display: flex; flex-wrap: wrap; gap: 8px 22px; font-size: 12px; color: var(--text); }
.dash-muted { color: var(--muted); margin-right: 4px; }
.dash-dot { display: inline-block; width: 8px; height: 8px; margin-right: 6px; border-radius: 50%; vertical-align: 1px; background: var(--viz-neutral); }
.dash-dot.good { background: var(--viz-good); }
.dash-dot.warn { background: var(--viz-warning); }
.dash-dot.bad { background: var(--viz-critical); }
.dash-table td { font-size: 12px; }

.ficha {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 6px 18px;
  padding: 10px 14px; border: 1px solid var(--border); border-radius: 8px; font-size: 12px;
}
.ficha-eti { color: var(--muted); margin-right: 6px; }
.ficha .ok { color: var(--ok, #3fb950); }
.ficha .aviso { color: var(--danger); }

.barra { display: flex; align-items: center; gap: 8px; }
.barra .spacer { flex: 1; }

.tabla-docs tr.ocupada { opacity: 0.55; pointer-events: none; }
.btn-ver.peligro:hover:not(:disabled) {
  color: var(--danger); border-color: var(--danger); background: var(--danger-bg);
}
.btn-ver:disabled { opacity: 0.35; cursor: default; }
/* A synchronized work item without documentation: its eye, download and ⋮ are off, but the
   tooltip saying why must read at full strength, so only the icon fades */
.btn-ver.sin-documentacion:disabled { opacity: 1; border-style: dashed; }
.btn-ver.sin-documentacion:disabled .mdi { opacity: 0.35; }
.btn-ver.sin-documentacion:disabled:hover { color: var(--muted); border-color: var(--border-strong); background: transparent; }

.yo {
  margin-left: 6px; padding: 1px 6px; border-radius: 10px;
  background: var(--accent-soft); color: var(--accent); font-size: 10px; font-weight: 600;
}
.estado { text-transform: capitalize; }
.estado.error { color: var(--danger); }
.estado.done { color: var(--ok, #3fb950); }

label.en-linea { flex-direction: row; align-items: center; gap: 8px; font-size: 12px; }
label.en-linea input { width: auto; margin: 0; }

/* Los grupos dentro del alta de usuario separan ambientes de herramientas. */
.modal .body > h4.sistema-titulo { margin: 8px 0 0; }

/* Resumen de permisos en la tabla de usuarios: etiquetas pequeñas en vez de una
   casilla por permiso, que hacía la fila más ancha que lo que informaba. */
.chips { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.chip {
  padding: 1px 7px; border-radius: 10px; font-size: 10px; white-space: nowrap;
  background: var(--accent-soft); color: var(--accent); border: 1px solid transparent;
}
.chip.admin { background: var(--danger-bg); color: var(--danger); border-color: var(--danger); }
/* El equipo de una cuenta en la tabla de usuarios. En neutro y no en el azul de los
   roles: comparten forma pero no significan lo mismo —uno dice qué puede hacer y el otro
   de quién es la cuenta— y teñirlos igual los haría leer como la misma cosa. */
.chip.equipo { background: var(--neutral-bg); color: var(--text); border-color: var(--border); }

/* ── Un campo con su acción al lado ────────────────────────────────────────────
   El selector de equipo y el `+` que abre su catálogo, o el nombre que se renombra y sus
   dos botones. El control ocupa lo que sobra y el botón se queda cuadrado: sin esto el
   `width: 100%` de los campos empujaba al botón fuera de la fila. */
.campo-con-boton { display: flex; align-items: center; gap: 6px; }
.campo-con-boton > input,
.campo-con-boton > select { flex: 1; min-width: 0; }
.campo-con-boton > .btn-ver { flex: none; }

/* ── El catálogo de equipos ────────────────────────────────────────────────────
   Se abre ENCIMA del alta o la edición de un usuario. Los dos son `position: fixed` con
   el mismo `z-index`, así que sin esto lo único que los separa es el orden del DOM. */
.backdrop.backdrop-encima { z-index: 60; }
.modal.modal-equipos { max-width: 520px; }
.lista-equipos { display: flex; flex-direction: column; }
.equipo-fila {
  display: flex; align-items: center; gap: 8px; min-height: 34px;
  padding: 4px 0; border-bottom: 1px solid var(--border);
}
.equipo-fila:last-child { border-bottom: 0; }
.equipo-fila.ocupada { opacity: 0.55; }
.equipo-fila .equipo-nombre { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* El recuento es un dato de servicio: explica por qué un equipo no se deja borrar. */
.equipo-fila .equipo-cuenta { flex: none; }
.equipo-fila .acciones { flex: none; display: flex; gap: 8px; }
.equipo-fila .campo-con-boton { flex: 1; min-width: 0; }

/* ── Modal de permisos ─────────────────────────────────────────────────────────
   Una fila por permiso, con interruptor: una lista de casillas sueltas no dejaba
   ver de un vistazo qué está concedido y qué no, que es lo único que se viene a
   mirar aquí. La fila entera es el control, no solo la casilla. */
.body-permisos { gap: 14px; max-height: min(72vh, 640px); overflow-y: auto; }

.grupo-permisos { display: flex; flex-direction: column; gap: 6px; }
.grupo-cabecera { display: flex; align-items: center; gap: 8px; }
.grupo-cabecera .spacer { flex: 1; }
.grupo-cabecera h4 {
  margin: 0; font-size: 11px; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
.grupo-cuenta {
  padding: 1px 7px; border-radius: 10px; font-size: 10px; font-weight: 600;
  background: var(--neutral-bg); color: var(--muted);
}
.grupo-cabecera .btn-link { padding: 2px 6px; font-size: 11px; }
.grupo-cabecera .btn-link:disabled { opacity: 0.4; cursor: default; border-color: transparent; color: var(--muted); }

.permiso {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 12px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--panel); cursor: pointer; transition: border-color 0.12s, background 0.12s;
}
.permiso:hover { border-color: var(--border-strong); }
.permiso.activo { border-color: var(--accent); background: var(--accent-soft); }
.permiso.activo.produccion { border-color: var(--danger); background: var(--danger-bg); }
.permiso.bloqueado { cursor: default; opacity: 0.75; }
.permiso.bloqueado:hover { border-color: var(--border); }

/* Lo que cuelga de un módulo va sangrado y con una guía a la izquierda: con cuarenta
   interruptores en la lista, sin la sangría no se ve de quién es cada uno. */
.permiso-hijo {
  margin-left: var(--sangria, 22px);
  width: calc(100% - var(--sangria, 22px));
  position: relative;
}
/* Tres niveles bajo el módulo: vista, grupo de funcionalidades y la funcionalidad. Cada
   escalón suma lo mismo, que es lo que deja leer la jerarquía sin contar líneas. */
.permiso-hijo.nivel-1 { --sangria: 22px; }
.permiso-hijo.nivel-2 { --sangria: 44px; }
.permiso-hijo.nivel-3 { --sangria: 66px; }
/* Sections like «Listado» push features one or two steps deeper */
.permiso-hijo.nivel-4 { --sangria: 88px; }
.permiso-hijo.nivel-5 { --sangria: 110px; }
.permiso-hijo::before {
  content: "";
  position: absolute;
  left: -12px; top: -5px; bottom: 50%;
  width: 10px;
  border-left: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  border-bottom-left-radius: 6px;
}
/* Sin el módulo concedido, lo de dentro no abre nada. Se atenúa en vez de esconderse:
   quien reparte permisos tiene que ver que existe y por qué no sirve todavía. */
.permiso-hijo.apagado { opacity: 0.45; }

.permiso-punto { width: 10px; height: 10px; border-radius: 50%; flex: none; box-shadow: 0 0 0 3px var(--neutral-bg); }
.permiso-icono { font-size: 19px; line-height: 1; color: var(--muted); flex: none; }
.permiso.activo .permiso-icono { color: var(--accent); }

.permiso-texto { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.permiso-eti { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text); }
.permiso-pie { font-family: var(--mono); font-size: 10px; color: var(--muted); }

/* El tipo del módulo (ambiente / herramienta) como subtítulo: en un solo grupo conviven
   los dos, y distinguirlos de un vistazo es lo que hace legible la lista. */
.etiqueta-tipo {
  font-size: 9px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted); background: var(--neutral-bg);
  border: 1px solid var(--border); border-radius: 4px; padding: 1px 5px;
}

/* Un permiso que NO se puede conceder ni quitar: el ambiente libre, la vista libre, la
   plataforma libre y «Sistema». Se enseñan para que la lista no mienta por omisión, y
   se atenúan para que se vea que están fuera de la decisión que se está tomando. */
.permiso.fijo { opacity: .62; cursor: default; }
.permiso.fijo .interruptor { cursor: not-allowed; }
.permiso.fijo .permiso-pie { font-family: inherit; font-size: 10px; font-style: italic; }

.etiqueta-prod {
  padding: 0 6px; border-radius: 10px; font-size: 9px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.04em;
  background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger);
}

/* Interruptor sobre una casilla real: el estado lo sigue llevando el input, así que
   el teclado y los lectores de pantalla funcionan sin añadir nada. */
.interruptor { position: relative; width: 36px; height: 20px; flex: none; }
.interruptor input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.interruptor > span {
  position: absolute; inset: 0; border-radius: 999px;
  background: var(--border-strong); transition: background 0.15s; pointer-events: none;
}
.interruptor > span::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
  border-radius: 50%; background: #fff; transition: transform 0.15s;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
.interruptor input:checked + span { background: var(--accent); }
.interruptor input:checked + span::after { transform: translateX(16px); }
.interruptor input:disabled { cursor: default; }
.interruptor input:disabled + span { opacity: 0.5; }
.interruptor input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }
.permiso.produccion .interruptor input:checked + span { background: var(--danger); }

.bloque-admin {
  display: flex; flex-direction: column; gap: 6px;
  padding: 10px; border: 1px solid var(--border); border-radius: 10px; background: var(--neutral-bg);
}
.bloque-admin.activo { border-color: var(--warn); background: var(--warn-bg); }
.bloque-admin .permiso { border-color: transparent; background: transparent; }
.bloque-admin .permiso:hover { border-color: transparent; }
.bloque-admin.activo .permiso-icono { color: var(--warn); }
.bloque-admin.activo .interruptor input:checked + span { background: var(--warn); }
.bloque-admin .hint { display: flex; align-items: center; gap: 6px; padding: 0 12px; }

.nota-final { display: flex; align-items: flex-start; gap: 6px; line-height: 1.5; }
.nota-final .mdi { font-size: 14px; line-height: 1.4; flex: none; }

/* La fila de la vista de inicio: misma caja que un permiso, pero con un select en vez
   del interruptor. No es un permiso y no debe parecerlo, pero sí vivir con ellos. */
.permiso-select { cursor: default; }
.permiso-select:hover { border-color: var(--border); }
.permiso-select select { width: auto; min-width: 150px; flex: none; }

/* With a solid bar (a tool, or an environment with colour) the modals copy it solid: a
   dialog covers the bar, and its header is where you still see where you are.
   Producción has no colour and stays neutral: its warning is the red badge. The viewer's
   «Comparar» has its header inside its own section, so it is named too (24-10-2026). */
body[data-bar="solid"] :is(.modal > header, .modal > .visor-comparar > header) {
  background: var(--bar-fill);
  border-bottom: 1px solid rgba(0, 0, 0, 0.22);
  color: #fff;
}
/* Lo que va ENCIMA del color: la aspa, el zoom del visor y los botones de la cabecera.
   Heredan el blanco y se apoyan en una veladura, igual que los controles de las dos
   barras, para no abrir un hueco claro en mitad de la franja. */
body[data-bar="solid"] :is(.modal > header, .modal > .visor-comparar > header) .modal-close {
  color: #fff;
  opacity: 0.85;
}
body[data-bar="solid"] :is(.modal > header, .modal > .visor-comparar > header) .modal-close:hover { opacity: 1; background: rgba(255, 255, 255, .16); }
/* A header's subtitle (`.hint`, grey on white) and an accent icon in its title were dark or blue
   on the blue: they follow the white of the header, softened, like the «×» */
body[data-bar="solid"] .modal > header .hint { color: #fff; opacity: 0.85; }
body[data-bar="solid"] .modal > header h2 .mdi { color: inherit; }
body[data-bar="solid"] :is(.modal > header, .modal > .visor-comparar > header) .zoom-visor,
body[data-bar="solid"] :is(.modal > header, .modal > .visor-comparar > header) .btn-icono {
  border-color: rgba(255, 255, 255, 0.65);
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
}
body[data-bar="solid"] :is(.modal > header, .modal > .visor-comparar > header) .zoom-visor select {
  background: transparent;
  border: 0;
  color: #fff;
}
/* El desplegable se pinta con los colores del sistema: sobre el azul, sus opciones
   heredarían texto blanco sobre fondo claro y quedarían ilegibles al abrirlo. */
body[data-bar="solid"] :is(.modal > header, .modal > .visor-comparar > header) .zoom-visor select option { color: var(--text); }
body[data-bar="solid"] :is(.modal > header, .modal > .visor-comparar > header) .btn-icono:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.24);
}

/* ── Pantallas estrechas ───────────────────────────────────────────────────────
   La app se diseñó para escritorio —es una herramienta de trabajo con tablas
   anchas— pero se consulta desde el teléfono, y ahí lo que pasaba no era que se
   viera apretado: era que el contenido útil quedaba fuera de la pantalla. Los
   cortes son dos: 900px para lo que solo necesita apilarse, y 560px para el
   teléfono, donde además hay que renunciar a cosas.

   La tabla de Documentación no se arregla con CSS: sus columnas se deciden en
   `DocsTablePanel.js` según el ancho, porque esconder celdas de una tabla con
   `rowspan`/`colspan` deja la cuadrícula descuadrada. */

@media (max-width: 900px) {
  /* Cabecera de las herramientas: los botones bajan a otra línea en vez de
     desbordarse a la derecha, que era lo que dejaba «Configuración» fuera. */
  .card > header.header-fuerte { flex-wrap: wrap; row-gap: 8px; padding: 12px 14px; }
  .header-fuerte h2 { font-size: 15px; }
  .header-fuerte .btn { padding: 6px 10px; font-size: 12px; }

  /* Filtros: cada uno a su línea completa. Medio ancho no le sirve a un rango de
     fechas y encima parte el texto de la etiqueta. */
  .filtros .field,
  .filtros .campo-buscar { flex: 1 1 100%; }
  .filtros .acciones-filtro { flex: 1 1 100%; justify-content: flex-end; }

  /* Visor de archivos: el árbol arriba y el documento debajo. En columna no cabían
     los 270px del árbol y el contenido a la vez; en fila, el documento se quedaba
     con 60px de ancho. */
  .visor { flex-direction: column; }
  .visor-lista {
    flex: 0 0 auto;
    max-height: 30vh;
    border-right: 0;
    border-bottom: 1px solid var(--border);
  }
  .visor-hoja,
  .visor-codigo { height: auto; min-height: 50vh; }

  /* El documento de Word se pinta al ancho real de una página A4, que no cabe. Centrado
     se cortaba por los DOS lados y la mitad izquierda no había forma de alcanzarla: al
     centrar un hijo más ancho que su contenedor, lo que sobra por la izquierda queda
     fuera del área desplazable. Alineado al inicio se lee desde el margen y el resto se
     alcanza desplazando (o con el pellizco del teléfono, que la página no bloquea). */
  .visor-word { justify-content: flex-start; }
  .visor-cuerpo { padding: 8px; }

  /* «Sistema»: el menú lateral pasa a ser una fila de pestañas. Una columna de
     190px se come un tercio de la pantalla de un teléfono. */
  .card-sistema { height: auto; }
  .sistema { flex-direction: column; height: auto; min-height: 0; }
  .sistema-lateral { width: auto; border-right: 0; border-bottom: 1px solid var(--border); }
  .sistema-menu {
    width: auto;
    flex-direction: row;
    overflow-x: auto;
    padding: 8px;
  }
  .sistema-opcion { white-space: nowrap; }
  .sistema-cuerpo { padding: 12px; overflow-y: visible; }

  /* Los modales anchos dejan de ser anchos: lo que manda es la pantalla. */
  .modal.modal-wide,
  .modal.modal-xl { max-width: 100%; }
}

@media (max-width: 560px) {
  .topbar { gap: 8px; padding: 8px 12px; }
  .topbar h1 { font-size: 14px; }
  .subbar { gap: 6px; }

  /* A pantalla completa y sin esquinas: en un teléfono, 16px de sombra alrededor
     de un diálogo es ancho que le falta al contenido. */
  .backdrop { padding: 0; align-items: stretch; }
  .backdrop > .modal,
  /* Los dos modales que se declaran con dos clases (`.modal.modal-visor`,
     `.modal.modal-facturas`) se nombran igual aquí: si no, su `max-width` de pantalla grande
     le gana a esto por estar más abajo en el archivo y el teléfono se queda sin ancho. */
  .backdrop > .modal.modal-visor,
  .backdrop > .modal.modal-facturas {
    max-width: 100%;
    width: 100%;
    height: 100%;
    border-radius: 0;
    border: 0;
    display: flex;
    flex-direction: column;
  }
  .modal > .body,
  .body-permisos { flex: 1 1 auto; overflow-y: auto; max-height: none; }
  .modal footer { flex-wrap: wrap; }

  /* El pie del visor y la paginación se parten en dos líneas antes que recortarse. */
  .paginacion { flex-wrap: wrap; row-gap: 8px; }
  .paginacion .spacer { flex: 1 1 100%; }

  /* La tabla conserva TODAS sus columnas y se desplaza en horizontal: en un teléfono no
     caben once, pero esconder unas cuantas obliga a abrir el portátil para ver el
     desglose de horas. Se aprieta el relleno y los botones para que quepa más de un
     vistazo, y las columnas mantienen su ancho natural en vez de comprimirse hasta
     partir cada palabra en dos líneas. */
  .tabla-docs { min-width: max-content; }
  .tabla-docs th,
  .tabla-docs td { padding: 6px 5px; }
  .tabla-docs .acciones .btn-ver + .btn-ver { margin-left: 4px; }
  .tabla-docs .btn-ver { width: 26px; height: 26px; }

  /* Los permisos: el interruptor manda, el nombre técnico del flag se puede ir. */
  .permiso { padding: 8px 10px; }
  .permiso-pie { display: none; }

  .metrica { padding: 10px 12px; }
  .metrica-num { font-size: 22px; }
}

/* ---------------------------------------------------------------- Visor de DOCS: origen
   El visor lee de dos sitios —el bucket de R2 o un clon local— y la elección cambia qué
   se puede hacer, así que se presenta como dos tarjetas con su explicación y no como un
   desplegable: quien elige tiene que ver de antemano qué pierde con cada opción. */
.opciones-origen { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 720px) { .opciones-origen { grid-template-columns: 1fr; } }

.opcion-origen {
  display: flex; align-items: flex-start; gap: 9px;
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 11px 12px; cursor: pointer; background: var(--panel);
}
.opcion-origen:hover { border-color: var(--border-strong); }
.opcion-origen.activa { border-color: var(--accent); background: var(--accent-soft); }
.opcion-origen input { margin-top: 2px; flex-shrink: 0; }
.opcion-origen > span { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.opcion-origen b { font-size: 13px; display: flex; align-items: center; gap: 6px; }
.opcion-origen .hint { line-height: 1.5; }
/* Deshabilitada cuando falta el `.env`: se deja verse, pero no elegirse. */
.opcion-origen:has(input:disabled) { opacity: .55; cursor: not-allowed; }

/* La etiqueta de la cabecera que recuerda de dónde se está leyendo ahora mismo. */
/* De dónde lee el visor. SIN fondo ni borde: con ellos parecía una ficha más de la fila
   de vistas y la gente intentaba pulsarla. Aquí solo informa, así que se comporta como
   texto: nada que invite al clic. */
.origen-dato {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; font-weight: 600;
  color: var(--muted);
  padding: 0 4px;
  white-space: nowrap;
}
/* La palabra «Origen» pesa menos que el valor: lo que se lee de un vistazo es «Nube». */
.origen-eti { font-weight: 500; opacity: 0.75; }
.origen-eti::after { content: ":"; }

/* ---------------------------------------------------------------- Puerta de entrada
   Sin sesión no se ve la aplicación, así que esta pantalla es lo primero que encuentra
   quien llega. Se centra en una caja estrecha y con la marca arriba: en un ancho de
   escritorio, un formulario de dos campos estirado de lado a lado se lee peor que uno
   acotado, y deja al usuario buscando dónde escribir. */
/* The old centred card (big logo, «CIELUM» divider) is gone: every screen before entering
   uses the «B» layout below (`.signin`). What stays here is the field with its icon and
   the legal links, which that layout reuses. */

/* The inputs with their icon inside, and the password's show/hide button at the end */
.portada-campo { position: relative; }
.portada-campo > .mdi {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  font-size: 17px; color: var(--muted); pointer-events: none;
  /* Por encima del campo, no por debajo. En el usuario el icono ya ganaba por ser lo
     único posicionado; en la contraseña el envoltorio del componente SÍ lo está, va
     después en el documento y su input tiene fondo opaco, así que tapaba el candado. */
  z-index: 1;
}
/* Same :not() chain as the base input rule, plus the wrapper: otherwise that rule
   (more specific) wins and the text runs under the icon.
   El segundo selector es para la contraseña: `PasswordField` cuelga su `<input>` de un
   `div.pass-field` propio, así que el selector de hijo directo no lo alcanzaba y el
   campo quedaba con la altura base (33px) y el radio base (4px) al lado de un usuario
   de 40px y radio 8. Se nombra el envoltorio en vez de usar el descendiente a secas
   para no pisar inputs de otros componentes que algún día se aniden aquí. */
.portada-campo > input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(.swal2-input),
.portada-campo > .pass-field > input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(.swal2-input) {
  height: 40px; padding-left: 36px; border-radius: 8px; font-size: 13.5px;
}
/* El ojo se superpone al final del input, así que ahí no puede acabar el texto. */
.portada-campo > .pass-field > input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(.swal2-input) {
  padding-right: 40px;
}
.portada-campo > input:focus,
.portada-campo > .pass-field > input:focus { outline: 2px solid var(--brand); outline-offset: -1px; }
.portada-campo:focus-within > .mdi { color: var(--accent); }
/* El ojo, con el área de pulsación y el redondeo de esta pantalla: el del resto de la
   app es más pequeño porque allí los campos miden 33px y aquí 40. */
.portada-campo > .pass-field > .pass-toggle {
  right: 4px; width: 32px; height: 32px; padding: 0; border-radius: 6px; justify-content: center;
}
.portada-campo > .pass-field > .pass-toggle:hover:not(:disabled) { color: var(--accent); background: var(--accent-soft); }

/* Los tres enlaces legales, bajo la caja de inicio de sesión: es el único rincón público
   de toda la app, y por eso es donde tienen que poder encontrarlos Meta (al revisar la
   plantilla de WhatsApp Business) y cualquier cliente. */
.portada-legal { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 16px; }
.portada-legal a { font-size: 12px; color: var(--muted); text-decoration: none; }
.portada-legal a:hover { color: var(--accent); text-decoration: underline; }

/* ---------------------------------------------------------------- Sign-in, layout «B»
   LoginGate and the recovery screens (modules/users/LoginGate.js and its parts): the brand
   panel on the left and the screen of the moment on the right. The panel is the SAME blue
   in light and dark (a band of brand colour with white text, like the header); the form
   side only uses the theme tokens, so both themes come from the `:root` blocks above.
   Narrow screens: no panel, the form alone with a small logo on top. */
.signin { min-height: 100vh; display: grid; grid-template-columns: minmax(0, 1fr); background: var(--bg); color: var(--text); }

.signin-brand {
  display: none; position: relative; overflow: hidden; flex-direction: column;
  padding: 44px 44px 32px; color: #fff;
  background:
    radial-gradient(600px 400px at 0% 0%, rgba(255, 255, 255, .16), transparent 60%),
    linear-gradient(150deg, var(--brand) 0%, var(--brand-strong) 55%, #015d8f 100%);
}
/* A soft ring in the corner: depth without an image to load */
.signin-brand::after {
  content: ""; position: absolute; right: -120px; bottom: -120px; width: 360px; height: 360px;
  border-radius: 50%; border: 50px solid rgba(255, 255, 255, .06); pointer-events: none;
}
/* The panel is a flex column: without align-self the logo stretches to the full width.
   Fixed height, natural width: never distorted. */
.signin-brand-logo {
  align-self: flex-start; width: auto; height: 52px; max-width: 100%; object-fit: contain; display: block;
  border-radius: 10px; box-shadow: 0 8px 20px -8px rgba(0, 0, 0, .4);
}
.signin-brand-monogram {
  align-self: flex-start; display: flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: 12px; background: rgba(255, 255, 255, .16);
  font-size: 17px; font-weight: 800; letter-spacing: .04em;
}
.signin-brand h2 { margin: 36px 0 6px; font-size: 32px; line-height: 1.15; letter-spacing: -.02em; font-weight: 700; }
.signin-brand > p { margin: 0; max-width: 34ch; font-size: 15px; color: rgba(255, 255, 255, .86); }
.signin-brand-list { list-style: none; margin: 32px 0 0; padding: 0; display: flex; flex-direction: column; gap: 16px; max-width: 38ch; }
.signin-brand-list li { display: flex; gap: 12px; align-items: flex-start; font-size: 14px; color: rgba(255, 255, 255, .9); }
.signin-brand-list strong { display: block; color: #fff; font-size: 14.5px; }
.signin-brand-icon {
  flex: none; width: 36px; height: 36px; border-radius: 10px; background: rgba(255, 255, 255, .14);
  display: inline-flex; align-items: center; justify-content: center; font-size: 19px;
}
.signin-brand-foot {
  margin-top: auto; padding-top: 32px; font-size: 11px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: rgba(255, 255, 255, .8);
}

/* The form side: the theme's surface, content centred, legal links and version at its foot */
.signin-side {
  display: flex; flex-direction: column; justify-content: center; align-items: center;
  gap: 24px; padding: 28px 16px 20px; min-width: 0;
}
.signin-content { width: 100%; max-width: 380px; min-width: 0; }
.signin-footer { display: flex; flex-direction: column; align-items: center; gap: 8px; width: 100%; max-width: 380px; }
.signin-footer .version-app { font-size: 11px; flex-wrap: wrap; text-align: center; }

.signin-mobile-brand { display: flex; align-items: center; gap: 10px; margin-bottom: 22px; font-weight: 700; font-size: 15px; min-width: 0; }
.signin-mobile-brand img { width: auto; height: 36px; max-width: 60%; object-fit: contain; border-radius: 8px; display: block; flex: none; }
.signin-mobile-monogram {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 36px; height: 36px; border-radius: 8px; background: var(--brand); color: #fff; font-size: 12px; font-weight: 800;
}

.signin-step h1 { margin: 0; font-size: 24px; line-height: 1.2; letter-spacing: -.02em; font-weight: 700; color: var(--text); }
.signin-sub { margin: 6px 0 0; font-size: 14px; color: var(--muted); line-height: 1.5; }
.signin-sub b { color: var(--text); }
.signin-sub + .signin-form { margin-top: 22px; }
.signin-form { display: flex; flex-direction: column; gap: 16px; margin: 0; }
.signin-form .field > label, .signin-label-row label { font-size: 13px; font-weight: 600; color: var(--text); }
.signin-label-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }
/* The forgot link and «Volver»: text buttons in the accent (lightened in dark) */
.signin button.signin-link {
  border: 0; background: none; padding: 0; border-radius: 4px;
  font-size: 13px; font-weight: 600; color: var(--accent); cursor: pointer;
}
.signin button.signin-link:hover { text-decoration: underline; }
.signin button.signin-back {
  display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%; margin-top: 14px;
  border: 0; background: none; padding: 4px; font-size: 13px; font-weight: 600; color: var(--accent); cursor: pointer;
}
.signin button.signin-back + .signin-back { margin-top: 4px; }
.signin button.signin-back:hover { text-decoration: underline; }
.signin button.signin-link:focus-visible,
.signin button.signin-back:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The primary action: brand blue with white text in both themes */
.signin button.signin-submit,
.signin button.signin-secondary {
  width: 100%; height: 44px; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border-radius: 10px; font-size: 14.5px; font-weight: 600; transition: background .12s, box-shadow .12s, border-color .12s;
}
.signin button.signin-submit {
  color: #fff; background: var(--brand); border: 1px solid var(--brand);
  background-image: linear-gradient(180deg, var(--brand) 0%, var(--brand-strong) 100%);
}
.signin button.signin-submit:hover:not(:disabled) {
  background: var(--brand-strong); border-color: var(--brand-strong);
  box-shadow: 0 6px 16px -6px color-mix(in srgb, var(--brand) 80%, transparent);
}
.signin button.signin-secondary { color: var(--text); background: var(--panel); border: 1px solid var(--border-strong); }
.signin button.signin-secondary:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.signin button.signin-submit .mdi, .signin button.signin-secondary .mdi { font-size: 17px; }

/* The inputs of the gate are 44px high here, like the buttons */
.signin .portada-campo > input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(.swal2-input),
.signin .portada-campo > .pass-field > input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(.swal2-input) {
  height: 44px; border-radius: 10px; font-size: 14.5px;
}
.signin .portada-campo > .pass-field > .pass-toggle { width: 36px; height: 36px; border-radius: 8px; }
.signin .alert { border-radius: 8px; font-size: 13px; padding: 9px 12px; line-height: 1.5; }

/* The big round icon of the confirmation, invalid-link and success screens */
.signin-icon {
  width: 56px; height: 56px; border-radius: 50%; margin-bottom: 14px;
  display: inline-flex; align-items: center; justify-content: center; font-size: 28px;
}
.signin-icon.info { background: var(--accent-soft); color: var(--accent); }
.signin-icon.ok { background: color-mix(in srgb, var(--ok) 16%, var(--panel)); color: var(--ok); }
.signin-icon.warn { background: var(--warn-bg); color: var(--warn); }
/* A calm note (not an error): the theme's soft accent with the body text */
.signin-note {
  display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px; border-radius: 10px;
  font-size: 13px; line-height: 1.5; color: var(--text);
  background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
}
.signin-note .mdi { font-size: 18px; line-height: 1.2; color: var(--accent); }
.signin-checking { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 14px; padding: 24px 0; }
.signin-checking .mdi { font-size: 20px; color: var(--accent); }

/* The live checklist of the new password */
.signin-rules { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 6px; font-size: 13px; }
.signin-rules li { display: flex; align-items: center; gap: 8px; color: var(--muted); }
.signin-rule-dot {
  flex: none; width: 18px; height: 18px; border-radius: 50%; border: 1.5px solid var(--border-strong);
  display: inline-flex; align-items: center; justify-content: center; font-size: 12px; color: transparent;
}
.signin-rules li.met { color: var(--text); }
.signin-rules li.met .signin-rule-dot { background: var(--ok); border-color: var(--ok); color: var(--panel); }
.signin-field-error { font-size: 12.5px; color: var(--danger); margin-top: 2px; }

/* «Server unavailable» (components/ServerUnavailable.js): when it retries, and the
   technical message folded under «Ver el detalle técnico» */
.signin-retry-status { margin: 0; font-size: 13px; color: var(--muted); }
.signin-retry-status .mdi { font-size: 15px; vertical-align: -2px; }
.signin-detail {
  margin: 8px 0 0; padding: 8px 10px; border-radius: 8px; background: var(--neutral-bg); color: var(--text);
  font-size: 12px; word-break: break-word;
}

/* Wide screens: the two halves as ONE centred card (as in the approved mockup), not two
   halves of the whole window — full width left a huge empty blue panel on big monitors */
@media (min-width: 860px) {
  .signin {
    /* Grows with the screen (up to 680px a half), so a big monitor is not mostly empty */
    grid-template-columns: minmax(0, 680px) minmax(0, 680px);
    justify-content: center; align-content: center; padding: 40px 32px;
    background:
      radial-gradient(900px 520px at 15% 0%, color-mix(in srgb, var(--brand) 14%, transparent), transparent 70%),
      var(--bg);
  }
  .signin-brand { display: flex; min-height: clamp(600px, 78vh, 860px); padding: clamp(44px, 5vw, 72px); border-radius: 18px 0 0 18px; }
  .signin-side {
    padding: 40px clamp(48px, 5vw, 88px) 24px; min-height: clamp(600px, 78vh, 860px); background: var(--panel);
    border: 1px solid var(--border); border-left: 0; border-radius: 0 18px 18px 0;
  }
  .signin-brand, .signin-side { box-shadow: 0 24px 60px -32px rgba(16, 24, 40, .45); }
  .signin-mobile-brand { display: none; }
}
/* Big screens: the type grows with the card */
@media (min-width: 1400px) and (min-height: 820px) {
  .signin-brand-logo { height: 64px; }
  .signin-brand h2 { font-size: 40px; margin-top: 48px; }
  .signin-brand > p { font-size: 17px; }
  .signin-brand-list { gap: 22px; margin-top: 40px; }
  .signin-brand-list li { font-size: 15.5px; }
  .signin-brand-list strong { font-size: 16px; }
  .signin-brand-icon { width: 42px; height: 42px; font-size: 21px; }
  .signin-content, .signin-footer { max-width: 440px; }
  .signin-step h1 { font-size: 30px; }
  .signin-sub { font-size: 15px; }
}
@media (max-width: 480px) {
  .signin-side { justify-content: flex-start; padding-top: 24px; }
  .signin-step h1 { font-size: 22px; }
}

/* Aviso de coste al elegir columnas que consultan el historial de estados: son una
   petición extra por orden, y con muchas órdenes se nota. Va donde se elige, no al
   lanzar: enterarse del coste cuando la corrida ya arrancó no sirve de nada. */
.aviso-historial {
  display: flex; align-items: flex-start; gap: 7px;
  margin-top: 8px; padding: 8px 10px;
  background: var(--warn-bg); border: 1px solid var(--warn); border-radius: var(--radius);
  color: var(--warn); line-height: 1.5;
}
.aviso-historial .mdi { font-size: 14px; flex-shrink: 0; margin-top: 1px; }

/* Botón de solo icono en la cabecera: sin texto, el relleno lateral del botón normal
   lo dejaba ancho y descentrado. Cuadrado y con el icono al medio. El nombre lo dice
   el tooltip de `.con-tooltip`, que sale al instante; el `title` nativo tarda casi un
   segundo y para un icono sin etiqueta eso es demasiado. */
.btn.btn-solo-icono {
  padding: 0;
  width: 34px;
  height: 34px;
  justify-content: center;
  gap: 0;
}
.btn.btn-solo-icono .mdi { font-size: 17px; line-height: 1; }

/* ── Subheader de la herramienta ───────────────────────────────────────────────
   Las dos vistas de Documentación. Mismo lenguaje que los modos de la barra
   superior —fichas con una sola activa—, para que se reconozca sin explicación. */
.subvistas { padding: 0 16px; margin: -8px 0 14px; }
/* El desplegable es el mismo que el de ambientes: hereda `.dropdown`, así que aquí solo
   queda dejar sitio al menú, que se abre por encima de los filtros. */
.subvistas .dropdown { display: inline-block; }
.subvistas .dropdown-toggle .mdi { font-size: 15px; line-height: 1; }

/* ── Estadísticas ──────────────────────────────────────────────────────────────
   Sin librería de gráficas: la app no tiene paso de compilación y estas son
   barras de una sola serie, que en HTML son un ancho en porcentaje. Tampoco hay
   rejilla de fondo ni eje: cada barra lleva su número al lado, que es lo que se
   viene a leer, y una cuadrícula solo añadiría tinta que no se mira. */
.estadisticas { display: flex; flex-direction: column; gap: 16px; }

.rejilla-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; }
/* Estadísticas as its own screen: the same top margin as Horas de gestión */
.layout-ancho .cuerpo-docs > .pantalla-estadisticas { padding-top: 16px; }
/* Presenting, the figures grow as a whole with the letter step (`usePresentation.js`) */
html[data-presentacion] .pantalla-estadisticas .estadisticas { zoom: var(--presentacion-escala, 1.15); }
/* Its skeleton: label + bar per line, and the months as columns of varied height */
.esqueleto-barra { display: flex; align-items: center; gap: 14px; }
.esqueleto-meses { display: flex; align-items: flex-end; gap: 8px; height: 140px; }
.esqueleto-meses > .esqueleto-bloque { flex: 1; border-radius: 4px 4px 0 0; }

.panel-stat {
  display: flex; flex-direction: column; gap: 10px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel);
}
.panel-stat h3 {
  margin: 0; font-size: 11px; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
  display: flex; align-items: baseline; gap: 8px;
}
.panel-stat h3 .hint { text-transform: none; letter-spacing: 0; font-weight: 400; }

/* Barras horizontales: etiqueta, pista y número. La pista se lleva el ancho que
   sobre para que todas midan lo mismo y se puedan comparar de un vistazo. */
.barras { display: flex; flex-direction: column; gap: 7px; }
.barra-fila { display: flex; align-items: center; gap: 10px; font-size: 12px; }
.barra-eti { flex: 0 0 96px; color: var(--text); }
.barra-pista { flex: 1; min-width: 0; height: 10px; border-radius: 5px; background: var(--neutral-bg); }
.barra-valor {
  display: block; height: 100%;
  /* Extremo redondeado solo por donde crece: pegado al origen, una barra redonda
     por los dos lados parece despegada de su base. */
  border-radius: 0 4px 4px 0;
  background: var(--c, var(--accent));
  min-width: 2px;
}
.barra-unica { --c: var(--accent); }
.barra-num { flex: 0 0 46px; text-align: right; font-variant-numeric: tabular-nums; color: var(--text); font-weight: 600; }

/* Por mes: columnas, porque el tiempo se lee de izquierda a derecha. */
.barras-mes { display: flex; align-items: flex-end; gap: 8px; overflow-x: auto; padding-top: 4px; }
.col-mes { flex: 1 1 0; min-width: 42px; display: flex; flex-direction: column; align-items: center; gap: 4px; }
.col-num { font-size: 11px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.col-pista { width: 100%; height: 110px; display: flex; align-items: flex-end; }
.col-valor { width: 100%; border-radius: 4px 4px 0 0; background: var(--accent); min-height: 2px; }
.col-eti { font-size: 10px; color: var(--muted); white-space: nowrap; }

/* ------------------------------------------------------------------ Estadísticas → Pago
   Lo que se cobra: el titular del mes, la gráfica de los meses y el detalle del mes elegido
   (sus tickets, sus horas de gestión por tipo y sus ventanas). Reusa lo de arriba (`.panel-stat`, `.barras`,
   `.barras-mes`) y solo añade lo que no existía: las bandas apiladas de una columna y las
   piezas del titular. */
.cobro { display: flex; flex-direction: column; gap: 16px; }
.panel-cobro { gap: 8px; }

/* El selector de mes es de esta sección y no un filtro de la tabla: va junto al titular */
.cobro-selector { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cobro-selector-eti { font-size: 12px; color: var(--muted); }
/* Los dos selectores ocupan lo suyo, no la fila entera: `select` lleva `width: 100%`
   de la regla global de formularios, y con eso cada uno se iba a su propia línea de
   1500 px para elegir «octubre». Visto en pantalla el 2026-10-07. */
.cobro-selector select { font-size: 12px; padding: 3px 6px; width: auto; min-width: 110px; }
.cobro-aviso { margin: 0; max-width: 62ch; }
.cobro-titular { margin: 2px 0 0; font-size: 15px; color: var(--text); }
.cobro-titular strong { font-size: 22px; font-variant-numeric: tabular-nums; }

/* Las tres partes del titular, con el mismo color que su banda en la gráfica */
.cobro-partes { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.cobro-parte { display: inline-flex; align-items: baseline; gap: 6px; font-size: 12px; }
.cobro-parte-punto { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; }
.cobro-parte-eti { color: var(--muted); }
.cobro-parte-num { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
.cobro-leyenda { display: flex; flex-wrap: wrap; gap: 4px 16px; font-size: 11px; color: var(--muted); }
.cobro-clave { display: inline-flex; align-items: center; gap: 5px; }
/* El valor de la serie en el mes elegido, al lado de su nombre: es lo que se compara */
.cobro-clave-num { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }

/* LA GRÁFICA DE LÍNEA (`DocsCobroLinea.js`). SVG a mano: esta app no tiene paso de
   compilación y no admite dependencias nuevas en el navegador. Los colores de las líneas los
   pone el componente (son los de las tres series, uno por serie); aquí van los del lienzo,
   todos por variable para que el modo oscuro no necesite una segunda regla. */
.cobro-linea { width: 100%; }
.cobro-svg { width: 100%; height: auto; display: block; overflow: visible; }
/* Discreta a propósito: la rejilla está para medir una altura, no para mirarla */
.cobro-rejilla line { stroke: var(--border); stroke-width: 1; opacity: 0.55; }
.cobro-eje-y text, .cobro-eje-x text { font-size: 10px; fill: var(--muted); font-variant-numeric: tabular-nums; }
.cobro-eje-x text.elegido { fill: var(--accent); font-weight: 600; }
.cobro-anio { opacity: 0.8; }
.cobro-total-mes { font-size: 12px; font-weight: 700; fill: var(--text); font-variant-numeric: tabular-nums; }
.cobro-mes-elegido { fill: var(--accent-soft); }
/* La banda sensible de cada mes: invisible, lleva el tooltip y el clic que elige el mes */
.cobro-zona { fill: transparent; cursor: pointer; }
.cobro-zona:hover { fill: var(--accent-soft); opacity: 0.55; }
.cobro-serie circle { stroke: var(--panel); stroke-width: 1.5; }
.cobro-fuera { margin: 0; max-width: 72ch; }

/* Los tickets del mes elegido: la tabla de Documentación en pequeño. Con tope de alto para
   que un mes con muchos tickets no empuje el resto de la sección fuera de la pantalla; la
   cabecera y el pie de `.tabla-docs` ya van fijos al hacer scroll dentro. */
.cobro-tabla { max-height: 420px; }

/* Las ventanas del mes elegido */
.cobro-ventanas { display: flex; flex-direction: column; gap: 12px; }
.cobro-ventana { display: flex; flex-direction: column; gap: 3px; }
/* Los tickets de la ventana, debajo de su barra y sangrados hasta donde empieza la pista */
.cobro-tickets { display: flex; flex-wrap: wrap; gap: 4px; margin-left: 106px; font-size: 11px; }
.cobro-excluido { margin: 0; }
/* Una fila de barra que NAVEGA (un tipo o una persona de las tarjetas de gestión abre «Horas de
   gestión» ya filtrada): un botón de verdad, con foco, que se ve igual que la fila de al lado */
button.barra-fila.barra-boton {
  width: 100%; margin: 0; padding: 2px 4px; border: 0; border-radius: 4px;
  background: none; font: inherit; color: inherit; text-align: left; cursor: pointer;
}
button.barra-fila.barra-boton:hover { background: var(--accent-soft); }
button.barra-fila.barra-boton:focus-visible, .cobro-enlace:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* El nombre de un tipo dentro de una frase, pulsable: sin el marco de `.btn-link` */
.btn-link.cobro-enlace { padding: 0; border: 0; background: none; color: var(--accent); font-size: inherit; text-decoration: underline; }

@media (max-width: 720px) {
  .cobro-tickets { margin-left: 0; }
}

/* ------------------------------------------------------------- Estadísticas → Bugs reportados
   La última gráfica (D-33): reusa las cifras de arriba (`.metricas`), la gráfica de columnas de la
   app (`DashColumnChart`, `.dash-*`) y sus colores (`--viz-*`); aquí solo lo que no existía: los
   controles de vista y ventana, la línea del promedio, el periodo en curso y la lista del modal.
   Todo por variable, así que el modo oscuro no necesita una segunda regla. */
.bugs { gap: 12px; }
/* La nota de qué se cuenta y de dónde sale, bajo el título: la leen quienes deciden */
.bugs-cobertura { display: flex; flex-direction: column; gap: 6px; }
.bugs-cobertura .hint { margin: 0; line-height: 1.45; }
.bugs-sin-ticket {
  display: inline-block; margin-left: 4px; padding: 0 6px; border-radius: 999px; font-size: 11px; font-family: inherit;
  color: var(--warn); background: var(--warn-bg); border: 1px solid var(--warn); white-space: nowrap;
}
.bugs-controles { display: flex; align-items: center; justify-content: space-between; gap: 8px 16px; flex-wrap: wrap; }
.bugs-vistas, .bugs-navegar { display: inline-flex; align-items: center; gap: 6px; }
.bugs-navegar .btn-pag { min-width: 30px; height: 28px; padding: 0 8px; }
/* Más bugs es peor: el color lo dice antes que el número */
.bugs-variacion.tono-malo { color: var(--danger); }
.bugs-variacion.tono-bueno { color: var(--ok); }
.bugs-leyenda { flex-direction: row; flex-wrap: wrap; gap: 4px 16px; }
.bugs-clave-promedio { display: inline-block; width: 16px; border-top: 2px dashed var(--muted); flex: none; }
/* La línea del promedio: discontinua y por encima de las barras, pero sin robarles el ratón */
.dash-reference { pointer-events: none; }
.dash-reference line { stroke: var(--muted); stroke-width: 1.5; stroke-dasharray: 5 4; }
.dash-reference text { font-size: 10px; fill: var(--muted); font-variant-numeric: tabular-nums; }
/* El periodo que aún no ha terminado, más claro: su barra todavía puede crecer */
.dash-mark.partial { opacity: 0.6; }
.dash-mark.partial.dim { opacity: 0.25; }
.dash-hit.selectable { cursor: pointer; }
.dash-hit.selectable:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.dash-tooltip-note { margin-top: 4px; max-width: 280px; color: var(--muted); overflow-wrap: anywhere; }
.dash-tooltip-row + .dash-tooltip-note,
.dash-tooltip-row.total + .dash-tooltip-note { padding-top: 5px; border-top: 1px solid var(--border); }

/* La lista de un periodo. La tabla tiene su ancho mínimo y se desplaza DENTRO de su caja si no
   cabe (nunca la página); el título se parte en líneas con un ancho máximo, y las columnas
   cortas no se parten, así ninguna queda cortada («ES» por «Estado»). En móvil, una tarjeta por bug. */
.modal.modal-xl.bugs-modal { max-width: min(1240px, 96vw); }
.bugs-buscar { display: flex; align-items: center; gap: 6px; }
.bugs-buscar .mdi { color: var(--muted); font-size: 16px; }
.bugs-tabla { max-height: 60vh; overflow: auto; max-width: 100%; }
.bugs-tabla table { min-width: 980px; table-layout: auto; }
.bugs-tabla td { vertical-align: top; }
.bugs-tabla th { white-space: nowrap; }
.bugs-clave { white-space: nowrap; }
.bugs-titulo { min-width: 200px; max-width: 340px; white-space: normal; overflow-wrap: anywhere; line-height: 1.4; }
.bugs-fecha, .bugs-col-estado, .bugs-col-asignado, .bugs-col-proyecto { white-space: nowrap; }
.bugs-col-asignado { max-width: 160px; overflow: hidden; text-overflow: ellipsis; }
.bugs-col-etiquetas { min-width: 140px; max-width: 240px; }
.bugs-ticket { display: block; font-family: inherit; }
.bugs-acciones { white-space: nowrap; }
.bugs-acciones > * + * { margin-left: 6px; }
.btn-link.bugs-enlace { padding: 3px 8px; font-size: 12px; }
.bugs-estado { display: inline-flex; align-items: center; gap: 5px; }
.bugs-estado::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--viz-neutral); flex: none; }
.bugs-estado-abierto::before { background: var(--viz-critical); }
.bugs-estado-cerrado::before { background: var(--viz-good); }
.bugs-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.bugs-chip {
  display: inline-flex; align-items: center; gap: 3px; padding: 1px 7px; border-radius: 999px; font-size: 11px;
  border: 1px solid var(--border-strong); background: var(--panel); color: var(--text); white-space: nowrap;
}
.bugs-chip-tipo { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
mark.bugs-resaltado { background: var(--resaltador); color: var(--resaltador-texto); padding: 0 2px; border-radius: 3px; }
/* El control del periodo de las gráficas («Bugs reportados» y «Horas de soporte»): con un mes
   desglosado en días, las migas y el botón de volver encima del selector */
.grafica-periodo { display: flex; flex-direction: column; gap: 8px; }
.grafica-migas { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.grafica-migas ol { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; margin: 0; padding: 0; list-style: none; }
.grafica-migas li + li::before { content: "›"; margin-right: 4px; color: var(--muted); }
.grafica-migas li [aria-current] { font-weight: 600; }
.grafica-mes-entero { display: flex; justify-content: flex-end; }
/* Más horas de soporte no es ni mejor ni peor: sin color de juicio */
.bugs-variacion.tono-neutro { color: var(--muted); }
/* Los registros de un día: cinco columnas, la descripción se parte en líneas */
.soporte-modal .bugs-tabla table { min-width: 720px; }
.soporte-modal .bugs-tabla td:last-child { min-width: 240px; white-space: normal; overflow-wrap: anywhere; line-height: 1.4; }
.soporte-modal .bugs-tabla td.num, .soporte-modal .bugs-tabla th.num { text-align: right; white-space: nowrap; }
@media (max-width: 720px) {
  .bugs-controles { align-items: flex-start; }
  /* Una tarjeta por bug: cada celda en su línea, con el nombre de su columna delante */
  .bugs-tabla { max-height: none; }
  .bugs-tabla table { min-width: 0; }
  .bugs-tabla thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .bugs-tabla tbody, .bugs-tabla tr, .bugs-tabla td { display: block; width: 100%; }
  .bugs-tabla tr { border: 1px solid var(--border); border-radius: var(--radius); padding: 8px 10px; margin-bottom: 8px; }
  .bugs-tabla td { border: 0; padding: 3px 0; max-width: none; white-space: normal; }
  .bugs-tabla td[data-label]::before {
    content: attr(data-label); display: block; font-size: 10.5px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em;
  }
  .bugs-col-asignado { overflow: visible; }
}

/* La subbarra de una herramienta: sus vistas y sus acciones. Las fichas llevan icono
   como el resto de la app, y los botones de la derecha son los de solo icono, algo
   más bajos para no engordar la franja. */
.subbar .chip-icono { display: inline-flex; align-items: center; gap: 6px; }
.subbar .chip-icono .mdi { font-size: 14px; line-height: 1; }
.subbar .btn-solo-icono { width: 28px; height: 28px; }
.subbar .btn-solo-icono .mdi { font-size: 15px; }

/* La cabecera fuerte va LLENA de color, así que el tinte de ambiente no la toca.
   `body[data-env] .card > header` le ganaba en especificidad y la dejaba en un 7% de
   azul con el texto blanco encima: sobre el fondo claro de la presentación, invisible.
   Se declara con `body[data-env]` delante para empatar esa especificidad y ganar por
   orden, que es lo que hace explícito cuál de las dos manda. */
body[data-env] .card > header.header-fuerte {
  background: var(--header-azul);
  box-shadow: none;
}

/* ── Cabecera de una herramienta: color LLENO ─────────────────────────────────
   El ambiente tiñe al 8% para no gritar mientras trabajas; una herramienta ocupa
   la pantalla entera y su cabecera va llena, que es lo que la separa de un
   vistazo. Con el tinte se veía translúcida y descolorida.

   El menú desplegable NO se toca: se abre sobre el panel, no sobre la franja. */
body[data-bar="solid"] .topbar,
body[data-bar="solid"] .subbar {
  background: var(--bar-fill);
  border-bottom-color: rgba(0, 0, 0, 0.22);
  color: #fff;
}
body[data-bar="solid"] .topbar h1 { color: #fff; }
/* The white above is inherited by what OPENS from the bar —the environment menu and the
   Ajustes modal live inside it— and they sit on the panel, not on the colour. Back to
   the theme's text: in dark it went unnoticed (white on dark), in light it vanished. */
body[data-bar="solid"] .topbar .dropdown-menu,
body[data-bar="solid"] .topbar .backdrop { color: var(--text); }

/* Los controles que van ENCIMA del color. `> div > button` alcanza el selector de
   herramienta y el de Ajustes sin entrar en los modales que cuelgan de ellos. */
body[data-bar="solid"] .topbar > div > button,
body[data-bar="solid"] .subbar .chip,
body[data-bar="solid"] .subbar .btn {
  border-color: rgba(255, 255, 255, 0.65);
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
}
body[data-bar="solid"] .topbar > div > button:hover:not(:disabled),
body[data-bar="solid"] .subbar .chip:hover:not(:disabled),
body[data-bar="solid"] .subbar .btn:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.24);
}
/* La vista activa se invierte: sobre color, «más blanco» lee como seleccionado
   mejor que «un poco más claro». */
body[data-bar="solid"] .subbar .chip.active {
  background: #fff;
  border-color: #fff;
  color: var(--bar-fill);
  font-weight: 600;
}
/* Sobre la franja de color: blanco atenuado, que es como se ve un dato al lado de unos
   botones sin competir con ellos. */
body[data-bar="solid"] .subbar .origen-dato { color: rgba(255, 255, 255, 0.82); }
/* The selector's dot is the environment's own colour, the same as the bar under it:
   a white ring keeps it visible */
body[data-bar="solid"] .dropdown-toggle .env-dot { box-shadow: 0 0 0 2px #fff; }
/* The platform session badge sits straight in the bar, so its «iniciar sesión» link
   caught the white of the bar's buttons and vanished on the light badge */
body[data-bar="solid"] .topbar .badge button.link {
  background: none;
  border: 0;
  color: var(--accent);
}

/* The strip's choices are TABS everywhere, not buttons: a tool's views (Documentación,
   Estadísticas…), an environment's run modes and its platforms, Producción included.
   No box; the active one is underlined by a bar that sits on the strip's bottom edge.
   In «Comparar» both platforms are underlined: both take part.
   Without colour (Producción) they wear the theme: muted text, the active one in the
   app's blue. On a solid bar they turn white (the rules right after). */
.subbar .chip {
  margin: -7px 6px -7px 0;
  padding: 10px 6px 8px;
  border: 0;
  border-bottom: 3px solid transparent;
  border-radius: 0;
  background: transparent;
  color: var(--muted);
  font-size: 12.5px;
  font-weight: 500;
}
/* Only the active tab is underlined: hovering the others must not borrow the base
   chip's accent border */
.subbar .chip:not(.active):hover:not(:disabled):not(.locked) {
  background: var(--neutral-bg);
  border-color: transparent;
  color: var(--text);
}
.subbar .chip.active {
  background: transparent;
  border-bottom-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}
body[data-bar="solid"] .subbar .chip {
  background: transparent;
  border-color: transparent;
  color: rgba(255, 255, 255, 0.78);
}
body[data-bar="solid"] .subbar .chip:not(.active):hover:not(:disabled):not(.locked) {
  background: rgba(255, 255, 255, 0.08);
  border-color: transparent;
  color: #fff;
}
body[data-bar="solid"] .subbar .chip.active {
  background: transparent;
  border-bottom-color: #fff;
  color: #fff;
}

/* Segunda fila de la documentación: lo que se HACE con lo listado, a la derecha y
   separado de los filtros, que deciden qué se lista. Se parte en varias líneas antes
   que desbordarse, igual que los filtros. */
.acciones-docs {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* Un enlace con aspecto de botón: sin esto se lleva el color y el subrayado de enlace
   del navegador, y en un pie de modal —al lado de «Cancelar»— parecía otra cosa. Va de
   enlace y no de botón porque la descarga la hace el navegador con el `href`. */
a.btn {
  text-decoration: none;
  color: var(--text);
  background: var(--panel);
  border-color: var(--border-strong);
}
a.btn:hover { border-color: var(--accent); color: var(--accent); }

/* El selector de tipos del inventario: el mismo de los filtros, pero a todo el ancho.
   En la barra de filtros compite por sitio con otros cinco controles; aquí el modal es
   suyo, así que el botón, el menú y cada ficha ocupan la línea entera. Apiladas y
   anchas son además un blanco más fácil de pulsar. */
.campo-tipos-inv,
.campo-tipos-inv .select-tipos { width: 100%; }
.campo-tipos-inv .menu-tipos .chip-tipo { flex: 1 1 100%; }

/* El rango: los dos campos comparten el ancho y la «y» no se estira. */
.rango-inv { display: flex; align-items: center; gap: 8px; }
.rango-inv input { flex: 1; min-width: 0; }

/* «Quitar fechas» vive en la etiqueta del campo, a la derecha: aparece solo cuando hay
   algo que quitar, así que no puede ocupar sitio fijo. */
.modal .field > label { display: flex; align-items: baseline; gap: 8px; }
.modal .field > label .btn-link { margin-left: auto; padding: 0 4px; font-size: 11px; }

/* ---------------------------------------------------------------- Fechas del ticket
   El modal que registra la vida de un ticket —aprobación, entrega a pruebas y salidas a
   producción— y la marca que deja en la fila de la tabla. */

/* «ESTO TIENE ALGO DETRÁS»: un solo realce para todos los botones de la celda de
   acciones que guardan datos por ticket —las fechas y los enlaces—. Nació solo para el
   calendario y el de enlaces se pintó por su cuenta en azul; eran dos reglas para una
   misma idea, y se leían como dos cosas distintas. Ahora la regla es una: el que tiene
   datos se enciende igual, y quien mira la fila sabe de un vistazo qué hay sin abrir.
   En verde y no en el azul de la aplicación porque el azul es el color de «el ratón está
   encima», y un estado que se ve igual que un hover no es un estado.
   Los demás botones de la celda —ver, descargar, copiar la ruta, abrir la carpeta— no se
   encienden nunca: hacen lo mismo en todas las filas, así que un realce siempre puesto no
   distinguiría nada. */
.btn-ver.con-datos {
  color: var(--ok);
  border-color: var(--ok);
  background: color-mix(in srgb, var(--ok) 10%, var(--panel));
}
.btn-ver.con-datos:hover { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }

/* «Fechas del ticket» (modules/ticketDates): a vertical timeline. The body scrolls alone, so
   the header and «Guardar» never leave the screen. */
.modal.modal-fechas { width: 600px; max-width: calc(100vw - 32px); }
.modal-fechas > .body { display: flex; flex-direction: column; gap: 16px; max-height: min(72vh, 680px); overflow-y: auto; }
.modal-fechas > .body > * { flex-shrink: 0; }
.modal-fechas > footer .spacer { flex: 1; }
.fechas-actualizado { display: inline-flex; align-items: center; gap: 4px; }

/* The rail: one line behind the marks, from the first to the last milestone */
.fechas-linea { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.fechas-hito { position: relative; display: grid; grid-template-columns: 28px 1fr; gap: 14px; padding-bottom: 18px; }
.fechas-hito:last-child { padding-bottom: 0; }
.fechas-hito::before {
  content: ""; position: absolute; left: 13px; top: 30px; bottom: 2px; width: 2px;
  background: var(--border); border-radius: 2px;
}
.fechas-hito:last-child::before { display: none; }
.fechas-hito.fechas-hecho::before { background: var(--accent); opacity: .45; }

/* The mark: hollow while the milestone has no day, filled once it has one */
.fechas-marca {
  width: 28px; height: 28px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  border: 2px solid var(--border); background: var(--panel); color: var(--muted);
  font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; position: relative; z-index: 1;
}
.fechas-hecho .fechas-marca { border-color: var(--accent); background: var(--accent); color: #fff; }

.fechas-hito-cuerpo {
  min-width: 0; display: flex; flex-direction: column; gap: 8px;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px;
}
.fechas-hecho > .fechas-hito-cuerpo { border-color: color-mix(in srgb, var(--accent) 35%, var(--border)); }
.fechas-hito-cabecera { display: flex; align-items: flex-start; gap: 12px; }
.fechas-hito-texto { flex: 1; min-width: 0; }
.fechas-hito-texto h4 { margin: 0; font-size: 14px; }
.fechas-hito-texto .hint { margin: 2px 0 0; line-height: 1.45; }
/* The global input rule (100% wide, with its :not() chain) would win over a bare class */
.fechas-hito-cabecera > input.fechas-dia:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(.swal2-input) { width: 170px; flex: none; }

/* How long after the previous milestone: a small chip under the title */
.fechas-lapso {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 600;
  background: var(--accent-soft); color: var(--accent);
}

/* The own releases: header and rows share one grid, so one release or six line up */
.fechas-total {
  flex: none; display: inline-flex; align-items: center; gap: 4px; padding: 3px 10px; border-radius: 999px;
  background: var(--neutral-bg); font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.fechas-salidas { display: flex; flex-direction: column; gap: 6px; }
.fechas-salida { display: grid; grid-template-columns: minmax(0, 1fr) 120px 30px; align-items: center; gap: 8px; }
.fechas-salida-cab { font-size: 11px; color: var(--muted); font-weight: 600; }
.fechas-salida input { min-width: 0; }
.fechas-horas { display: flex; align-items: center; gap: 6px; }
/* Hours read as a column: right-aligned, fixed-width digits */
.fechas-horas input { text-align: right; font-variant-numeric: tabular-nums; }
.fechas-vacio {
  margin: 0; display: flex; align-items: center; gap: 8px; padding: 10px 12px;
  border: 1px dashed var(--border); border-radius: 8px; color: var(--muted); font-size: 12.5px;
}
.fechas-vacio .mdi { font-size: 18px; }
button.fechas-agregar {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px;
  border: 1px dashed var(--accent); border-radius: 8px; background: transparent; color: var(--accent);
  font-size: 12.5px; font-weight: 600; cursor: pointer;
}
button.fechas-agregar:hover { background: var(--accent-soft); }

/* The shared windows, read only: a lock and another background say it is not changed here */
.fechas-compartidas { display: flex; flex-direction: column; gap: 4px; padding: 10px 12px; border-radius: 8px; background: var(--neutral-bg); }
.fechas-compartidas-titulo { display: flex; align-items: center; gap: 6px; font-size: 12.5px; }
.fechas-compartidas-titulo .mdi { color: var(--muted); }
.fechas-compartida { display: grid; grid-template-columns: 100px 1fr auto; align-items: baseline; gap: 10px; font-size: 12px; }
.fechas-compartida strong { font-variant-numeric: tabular-nums; }

.fechas-avisos { display: flex; flex-direction: column; gap: 4px; }

@media (max-width: 560px) {
  .fechas-hito-cabecera { flex-direction: column; }
  .fechas-hito-cabecera > input.fechas-dia:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(.swal2-input) { width: 100%; }
}

/* ------------------------------------------------- Ventanas de salida a producción
   El modal del botón «Ventana»: el listado de ventanas, los tickets de cada una
   desplegados dentro de su fila, y el editor. Todo en el MISMO modal, porque apilar
   fondos oscuros deja la pantalla negra y el de arriba se cierra pisando al de abajo. */

.modal.modal-ventanas { max-width: 720px; }
.modal-ventanas .body { max-height: min(68vh, 620px); overflow-y: auto; }
.modal-ventanas > footer .spacer { flex: 1; }

/* Volver al listado desde el editor: va en la cabecera, delante del título, porque es
   de donde se viene y no una acción más del pie. */
.volver-ventanas { padding: 2px 8px; font-size: 11px; margin-right: 8px; }
.volver-ventanas .mdi { font-size: 14px; line-height: 1; }

/* El listado. Una rejilla que comparten la cabecera y todas las filas: con una ventana
   o con veinte, fecha, horas y conteo caen siempre en el mismo sitio. */
.tabla-ventanas { display: flex; flex-direction: column; gap: 2px; }
.ventana-fila {
  display: grid;
  grid-template-columns: 110px 80px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  border-radius: var(--radius);
  font-size: 12px;
}
.ventana-fila:not(.ventana-cabecera):hover { background: var(--neutral-bg); }
.ventana-fila.desplegada { background: var(--accent-soft); }
.ventana-cabecera { font-size: 11px; color: var(--muted); font-weight: 600; padding-bottom: 0; }
.ventana-fila .num { text-align: right; font-variant-numeric: tabular-nums; }

/* El conteo de tickets es un BOTÓN: es lo que se pulsa para ver quiénes fueron en esa
   salida. Se deja con aire a la izquierda para que no parezca una columna de texto. */
.cuenta-tickets { justify-self: start; gap: 4px; padding: 3px 8px; font-size: 12px; }
.cuenta-tickets .mdi { font-size: 15px; line-height: 1; }
.acciones-ventana { display: flex; gap: 6px; }

/* EL RUNBOOK ADJUNTO de una ventana.
   Una sola línea: el archivo, su peso y los tres gestos. El `<input type="file">` del
   navegador no se puede peinar, así que se esconde y lo dispara el botón de al lado; eso
   obliga a limpiar su valor en cada elección, o volver a elegir el mismo archivo no
   dispara `change` y parece que el botón no responde (está en el componente). */
.adjunto-runbook { display: flex; flex-direction: column; gap: 6px; }
.adjunto-runbook input[type="file"] { display: none; }
.runbook-ficha {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--neutral-bg);
  font-size: 12px;
}
.runbook-ficha > .mdi { font-size: 16px; color: var(--accent); }
/* El nombre cede antes que los botones: son largos («RUNBOOK-PRODUCCION-24092026.html»)
   y lo que no puede desaparecer de la fila es lo que se puede hacer con él. */
.runbook-nombre { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.runbook-ficha .btn-link { padding: 2px 6px; font-size: 11px; white-space: nowrap; }
.runbook-ficha .btn-link.peligro { color: var(--danger); }
.runbook-ficha .btn-link.peligro:hover { border-color: var(--danger); }
.runbook-vacio { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* La observación de una sesión de pruebas de carga, bajo su fila. Sangrada como el
   detalle y en dos líneas como mucho: es una explicación, no un párrafo que empuje el
   listado; el texto entero está en su tooltip y en el editor. */
.nota-sesion {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: -2px 8px 6px 18px;
  color: var(--muted);
  font-size: 11.5px;
  line-height: 1.45;
}
.nota-sesion .mdi { font-size: 13px; line-height: 1; }

/* Los tickets de la ventana, desplegados bajo su fila y sangrados: se ve de dónde
   cuelgan sin tener que recordar en qué fila se pulsó. */
.ventana-detalle {
  margin: 0 8px 6px 18px;
  padding: 8px 10px;
  border-left: 2px solid var(--accent);
  background: var(--neutral-bg);
  border-radius: 0 var(--radius) var(--radius) 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.ticket-de-ventana {
  display: grid;
  grid-template-columns: 110px 1fr auto;
  align-items: baseline;
  gap: 10px;
  font-size: 12px;
}
.ticket-de-ventana strong { font-variant-numeric: tabular-nums; }
.titulo-ticket { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); }

/* El reparto en vivo: destacado, porque es lo que hay que leer ANTES de guardar. */
.reparto-vivo {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 8px 10px;
  border: 1px solid var(--accent);
  background: var(--accent-soft);
  border-radius: var(--radius);
  color: var(--accent);
  font-size: 12px;
}
.reparto-vivo .mdi { font-size: 16px; line-height: 1; flex: none; }

/* Los tickets ya elegidos, a la vista y con lo que le toca a cada uno: el reparto se
   entiende mirando la lista, no haciendo la división uno mismo. */
.elegidos { display: flex; flex-wrap: wrap; gap: 6px; }
.chip-ticket {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 4px 3px 8px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--panel);
  font-size: 11px;
  /* La ficha ENTERA envuelve a la siguiente línea si no cabe; lo que no vale es que el
     texto DE DENTRO se parta ("TL-\n10001"). Explícito y no heredado: en la celda de
     Ticket(s) el padre pasó a `white-space: normal` para que varias fichas se acomoden
     en la fila, y sin esto esa misma regla le partía el número a cada una. */
  white-space: nowrap;
}
/* A date chip while «Mes de pago» is on: kept (its value comes back) but not applied */
.chip-ticket.chip-no-aplica { opacity: 0.6; text-decoration: line-through; text-decoration-thickness: 1px; }
.chip-ticket .chip-horas { color: var(--muted); font-variant-numeric: tabular-nums; }
.chip-ticket button {
  display: inline-flex;
  align-items: center;
  border: 0;
  background: none;
  padding: 0 2px;
  color: var(--muted);
  cursor: pointer;
}
.chip-ticket button:hover { color: var(--danger); }
.chip-ticket .mdi { font-size: 14px; line-height: 1; }

/* ---------------------------------------------------------------- CREAR UN TICKET
   El formulario va en GRUPOS separados por una línea: son cinco preguntas distintas
   —qué ticket es, cómo se clasifica, cuánto cuesta, dónde entra y su documento— y una
   lista corrida de doce campos obliga a leerlos todos para contestar uno. */
.modal-crear-ticket .body { gap: 14px; }
.grupo-ticket { display: flex; flex-direction: column; gap: 10px; }
.grupo-ticket + .grupo-ticket { border-top: 1px solid var(--border); padding-top: 14px; }
.grupo-ticket > h4 {
  margin: 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  display: flex;
  align-items: baseline;
  gap: 8px;
}
/* El prefijo pegado al campo: se ve que la clave es «TL-11868» y no se teclea dos veces. */
.campo-clave { display: flex; align-items: center; gap: 0; }
.campo-clave .prefijo-clave {
  padding: 0 8px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--border);
  border-right: 0;
  border-radius: var(--radius) 0 0 var(--radius);
  background: var(--neutral-bg);
  color: var(--muted);
}
.campo-clave input { flex: 1; min-width: 0; border-radius: 0 var(--radius) var(--radius) 0; }
.tipos-elegibles { display: flex; flex-wrap: wrap; gap: 6px; }
.fila-relacionado { align-items: center; }
.fila-relacionado .campo-corto { flex: 0 0 110px; min-width: 110px; }
/* Cinco fases en una fila: la estimación se lee de un vistazo, como en la tabla. */
.fila-fases > .field { flex: 1 1 90px; min-width: 90px; }
.fila-fases input.num { text-align: right; font-variant-numeric: tabular-nums; }
.modal-crear-ticket .total-vivo strong { font-variant-numeric: tabular-nums; }
.modal-crear-ticket .aviso-reparto { align-items: flex-start; line-height: 1.45; }
.modal-crear-ticket .aviso-reparto .mdi { margin-top: 1px; }
.campo-archivo-oculto { display: none; }
.modal-crear-ticket .runbook-nombre { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.modal-crear-ticket > footer .label-danger { margin-right: auto; align-self: center; }
/* «Crear también en Azure DevOps» (D-32): el interruptor y el bloque del work item */
.interruptor-devops { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; cursor: pointer; }
.interruptor-devops > span:first-of-type { font-weight: 600; }
.interruptor-devops .hint { flex-basis: 100%; }
.interruptor-devops:has(input:disabled) { cursor: not-allowed; opacity: .85; }
.grupo-devops { padding: 12px; border: 1px solid var(--accent); border-radius: 10px; }
.grupo-devops > h4 .mdi { color: var(--accent); }

/* El origen de la fila en la tabla: un ticket creado desde aquí lleva su carpeta en el
   repositorio, y hasta que la tenga hay que poder distinguirlo. Discreto a propósito:
   es un dato de servicio, no una columna más. */
.marca-carpeta {
  display: inline-flex;
  align-items: center;
  margin-left: 4px;
  font-size: 13px;
  line-height: 1;
  vertical-align: text-bottom;
  cursor: help;
}
.marca-carpeta.carpeta-creada { color: var(--ok); }
.marca-carpeta.carpeta-pendiente { color: var(--warn); }
.marca-carpeta.carpeta-error { color: var(--danger); }
/* Cuando la carpeta falta, la marca es un BOTÓN: reintentarla es lo único que hay que
   hacer, y mandar a buscar la acción a otro sitio sobra. Se le quita el aspecto de botón
   —es un icono dentro de una celda— pero conserva su foco de teclado. */
button.marca-carpeta {
  border: 0;
  padding: 0;
  background: none;
  font-family: inherit;
}
.marca-carpeta.marca-reintentable { cursor: pointer; }
.marca-carpeta.marca-reintentable:hover:not(:disabled) { filter: brightness(1.25); }
.marca-carpeta.marca-reintentable:disabled { cursor: progress; opacity: 0.7; }
.marca-carpeta:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

/* El buscador de tickets, con su lista en una caja de alto fijo: sin tope, marcar seis
   tickets empujaba el pie del modal fuera de la pantalla. */
.lista-tickets {
  max-height: 200px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 4px;
}
.opcion-ticket {
  display: grid;
  grid-template-columns: auto 100px 1fr;
  align-items: center;
  gap: 8px;
  padding: 4px 6px;
  border-radius: 4px;
  font-size: 12px;
  cursor: pointer;
}
.opcion-ticket:hover { background: var(--neutral-bg); }
.opcion-ticket input { width: auto; }
/* Una lista pegada en el buscador (components/BuscadorDeTickets.js): «Marcar los N» y el aviso
   de lo que no se encontró, entre el campo y la caja de candidatos. */
.marcar-lista { display: flex; align-items: center; gap: 8px; margin: 6px 0; }
.aviso-lista { margin: 6px 0; }


/* La cabecera de las horas, sobre la columna que encabeza: el valor va alineado a la
   derecha, y con la etiqueta a la izquierda las dos no se leían como una sola columna. */
.ventana-cabecera span:nth-child(2) { text-align: right; }

/* El triángulo que pliega una rama del árbol de permisos. Va DENTRO de la fila, que es
   un `<label>`, así que su clic se para aparte: si no, desplegar marcaría el permiso. */
.desplegar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; flex: none;
  border: 0; border-radius: 4px; padding: 0;
  background: transparent; color: var(--muted); cursor: pointer;
}
.desplegar:hover { background: var(--accent-soft); color: var(--text); }
.desplegar .mdi { font-size: 18px; line-height: 1; }
/* Las hojas no tienen triángulo, pero sí su hueco: sin él, sus etiquetas quedaban
   desalineadas respecto a las ramas de su mismo nivel. */
.permiso > .permiso-icono:first-child,
.permiso > .permiso-punto:first-child { margin-left: 20px; }

/* La ficha de un rol en la tabla de usuarios. */
.chip.rol { background: var(--accent-soft); border-color: var(--accent); }

/* La barra del árbol de permisos, pegada arriba mientras se scrollea: con ochenta filas,
   el contador y los atajos tienen que seguir a la vista. */
.arbol-barra {
  position: sticky; top: -14px; z-index: 2;
  display: flex; align-items: center; gap: 8px;
  margin: -14px -14px 0; padding: 10px 14px;
  background: var(--panel); border-bottom: 1px solid var(--border);
}

/* «Conceder todo» y «Quitar todo» de todo el árbol, en su barra. Deshabilitados cuando
   no hay nada que dar o nada que quitar: el gris apagado es la respuesta, y el `title`
   dice por qué — un botón que no reacciona y no explica nada se lee como una avería. */
.arbol-barra .btn-link:disabled { opacity: 0.4; cursor: default; border-color: transparent; color: var(--muted); }

/* El aviso del techo baja a su propia línea, y los botones no se encogen nunca. En una
   sola fila, «Quitados 66. 4 siguen puestos: no los podrías volver a conceder.» le comía
   el sitio a los botones: «Conceder todo» partido en dos líneas y «Quitar todo» cortado
   por el borde del modal. El aviso explica lo que acaba de pasar; dejar de poder pulsar
   el botón siguiente para leerlo es cambiar un problema por otro peor. */
.arbol-barra { flex-wrap: wrap; }
.arbol-barra .btn-link { flex: none; white-space: nowrap; }
.arbol-barra .arbol-techo { flex: 1 1 100%; order: 1; cursor: help; }

/* The role modal scrolls only its tree: the body stops scrolling, the fields and the
   «Permisos» bar keep their place, and the list takes the height that is left. */
.modal .body.body-arbol { overflow: hidden; }
.body-arbol .arbol-barra { position: static; margin: 0 -14px; flex: none; }
.body-arbol .arbol-lista {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 10px;
  margin: -10px -14px -14px; padding: 10px 14px 14px;
}

/* El contador y los atajos de un módulo, dentro de su propia fila. Antes vivían en una
   cabecera por módulo: ocho cabeceras ocupaban más que los permisos que encabezaban. */
.permiso-acciones {
  display: flex; align-items: center; gap: 6px; flex: none; margin-left: auto;
}
.permiso-acciones .btn-link { font-size: 11px; }
/* «Grant all» / «Remove all» of a branch: icon buttons, a little smaller than the row's */
.permiso-acciones .btn-rama { width: 26px; height: 26px; }
.permiso-acciones .btn-rama .mdi { font-size: 15px; }

/* «+1» en la columna Ventana: cuántas salidas más tuvo el ticket además de la que se
   enseña. Pequeño y apagado, para que la fecha siga siendo lo que se lee. */
.mas-ventanas {
  margin-left: 4px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--neutral-bg);
  color: var(--muted);
  font-size: 10px;
}

/* ------------------------------------------------- Relación entre un DevOps y su TL */

/* LAS CELDAS QUE SE EDITAN CON DOBLE CLIC: la del ticket, la de la ventana, la de «Pago»
   y la de «Despliegue» (el mes de esas horas).
   No marcan la fila —su gesto es otro—, así que tampoco llevan el cursor de «esto marca»
   del resto. Pero tampoco pueden quedarse mudas: un tooltip solo lo descubre quien ya
   sospecha que ahí hay algo, y el gesto se estaba perdiendo. Así que lo anuncian sin
   necesidad de leer nada — el cursor de celda editable y un realce al pasar por encima —
   y las dos igual, porque si el doble clic es LA forma de editar en esta tabla tiene que
   verse siempre igual y no columna por columna.
   La de «P. carga» se queda fuera a propósito: es de solo lectura y sus horas se
   gobiernan desde «Horas de carga», así que anunciar ahí un doble clic sería mentir. */
.tabla-docs tbody .col-ventana.col-editable,
.tabla-docs tbody .col-mes-pago.col-editable,
/* La de «Despliegue» solo cuando la cuenta PUEDE apuntar ese mes —de ahí la clase que pone
   la fila—: el permiso nace concedido a nadie, y anunciar un doble clic que va a responder
   403 es peor que no anunciarlo. Las horas se siguen viendo igual. */
.tabla-docs .col-despliegue.col-editable { cursor: cell; }
/* The Ticket cell keeps the normal pointer: the cell cursor (a «+») read as something to
   click, and its blue highlight on hover was removed for the same reason */
.tabla-docs .col-ticket { cursor: default; }
/* Los ids del mismo trabajo, uno por línea. El de la fila con el color del texto y los
   referenciados apagados: los dos son el mismo ticket, pero solo el primero es la
   carpeta que se está listando, y si se vieran iguales nadie sabría cuál abre el
   documento. Sin sangrar el segundo: la columna ya va justa y la diferencia de tono
   basta para leer cuál es cuál. */
.tabla-docs .col-ticket .ticket-propio { display: block; color: var(--text); }
/* The related ids, smaller than the row's own: they are context under it, not peers */
.tabla-docs .col-ticket .ticket-referido { display: block; color: var(--muted); font-size: 9px; line-height: 1.25; }

/* EL BOTÓN DE COPIAR de cada id, que NO puede ensanchar la columna.
   Va posicionado sobre el final de su propia línea —fuera del flujo, así que no ocupa—
   y aparece al pasar el ratón por esa línea o al recibir el foco con el teclado. Lleva
   el fondo de la fila detrás para que se lea encima de lo que tape: la columna mide 86 px
   y con «DevOps-6005» no sobra sitio donde ponerlo al lado. */
.tabla-docs .col-ticket .linea-id { position: relative; display: block; }
.copiar-id {
  position: absolute;
  right: -2px;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  padding: 1px 2px;
  border: 0;
  border-radius: 3px;
  background: var(--panel);
  color: var(--muted);
  cursor: pointer;
  opacity: 0;
  /* Invisible NO es inexistente: sin esto seguiría recibiendo el ratón sobre un icono
     que no se ve, y pulsar el hueco de la celda dejaría de marcar la fila. */
  pointer-events: none;
}
.copiar-id .mdi { font-size: 12px; line-height: 1; }
/* Al pasar por la línea, y también al tabular hasta él: un botón que solo aparece con el
   ratón es inalcanzable con el teclado, y uno que nunca aparece es una trampa. */
.linea-id:hover .copiar-id,
.copiar-id:focus-visible { opacity: 1; pointer-events: auto; }
.copiar-id:hover { color: var(--accent); background: var(--accent-soft); }
.tabla-docs tbody tr:hover .copiar-id { background: var(--accent-soft); }
.tabla-docs tbody tr.marcada .copiar-id { background: var(--accent-soft); }
/* Only where the account may edit by double click: a frame on a cell that opens nothing
   promises a gesture that does not exist */
.tabla-docs tbody .col-ventana.col-editable:hover,
.tabla-docs tbody .col-mes-pago.col-editable:hover,
.tabla-docs tbody .col-despliegue.col-editable:hover {
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent);
}

/* Las fichas de la columna Tipo van APILADAS, una debajo de otra.
   En fila, un DevOps con su TL y su estado pedían el ancho de dos y tres fichas para
   escribir tres palabras cortas, y ese ancho salía del Título y del sitio que a 1440 no
   había: la columna medía 98 px y ahora mide 74, que son justo los once que le faltaban
   a la tabla para caber entera con los cinco botones de Acciones.
   El precio, elegido a sabiendas: la fila crece de alto cuando hay más de una ficha.
   Para que eso no deje la tabla con aspecto de escalera, cada ficha ocupa el ancho
   entero de la celda —así quedan todas iguales y alineadas a la izquierda, leyéndose
   como un bloque y no como un borde dentado— y el resto de las celdas sigue centrado,
   que es lo que hace la tabla por su cuenta.
   En bloque y no en una caja flexible, por lo mismo que la celda de acciones: siendo
   celda de tabla, el centrado vertical lo pone la tabla y no hay que pelearse con el
   alto. El ancho lo marca ahora la etiqueta más larga, en vez del `min-width` de 88 px
   que sostenía la igualdad cuando iban en fila. */
.tabla-docs .col-tipo .tipo-doc { display: block; min-width: 0; }
.tabla-docs .col-tipo .tipo-doc + .tipo-doc { margin-top: 3px; }
/* Narrower Tipo column: the widest chip ("Estimación", "QA P2H") sets its width, so the
   table's chips drop to the size of the dates (10 px) with less side padding. Only in
   the working view; presenting and the filter chips keep their size. */
html:not([data-presentacion]) .tabla-docs .col-tipo .tipo-doc { font-size: 10px; padding: 1px 5px; }
/* The table's chips SOLID, with white text: vivid like the app's bars instead of a pale
   tint. Fixed deep shades rather than the theme's `--c`, whose dark-mode variants are
   light and would not carry white text. */
.tabla-docs .col-tipo .tipo-doc { background: var(--c-solid, var(--c)); color: var(--c-ink, #fff); }
/* The Tipo chips: the plain cursor unless the chip has something — links to open, or
   who asked for a Solicitud. Without this they took the row's pointer */
.tabla-docs .col-tipo,
.tabla-docs .col-tipo .tipo-doc { cursor: default; }
.tabla-docs .col-tipo .tipo-doc.tipo-con-info { cursor: pointer; }
/* A TL/DevOps chip with links: it opens them on click, so it says so */
.tabla-docs .col-tipo .tipo-doc.tipo-con-enlaces { cursor: pointer; }
.tabla-docs .col-tipo .tipo-doc.tipo-con-enlaces:hover { background: color-mix(in oklch, var(--c-solid, var(--c)) 85%, white); }
.tabla-docs .col-tipo .tipo-doc.tipo-con-enlaces:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.modal.modal-relacion { max-width: 430px; }
.modal-relacion > footer .spacer { flex: 1; }
.modal-relacion > footer .btn-link:first-child { color: var(--danger); border-color: var(--border-strong); }
.modal-relacion > footer .btn-link:first-child:hover { border-color: var(--danger); }

/* ------------------------------------- Apuntar la ventana desde la propia celda */

/* El cursor y el realce de esta celda van con los de la del ticket, arriba: las dos se
   editan con el mismo gesto y se anuncian igual. */

/* El día y los dos botones, en una línea y sin estirar la columna. */
.editor-ventana { display: inline-flex; align-items: center; gap: 4px; }
.editor-ventana input[type="date"] { width: auto; min-width: 128px; padding: 3px 6px; font-size: 11px; }
.editor-ventana .btn-ver { width: 24px; height: 24px; font-size: 12px; }
.editor-ventana .btn-ver .mdi { font-size: 14px; }

/* Lo que va a pasar al guardar, debajo del campo. Se deja partir en varias líneas: es
   una frase, no un dato de la tabla, y recortarla sería no decirlo. */
.aviso-en-linea {
  display: block;
  margin-top: 4px;
  max-width: 230px;
  white-space: normal;
  line-height: 1.4;
}
.aviso-en-linea.error { color: var(--danger); }

/* ------------------------------------- Apuntar el mes de pago desde la propia celda */

/* El cursor y el realce de esta celda van con los de la del ticket y la ventana, arriba: las
   tres se editan con el mismo gesto y se anuncian igual. El aviso de debajo del campo es el
   mismo `.aviso-en-linea`, por lo mismo.

   La columna va NOWRAP y estrecha: lo que enseña es «oct 2026», ocho caracteres, y el nombre
   entero del mes vive en el tooltip.
   Quien fijaba su ancho NO era el valor sino la CABECERA: «Mes de pago» con su flecha de
   ordenación pedía 102 px contra los 63 que pide «oct 2026», y ese exceso desbordaba la tabla
   24 px a 1440 px DE FORMA PERMANENTE —editara alguien o no—, con el chip de Estado cortado en
   «En re» en todas las filas. El tope de 92 px de aquí no bastaba: solo recortaba el rótulo,
   no el hueco que la columna le pedía a la tabla. Lo que lo arregla es el rótulo corto («Pago»,
   en la plantilla), y entonces la columna mide lo que su valor y la tabla vuelve a medir lo que
   medía antes de que existiera esta columna: lo que ocupa sale del Título, que es la que está
   hecha para ceder (recorta con puntos suspensivos y lleva su tooltip).
   El tope se queda como techo por si algún día el valor crece, no como la medida de nada. */
.tabla-docs .col-mes-pago { white-space: nowrap; max-width: 92px; }

/* EL SELECTOR DE MES: el año arriba, los doce meses debajo y los botones al pie, en una
   columna de ANCHO FIJO, y el ancho es lo que hay que mirar: el editor vive DENTRO de la
   celda —la caja de la tabla recorta lo que flota, así que no puede salirse— y mientras se
   edita es ÉL quien manda sobre el ancho de la columna y, con ella, sobre si la de Acciones
   sigue en pantalla a 1440 px.
   140 px es lo que mide la rejilla con las tres letras del mes legibles y el pie sin
   apretar; por debajo, «Sin mes» y los dos botones empiezan a pisarse. Medido en una maqueta
   de la tabla con esta misma hoja a 1440 px: la celda pasa de 92 px a 150 mientras se edita,
   donde el campo nativo que había antes la dejaba en 235 (Chrome le añade su icono de
   calendario al `min-width`). Es decir, 85 px MENOS de los que se llevaba el editor que
   sustituye.
   Hereda la tipografía monoespaciada de la celda a propósito: con tres letras por mes, la
   rejilla queda cuadrada sin tener que darle un ancho a cada casilla. */
.editor-mes-pago-celda, .editor-ventana-celda, .docs-stats { display: contents; }
.editor-mes-pago { display: inline-flex; flex-direction: column; align-items: stretch; gap: 4px; width: 140px; }
.editor-mes-pago .btn-ver { width: 24px; height: 24px; font-size: 12px; }
.editor-mes-pago .btn-ver .mdi { font-size: 14px; }

/* EL CAMPO DE HORAS del editor (decisión D-26), cuando la celda «Despliegue» las pide. Va
   ARRIBA y a todo el ancho porque es el dato que trae a esta celda: el mes es la consecuencia.
   Su rótulo encima y no un `placeholder` a secas: lo que se escribe aquí acaba en una factura,
   y un campo numérico sin etiqueta dentro de una tabla de horas no dice en qué unidad va. */
.horas-despliegue-campo { display: flex; flex-direction: column; gap: 2px; }
.horas-despliegue-campo > .hint { font-size: 9px; text-transform: uppercase; letter-spacing: 0.04em; }
.horas-despliegue-input {
  width: 100%;
  min-width: 0;
  padding: 3px 6px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--card);
  color: var(--text);
  font: inherit;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.horas-despliegue-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* El año y sus dos flechas, repartidos a los extremos. */
.mes-pago-anio { display: flex; align-items: center; justify-content: space-between; gap: 4px; }
.mes-pago-anio .anio { font-size: 12px; font-weight: 600; color: var(--text); letter-spacing: 0.02em; }

/* Los doce meses, cuatro por fila: tres filas que caben en el alto de una celda sin
   convertir la fila de la tabla en un bloque. */
.mes-pago-rejilla { display: grid; grid-template-columns: repeat(4, 1fr); gap: 3px; }
.mes-opcion {
  padding: 3px 0;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  font: inherit;
  font-size: 11px;
  line-height: 1.25;
  cursor: pointer;
}
/* El realce del ratón en gris y NO en el azul del tema: el azul ya significa «este es el
   elegido», y con los dos del mismo color se leía como que el mes cambiaba al pasar por
   encima. */
.mes-opcion:hover { border-color: var(--border-strong); background: var(--neutral-bg); }
.mes-opcion:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* EL ELEGIDO: relleno y con el borde marcado. Con el azul del tema de FONDO y texto blanco
   no se podía: en oscuro `--accent` se aclara (es lo que dice su propio comentario arriba) y
   el texto blanco encima se queda sin contraste. */
.mes-opcion.elegido {
  background: var(--accent-soft);
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
  color: var(--accent);
  font-weight: 700;
}
/* HOY es otra cosa que «elegido» y por eso se dice con otra marca: un punto debajo del mes.
   Los dos pueden coincidir —al abrir sobre una celda vacía coinciden— y entonces se ven las
   dos cosas a la vez, que es justo lo que hay que poder distinguir cuando no coinciden. */
.mes-opcion.hoy { position: relative; padding-bottom: 8px; }
.mes-opcion.hoy::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 3px;
  width: 4px;
  height: 4px;
  margin-left: -2px;
  border-radius: 50%;
  background: var(--accent);
}

/* El pie: vaciar a la izquierda, guardar y cerrar a la derecha. */
.mes-pago-pie { display: flex; align-items: center; gap: 4px; }
.mes-pago-pie .pie-hueco { flex: 1; }
/* «Partir en varios meses…» (los tramos de pago): el enlace del selector, la marca de la celda y el modal */
.mes-pago-partir { align-self: flex-start; font-size: 12px; padding: 0; }
.mes-pago-tramos { display: inline-flex; align-items: center; gap: 3px; }
.mes-pago-tramos.negativo { color: var(--warn); }
.modal.modal-tramos-pago { width: 720px; max-width: calc(100vw - 32px); }
.modal-tramos-pago > .body { display: flex; flex-direction: column; gap: 12px; max-height: min(74vh, 700px); overflow-y: auto; }
.modal-tramos-pago > .body > * { flex-shrink: 0; }
.modal-tramos-pago > footer .spacer { flex: 1; }
.tabla-tramos { width: 100%; border-collapse: collapse; }
.tabla-tramos th, .tabla-tramos td { padding: 4px 6px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: middle; }
.tabla-tramos .num { text-align: right; }
/* EL MES DE UN TRAMO (03-11-2026): un botón con el mes legible y, mientras se elige, la misma rejilla
   de la celda «Pago» DEBAJO, en el flujo de la celda. En el flujo y no flotando a propósito: el cuerpo
   del modal recorta lo que se sale (`overflow-y: auto`) y una rejilla flotante se quedaba a medias;
   la fila crece mientras se elige y vuelve sola a su alto al cerrar. Una sola abierta a la vez. */
.tabla-tramos .tramo-mes { display: inline-flex; flex-direction: column; align-items: stretch; gap: 4px; width: 150px; vertical-align: middle; }
.tabla-tramos .tramo-mes .mes-pago-boton { justify-content: flex-start; gap: 4px; padding: 4px 8px; font-size: 12px; white-space: nowrap; }
.tabla-tramos .tramo-mes .mes-pago-boton .mdi { font-size: 14px; color: var(--muted); }
.tabla-tramos .tramo-mes .mes-pago-boton.vacio { color: var(--muted); }
.tabla-tramos .tramo-mes .mes-pago-boton:disabled { cursor: default; opacity: 0.75; }
.tabla-tramos .tramo-mes .mes-pago-boton:disabled:hover { border-color: var(--border-strong); color: inherit; }
.tabla-tramos .tramo-mes .editor-mes-pago { width: 100%; }
.tabla-tramos .tramo-horas { width: 64px; text-align: right; }
.tabla-tramos tr.bloqueado td { opacity: 0.75; }
.tabla-tramos tr.fila-resto td { font-weight: 600; }
.tabla-tramos tr.fila-resto.negativo td { color: var(--warn); background: var(--warn-bg); }
@media (max-width: 640px) {
  .tabla-tramos .tramo-mes { width: 120px; }
  .tabla-tramos .tramo-horas { width: 48px; }
}
.mes-pago-quitar {
  padding: 2px 6px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 11px;
  cursor: pointer;
}
.mes-pago-quitar:hover { color: var(--danger); border-color: var(--danger); }
.mes-pago-quitar:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Editando, la celda deja de estar apretada: el editor es más ancho que «oct 2026» y con el
   tope de arriba el campo se recortaba. Solo mientras se edita, para que la columna vuelva
   sola a su sitio al salir. */
.tabla-docs .col-mes-pago:has(.editor-mes-pago) { max-width: none; }
/* Y el aviso NO puede ser lo que marque ese ancho. Con los 230 px que usa por defecto (el del
   editor de la ventana, que vive en una columna con más sitio) la celda se ensanchaba 65 px
   más que su propio editor y, a 1440, eso se lo comía la columna Estado, que quedaba en «Si».
   Aquí el aviso mide lo MISMO que el selector y crece hacia abajo, que es lo que no le quita
   ancho a nadie: los dos números van juntos a propósito, y el día que uno cambie cambia el
   otro. Medido en una maqueta de la tabla con esta misma hoja a 1440 px. */
.tabla-docs .col-mes-pago .aviso-en-linea { max-width: 140px; }

/* ------------------------------- Las horas de despliegue y el mes en el que se cobran */

/* DOS LÍNEAS EN UNA CELDA QUE NO CRECE DE ANCHO: las horas arriba y debajo, más pequeño, el
   mes en el que se pagan. Va en bloque y no al lado porque la columna mide lo que mide
   «Despliegue» (unos 70 px) y el mes a su derecha habría pedido medio centímetro más a una
   tabla que a 1440 px ya no tiene de dónde sacarlo. Crece de ALTO, que es lo que no le quita
   sitio a nadie. */
.tabla-docs .col-despliegue .despliegue-horas { display: block; }

/* Y SE VE QUE LA CIFRA ESTÁ APUNTADA A MANO (decisión D-26). Es la única de esta columna que no
   sale de un documento ni de una ventana, así que sin marca nadie sabría que detrás hay una
   decisión de alguien y no un cálculo. Un lápiz pequeño antes del número, y el número en el
   color del texto: es un dato decidido, no un aviso. El tooltip dice quién lo escribió y qué
   habría dicho la ventana; la marca distingue de un vistazo, no explica. */
.tabla-docs .col-despliegue .despliegue-horas.apuntada { color: var(--text); font-weight: 600; }
.tabla-docs .col-despliegue .marca-apuntada { font-size: 10px; line-height: 1; color: var(--accent); margin-right: 2px; vertical-align: baseline; }
.tabla-docs .col-despliegue .despliegue-mes { display: block; font-size: 9px; line-height: 1.25; }
/* The payment month(s) of P. carga, Gestión and Total, like Despliegue's */
.tabla-docs .col-gestion .gestion-mes,
.tabla-docs .col-carga .carga-mes,
.tabla-docs .total .total-mes { display: block; font-size: 9px; line-height: 1.25; color: var(--muted); white-space: nowrap; }

/* Y SE DISTINGUE A SIMPLE VISTA DE DÓNDE SALE ESE MES, que es lo que pidió Gerson: lo puesto
   a mano manda sobre lo deducido, y si los dos se vieran igual nadie sabría cuál está
   decidido y cuál lo acaba de calcular la pantalla.
   - deducido: gris y atenuado, como lo que la pantalla deduce de la ventana y cambiará solo
     si la ventana se mueve de día;
   - manual: el color del texto, porque es una decisión de una persona;
   - pendiente: en ámbar, que es lo único de los tres que pide algo —hay horas de despliegue
     y nadie puede decir en qué mes se cobran—.
   El tooltip de la celda dice además de dónde sale y cuál es el otro número: el color
   distingue de un vistazo, no explica. */
.tabla-docs .col-despliegue .despliegue-mes.mes-deducido { color: var(--muted); opacity: 0.8; }
.tabla-docs .col-despliegue .despliegue-mes.mes-manual { color: var(--text); }
.tabla-docs .col-despliegue .despliegue-mes.mes-pendiente { color: var(--warn); }

/* El editor dentro de esta celda, con los mismos dos topes que en la de «Pago» y por el mismo
   motivo: mientras se edita es ÉL quien manda sobre el ancho de la columna, y el aviso no
   puede ser quien lo marque (con sus 230 px por defecto se llevaba 65 px más que el propio
   selector, y a 1440 px eso se lo comía la columna Estado). El valor es el mismo a propósito:
   el día que cambie uno cambia el otro.
   Y el texto a la izquierda: la celda centra sus horas, y un selector centrado dentro de una
   columna estrecha deja el aviso con las líneas descuadradas. */
.tabla-docs .col-despliegue .editor-mes-pago { text-align: left; }
.tabla-docs .col-despliegue .aviso-en-linea { max-width: 140px; }


/* Documentación: los dos estados de carga.

   1. Al RECARGAR, una línea fina sobre la tabla. Su alto está siempre reservado (aunque
      no se vea), para que aparecer y desaparecer no empuje la tabla.
   2. En la PRIMERA carga, un esqueleto con la forma de lo que viene: los contadores y la
      tabla. El brillo que lo recorre dice que trabaja; la forma, qué está trayendo. */
.recarga-linea {
  position: relative;
  height: 3px;
  margin: 6px 0 2px;
  border-radius: 999px;
  overflow: hidden;
}
.recarga-linea.activa { background: var(--accent-soft); }
.recarga-linea.activa::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 35%;
  border-radius: inherit;
  background: var(--accent);
  animation: recarga-va 1.2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
@keyframes recarga-va {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(300%); }
}

.docs-esqueleto { display: flex; flex-direction: column; gap: 18px; padding-top: 6px; }
.esqueleto-tarjetas { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.esqueleto-tarjeta {
  display: flex; flex-direction: column; gap: 8px;
  padding: 16px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel);
}
.esqueleto-tabla { border-top: 1px solid var(--border); }
.esqueleto-fila {
  display: grid;
  grid-template-columns: 26px 1.1fr 0.8fr 2.6fr 0.7fr 0.7fr 1fr 1fr;
  gap: 18px;
  align-items: center;
  padding: 14px 4px;
  border-bottom: 1px solid var(--border);
}
.esqueleto-fila.cabecera { padding: 10px 4px; }
.esqueleto-fila.cabecera .esqueleto-bloque { height: 8px; width: 60%; }

/* Un trozo de esqueleto: su color de fondo y un brillo que lo cruza. */
.esqueleto-bloque {
  position: relative;
  display: block;
  height: 10px;
  border-radius: 6px;
  background: var(--neutral-bg);
  overflow: hidden;
}
.esqueleto-bloque::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, var(--esqueleto-brillo), transparent);
  animation: esqueleto-brillo 1.4s ease-in-out infinite;
}
@keyframes esqueleto-brillo {
  100% { transform: translateX(100%); }
}
.esqueleto-cifra { width: 64px; height: 26px; border-radius: 8px; }
.esqueleto-linea { height: 10px; }
.esqueleto-linea.corta { height: 8px; }
.esqueleto-check { width: 14px; height: 14px; border-radius: 4px; }
.esqueleto-pastilla { width: 56px; height: 18px; border-radius: 999px; }

.esqueleto-aviso {
  display: flex; align-items: center; gap: 10px;
  font-size: 13px; color: var(--muted);
}
.esqueleto-giro {
  width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid var(--accent-soft);
  border-top-color: var(--accent);
  animation: esqueleto-gira 0.8s linear infinite;
}
@keyframes esqueleto-gira { to { transform: rotate(360deg); } }

@media (max-width: 900px) {
  .esqueleto-tarjetas { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .esqueleto-fila { grid-template-columns: 26px 1fr 0.8fr 2fr; }
  .esqueleto-fila > :nth-child(n + 5) { display: none; }
}
/* Quien prefiere no ver animaciones ve el esqueleto quieto, no uno roto. */
@media (prefers-reduced-motion: reduce) {
  .esqueleto-bloque::after, .recarga-linea.activa::after { animation: none; }
  .recarga-linea.activa::after { width: 100%; opacity: 0.5; }
  .esqueleto-giro { animation-duration: 2.4s; }
}

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

/* ------------------------------------------- Contadores del listado (y su filtro) */

/* Más estrechos que las métricas de la vista de cifras: son tres y van encima de una
   tabla que ya va justa de ancho, así que se reparten sin empujarla. En una pantalla
   angosta caen uno debajo de otro solos, por el `auto-fit` que ya trae `.metricas`. */
.metricas-contadores { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); margin-bottom: 10px; }

/* Son botones, así que tienen que dejar de parecer un `<button>` y parecer la métrica
   vecina: sin el borde ni el fondo del botón, alineados a la izquierda y con el cursor
   que promete que pulsarlos hace algo. */
.metrica-filtro {
  align-items: flex-start;
  text-align: left;
  cursor: pointer;
  font: inherit;
}
.metrica-filtro:hover { border-color: var(--accent); }
.metrica-filtro.activa {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.metrica-filtro.activa .metrica-num,
.metrica-filtro.activa .metrica-eti { color: var(--accent); }

/* Columna «Pruebas de carga»: el encabezado «P. carga» va en una sola línea (`.num`
   ya lo deja en nowrap), como el resto de las fases. */
.tabla-docs .col-carga { cursor: default; }

/* Columna «Gestión»: la hermana de «P. carga» —vive en el grupo de estimación y no
   entra en el Total— con una diferencia de gesto: su celda SE PULSA y abre el desglose.
   Por eso su cifra va como enlace y no como texto plano: un número que se puede pulsar
   y no lo parece no lo pulsa nadie. Sin gestiones es una raya y no hay nada que pulsar. */
.tabla-docs .col-gestion { cursor: default; }
.celda-gestion {
  font-variant-numeric: tabular-nums;
  font-size: inherit;
  padding: 0;
}

/* ---------------------------------------------------- Estado del ticket */

/* La ficha del estado convive con las de tipo pero no se confunde con ellas: va con el
   borde de rayas en vez de continuo, porque son dos preguntas distintas —qué es el ticket
   y en qué va— y a un vistazo tienen que separarse. El color lo pone la paleta común. */
.ficha-estado { --c: var(--muted); border-style: dashed; }

/* Los tres estados del modal, en una línea: son pocos y se eligen de un vistazo. */
.fichas-estado { display: flex; flex-wrap: wrap; gap: 6px; }

/* El registro de cambios: misma rejilla para la cabecera y las filas, para que con una
   entrada o con diez las tres columnas caigan donde deben. */
.historial { display: flex; flex-direction: column; gap: 4px; max-height: 190px; overflow-y: auto; }
.historial-fila {
  display: grid;
  grid-template-columns: 110px 120px 1fr;
  align-items: center;
  gap: 8px;
  font-size: 11px;
}
.historial-cabecera { color: var(--muted); font-weight: 600; }
.historial-fila > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ------------------------------------------ La columna de Acciones, fijada a la derecha

   Aun recortando el título, la tabla no cabe en 1440 px y hay que desplazarla. Los
   botones de la fila no pueden ser lo primero que se pierde al hacerlo —ya pasó: se dio
   por perdida una columna que sí estaba—, así que Acciones se queda pegada al borde y el
   resto se desplaza por debajo.

   Fondo PROPIO en los tres estados de la fila (normal, con el ratón encima y marcada):
   una celda fija sin fondo deja ver pasar el texto de las columnas de debajo. Y una
   línea a la izquierda con un desvanecido, para que se entienda que ahí hay un corte y no
   un hueco.

   La de Horas de gestión (`.acciones-gestion`, el lápiz y la papelera) entra en la MISMA
   regla: a 1440 px también se sale por la derecha —menos que antes de paginar, porque con
   menos filas pintadas a la vez el navegador calcula columnas más angostas, pero sigue
   pasando—, y antes de este cambio el botón de borrar quedaba cortado o había que
   adivinar que la tabla seguía deslizando. Dos botones y no tres, así que no necesita la
   fila "marcada" (Gestión no tiene casillas de selección). */
.tabla-docs th.col-acciones,
.tabla-docs td.acciones,
.tabla-gestion th.col-acciones-gestion,
.tabla-gestion td.acciones-gestion {
  position: sticky;
  right: 0;
  background: var(--panel);
  border-left: 1px solid var(--border);
  box-shadow: -8px 0 8px -8px rgba(0, 0, 0, 0.45);
  z-index: 2;
}
/* La cabecera se fija por los DOS lados a la vez —arriba y a la derecha—, así que tiene
   que quedar por encima del resto de la cabecera, que solo se fija arriba. */
.tabla-docs th.col-acciones,
.tabla-gestion th.col-acciones-gestion { top: 0; z-index: 5; }
.tabla-docs tbody tr:hover td.acciones,
.tabla-docs tbody tr.marcada td.acciones,
.tabla-gestion tbody tr:hover td.acciones-gestion { background: var(--accent-soft); }

/* Que se VEA que hay más tabla a la derecha. En macOS la barra está oculta hasta que se
   arrastra, y eso fue lo que hizo creer que faltaba una columna. Se fuerza la barra
   horizontal —solo esa: la vertical se deja como la pinta el sistema, que ahí no engaña
   porque el alto sí se nota—. */
.tabla-scroll { scrollbar-width: thin; }
/* El `appearance: none` va en la regla BASE y no en la del eje: es lo que hace que el
   navegador cambie la barra flotante del sistema por una clásica, que ocupa sitio y por
   tanto se ve siempre. Puesto solo en `:horizontal` no surtía efecto —comprobado: la
   barra seguía ocupando 0 px—. El tamaño sí se da por eje. */
.tabla-scroll::-webkit-scrollbar { -webkit-appearance: none; appearance: none; width: 10px; height: 10px; }
.tabla-scroll::-webkit-scrollbar:horizontal { height: 10px; }
.tabla-scroll::-webkit-scrollbar:vertical { width: 10px; }
.tabla-scroll::-webkit-scrollbar-thumb:vertical {
  background: var(--border-strong);
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: content-box;
}
.tabla-scroll::-webkit-scrollbar-thumb:horizontal {
  background: var(--border-strong);
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: content-box;
}
.tabla-scroll::-webkit-scrollbar-thumb:horizontal:hover { background: var(--muted); background-clip: content-box; }
.tabla-scroll::-webkit-scrollbar-track:horizontal { background: transparent; }

/* Presentando no hay columna de Acciones ni desplazamiento lateral: la tabla enseña
   menos columnas y a letra grande. Se deshace lo de arriba para no dejar una sombra
   colgando en mitad de una tabla proyectada. */
html[data-presentacion] .tabla-docs th.col-acciones,
html[data-presentacion] .tabla-docs td.acciones { position: static; box-shadow: none; border-left: 0; }

/* El aviso de que la tabla sigue a la derecha. Apagado como el resto del pie: informa,
   no reclama, y desaparece solo en cuanto la tabla cabe entera. */
.aviso-lateral { display: inline-flex; align-items: center; gap: 4px; }
.aviso-lateral .mdi { font-size: 14px; line-height: 1; }

/* «sin asignar» en el listado de sesiones: unas horas apuntadas que todavía no se han
   repartido. Va donde iría el conteo de tickets, para que la fila se lea igual. */
.sin-asignar { justify-self: start; font-style: italic; }

/* ---------------------------------------------------- Enlaces del ticket */

/* Un ticket con enlaces se distingue del que no tiene ninguno sin abrir nada: lo hace
   con `con-datos`, el mismo realce que el calendario, definido junto a las fechas. */

.modal.modal-enlaces { max-width: 620px; }
/* The references table: Tipo · Número o descripción · Enlace · actions */
.tabla-refs { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.tabla-refs th {
  text-align: left; font-size: 10.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted); padding: 4px 6px; border-bottom: 1px solid var(--border);
}
.tabla-refs td { padding: 6px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.tabla-refs td:first-child { width: 96px; }
.tabla-refs .tipo-doc { min-width: 0; }
.tabla-refs .refs-url { max-width: 280px; }
/* The links the pop-up blocker held back, listed in the dialog to open one by one */
.enlaces-bloqueados { text-align: left; margin: 8px 0; padding-left: 18px; font-size: 12px; word-break: break-all; }
.enlaces-bloqueados li + li { margin-top: 4px; }
/* A Solicitud's «Solicitado por» spans the description and link columns */
.tabla-refs td.refs-url[colspan] { max-width: none; }
.tabla-refs .refs-url .enlace-url { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tabla-refs .refs-url input { width: 100%; min-width: 0; font-size: 12px; }
/* A relation's link block (`TicketRefLinkBlock`, «Ver DevOps» → Interno) */
.refs-panel-link { display: flex; gap: 8px; align-items: center; }
.refs-panel-link input { flex: 1; }
.refs-panel-link input { min-width: 0; font-size: 12px; }
/* The blocks of a work item («Ver DevOps» → Interno, Adjuntos): a titled box */
.wi-sub { border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); }
.wi-sub > header {
  display: flex; align-items: center; gap: 8px; padding: 7px 12px; border-bottom: 1px solid var(--border);
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
}
.wi-sub > header label { font: inherit; color: inherit; margin: 0; }
.wi-sub-body { padding: 10px 12px; margin: 0; }
.wi-attach { display: grid; gap: 8px; }
.wi-attach textarea { width: 100%; resize: vertical; }
.wi-attach-foot { display: flex; align-items: center; gap: 10px; }
.wi-attach-foot .btn { margin-left: auto; }
.wi-sub .wi-movements { border: 0; border-radius: 0; }
/* A movement that went to Azure DevOps (a file, a state) stands out in the «Tipo» column */
.chip.mov-tipo { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.chip.mov-tipo.mov-devops {
  border-color: var(--ok); background: color-mix(in srgb, var(--ok) 12%, var(--panel)); color: var(--ok); font-weight: 600;
}
.chip.mov-tipo .mdi { font-size: 13px; line-height: 1; }
.tabla-refs .refs-acciones { width: 64px; text-align: right; white-space: nowrap; }
.tabla-refs td:first-child { width: 110px; }
/* «Enviar por correo»: the attachment choice, the recipients as chips, subject and message */
.modal.modal-correo { max-width: 620px; }
.modal-correo > footer .spacer { flex: 1; }
/* Why the e-mail cannot go yet: next to the button, where the person is looking */
.modal-correo > footer .motivo-envio { flex: 1 1 auto; min-width: 0; color: var(--muted); font-size: 12px; }
.modal-correo > footer .motivo-envio + .spacer { flex: 0; }
.modal-correo .elegidos { margin-bottom: 6px; }
.modal-correo textarea { width: 100%; }
.modal-enlaces > footer .spacer { flex: 1; }

/* La tabla de enlaces: origen, dirección y la ✕, con la dirección quedándose el sitio que
   sobre y recortada si no cabe —el título completo va en su tooltip—. */
.tabla-enlaces { display: flex; flex-direction: column; gap: 4px; max-height: 240px; overflow-y: auto; }
.enlace-fila {
  display: grid;
  grid-template-columns: 96px 1fr 28px;
  align-items: center;
  gap: 8px;
  padding: 4px 6px;
  border-radius: var(--radius);
  font-size: 12px;
}
.enlace-fila:hover { background: var(--neutral-bg); }
.enlace-url { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--accent); }
.enlace-url:hover { text-decoration: underline; }

/* Con cinco botones, la columna fijada se pasaba del hueco que le quedaba: se aprieta la
   separación y se recortan dos píxeles por botón. Siguen siendo blancos de sobra. */
.tabla-docs .acciones .btn-ver + .btn-ver { margin-left: 4px; }
.tabla-docs .acciones .btn-ver { width: 26px; height: 26px; }
/* The ⋮ always at the right edge, also in rows without «Ver DevOps»: the sibling margin above
   is more specific than `.acciones-fila .acciones-mas` and kept it next to the download */
.tabla-docs .acciones .btn-ver.acciones-mas { margin-left: auto; }

/* ------------------------------------------------------ Horas de gestión */

/* LA PALETA COMÚN de las fichas que declaran su color en un catálogo del servidor: los
   tipos de gestión y los estados del ticket. No hay una clase por tipo ni por estado,
   sino una por color disponible, así que añadir cualquiera de los dos es una línea en su
   catálogo y ninguna aquí. */
.paleta-accent { --c: var(--accent); }
.paleta-info { --c: var(--info); }
.paleta-ok { --c: var(--ok); }
.paleta-warn { --c: var(--warn); }
.paleta-danger { --c: var(--danger); }
.paleta-muted { --c: var(--muted); }

/* ── SOLID chips ──────────────────────────────────────────────────────────────
   Types and statuses are painted SOLID with white text, vivid like the app's bars; the
   pale tints read as dull. `--c-solid` is a fixed deep shade per colour, the same in
   both themes: the theme's `--c` turns into a light pastel in dark mode, which would
   not carry white text. */
.tipo-tl, .paleta-accent { --c-solid: var(--brand); }
.tipo-devops, .paleta-ok { --c-solid: #1a7f45; }
.tipo-estimacion, .paleta-info { --c-solid: #4a3fb5; }
.paleta-warn { --c-solid: #b45f00; }
.paleta-danger { --c-solid: #c62828; }
.tipo-neutro, .paleta-muted { --c-solid: #61686f; }
/* More colours for the catalogs (Sistema → Parametrización). They have no theme token of
   their own, so the tint (`--c`) and the solid shade are the same deep colour, dark
   enough for the white chip text in both themes. No more blues: that family is the
   brand's (#017fc3). */
.paleta-teal { --c: #00796b; --c-solid: #00796b; }
.paleta-cyan { --c: #00838f; --c-solid: #00838f; }
.paleta-lime { --c: #4f7a28; --c-solid: #4f7a28; }
.paleta-amber { --c: #9a6b00; --c-solid: #9a6b00; }
.paleta-brown { --c: #6d4c41; --c-solid: #6d4c41; }
.paleta-pink { --c: #c2185b; --c-solid: #c2185b; }
.paleta-magenta { --c: #8e24aa; --c-solid: #8e24aa; }
.paleta-slate { --c: #37474f; --c-solid: #37474f; }

/* The ticket's status chip, solid too and without the dashed edge: over a solid fill
   the dashes only looked broken. Its own column already tells it from a type. */
.ficha-estado {
  background: var(--c-solid, #61686f);
  border: 0;
  color: var(--c-ink, #fff);
}

/* The filter menus (Tipo, Estado) and the status picker: every chip solid; the chosen
   one gets a ring of its colour around it, since the fill no longer tells it apart */
.chip-tipo {
  background: var(--c-solid, #61686f);
  border-color: var(--c-solid, #61686f);
  color: var(--c-ink, #fff);
}
.chip-tipo:hover {
  background: color-mix(in oklch, var(--c-solid, #61686f) 88%, white);
  border-color: var(--c-solid, #61686f);
}
.chip-tipo.activo {
  background: var(--c-solid, #61686f);
  border-color: var(--c-solid, #61686f);
  color: var(--c-ink, #fff);
  box-shadow: 0 0 0 2px var(--panel), 0 0 0 4px var(--c-solid, #61686f);
}
/* «Todos» in the theme's ink (dark in light mode, light in dark), so it reads as «no
   filter» and not as one more type */
.menu-tipos .chip-todos { --c-solid: var(--text); }
.menu-tipos .chip-todos,
.menu-tipos .chip-todos.activo { color: var(--panel); }

/* La tarjeta que NAVEGA, distinta de las tres que filtran: sin el realce de «activa» y
   con la flecha que anuncia que lleva a otro sitio. */
.metrica-navega .metrica-pie { color: var(--accent); display: inline-flex; align-items: center; gap: 4px; }
.metrica-navega .metrica-pie .mdi { font-size: 13px; line-height: 1; }
.metrica-navega:hover { border-color: var(--accent); background: var(--accent-soft); }

/* Los filtros de la pantalla de gestión, con la misma rejilla elástica que los de la
   tabla de documentos: se reparten el ancho y se apilan solos cuando no caben. */
.filtros-gestion { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; margin-bottom: 10px; }
.filtros-gestion .field { flex: 1 1 150px; min-width: 0; }

/* EL TABLERO de la pantalla de gestión: una tarjeta por tipo y otra con el total.
   Reusa `.metricas` y `.metrica` —el mismo aspecto que las cifras de la herramienta, que
   es lo que hace que se lea como parte de la misma pantalla y no como un añadido— y solo
   aprieta la rejilla: son tarjetas de una cifra corta y siete no tienen por qué ocupar lo
   que ocupan cuatro. La cifra de cada tipo va en el color de su ficha, que ya declara el
   catálogo del servidor, para que la tarjeta y la ficha de la fila se emparejen solas. */
.metricas-gestion { grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); margin-bottom: 10px; }
.metricas-gestion .metrica-num { font-size: 20px; font-variant-numeric: tabular-nums; }
/* El total, marcado: es el que se mira primero y el único que está siempre. */
.metrica-total-gestion { border-color: var(--border-strong); background: var(--neutral-bg); }

/* Las horas de inicio y fin, en la tabla: estrechas y sin partirse. */
.tabla-gestion .col-hora { width: 62px; white-space: nowrap; }

/* Las horas calculadas del formulario. Se ven como un campo para que se lea junto a los
   otros dos, pero no se escriben: salen de la franja. */
.horas-calculadas {
  background: var(--neutral-bg);
  color: var(--text);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  cursor: default;
}

/* La tabla de gestiones reusa `.tabla-docs`, así que hereda cabecera fija, bordes y
   tipografía; solo cambia que aquí ninguna fila se marca ni se pulsa. */
.tabla-gestion tbody tr { cursor: default; }
/* Dos botones por fila desde que se puede corregir: caben en línea y sin estirar. */
.tabla-gestion .acciones-gestion { width: 70px; text-align: center; white-space: nowrap; }
.tabla-gestion .acciones-gestion .btn-ver + .btn-ver { margin-left: 4px; }
.tabla-gestion .mdi-note-text-outline { font-size: 13px; opacity: 0.7; margin-left: 4px; }

/* A qué tickets pertenece la gestión. Varias fichas caben en la celda sin estirar la
   fila: envuelven. El ancho tiene tope para que una gestión de ocho tickets no se coma
   la columna del asunto, que es por la que se recorre la tabla.
   `white-space: normal` es lo que de verdad las hace envolver: sin esto, la celda hereda
   el `nowrap` genérico de la línea 1398 (`th, td { white-space: nowrap }`, de OTRA tabla
   más simple) y, como cada ficha es `inline-flex` y no `block`, nada las manda a la
   siguiente línea: se salían del tope y pisaban la columna de Persona con varios
   tickets. Nunca se vio porque ningún registro real había tenido más de uno. */
.tabla-gestion .col-tickets-gestion { max-width: 260px; white-space: normal; }
.tabla-gestion .col-tickets-gestion .chip-ticket { margin: 1px 4px 1px 0; }
/* The cell is ONE line (the first ticket and «+N», which opens the menu with all of them)
   so a record with ten tickets keeps the row's height. */
.tickets-gestion { display: flex; flex-wrap: nowrap; align-items: center; overflow: hidden; }
.tabla-gestion .col-tickets-gestion .chip-ticket { flex: 0 0 auto; }
.chip-ticket.chip-mas {
  padding: 2px 8px; border-radius: 999px; cursor: pointer;
  color: var(--accent); background: var(--accent-soft); border-color: transparent;
  font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.chip-ticket.chip-mas:hover, .chip-ticket.chip-mas.abierto { border-color: var(--accent); }
/* The record's tickets, in the row menu's box: a header with the split, then one line per
   ticket (key, title cut to the width, share). Long lists scroll inside. */
.menu-tickets-gestion { width: 340px; max-width: calc(100vw - 16px); }
.menu-tickets-cabecera {
  padding: 6px 14px 8px; border-bottom: 1px solid var(--border);
  font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.menu-tickets-lista { max-height: 280px; overflow-y: auto; }
.menu-acciones-item.menu-tickets-item { height: 40px; cursor: default; }
.menu-tickets-clave { flex: 0 0 auto; font-size: 12px; }
.menu-tickets-titulo { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--muted); font-size: 12px; }
.menu-tickets-horas { flex: 0 0 auto; color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }

/* Una ficha de SOLO LECTURA: la misma que la del editor pero sin el botón de quitar, así
   que no necesita el hueco de la derecha que aquél le deja. */
.chip-ticket.chip-lectura { padding: 2px 8px; }

/* El ticket que TODAVÍA NO EXISTE: se apuntó su número y se asociará solo el día que
   aparezca en la documentación. Se marca con el borde de rayas, igual que la ficha de
   estado, porque es lo mismo que dice allí: esto todavía no es firme. */
.chip-ticket.chip-futuro { border-style: dashed; color: var(--muted); }

/* Escribir a mano uno o varios números y añadirlos, en una línea: el campo manda y el
   botón no crece. Sin esto el `.row` les daba el mismo ancho a los dos. El campo es un
   «textarea» porque una lista se pega con saltos de línea dentro, y se deja crecer a lo
   alto —nunca a lo ancho, que desbarataría la fila—. */
.fila-a-mano { align-items: flex-end; }
.fila-a-mano input,
.fila-a-mano textarea { flex: 1 1 auto; }
.fila-a-mano textarea { resize: vertical; min-height: 2.6rem; }
.fila-a-mano .btn { flex: none; }

/* El desglose de la columna «Gestión» de un ticket. La tabla va dentro de un modal, así
   que sus filas no se estiran para llenar nada: cada una ocupa lo que ocupa su contenido
   —si no, con dos gestiones el modal las separaba media pantalla—. */
.modal-gestion-ticket .tabla-docs tbody tr { height: auto; }
.modal-gestion-ticket .tabla-scroll { max-height: 56vh; }

/* La observación, debajo del asunto: entera y ajustada, que es lo que se viene a leer
   aquí. En su propia columna dejaba el «Le tocó» fuera del modal. */
.nota-gestion {
  margin-top: 2px;
  white-space: normal;
  color: var(--muted);
  font-size: 11px;
}
/* El soporte y lo demás que no se cobra (D-46): sale en la lista, pero apagado y sin sumar */
.tabla-gestion tr.gestion-no-cobrada td { color: var(--muted); }
.tabla-gestion tr.gestion-no-cobrada td.horas { text-decoration: line-through; }

/* ------------------------------------------------- La paleta de comandos (⌘K)

   Va ARRIBA y no centrada: al abrirse, lo que se escribe queda donde estaban los ojos
   —la barra de la herramienta—, y la lista crece hacia abajo sin mover el campo. Es la
   colocación de todas las paletas que la gente ya sabe usar, y aquí eso vale más que
   cualquier idea propia. */
.backdrop-paleta { align-items: flex-start; padding-top: 10vh; }
.paleta {
  width: min(680px, 94vw);
  max-height: 72vh;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  background: var(--panel);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
  overflow: hidden;
}

.paleta-campo { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--border); }
.paleta-campo .mdi-magnify { font-size: 18px; color: var(--muted); }
/* El campo sin marco: el marco es la propia paleta, y uno dentro de otro es ruido. */
.paleta-campo input {
  flex: 1; min-width: 0;
  border: 0; background: transparent; color: var(--text);
  font-size: 15px; padding: 2px 0; outline: none;
}
/* De qué ticket se está hablando, cuando la paleta se centra en uno. */
.paleta-contexto {
  padding: 2px 8px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent);
  font-family: var(--mono, monospace); font-size: 11px; white-space: nowrap;
}

.paleta-lista { overflow-y: auto; padding: 6px 0; }
.paleta-grupo {
  padding: 8px 14px 4px; font-size: 10px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted);
}
.paleta-op {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 14px; cursor: pointer;
}
/* Una sola marca de «esto es lo que se ejecuta con Enter», y la mueven tanto las flechas
   como el ratón: dos marcas distintas —una de teclado y otra de hover— harían dudar de
   cuál se va a ejecutar, que es lo único que esta lista no se puede permitir. */
.paleta-op.elegida { background: var(--accent-soft); box-shadow: inset 2px 0 0 var(--accent); }
.paleta-icono { font-size: 16px; color: var(--muted); flex: 0 0 auto; }
.paleta-op.elegida .paleta-icono { color: var(--accent); }
.paleta-texto { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.paleta-etiqueta { display: flex; align-items: baseline; gap: 8px; font-size: 13px; color: var(--text); }
.paleta-etiqueta .mono { color: var(--accent); }
.paleta-etiqueta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* La pista de cómo se hace a mano: en pequeño, porque se lee de refilón y su trabajo es
   quedarse, no interrumpir. */
.paleta-pista { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.paleta-fichas { display: flex; gap: 4px; flex: 0 0 auto; }
.paleta-vacio { padding: 14px; margin: 0; }

.paleta-pie {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; border-top: 1px solid var(--border);
  background: var(--neutral-bg); font-size: 11px;
}
.paleta-ejemplos { color: var(--muted); display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.paleta-ejemplos .btn-link { font-size: 11px; padding: 1px 6px; border: 1px solid var(--border); border-radius: 999px; }
.paleta-teclas { display: flex; align-items: center; gap: 4px; }
kbd {
  display: inline-block; padding: 1px 5px;
  border: 1px solid var(--border-strong); border-bottom-width: 2px; border-radius: 4px;
  background: var(--neutral-bg); color: var(--text);
  font-family: inherit; font-size: 10px; line-height: 1.5;
}
/* EL ATAJO DENTRO DEL CAMPO DE BUSCAR.
   El campo no cambia de aspecto —sigue siendo el `input` de siempre—: el distintivo se
   superpone a la derecha y el texto se aparta con un relleno del mismo ancho, así que ni
   lo que se escribe ni el marcador de sugerencia pasan por debajo. */
.con-atajo { position: relative; display: flex; align-items: center; }
.con-atajo input { flex: 1; min-width: 0; padding-right: 58px; }
.atajo-paleta {
  position: absolute;
  right: 5px;
  display: inline-flex;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  opacity: 0.75;
}
/* Que se note que es pulsable, que si no se lee como un adorno. */
.atajo-paleta:hover { opacity: 1; }
.atajo-paleta:hover kbd { border-color: var(--accent); color: var(--accent); }
.atajo-paleta:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

/* La fila a la que acaba de llevar la paleta: se enciende un momento y se apaga sola.
   Sin esto, «ya te he llevado» no se ve en una tabla de doscientas filas. */
@keyframes recien-llegado {
  from { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
  to { background: transparent; box-shadow: none; }
}
.tabla-docs tbody tr.recien-llegado { animation: recien-llegado 2.2s ease-out; }

/* ------------------------------------------------------------- La factura del ticket

   Dos líneas en una sola celda: la fecha arriba y el número debajo. Son un dato solo
   —cuándo y con qué número se cobró—, y en dos columnas habrían costado el doble de
   ancho para decir lo mismo. La fecha con el color del texto porque es lo que se busca
   al recorrer la columna, y el número en tono apagado, que se lee cuando ya has parado
   en la fila. */
.tabla-docs .col-factura { white-space: nowrap; }
/* The status column: one chip, the same compact size as the Tipo chips */
.tabla-docs .col-estado { white-space: nowrap; }
html:not([data-presentacion]) .tabla-docs .col-estado .tipo-doc { min-width: 0; font-size: 10px; padding: 1px 8px; }
/* The read-only chip (an account that cannot change the status) as wide as the select
   (`.select-estado.con-estado`, 124px), so the column reads as one block either way */
html .tabla-docs .col-estado > .tipo-doc.ficha-estado {
  display: inline-block; box-sizing: border-box; min-width: 124px; text-align: center;
}
/* El proyecto (decisión D-29): la misma ficha compacta que el estado, más estrecha porque los
   códigos son cortos (P2H, LIS, AGENDA). Su color es el del catálogo, puesto en línea. */
.tabla-docs .col-proyecto { white-space: nowrap; }
html:not([data-presentacion]) .tabla-docs .col-proyecto .tipo-doc { min-width: 0; font-size: 10px; padding: 1px 8px; }
.tabla-docs .col-proyecto .select-estado.con-estado { min-width: 84px; }
html .tabla-docs .col-proyecto > .tipo-doc.ficha-estado {
  display: inline-block; box-sizing: border-box; min-width: 84px; text-align: center;
}
.campo-proyectos { position: relative; }
/* Estado (the Azure DevOps work item's state, 16-10-2026) and «Asignado a»: the same compact
   chip as before, painted with the colour Azure DevOps gives each state (inline). A row with
   no work item, or one not synchronized yet, shows a faint dash. */
.tabla-docs .col-estado .estado-devops-vacio,
.tabla-docs .col-asignado .estado-devops-vacio { color: var(--muted); }
.tabla-docs .col-asignado { white-space: nowrap; }
.tabla-docs .col-asignado .asignado-nombre {
  display: inline-block; max-width: 160px; overflow: hidden; text-overflow: ellipsis; vertical-align: middle; font-size: 12px;
}
.tabla-docs .col-asignado .asignado-nombre.sin-asignar { color: var(--muted); }
/* Todos los selectores de una columna «Asignado a» con el ancho de la columna (03-11-2026): el
   recuadro al pasar el mouse mide lo mismo con un nombre corto o largo, y la flecha queda alineada. */
.tabla-docs .col-asignado .wi-linea > .celda-asignado,
.tabla-docs .col-asignado > .celda-asignado { display: block; flex: 1; width: 100%; }
.tabla-docs .col-asignado .select-asignado { width: 100%; max-width: 190px; box-sizing: border-box; }
.tabla-docs .col-asignado .select-asignado .mdi-menu-down,
.tabla-docs .col-asignado .select-asignado .mdi-loading { margin-left: auto; }
/* «Asignación interna»: the same look as «Asignado a» */
.tabla-docs .col-asignacion-interna { white-space: nowrap; }
.tabla-docs .col-asignacion-interna .asignado-nombre {
  display: inline-block; max-width: 160px; overflow: hidden; text-overflow: ellipsis; vertical-align: middle; font-size: 12px;
}
.tabla-docs .col-asignacion-interna .asignado-nombre.sin-asignar { color: var(--muted); font-style: italic; }
.menu-asignacion-interna { position: fixed; z-index: 80; overflow: auto; min-width: 220px; }
.menu-asignacion-interna .menu-acciones-item.activo { color: var(--accent); font-weight: 600; }
/* «Estado» of «Asignación interna» (26-10-2026): the menu of the team's statuses, the mark of the
   ones that ask for a reason, and that reason's modal */
.menu-tipos.menu-estado-interno { width: 200px; max-height: min(340px, 55vh) !important; overflow-y: auto; overscroll-behavior: contain; }
.menu-estado-interno .marca-justificacion { margin-left: 4px; font-size: 12px; opacity: 0.85; }
.modal-justificacion-interna { width: min(480px, 100%); }
.modal-justificacion-interna textarea { width: 100%; box-sizing: border-box; resize: vertical; }
.select-asignado {
  display: inline-flex; align-items: center; gap: 2px; max-width: 190px;
  padding: 1px 2px 1px 6px; border: 1px solid transparent; border-radius: 6px;
  background: transparent; color: var(--text); cursor: pointer;
}
.select-asignado:hover, .select-asignado.abierto { border-color: var(--border-strong); background: var(--neutral-bg); }
.select-asignado:disabled { cursor: progress; opacity: 0.7; }
.select-asignado .mdi { font-size: 16px; line-height: 1; color: var(--muted); }
.menu-tipos.menu-estado-devops { width: 180px; }
.menu-tipos.menu-asignado-devops { width: 220px; }
.menu-asignado-devops input[type="search"] { width: 100%; box-sizing: border-box; margin-bottom: 4px; }
.menu-asignado-devops .chip-persona { --c: var(--muted); text-align: left; }
.menu-asignado-devops .hint { padding: 2px 4px; }
/* THE «ASIGNABLES» MENU (azureDevops/AssignablesMenu.js, 21-10-2026): the same list inside the
   «Asignado a» filter and the column's picker — search, groups «Con token de DevOps» / «Sin token
   (extraAssignees)», a row per person with their avatar in the colour of their label */
.menu-tipos.menu-asignado-devops { width: 300px; }
.filtros .menu-tipos.menu-asignables-filtro { display: block; width: 320px; }
.menu-asignables { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.menu-asignables .asignables-buscar { width: 100%; box-sizing: border-box; margin-bottom: 4px; }
.asignables-grupo {
  padding: 8px 8px 4px; color: var(--muted); font-size: 11px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.06em;
}
.asignable-opcion {
  display: flex; align-items: center; gap: 10px; width: 100%; box-sizing: border-box;
  padding: 6px 8px; border: 0; border-radius: 8px; background: transparent;
  color: var(--text); font: inherit; font-size: 12px; text-align: left; cursor: pointer;
}
.asignable-opcion:hover, .asignable-opcion.activo { background: var(--neutral-bg); }
.asignable-opcion.activo strong { color: var(--brand); }
.asignable-opcion.asignable-fuera { cursor: not-allowed; opacity: 0.75; }
.asignable-opcion.asignable-fuera:hover { background: transparent; }
.asignable-avatar {
  display: grid; place-items: center; flex: none; width: 26px; height: 26px; border-radius: 50%;
  color: #fff; font-size: 10px; font-weight: 700;
}
.asignable-datos { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.asignable-datos strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.asignable-datos small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-size: 11px; }
.asignable-cuenta { flex: none; color: var(--muted); font-size: 11px; }
.asignable-tag, .tag-fuera-lista {
  flex: none; padding: 1px 8px; border-radius: 999px; font-size: 10px; font-weight: 600; white-space: nowrap;
  background: var(--neutral-bg); color: var(--muted);
}
.asignable-tag.tag-actual { background: color-mix(in srgb, var(--brand) 18%, transparent); color: var(--brand); }
.asignable-tag.tag-sin-token { background: var(--warn-bg); color: var(--warn); }
.asignables-vacio { padding: 4px 8px; }
/* Assigned in DevOps to someone outside the list: grey, with its tag, never an option */
.select-asignado.fuera-lista, .asignado-nombre.fuera-lista { color: var(--muted); }
.select-asignado .tag-fuera-lista, .asignado-nombre .tag-fuera-lista { margin-left: 6px; }
.tabla-docs .col-factura .factura-fecha { display: block; color: var(--text); }
.tabla-docs .col-factura .factura-numero { display: block; color: var(--muted); }

/* El modal de facturas reusa el de ventanas; solo cambia el reparto de sus columnas,
   que aquí son número, fecha y tickets en vez de fecha, horas y tickets. */
/* Cinco columnas desde que la fila dice su TOTAL: número, fecha y periodo, conteo de
   tickets, total y acciones. El total va a la derecha del conteo porque es lo que se compara
   entre filas, y en `tabular-nums` para que las cifras caigan unas debajo de otras. */
.modal-facturas .ventana-fila { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr) minmax(0, 1fr) minmax(84px, auto) auto; }
/* La fecha de emisión arriba y el periodo debajo, en pequeño: son un solo dato —cuándo
   se emitió y qué cubre— y en dos columnas costarían el doble para decir lo mismo. */
.modal-facturas .ventana-fila .hint { display: block; }

/* La sección de horas de gestión del editor: su filtro arriba y la lista debajo, con la
   misma rejilla de opciones que la de tickets más las columnas propias. */
.seccion-gestion .row { align-items: flex-end; }
.campo-personas-factura { flex: 1 1 160px; }
.opcion-gestion { grid-template-columns: auto 92px minmax(0, 1fr) auto auto auto; gap: 8px; }
/* Una gestión ya facturada se ve, pero no se elige: descubrir el choque al guardar es la
   peor manera de enterarse. */
.opcion-gestion.facturada { opacity: 0.55; cursor: not-allowed; }
/* El enlace de descarga se pinta como los botones de su fila. */
.modal-facturas .acciones-ventana a.btn-ver { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }

/* ---------------------------------------------------------------- EL MODAL, MÁS GRANDE

   Pedido de Gerson el 07-10-2026 junto a los totales: «que agrandes ese modal para que se vea
   la informacion mejor». Se agranda con el patrón que ya usa el visor (`min(<tope>, <vw>)`) y
   no con un `width` suelto: el tope manda en pantalla grande y el `vw` en pantalla pequeña, así
   que no hay scroll horizontal en ningún ancho. A 1280 px el modal mide 1180; a 1440, los
   mismos 1180 con más margen alrededor. Por debajo manda el 96vw, y en móvil lo recoge el
   bloque de 560 px de más abajo, como los demás modales. */
.modal.modal-facturas { max-width: min(1180px, 96vw); width: 96vw; }
/* El alto también: con dos listas y el total debajo, 68vh dejaba el total fuera de la vista. */
.modal-facturas .body { max-height: min(78vh, 780px); }

/* El total de la fila del listado. Es un `<button>` (decisión D-25: «si yo le doy clic en el
   total me debe decir como esta desglosado dicho total»), así que hay que quitarle la pinta que
   le pone el navegador y darle la propia: subrayado punteado para que se vea pulsable, y un foco
   visible, que es lo que lo hace usable con el tabulador. */
.celda-total-factura {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-family: inherit;
  font-size: inherit;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  text-align: right;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  cursor: pointer;
}
.celda-total-factura:hover { text-decoration-style: solid; }
.celda-total-factura:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
/* La marca de «su despliegue se cobra en otro mes»: ámbar, como el resto de los avisos de mes
   de pago de esta herramienta, y con el mes y las horas en su `title`. */
.marca-otro-mes { color: var(--warn); font-size: 15px; line-height: 1; cursor: help; }

/* EL EDITOR EN DOS COLUMNAS: tickets a la izquierda, gestión a la derecha. Una sola columna
   por debajo de 1100 px, que es donde la de gestión deja de caber con sus seis campos. */
.editor-factura { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0 20px; }
@media (min-width: 1100px) {
  .editor-factura { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  /* Las dos columnas arrancan a la misma altura aunque una tenga más campos arriba */
  .editor-factura > .columna-factura { align-content: start; }
}
.columna-factura { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
/* LAS FILAS DE TICKETS DE UNA FACTURA DESPLEGADA (decisión D-25): ticket, título y las horas
   que ESE ticket aporta a ESTA factura. La columna de horas se alinea a la derecha y con cifras
   de ancho fijo, porque el que la lee la está sumando con el dedo contra el total. */
.modal-facturas .ticket-de-ventana { grid-template-columns: 92px minmax(0, 1fr) minmax(74px, auto); }
.modal-facturas .cabecera-tickets {
  font-size: 10px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--border);
  padding-bottom: 3px;
}
.celda-horas-ticket { display: flex; align-items: baseline; justify-content: flex-end; gap: 4px; font-variant-numeric: tabular-nums; }
/* La suma de la columna, separada por una línea: tiene que dar los dos primeros sumandos del
   total («horas de tickets» + «despliegue de este periodo»), y se enseña para que cuadre a la
   vista sin abrir el desglose. */
.modal-facturas .suma-tickets {
  border-top: 1px solid var(--border);
  margin-top: 2px;
  padding-top: 4px;
  font-weight: 600;
}
.modal-facturas .suma-tickets > .num { font-variant-numeric: tabular-nums; text-align: right; }

/* Las listas respiran: con el modal ancho, siete filas visibles era desaprovechar el alto, y
   comprobar una factura de cuarenta tickets obligaba a rodar la caja entera. */
.modal-facturas .lista-tickets { max-height: 320px; }
@media (max-width: 1099px) { .modal-facturas .lista-tickets { max-height: 240px; } }

/* --------------------------------------------------------- EL DESGLOSE Y EL TOTAL

   Dos bloques lado a lado: a la izquierda las fases (el desglose) y a la derecha los sumandos
   con el total en grande, que es la cifra por la que se pasa la factura. Separados a propósito:
   las fases son el detalle de UN sumando, y en una sola columna se leían como si sumaran todas
   al total —que es exactamente el error que esto viene a evitar—. */
.desglose-factura { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
/* EL TOTAL, que es el botón que abre el desglose (decisión D-25). Tiene pinta de botón —borde,
   cursor, foco visible y una pista escrita— porque un número que es pulsable y no lo parece no
   lo pulsa nadie. `<button>` de verdad: Enter y Espacio salen gratis. */
.desglose-cabecera {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--accent-soft);
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.desglose-cabecera:hover { border-color: var(--accent); }
.desglose-cabecera:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.desglose-cabecera-texto { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.desglose-cabecera-texto > .hint { text-transform: none; letter-spacing: 0; font-weight: 400; }
.desglose-cabecera > .num { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 20px; line-height: 1.1; white-space: nowrap; }
.desglose-cabecera > .mdi { color: var(--muted); font-size: 18px; line-height: 1; flex: none; }
/* El cuerpo: fases a la izquierda, sumandos a la derecha. En una sola columna se leían como si
   las fases sumaran al total, que es justo el error que esto viene a evitar. */
.desglose-cuerpo { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
@media (min-width: 860px) { .desglose-cuerpo { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.desglose-bloque {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px;
  min-width: 0;
}
.desglose-total { background: var(--accent-soft); }
.desglose-titulo { margin: 0 0 6px; font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.desglose-fila { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 3px 0; font-size: 12px; }
.desglose-fila > .num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.desglose-fila .hint { font-weight: 400; }
.desglose-subtotal { border-top: 1px solid var(--border); margin-top: 4px; padding-top: 5px; font-weight: 600; }
/* El despliegue, separado del desglose por una línea: no es una fase más de la suma de arriba */
.desglose-aparte { border-top: 1px dashed var(--border); margin-top: 6px; padding-top: 6px; }
/* EL número. Grande porque es el que se copia a la factura de verdad. */
.desglose-grande { border-top: 1px solid var(--border); margin-top: 6px; padding-top: 7px; font-weight: 700; font-size: 13px; }
.desglose-grande > .num { font-size: 20px; line-height: 1.1; }
/* Los avisos, en el ámbar de siempre y a lo ancho: son frases, no cifras */
.desglose-aviso {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0;
  padding: 8px 10px;
  border: 1px solid var(--warn);
  border-radius: var(--radius);
  background: var(--warn-bg);
  font-size: 0.84rem;
  line-height: 1.4;
}
.desglose-aviso > .mdi { margin-top: 1px; color: var(--warn); font-size: 1.05rem; flex: none; }
/* En el listado va apretado: cabe dentro de la fila desplegada sin empujar los tickets */
.desglose-factura.compacto { margin-top: 2px; margin-bottom: 10px; gap: 8px; }
.desglose-factura.compacto .desglose-grande > .num { font-size: 17px; }
.desglose-factura.compacto .desglose-cabecera > .num { font-size: 17px; }

/* ------------------------------------- La cabecera de la herramienta, reorganizada

   La fila de filtros llevaba cuatro campos de fecha —los menos usados— ocupando más de
   la mitad del ancho, y de paso apretaba a «Buscar». Ahora: buscar ancho, tipo, fecha de
   ventana, «Más filtros» y limpiar; las fechas viven en un panel que se despliega DEBAJO
   y lo que esté puesto se sigue viendo en fichas. */

/* «Más filtros» se enciende cuando hay alguno puesto: recogerlos no puede significar
   esconderlos, y el color es lo primero que se ve de un vistazo. */
.filtros .acciones-filtro .btn-link.activo { color: var(--accent); border-color: var(--accent); }

/* Las fichas de lo que está filtrando, entre la fila y la tabla. */
.fichas-filtro { display: flex; flex-wrap: wrap; gap: 6px; margin: -4px 0 8px; }

/* EL AVISO DE UNA LISTA PEGADA (el buscador de la pantalla y el de la factura).
   Sale en dos tonos a propósito: NEUTRO cuando todo lo pegado se encontró —solo confirma lo
   que acaba de pasar y no pide nada— y de AVISO cuando algo se quedó fuera, que es cuando hay
   que leerlo. El mismo recuadro en los dos sitios: es el mismo gesto y la misma información,
   y dos diseños distintos para lo mismo se leen como dos funcionalidades distintas. */
.aviso-pegado {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: -4px 0 10px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--neutral-bg);
  font-size: 0.88rem;
  line-height: 1.35;
}
.aviso-pegado.con-fallos { border-color: var(--warn); background: var(--warn-bg); }
.aviso-pegado > .mdi { margin-top: 1px; color: var(--muted); font-size: 1.05rem; }
.aviso-pegado.con-fallos > .mdi { color: var(--warn); }
.aviso-pegado-texto { flex: 1; min-width: 0; }
/* Una frase por línea: la de lo que falta no se puede perder al final de un párrafo largo */
.aviso-pegado-texto p { margin: 0; }
.aviso-pegado-texto p + p { margin-top: 3px; }
/* Las claves que se nombran pueden ser muchas: se dejan partir en vez de desbordar */
.aviso-pegado-texto p { overflow-wrap: anywhere; }
.aviso-pegado-acciones { display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }

/* «LO PAGADO EN ESOS MESES» (D-46): qué enseña la tabla con el mes de pago puesto y cómo cuadra
   con Pago. El mismo recuadro que el de la lista pegada, con el borde del color de la app: no
   avisa de un fallo, dice cómo leer las cifras. */
.aviso-pagado {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: -4px 0 10px;
  padding: 8px 10px;
  border: 1px solid var(--accent, #017fc3);
  border-left-width: 4px;
  border-radius: var(--radius);
  background: var(--neutral-bg);
  font-size: 0.88rem;
  line-height: 1.35;
}
.aviso-pagado > .mdi { margin-top: 1px; color: var(--accent, #017fc3); font-size: 1.05rem; }
.aviso-pagado p { margin: 0; flex: 1; min-width: 0; }

/* El panel de fechas: dos RANGOS con su etiqueta, no cuatro campos sueltos. Así se lee
   «creado entre esto y esto», que es como se piensa la pregunta. */
.panel-filtros {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin: -4px 0 10px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--neutral-bg);
}
.rango-filtro { display: flex; align-items: center; gap: 8px; }
.rango-filtro > label { font-size: 12px; color: var(--muted); min-width: 78px; }
.rango-filtro input[type="date"] { width: auto; }
/* «Excluir»: a list like «Buscar», wide enough to read what is hidden */
.filtro-excluir input { width: 320px; max-width: 100%; }
/* Estado Jira, Asignado Jira and Sprint when the window is narrow (DocsFiltersBar.js): the same
   fields as in the row, on a line of their own above Excluir and the dates. No overflow here,
   so their menus open over what is below, as in the row. */
.panel-filtros > .filtros-movidos { flex: 1 1 100%; display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }

/* «DEVOPS/JIRA» Y «MÁS FILTROS» (24-10-2026): dos menús que flotan bajo su botón
   (useFilterPopover.js los coloca con position: fixed dentro de la ventana). Los selectores de
   dentro se despliegan EN el menú, no flotando sobre él: así nada queda cortado, y el menú
   entero se desplaza si no cabe en alto. */
.filtros .campo-menu-filtros { position: relative; }
.filtros .menu-filtros {
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: 12px;
  width: max-content;
  max-width: calc(100vw - 32px);
  max-height: min(75vh, 640px);
  overflow: auto;
  overscroll-behavior: contain;
  margin: 0;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--text);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.28);
  box-sizing: border-box;
  text-align: left;
}
/* «DevOps/Jira»: its selects open FLOATING over the menu (24-10-2026: opening one inside it pushed
   the sections down and broke the two columns), so the menu itself must not clip them */
.filtros .menu-filtros.menu-devops-jira { width: 480px; overflow: visible; max-height: none; }
.seccion-menu-filtros { margin: 0; }
.seccion-menu-filtros + .seccion-menu-filtros { padding-top: 10px; border-top: 1px solid var(--border); }
.seccion-menu-filtros > h4 { margin: 0 0 6px; font-size: 12px; font-weight: 600; letter-spacing: 0.03em; text-transform: uppercase; color: var(--muted); }
.seccion-campos { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; align-items: start; }
.seccion-campos > .field { position: relative; min-width: 0; }
.filtros .menu-filtros .select-tipos { width: 100%; }
.filtros .menu-filtros .menu-tipos {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 70;
  width: max-content;
  min-width: 100%;
  max-width: 320px;
  max-height: min(300px, 45vh);
  overflow: auto;
  margin: 0;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.28);
}
/* Never taller than the room it has (`--lista-max`, measured on opening), scrolling inside; and
   above the field when there is no room below (25-10-2026: on a short screen the last people of the
   «Asignación interna» list were off the screen) */
.filtros .menu-filtros.menu-devops-jira .menu-tipos { max-height: var(--lista-max, min(300px, 45vh)); overflow: auto; }
.filtros .menu-filtros.menu-devops-jira.listas-arriba .menu-tipos { top: auto; bottom: calc(100% + 4px); }
/* The right column's list opens towards the left, so it never leaves the menu */
.seccion-campos > .field:nth-child(2) > .menu-tipos { left: auto; right: 0; }
.filtros .menu-filtros .menu-tipos.menu-asignables-filtro { display: block; width: 300px; }
/* «Asignación interna» has two filters since 26-10-2026 («Asignado a» · «Estado»): two columns like the other sections */
/* «Más filtros»: each range on ONE line (label · from · y · to), so it reads which dates go together */
.filtros .menu-filtros .rango-filtro { display: flex; flex-wrap: nowrap; align-items: center; gap: 8px; }
.filtros .menu-filtros .rango-filtro > label { min-width: 80px; margin: 0; }
.filtros .menu-filtros .rango-filtro input[type="date"] { width: 150px; flex: none; }
.filtros .menu-filtros .rango-filtro.filtro-excluir input { width: 320px; flex: 1 1 auto; }
.filtros .menu-filtros .rango-filtro .fecha-no-aplica { white-space: nowrap; }
/* The Sprint moved here on narrow windows: one line like the others (label · select as wide as
   Excluir), its list floating; this menu does not clip it */
.filtros .menu-filtros.panel-filtros { overflow: visible; max-height: none; }
.filtros .menu-filtros .filtros-movidos .field { position: relative; display: flex; flex-direction: row; align-items: center; gap: 8px; margin: 0; }
.filtros .menu-filtros .filtros-movidos .field > label { min-width: 80px; margin: 0; font-size: 12px; font-weight: 400; color: var(--muted); }
.filtros .menu-filtros .filtros-movidos .field > .select-tipos { width: 320px; flex: 1 1 auto; }
.filtros .menu-filtros .filtros-movidos .field > .menu-tipos { left: 88px; }
@media (max-width: 560px) {
  .filtros .menu-filtros .rango-filtro { flex-wrap: wrap; }
  .filtros .menu-filtros .rango-filtro > label { flex-basis: 100%; }
  .filtros .menu-filtros .rango-filtro input[type="date"] { width: calc(50% - 18px); }
  .seccion-campos { grid-template-columns: 1fr; }
  .seccion-campos > .field:nth-child(2) > .menu-tipos { left: 0; right: auto; }
}

/* El divisor de la fila de acciones: evidente pero discreto. Una línea y aire a los dos
   lados; sin rótulos, que con siete botones añadirían dos palabras más que leer. */
.divisor-acciones {
  width: 1px;
  align-self: stretch;
  min-height: 22px;
  /* El AIRE es la mitad del divisor. Con la separación de siempre, la línea quedaba
     entre dos botones que ya tienen borde y se leía como un hueco más; con el doble de
     hueco a cada lado, los dos bloques se distinguen antes de mirar la línea. */
  margin: 0 12px;
  background: var(--border-strong);
}

/* Switch de dos opciones (Avanzado → Búsqueda del respaldo) */
.switch-seg { display: inline-flex; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.switch-seg button { border: 0; border-radius: 0; background: transparent; padding: 6px 14px; cursor: pointer; }
.switch-seg button + button { border-left: 1px solid var(--border); }
.switch-seg button.on { background: var(--accent, #1f6fd1); color: #fff; }

/* The teams of a ticket status or type (Parametrización → Documentación): chips in the
   table, and toggle chips in its modal. None chosen = every team. */
.chips-equipos { display: flex; flex-wrap: wrap; gap: 4px; }
.campo-titulo { display: block; font-size: 11px; color: var(--muted); font-weight: 600; }
/* The teams select of the status/type modal: a field like an input, the chosen teams as
   light chips inside it (each with its «×»), and a checkbox list under it. */
.campo-equipos { position: relative; min-width: 0; }
.select-equipos {
  display: flex; align-items: center; gap: 6px; width: 100%; min-height: 38px;
  padding: 4px 8px 4px 10px; border: 1px solid var(--border-strong); border-radius: 4px;
  background: var(--panel); color: var(--text); cursor: pointer;
}
.select-equipos:focus-visible, .select-equipos.abierto { border-color: var(--accent); outline: none; }
.select-equipos-valor { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; gap: 4px; }
.select-equipos-vacio { color: var(--muted); padding: 2px 0; }
.select-equipos-flecha { font-size: 18px; line-height: 1; color: var(--muted); }
.chip-equipo-elegido {
  display: inline-flex; align-items: center; gap: 2px; padding: 2px 4px 2px 8px; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--brand) 35%, transparent);
  background: color-mix(in srgb, var(--brand) 10%, transparent); color: var(--text); font-size: 12px; line-height: 1.4;
}
.chip-equipo-elegido button {
  display: inline-flex; padding: 0 2px; border: 0; background: transparent; color: var(--muted); cursor: pointer;
}
.chip-equipo-elegido button:hover { color: var(--text); }
.menu-equipos {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 30; margin: 4px 0 0; padding: 4px 0;
  list-style: none; max-height: 240px; overflow-y: auto;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
}
.opcion-equipo { display: flex; align-items: center; gap: 8px; padding: 7px 12px; cursor: pointer; font-size: 13px; }
.opcion-equipo:hover { background: var(--neutral-bg); }
.opcion-equipo .mdi { font-size: 18px; line-height: 1; color: var(--muted); }
.opcion-equipo.elegida .mdi { color: var(--brand); }
.opcion-todos { border-bottom: 1px solid var(--border); }
.opcion-vacia { padding: 7px 12px; }

/* The people autocomplete (`PersonPicker.js`): ONE box that looks like the other
   fields (same border, padding and height as a select), its chips and the text inside, and
   the same menu as the teams select */
.person-picker { position: relative; min-width: 0; }
/* ONE line always, like a select: with several chosen it shows the first and «+N» */
.person-picker-campo {
  display: flex; flex-wrap: nowrap; align-items: center; gap: 4px; width: 100%; overflow: hidden;
  padding: 0 6px 0 8px; border: 1px solid var(--border-strong); border-radius: 4px;
  background: var(--panel); color: var(--text); cursor: text;
}
.person-picker.abierto .person-picker-campo, .person-picker-campo:focus-within {
  outline: 2px solid var(--accent); outline-offset: -1px;
}
/* The global field rule (`input:not(...)…`, specificity 0,4,1) would draw a second box
   inside: the same chain plus the class beats it */
.person-picker input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(.swal2-input) {
  flex: 1; width: auto; min-width: 40px; padding: 6px 0; border: 0; border-radius: 0;
  background: transparent; color: inherit; font: inherit; outline: none; box-shadow: none;
}
.person-picker .chip-equipo-elegido { margin: 3px 0; flex: 0 1 auto; min-width: 0; max-width: 60%; }
.person-picker .chip-equipo-nombre { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.person-picker-mas {
  flex: none; padding: 1px 7px; border-radius: 999px; font-size: 11px; font-weight: 600;
  color: var(--brand); background: color-mix(in srgb, var(--brand) 12%, transparent); cursor: default;
}
.person-picker .opcion-limpiar { color: var(--muted); border-bottom: 1px solid var(--border); margin-bottom: 4px; }
.person-picker .opcion-limpiar .opcion-check { color: var(--muted); }
.person-picker-flecha { font-size: 18px; line-height: 1; color: var(--muted); margin-left: auto; }
.person-picker-limpiar { display: inline-flex; padding: 0 2px; border: 0; background: transparent; color: var(--muted); cursor: pointer; }
.person-picker-limpiar:hover { color: var(--text); }
.person-picker .opcion-equipo.activa { background: var(--neutral-bg); }
.person-picker .opcion-equipo.elegida {
  font-weight: 600; color: var(--brand); background: color-mix(in srgb, var(--brand) 12%, transparent);
}
.person-picker .opcion-equipo.elegida.activa { background: color-mix(in srgb, var(--brand) 18%, transparent); }
.person-picker .opcion-check { width: 16px; flex: none; font-size: 16px; line-height: 1; color: var(--brand); }

/* ------------------------------------------------- Sprint: columna, filtro y su modal

   El sprint es el tercer agrupador de la tabla, junto a la ventana y la factura, y se
   pinta como lo que es: un nombre corto. Una sola línea —a diferencia de la factura, que
   lleva fecha y número— porque el nombre ya identifica al sprint y su periodo vive en el
   tooltip, que es donde se consulta de vez en cuando. */
.tabla-docs .col-sprint {
  white-space: nowrap;
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* El modal de sprints reusa el de ventanas; solo cambia el reparto de sus columnas, que
   aquí son nombre, fechas y tickets. */
/* La última columna va con un ancho FIJO y no `auto`: la cabecera no lleva botones y la
   fila sí, así que con `auto` cada una repartía los `fr` de forma distinta y los títulos
   quedaban corridos respecto a sus valores. */
.modal-sprints .ventana-fila { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1.1fr) minmax(0, 0.9fr) 72px; }
/* La segunda columna del listado de ventanas son HORAS y por eso su título va a la
   derecha; aquí son fechas, así que el título vuelve a la izquierda o no se lee sobre
   el valor que encabeza. */
.modal-sprints .ventana-cabecera span:nth-child(2) { text-align: left; }
.sprint-nombre { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }

/* ------------------------------------------- Aprobación de la estimación

   Lo que se mira aquí es una línea por persona, así que el modal reusa la rejilla del de
   ventanas con sus propias columnas: quién, qué decidió y cómo acabó su correo. */
.modal.modal-aprobacion { max-width: 760px; }
.modal-aprobacion .body { max-height: min(68vh, 620px); overflow-y: auto; }
.modal-aprobacion > footer .spacer { flex: 1; }
/* La última columna da para TRES botones: copiar el enlace, el gesto de correo que toque
   —reenviar o pedir otra decisión, nunca los dos— y revocar. */
.lista-aprobadores .ventana-fila { grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr) minmax(0, 1fr) 104px; }
/* Misma corrección que en los sprints: aquí la segunda columna es la decisión, no horas. */
.lista-aprobadores .ventana-cabecera span:nth-child(2) { text-align: left; }
.lista-aprobadores .ventana-fila > span { min-width: 0; }
.aprob-correo { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.aprob-correo .hint, .lista-aprobadores .ventana-fila .hint { display: block; }
.aprob-envio { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* La lista de usuarios de la app para elegir a quién se le pide: la misma rejilla de
   casillas que la de tickets de una factura, con sus columnas —nombre, correo y la marca
   de quien ya está invitado—. */
.opcion-usuario { grid-template-columns: auto minmax(0, 1fr) minmax(0, 1.2fr) auto; gap: 8px; }
.nombre-usuario { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A quien ya se le pidió se le ve, pero no se le vuelve a elegir: pedir dos veces la
   misma aprobación a la misma persona es el error que esta marca evita. */
.opcion-usuario.invitado { opacity: 0.55; cursor: not-allowed; }

/* La cabecera de cada EQUIPO dentro de esa lista. Discreta a propósito —en versales, sin
   fondo y sin caja—: separa y etiqueta, pero quien lee viene a mirar nombres, y una
   cabecera con el peso de una fila se confundiría con una persona más. Se pega arriba al
   desplazar, que es cuando de verdad hace falta saber de qué equipo es la fila que se
   está mirando. */
.lista-tickets .cabecera-equipo {
  position: sticky;
  top: -4px; /* compensa el padding de .lista-tickets: queda a ras del borde */
  z-index: 1;
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 6px 0 2px;
  padding: 3px 6px;
  background: var(--panel);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  border-bottom: 1px solid var(--border);
}
.lista-tickets .cabecera-equipo:first-child { margin-top: 0; }
.lista-tickets .cabecera-equipo-nombre { font-weight: 600; color: var(--text); }
.lista-tickets .cabecera-equipo .hint { margin-left: auto; text-transform: none; letter-spacing: 0; }

/* La cabecera del modal: en qué estado está la solicitud y cómo va el recuento. Es lo
   que contesta «¿y esto en qué quedó?» sin leer fila por fila. */
.resumen-aprobacion {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid var(--border);
}
.resumen-aprobacion .spacer { flex: 1; }
.estado-solicitud { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600; }
.estado-solicitud.abierta { color: var(--accent); }
.estado-solicitud.cerrada { color: var(--muted); }
.estado-solicitud .mdi { font-size: 15px; line-height: 1; }

/* Las fichas de decisión, con los mismos colores que el resto de la app: verde lo que
   salió bien, rojo lo que no, y gris lo que todavía no es nada. */
.ficha-aprob { display: inline-flex; align-items: center; gap: 4px; min-width: 0; }
.ficha-aprob .mdi { font-size: 13px; line-height: 1; }
.aprob-pendiente { --c: var(--muted); }
.aprob-si { --c: var(--ok); }
.aprob-no { --c: var(--danger); }
.aprob-revocado { --c: var(--warn); }

/* Sistema → Parametrización → Usuarios → Aprobaciones: los conteos de cada solicitud en fila */
.aprobaciones-conteos { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.aprobaciones-personas-cabecera { margin: 0 0 10px; }

/* QUIEN RECHAZÓ PROPONIENDO OTRAS HORAS. Va debajo de su ficha de decisión y en el color
   de acento, no en rojo: el rechazo ya está dicho arriba y esto no es más alarma, es que
   hay algo que leer. Sin esta marca nadie pulsaría el botón para descubrirlo. */
.ficha-contrapropuesta { --c: var(--accent); margin-top: 4px; }

/* La comparación de horas: cuatro columnas —fase, estimado, propuesto y diferencia— con
   las cifras alineadas a la derecha para poder leerlas en vertical de un vistazo. */
.modal-contrapropuesta { max-width: 560px; }
.tabla-contrapropuesta .ventana-fila { grid-template-columns: minmax(0, 1.4fr) 84px 84px 84px; }
.tabla-contrapropuesta .cifra { text-align: right; font-variant-numeric: tabular-nums; }
.tabla-contrapropuesta .cifra.suave { color: var(--muted); }
/* LA DIFERENCIA DE HORAS como insignia, la misma en la contrapropuesta y en la matriz de
   las horas acordadas (`lib/diferenciaHoras.mjs` decide texto, tono y frase). Ámbar por
   debajo de la referencia, azul índigo por encima —pedir más horas no es un error, así que
   no va en rojo— y neutro con ✓ si coincide. El color solo acompaña: el texto lleva signo
   y unidad y el título dice contra qué se compara. Con los tokens del tema, así que el
   modo oscuro sale solo. */
.dif-horas {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: 10.5px;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.dif-horas.dif-menos { background: var(--warn-bg); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
.dif-horas.dif-mas { background: var(--info-bg); color: var(--info); border-color: color-mix(in srgb, var(--info) 35%, transparent); }
.dif-horas.dif-igual { background: var(--neutral-bg); color: var(--muted); }
.tabla-contrapropuesta .fila-total { border-top: 1px solid var(--border); background: var(--bg); }
/* La observación la escribió alguien de fuera: se respeta cómo la escribió (saltos de
   línea incluidos) y se deja romper por cualquier punto, que un correo o una URL largos
   no desborden la caja. */
.observacion-contrapropuesta {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  line-height: 1.5;
}

/* ------------------------------------------------------- las horas acordadas de un ticket
   La matriz de la reunión: una columna fija para la fase, otra para lo estimado, UNA POR
   PERSONA y la del consenso. El número de personas es variable, así que la rejilla se
   arma con `--columnas-persona`, que pone el componente; con columnas escritas a mano
   habría que elegir un máximo y la quinta persona rompería la tabla. */
.modal-consenso { max-width: 880px; }
/* Se desplaza en horizontal cuando no cabe —muchas personas, o un móvil— antes que
   apretar las cifras hasta no poder leerlas. El modal ya no crece más de lo que da la
   pantalla, así que el desplazamiento es de esta caja y no de la página. */
/* `flex: none` NO sobra: `.modal .body` es un contenedor flex en columna, y un hijo con
   `overflow-x: auto` pasa a tener también desplazamiento vertical (la regla de CSS: si un
   eje no es `visible`, el otro deja de serlo). Sin esto el flex lo encogía y la fila
   TOTAL quedaba recortada por abajo justo en pantalla estrecha, que es donde más falta
   hace. Ahora la caja mide lo suyo y quien desplaza en vertical es el cuerpo del modal. */
.matriz-consenso-scroll { overflow-x: auto; margin: 0 -2px; padding: 0 2px 2px; flex: none; }
.tabla-consenso { min-width: calc(190px + 92px + (var(--columnas-persona, 0) * 104px) + 118px); }
.tabla-consenso .ventana-fila {
  grid-template-columns: minmax(150px, 1.4fr) 92px repeat(var(--columnas-persona, 0), 104px) 118px;
  align-items: center;
}
/* Sin nadie que haya contrapropuesto: tres columnas y punto. Hace falta una regla aparte
   porque `repeat(0, 104px)` no es «ninguna columna», es una declaración INVÁLIDA, y la
   rejilla entera se caía dejando la matriz en una sola columna apilada. */
.tabla-consenso.sin-personas { min-width: 0; }
.tabla-consenso.sin-personas .ventana-fila { grid-template-columns: minmax(150px, 1.4fr) 92px 118px; }
.tabla-consenso .cifra { text-align: right; font-variant-numeric: tabular-nums; }
.tabla-consenso .cifra.suave { color: var(--muted); }
/* La cifra de cada persona en el color del texto y, a su derecha, la insignia de la
   diferencia (`.dif-horas`). Si no caben en los 104 px de la columna, la insignia baja de
   línea alineada a la derecha en vez de desbordar. */
.tabla-consenso .celda-diferencia { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 2px 5px; }
.tabla-consenso .fila-total { border-top: 1px solid var(--border); background: var(--bg); }
/* «PRUEBAS DE CARGA» Y «GESTIÓN» son dos fases más de la lista y se pintan como las otras
   cinco. Lo único suyo es la línea de debajo del nombre con lo que el ticket ya llevaba
   consumido: es la cifra con la que arranca su campo, y sin decirlo el número parecería
   salido de la nada. Va DEBAJO DEL NOMBRE y no al lado de la cifra porque la columna de la
   fase es la ancha; pegado al número se quedaba en una tira de 92 px cuando nadie había
   contrapropuesto. */
.tabla-consenso .fase-con-consumo { display: flex; flex-direction: column; gap: 1px; line-height: 1.35; }
.tabla-consenso .fase-con-consumo small { color: var(--muted); font-size: 11px; }
/* La cabecera de cada persona: su nombre y, debajo, el gesto de adoptar su columna. En
   dos líneas porque un nombre completo no cabe al lado de un botón en 104px. */
.tabla-consenso .col-persona { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.tabla-consenso .nombre-persona { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tabla-consenso .btn-adoptar { padding: 1px 6px; font-size: 10px; font-weight: 600; }
/* QUIENES APROBARON (23-10-2026): sus columnas van primero y con un verde suave de arriba
   abajo, para que en la reunión se vea de un vistazo que hubo quien dio por buena la
   estimación (el efecto ancla). El verde sale de `--ok` mezclado con `--panel`, así que el
   modo oscuro y el de presentar salen solos; y es OPACO, para que las celdas, que se estiran
   hasta tocarse (la fila pierde su hueco y cada celda se come la mitad del espacio entre
   columnas), no se oscurezcan donde se solapan. El color nunca va solo: la cabecera dice
   «✓ Aprobó» con letras y su título dice cuándo. */
.tabla-consenso { --tinte-aprobo: color-mix(in srgb, var(--ok) 9%, var(--panel)); }
.tabla-consenso.con-aprobaciones { gap: 0; }
.tabla-consenso .col-aprobo { align-self: stretch; background: var(--tinte-aprobo); margin: -7px -5px; padding: 7px 5px; }
.tabla-consenso .ventana-cabecera .col-aprobo { margin-bottom: 0; padding-bottom: 4px; }
/* El resaltado de la fila al pasar el ratón sigue viéndose sobre el verde (sería opaco y lo taparía). */
.tabla-consenso .ventana-fila:not(.ventana-cabecera):hover .col-aprobo { background: color-mix(in srgb, var(--ok) 9%, var(--neutral-bg)); }
/* La raya entre «Aprobaron» y «Contrapropuestas», a mitad del hueco entre las dos columnas. */
.tabla-consenso .col-separador { align-self: stretch; border-left: 2px solid var(--border-strong); margin: -7px 0 -7px -6px; padding: 7px 0 7px 4px; }
.tabla-consenso .ventana-cabecera .col-separador { margin-bottom: 0; padding-bottom: 4px; }
.tabla-consenso .fila-grupos { padding-top: 4px; }
.tabla-consenso .grupo-aprobaron,
.tabla-consenso .grupo-contrapropuestas { font-size: 10px; letter-spacing: 0.05em; text-transform: uppercase; text-align: center; }
.tabla-consenso .grupo-aprobaron { color: var(--ok-texto); background: var(--tinte-aprobo); margin: 0 -5px; padding: 3px 5px 2px; border-radius: 8px 8px 0 0; }
.tabla-consenso .grupo-contrapropuestas { align-self: stretch; border-left: 2px solid var(--border-strong); margin-left: -6px; padding: 3px 0 2px 4px; }
.pildora-aprobo {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--ok) 40%, transparent);
  background: color-mix(in srgb, var(--ok) 16%, var(--panel));
  color: var(--ok-texto);
  font-size: 10.5px;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
}
/* Aprobó una versión anterior: la misma píldora con el borde discontinuo; el título lo dice. */
.pildora-aprobo.version-anterior { border-style: dashed; }
/* La línea de resumen bajo la solicitud: la parte de las aprobaciones, en verde. */
.resumen-participacion { line-height: 1.8; }
.resumen-aprobaron { color: var(--ok-texto); font-weight: 600; background: color-mix(in srgb, var(--ok) 12%, var(--panel)); padding: 1px 8px; border-radius: 999px; }
.resumen-aprobaron .mdi { margin-right: 4px; }
/* La columna editable se distingue a simple vista de las que solo se leen: es la única
   en la que se escribe, y sin marcarla la gente intenta teclear sobre las otras. */
.tabla-consenso .celda-consenso { padding: 0; }
.tabla-consenso .input-consenso {
  width: 100%;
  text-align: right;
  font-variant-numeric: tabular-nums;
  padding: 4px 8px;
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: var(--panel);
  color: inherit;
  font-size: 12px;
}
.tabla-consenso .input-consenso:disabled { border-color: var(--border); color: var(--muted); }
.aviso-sin-propuestas { display: flex; align-items: baseline; gap: 6px; }
/* Lo que hay aplicado hoy se lee en el color de acento y no en gris: es el dato por el
   que se abrió esta pantalla, no una nota al pie. En flujo normal y NO en `flex`: con
   `display:flex` cada `<b>` se volvía un elemento de la rejilla y la frase se partía en
   trozos sueltos en vez de leerse como una línea. */
.aviso-aplicado { color: var(--accent); line-height: 1.6; }
.aviso-aplicado .mdi { margin-right: 4px; }
/* What the DOCS did with the agreed hours, under the notice above (`ConsensusDocsResult.js`) */
.resultado-docs-consenso { display: flex; flex-direction: column; gap: 6px; margin: 4px 0 8px; }
.resultado-docs-consenso .alert .mdi, .resultado-docs-consenso > .hint .mdi { margin-right: 4px; }
.resultado-docs-consenso ul { margin: 0; padding-left: 18px; }
.observaciones-consenso { display: flex; flex-direction: column; gap: 10px; }
.rastro-consenso summary { cursor: pointer; font-size: 12px; color: var(--muted); }
.rastro-consenso .ventana-fila { grid-template-columns: 70px 1fr 1.4fr 1.4fr; }
/* Una aplicación deshecha se queda en el rastro —es justo lo que se viene a consultar—,
   tachada para que no se confunda con la vigente. */
.rastro-deshecho { color: var(--muted); text-decoration: line-through; }

/* LA MARCA DE LA TABLA: la celda Total de una fila cuyas horas son acordadas y no las del
   documento. Un fondo de acento y un punto, y NO la cifra en otro color: la columna se
   lee en vertical y un número teñido se interpretaría como un aviso sobre el número. Con
   el fondo se ve qué filas llevan horas pactadas sin tener que pasar el ratón por todas,
   que es lo que hay que poder hacer de un vistazo. */
.horas-acordadas { position: relative; background: var(--accent-soft); }
.horas-acordadas::after {
  content: "";
  position: absolute;
  top: 4px;
  right: 3px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
}

/* «Estado de la publicación» (PublicationToast.js): a card at the top right that follows a push
   to p2h-docs, FOLDABLE into a tab on the right edge. Not a SweetAlert2 toast any more: that one
   kept Escape from closing the modals and covered their «×». Its colour says its state: blue
   publishing, green done, red failed. Above the modals (z-index 55) so it is not lost behind a
   backdrop; folding it frees the corner. */
.pub-aviso { position: fixed; top: 12px; right: 12px; z-index: 55; --pub-color: var(--accent); }
.pub-aviso.pub-success { --pub-color: var(--ok); }
.pub-aviso.pub-failed { --pub-color: var(--danger); }
.pub-aviso-card {
  position: relative; display: flex; align-items: stretch; width: 370px; max-width: calc(100vw - 24px);
  background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14); overflow: hidden;
}
.pub-aviso-plegar {
  flex: none; width: 30px; padding: 0; border: 0; border-radius: 0; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: var(--pub-color); color: #fff; font-size: 18px; transition: filter 0.15s ease;
}
.pub-aviso-plegar:hover, .pub-aviso-pestana:hover { filter: brightness(1.08); border-color: transparent; }
.pub-aviso-plegar:focus-visible, .pub-aviso-pestana:focus-visible { outline: 3px solid color-mix(in srgb, var(--pub-color) 45%, transparent); outline-offset: 2px; }
.pub-aviso-cuerpo { flex: 1; min-width: 0; padding: 12px 14px 12px 12px; font-size: 12px; }
.pub-aviso.pub-failed .pub-aviso-cuerpo { padding-right: 34px; }
.pub-aviso-cerrar {
  position: absolute; top: 6px; right: 6px; width: 24px; height: 24px; padding: 0; border: 0; background: none;
  color: var(--muted); font-size: 16px; cursor: pointer;
}
.pub-aviso-cerrar:hover { color: var(--text); }
/* Folded: only the tab on the edge, with the step it is in and its little bar */
.pub-aviso-pestana {
  position: fixed; top: 12px; right: 0; width: 46px; height: 78px; padding: 0; border: 0; border-radius: 10px 0 0 10px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px; cursor: pointer;
  background: var(--pub-color); color: #fff; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.22);
}
.pub-aviso-pestana .mdi { font-size: 18px; line-height: 1; }
.pub-aviso-paso { font-size: 12px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
.pub-aviso-mini { width: 26px; height: 4px; border-radius: 2px; background: rgba(255, 255, 255, 0.35); overflow: hidden; }
.pub-aviso-mini i { display: block; height: 100%; background: #fff; transition: width 0.3s ease; }
.publication-toast-head { display: flex; align-items: flex-start; gap: 10px; }
/* A fixed box for the icon: spinning, its glyph is wider than its box at some angles, and
   the toast (SweetAlert's `overflow: auto`) showed a horizontal scrollbar on each turn */
.publication-toast-icon {
  flex: none; width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center;
  font-size: 22px; line-height: 1; color: var(--accent);
}
.publication-toast-head.success .publication-toast-icon { color: var(--ok); }
.publication-toast-head.failed .publication-toast-icon { color: var(--danger); }
.publication-toast-heading { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.publication-toast-heading strong { font-size: 13px; font-weight: 600; line-height: 1.3; }
.publication-toast-meta { color: var(--muted); font-size: 11.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.publication-toast-elapsed { color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; white-space: nowrap; padding-top: 2px; }
/* One segment per step: done fills, the one in course moves, a failure stays red */
.publication-toast-progress { display: flex; gap: 3px; margin: 12px 0 6px; }
.publication-toast-progress span { flex: 1; height: 6px; border-radius: 3px; background: var(--border); overflow: hidden; transition: background-color 0.3s ease; }
.publication-toast-progress span.done { background: var(--accent); }
.publication-toast-progress.success span.done { background: var(--ok); }
.publication-toast-progress span.skipped { background: var(--warn-bg); }
.publication-toast-progress span.failed { background: var(--danger); }
.publication-toast-progress span.running {
  background: linear-gradient(90deg, var(--accent-soft) 0%, var(--accent) 50%, var(--accent-soft) 100%);
  background-size: 200% 100%;
  animation: publication-toast-flow 1.2s linear infinite;
}
@keyframes publication-toast-flow { from { background-position: 100% 0; } to { background-position: -100% 0; } }
@media (prefers-reduced-motion: reduce) { .publication-toast-progress span.running { animation: none; background: var(--accent); opacity: 0.6; } }
.publication-toast-stage { display: flex; align-items: baseline; gap: 8px; color: var(--text); font-weight: 600; }
.publication-toast-stage span { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.publication-toast-stage small { color: var(--muted); font-weight: 400; font-size: 11px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.publication-toast-stage.success { color: var(--ok); }
.publication-toast-stage.failed { color: var(--danger); }
.publication-toast-result { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--border); color: var(--muted); }
.publication-toast-error { margin-top: 8px; color: var(--danger); overflow-wrap: anywhere; }

/* DOCUMENTACIÓN EN PANTALLAS ANGOSTAS.
   En escritorio la pantalla ocupa el alto de la ventana y la tabla se queda con lo que
   sobra (`flex: 1`). En un teléfono los filtros, los botones y las tarjetas ya se comen
   ese alto entero y a la tabla le tocaban 0 px: había filas y no se veía ninguna. Aquí
   la tabla tiene alto propio (se desplaza por dentro) y la página baja con la rueda. */
.paginacion-nav { display: inline-flex; align-items: center; gap: 8px; }
@media (max-width: 900px) {
  .layout-ancho .pantalla-docs > .tabla-scroll { flex: 0 0 auto; min-height: 240px; max-height: 70vh; }
  .layout-ancho .pantalla-docs > .tabla-scroll > .tabla-docs { height: auto; }
  /* «Más filtros» y «Limpiar» juntos y a la derecha, no una fila cada uno */
  .filtros .acciones-filtro { flex: 0 0 auto; }
  .filtros .field:not(.acciones-filtro) + .acciones-filtro { margin-left: auto; }
}
@media (max-width: 640px) {
  /* Los botones de la pantalla, en dos columnas a lo ancho: alineados a la derecha
     quedaban en filas de distinto largo, con el divisor flotando en medio */
  .acciones-docs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .acciones-docs > .btn,
  .acciones-docs > a.btn { width: 100%; justify-content: center; }
  .acciones-docs .divisor-acciones { display: none; }

  /* El pie: «Mostrar» y el recuento, la navegación centrada debajo y el aviso al final */
  .paginacion { flex-wrap: wrap; row-gap: 8px; }
  .paginacion > .spacer { display: none; }
  .paginacion-nav { flex: 1 1 100%; justify-content: center; order: 5; }
  .paginacion .aviso-lateral { flex: 1 1 100%; order: 10; }
}

/* LA CABECERA EN UN TELÉFONO: una línea para la marca, la herramienta y «Ajustes», y otra
   para las pestañas. Con el logo a la vista el nombre de la app sobra, y «Ajustes» se
   queda sin el nombre de la cuenta (sigue en su tooltip y dentro del panel). Las
   pestañas no se parten en dos líneas: se deslizan de lado, como en cualquier app. */
@media (max-width: 560px) {
  .topbar { flex-wrap: nowrap; }
  .topbar .marca-app:has(.marca-logo, .marca-monograma) .marca-nombre { display: none; }
  .topbar .ajustes-usuario { display: none; }
  .topbar .dropdown-toggle,
  .topbar .ajustes-boton { white-space: nowrap; }
  .subbar { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; gap: 0; padding-left: 8px; padding-right: 8px; }
  .subbar::-webkit-scrollbar { display: none; }
  /* Tighter, so the usual three tabs fit a phone without sliding */
  .subbar .chip { flex: 0 0 auto; white-space: nowrap; margin-right: 2px; font-size: 12px; }
}

/* While `/page` answers (paging, sorting, filtering, a save): the SAME skeleton as the
   first load covers the table (DocsSkeleton.js), so loading always looks the same. The
   rows keep their place underneath, hidden, and the box does not jump. */
.tabla-scroll { position: relative; }
.tabla-scroll.tabla-cargando > .tabla-docs { visibility: hidden; }
.esqueleto-sobre-tabla {
  position: absolute;
  inset: 0;
  z-index: 3;
  overflow: hidden;
  background: var(--panel);
}

/* «Descargar»: the explorer of the tickets' files (DownloadModal.js). Rows like the
   viewer's tree, each with its box; the total of what is ticked at the foot. */
.explorador-descarga { max-height: 60vh; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
.explorador-ticket { display: flex; flex-direction: column; padding-bottom: 6px; border-bottom: 1px solid var(--border); }
.explorador-ticket:last-child { border-bottom: 0; }
.explorador-fila { display: flex; align-items: center; gap: 8px; min-height: 30px; padding: 2px 8px; border-radius: 6px; cursor: pointer; font-size: 13px; }
.explorador-fila:hover { background: var(--accent-soft); }
.explorador-fila .mdi { color: var(--muted); font-size: 16px; }
.explorador-fila .hint { margin-left: auto; white-space: nowrap; }
.explorador-raiz { font-size: 13.5px; }
.explorador-raiz .hint { margin-left: 4px; white-space: normal; overflow: hidden; text-overflow: ellipsis; }
.explorador-nombre { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.explorador-carpeta { cursor: default; }
.explorador-plegar { border: 0; background: none; padding: 0; width: 18px; display: inline-flex; justify-content: center; cursor: pointer; color: var(--muted); }
.modal-descarga footer .explorador-total { margin-right: auto; align-self: center; }
/* The explorer while it reads a ticket's files: rows of the same skeleton as the table */
.explorador-esqueleto { display: flex; flex-direction: column; gap: 2px; padding: 4px 0; }
.esqueleto-fila-explorador { cursor: default; padding-left: 28px; }
.esqueleto-fila-explorador:hover { background: none; }
.explorador-esqueleto-peso { width: 48px; margin-left: auto; }
.explorador-esqueleto-total { display: inline-block; width: 160px; height: 10px; }

/* The loading state of every modal (LoadingSkeleton.js): rows of the table's skeleton */
.esqueleto-modal { display: flex; flex-direction: column; gap: 10px; padding: 6px 0; }
.esqueleto-modal-fila { display: flex; align-items: center; gap: 10px; }
.esqueleto-modal-dato { width: 56px; margin-left: auto; }

/* El token de integración recién creado (IntegrationTokensPanel): la única vez que se puede
   leer, así que se enseña entero y seleccionable. `break-all` porque son 43 caracteres sin un
   solo espacio donde partir, y sin eso se sale del recuadro en una pantalla estrecha. */
.token-reciente {
  font-size: 13px;
  word-break: break-all;
  user-select: all;
  margin: 6px 0;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--accent-soft);
}

/* «Compartir» (modules/docShare/ShareTicketModal.js): one row per way of sharing, its icon,
   what it does and, below, what it copies or how it goes */
.modal.modal-compartir { width: 520px; max-width: calc(100vw - 32px); }
.modal-compartir > .body { display: flex; flex-direction: column; gap: 16px; }
/* The ticket a modal is about (TicketCard.js): its key and its title, the way the table names it */
.ticket-ficha {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--accent-soft);
}
.ticket-ficha > .mdi { flex: none; font-size: 26px; color: var(--accent); }
.ticket-ficha-texto { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ticket-ficha-texto strong { font-size: 14px; }
.ticket-ficha-texto span { font-size: 12.5px; color: var(--muted); line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.compartir-grupo h4 { margin: 0 0 8px; font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.compartir-opciones { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.compartir-opcion {
  display: flex; align-items: center; gap: 10px; width: 100%; min-width: 0; padding: 12px; text-align: left;
  border: 1px solid var(--border); border-radius: 10px; background: var(--panel); color: var(--text); cursor: pointer;
  transition: border-color .15s, background .15s, transform .15s, box-shadow .15s;
}
.compartir-opcion:hover, .compartir-opcion:focus-visible {
  border-color: var(--tono, var(--accent)); background: color-mix(in srgb, var(--tono, var(--accent)) 7%, var(--panel));
  transform: translateY(-1px); box-shadow: 0 4px 12px color-mix(in srgb, var(--tono, var(--accent)) 16%, transparent); outline: none;
}
.compartir-opcion > .mdi:first-child { flex: none; width: 36px; height: 36px; border-radius: 10px; display: flex; align-items: center;
  justify-content: center; font-size: 19px; color: var(--tono, var(--accent)); background: color-mix(in srgb, var(--tono, var(--accent)) 13%, transparent); }
.compartir-opcion .compartir-ir { flex: none; font-size: 18px; color: var(--muted); opacity: 0; transition: opacity .15s; }
.compartir-opcion:hover .compartir-ir, .compartir-opcion:focus-visible .compartir-ir { opacity: 1; color: var(--tono, var(--accent)); }
.compartir-opcion.compartir-path { --tono: var(--muted); }
.compartir-opcion.compartir-whatsapp { --tono: #25a244; }
.ticket-ficha.refs-ficha { margin-bottom: 16px; }
/* «Urgente» de una solicitud de aprobación (UrgentChip.js): rojo, con su icono; en la ficha del
   ticket va a la derecha (lo que se le pasa al hueco de TicketCard.js) */
.chip-urgente {
  display: inline-flex; align-items: center; gap: 4px; flex: none; padding: 2px 9px;
  border: 1px solid var(--danger); border-radius: 999px; background: var(--danger-bg); color: var(--danger);
  font-size: 11px; font-weight: 700; line-height: 1.4; white-space: nowrap;
}
.chip-urgente .mdi { font-size: 13px; line-height: 1; }
.ticket-ficha > .chip-urgente { margin-left: auto; }
.settings-subtitle .chip-urgente { margin-left: 6px; vertical-align: middle; letter-spacing: 0; text-transform: none; }
@media (max-width: 480px) { .compartir-opciones { grid-template-columns: 1fr; } }
.compartir-texto { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.compartir-texto strong { font-size: 13px; font-weight: 600; }
.compartir-texto small { font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Where a sprint comes from (SprintsModal): created in the app, or brought by the DevOps sync */
.sprint-origen {
  display: inline-flex; align-items: center; gap: 3px; margin-left: 6px; padding: 1px 6px;
  border-radius: 999px; font-size: 10.5px; font-weight: 600; vertical-align: middle; white-space: nowrap;
}
.sprint-origen .mdi { font-size: 12px; }
.sprint-origen.origen-devops { color: #0a6ebd; background: color-mix(in srgb, #0a6ebd 13%, transparent); }
.sprint-origen.origen-app { color: var(--muted); background: color-mix(in srgb, var(--muted) 13%, transparent); }

/* «Teléfono / WhatsApp» (components/PhoneField.js, vue-tel-input): the app's own input, in both
   themes. The library's CSS paints a white list and a light border; these use the tokens. */
.campo-telefono.vue-tel-input {
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); color: var(--text);
  font: inherit; width: 100%;
}
.campo-telefono.vue-tel-input:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
.campo-telefono .vti__input { background: transparent; color: var(--text); font: inherit; border-radius: 0 var(--radius) var(--radius) 0; }
.campo-telefono .vti__input::placeholder { color: var(--muted); }
.campo-telefono .vti__dropdown { border-right: 1px solid var(--border); border-radius: var(--radius) 0 0 var(--radius); padding: 0 8px; }
.campo-telefono .vti__dropdown:hover, .campo-telefono .vti__dropdown.open { background: var(--accent-soft); }
.campo-telefono .vti__country-code { color: var(--muted); font-size: 12.5px; }
.campo-telefono .vti__dropdown-list {
  background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 12px 28px rgba(0, 0, 0, .18); width: 340px; max-height: 260px; z-index: 60; left: -1px; top: calc(100% + 4px);
  overflow-x: hidden;
}
.campo-telefono .vti__dropdown-item { color: var(--text); padding: 6px 10px; }
.campo-telefono .vti__dropdown-item strong { font-weight: 500; }
.campo-telefono .vti__dropdown-item span { color: var(--muted); }
.campo-telefono .vti__dropdown-item.highlighted { background: var(--accent-soft); }
.campo-telefono .vti__dropdown-item.last-preferred { border-bottom: 1px solid var(--border); }
.campo-telefono .vti__search_box {
  background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: var(--radius);
  margin: 6px; width: calc(100% - 12px); padding: 6px 8px; font: inherit;
}
.campo-telefono.invalido.vue-tel-input { border-color: var(--danger, #c0392b); }
/* A field whose control cannot live inside a <label> (the phone's country selector would hand
   every click to the first input): the same look, text above and control below */
.campo-con-etiqueta { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
.campo-con-etiqueta > span:first-child { font-weight: 500; }
/* A REQUIRED field says so with «*» after its name; an optional one carries no mark at all */
.obligatorio { color: var(--danger); font-weight: 600; margin-left: 1px; }

/* ===================================================== «Enviar por WhatsApp» (modules/docShare) */
.modal.modal-whatsapp { width: 640px; max-width: calc(100vw - 32px); }
.modal-whatsapp > .body { display: flex; flex-direction: column; gap: 16px; }
/* The body scrolls; its parts keep their height (a flex column of fixed height would squeeze the history to nothing) */
.modal-whatsapp > .body > * { flex-shrink: 0; }
.modal-whatsapp .campo-titulo { display: block; font-weight: 600; font-size: 13px; margin-bottom: 6px; }
.btn.btn-whatsapp { background: #25a244; border-color: #25a244; color: #fff; font-weight: 600; }
.btn.btn-whatsapp:hover:not(:disabled) { background: #1e8a39; border-color: #1e8a39; }
.btn.btn-whatsapp:disabled { opacity: .5; }

/* The result of a send, said inside the modal (it stays open) */
.aviso-envio { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-radius: 10px; font-size: 13px; border: 1px solid; }
.aviso-envio > .mdi { font-size: 18px; }
.aviso-envio > button { margin-left: auto; border: 0; background: none; color: inherit; cursor: pointer; font-size: 16px; }
.aviso-envio.aviso-ok { color: #1a7f37; background: color-mix(in srgb, #25a244 12%, var(--panel)); border-color: color-mix(in srgb, #25a244 35%, transparent); }
.aviso-envio.aviso-partial { color: #9a5b00; background: color-mix(in srgb, #d97706 12%, var(--panel)); border-color: color-mix(in srgb, #d97706 35%, transparent); }
.aviso-envio.aviso-failed { color: var(--danger); background: color-mix(in srgb, var(--danger) 10%, var(--panel)); border-color: color-mix(in srgb, var(--danger) 35%, transparent); }

/* The file that goes */
.archivo-envio { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; }
.archivo-icono { width: 38px; height: 44px; border-radius: 6px; background: #2b579a; color: #fff; display: flex; align-items: flex-end; justify-content: center;
  font-size: 10px; font-weight: 700; padding-bottom: 5px; flex: none; }
.archivo-icono.pequeno { width: 28px; height: 34px; font-size: 8px; padding-bottom: 3px; }
.archivo-texto { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.archivo-texto b { font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.archivo-texto small { color: var(--muted); font-size: 12px; }
.archivo-listo { color: #25a244; font-size: 12px; font-weight: 600; white-space: nowrap; }
.archivo-nota { margin: 6px 0 0; }
.archivo-nota .btn-link { padding: 0; font-weight: 600; }
.para-pie { display: flex; justify-content: space-between; gap: 8px; margin-top: 6px; }

/* «Para»: the chips and the list that opens only while it is used (RecipientPicker) */
.destinatarios { position: relative; }
.destinatarios-campo { border: 1px solid var(--border); border-radius: 10px; padding: 5px 6px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  background: var(--panel); cursor: text; }
.destinatarios-campo:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
.destinatarios-campo input { flex: 1; min-width: 160px; border: 0; outline: 0; background: none; color: var(--text); font: inherit; padding: 6px 4px; box-shadow: none; }
.destinatarios-flecha { border: 0; background: none; color: var(--muted); cursor: pointer; padding: 0 4px; font-size: 18px; }
.destinatario-ficha { display: inline-flex; align-items: center; gap: 6px; padding: 3px 6px 3px 3px; border-radius: 999px; font-size: 12.5px;
  background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent); }
.destinatario-ficha button { border: 0; background: none; color: var(--muted); cursor: pointer; padding: 0 2px; font-size: 13px; line-height: 1; }
.destinatario-avatar { width: 22px; height: 22px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 700; font-size: 10px; flex: none; }
.destinatario-avatar.grande { width: 32px; height: 32px; font-size: 12px; }
.destinatarios-lista { position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 30; border: 1px solid var(--border); border-radius: 10px;
  background: var(--panel); box-shadow: 0 16px 36px rgba(0, 0, 0, .18); overflow: hidden; }
.destinatarios-scroll { max-height: 240px; overflow: auto; }
.destinatarios-grupo { display: flex; justify-content: space-between; padding: 8px 12px 4px; font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted); }
.destinatario-opcion { display: flex; align-items: center; gap: 10px; padding: 7px 12px; cursor: pointer; }
.destinatario-opcion.activa { background: var(--accent-soft); }
.destinatario-quien { display: flex; flex-direction: column; min-width: 0; }
.destinatario-quien b { font-weight: 600; font-size: 13.5px; }
.destinatario-quien span { color: var(--muted); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.destinatario-opcion.sin-numero { cursor: not-allowed; opacity: .55; }
.destinatario-opcion.sin-numero .destinatario-quien span { font-style: italic; }
.destinatario-fuera { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-top: 1px solid var(--border); color: var(--accent); font-weight: 600; cursor: pointer; }
.destinatario-fuera:hover { background: var(--accent-soft); }
.destinatario-mas { width: 32px; height: 32px; border-radius: 50%; border: 1.5px dashed var(--accent); display: inline-flex; align-items: center; justify-content: center; }

/* The message as it arrives: a WhatsApp chat */
.chat-whatsapp { --chat-bg: #efeae2; --burbuja: #fff; --burbuja-texto: #111b21; background: var(--chat-bg); border: 1px solid var(--border); border-radius: 10px; padding: 14px; }
.burbuja { max-width: 90%; background: var(--burbuja); color: var(--burbuja-texto); border-radius: 0 8px 8px 8px; padding: 4px 4px 8px; position: relative;
  box-shadow: 0 1px 1px rgba(0, 0, 0, .12); }
.burbuja::before { content: ""; position: absolute; left: -7px; top: 0; border-top: 8px solid var(--burbuja); border-left: 8px solid transparent; }
.burbuja-adjunto { display: flex; align-items: center; gap: 10px; padding: 8px 10px; margin-bottom: 6px; border-radius: 6px;
  background: color-mix(in srgb, var(--burbuja-texto) 6%, transparent); }
.burbuja-adjunto .archivo-texto small { color: inherit; opacity: .7; }
.burbuja-texto { white-space: pre-wrap; font-size: 13.5px; line-height: 1.45; padding: 0 6px; }
.burbuja-botones { display: grid; gap: 4px; margin-top: 8px; padding: 0 2px; }
.burbuja-boton { display: flex; align-items: center; justify-content: center; gap: 6px; padding: 7px; border-radius: 6px; font-size: 13.5px;
  background: color-mix(in srgb, var(--burbuja-texto) 6%, transparent); }
.vista-previa-aprobacion { display: grid; gap: 8px; }
.vista-previa-pestanas { display: flex; gap: 4px; border-bottom: 1px solid var(--border); }
.vista-previa-pestanas button { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 6px; border: 0; background: none; padding: 6px 12px; color: var(--muted); border-bottom: 2px solid transparent; cursor: pointer; font: inherit; }
.vista-previa-pestanas button.activa { color: var(--brand); border-bottom-color: var(--brand); }
.vista-previa-asunto { margin: 0; }
.vista-previa-marco { height: 224px; overflow: hidden; border: 1px solid var(--border); border-radius: 10px; background: #fff; }
.vista-previa-correo { height: 320px; display: block; border: 0; transform-origin: top left; }
.vista-previa-aprobacion .chat-whatsapp { padding: 10px; }
.vista-previa-aprobacion .burbuja { max-width: 70%; }
.vista-previa-aprobacion .burbuja-texto, .vista-previa-aprobacion .burbuja-boton { font-size: 12px; }

/* «Envíos de este ticket» (WhatsappSendHistory) */
.envios-whatsapp { border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.envios-whatsapp > header { padding: 9px 12px; font-weight: 600; font-size: 13px; border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--muted) 7%, var(--panel)); }
.envios-whatsapp .envios-vacio { margin: 0; padding: 12px; }
.envios-caja { max-height: 240px; overflow: auto; }
.envios-caja table { margin: 0; }
.envio-para { display: flex; align-items: center; gap: 8px; }
.envio-para + .envio-para { margin-top: 6px; }
.envio-asunto { margin-top: 4px; max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.envio-para small { display: block; color: var(--muted); font-size: 11.5px; font-variant-numeric: tabular-nums; }
.envios-caja tr.envio-nuevo td { animation: envio-nuevo 2.4s ease-out; }
@keyframes envio-nuevo { from { background: color-mix(in srgb, #25a244 22%, transparent); } to { background: transparent; } }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .chat-whatsapp { --chat-bg: #0b141a; --burbuja: #1f2c34; --burbuja-texto: #e9edef; } }
:root[data-theme="dark"] .chat-whatsapp { --chat-bg: #0b141a; --burbuja: #1f2c34; --burbuja-texto: #e9edef; }
/* Inside the chips' box the search is bare (the box is the field), and the e-mail link is a link */
/* Same :not() chain as the global input rule (which would otherwise win) plus this class */
.destinatarios-campo input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(.swal2-input) {
  width: auto; border: 0; border-radius: 0; background: none; box-shadow: none; padding: 6px 4px; margin: 0;
}
.modal .archivo-nota .btn-link { border: 0; background: none; color: var(--accent); padding: 0; min-height: 0; text-decoration: underline; text-underline-offset: 2px; }
.envio-fecha { font-variant-numeric: tabular-nums; color: var(--muted); }
/* «Enviar por correo»: what goes, as two cards to choose from (the same card as WhatsApp's file) */
.adjunto-opciones { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.archivo-envio.elegible { cursor: pointer; position: relative; transition: border-color .15s, background .15s; }
.archivo-envio.elegible > input[type="radio"] { position: absolute; opacity: 0; pointer-events: none; }
.archivo-envio.elegible:hover { border-color: var(--accent); }
.archivo-envio.elegible.elegido { border-color: var(--accent); background: var(--accent-soft); box-shadow: 0 0 0 1px var(--accent) inset; }
.archivo-envio.elegible.bloqueado { cursor: not-allowed; opacity: .55; }
.archivo-envio.elegible.bloqueado:hover { border-color: var(--border); }
/* WhatsApp's single card without a main document: nothing to send, said greyed */
.archivo-envio.bloqueado { opacity: .55; }
/* Why «Enviar» is disabled, next to it in the footer */
.motivo-envio { font-size: 12px; max-width: 60%; }
.archivo-icono.zip { background: #8a6d1f; }
.modal-correo textarea, .modal-correo input[type="text"]:not(.destinatarios-campo input) { width: 100%; }
@media (max-width: 560px) { .adjunto-opciones { grid-template-columns: 1fr; } }

/* «Pedir la aprobación»: «Para» and the message as in Compartir (WhatsApp and e-mail) */
.modal-aprobacion .campo-titulo { display: block; font-weight: 600; font-size: 13px; margin-bottom: 6px; }
.modal-aprobacion textarea { width: 100%; }
/* A mark after the name in «Para»'s list («ronda anterior») */
.destinatario-nota {
  margin-left: 6px; padding: 0 6px; border-radius: 999px; font-size: 11px; font-weight: 600;
  background: var(--warn-bg); color: var(--warn); vertical-align: 1px;
}
.aprobacion-pedido { display: flex; flex-direction: column; gap: 16px; }
.aprobacion-pedido > p { margin: 0; }

/* «Enviar por» of the approval request: three cards in a row, with a round channel icon */
.adjunto-opciones.canales-aprobacion { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.canales-aprobacion .archivo-icono { width: 32px; height: 32px; border-radius: 50%; align-items: center; padding: 0; font-size: 17px; }
.canales-aprobacion .archivo-icono.canal-ambos { background: var(--brand); }
.canales-aprobacion .archivo-icono.canal-correo { background: var(--muted); }
.canales-aprobacion .archivo-icono.canal-whatsapp { background: #25a244; }
.aprobacion-pedido .canales-aprobacion + .hint { margin: 6px 0 0; }
/* Under «Para» only the counter «0 de 20» is left: it keeps its place on the right */
/* «Para» with the counter «0 de 20» on its own line, on the right: no extra row under the picker */
.aprobacion-pedido .para-titulo { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.aprobacion-pedido .para-titulo .hint { margin: 0; }
/* «Prioridad»: the same option cards as «Enviar por», two that take the whole width */
.adjunto-opciones.canales-aprobacion.prioridades-aprobacion { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.canales-aprobacion .archivo-icono.prioridad-normal { background: var(--brand); }
.canales-aprobacion .archivo-icono.prioridad-urgent { background: #d93025; }
@media (max-width: 560px) { .adjunto-opciones.canales-aprobacion { grid-template-columns: 1fr; } }

/* «Aprobación de la estimación», the open request: a summary card with its progress and one
   card per person, as in Compartir (avatar, name, contact) */
.aprobacion-resumen { display: flex; flex-direction: column; gap: 10px; padding: 14px 16px; border: 1px solid var(--border); border-radius: 10px; margin-bottom: 14px; }
.aprobacion-resumen.abierta { border-color: color-mix(in srgb, var(--accent) 35%, var(--border)); }
.aprobacion-resumen-cabecera { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.aprobacion-resumen-cabecera .spacer { flex: 1; }
.aprobacion-resumen .estado-solicitud { font-size: 13px; }
.aprobacion-canal {
  display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; border-radius: 999px;
  background: var(--neutral-bg); font-size: 11.5px; font-weight: 600; color: var(--muted);
}
.aprobacion-barra { display: flex; height: 8px; border-radius: 999px; overflow: hidden; background: var(--neutral-bg); }
.aprobacion-barra .tramo-si { background: var(--ok); }
.aprobacion-barra .tramo-no { background: var(--danger); }
.aprobacion-cifras { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 12.5px; color: var(--muted); }
.aprobacion-cifras b { color: var(--text); }
.aprobacion-cifras .mdi { font-size: 14px; vertical-align: -1px; }
/* D-35: si el último correo llevó el detalle de DevOps y su zip, o qué se quedó fuera */
.aprobacion-devops { display: flex; gap: 6px; align-items: flex-start; margin: 8px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
.aprobacion-devops.aviso { color: var(--warn); }
.aprobacion-devops .mdi { font-size: 14px; margin-top: 1px; }
.opcion-devops { display: flex; gap: 8px; align-items: flex-start; cursor: pointer; }
.opcion-devops input { margin-top: 3px; }
.opcion-devops small { display: block; font-weight: normal; }
.aprobacion-cifras .cifra-si .mdi { color: var(--ok); }
.aprobacion-cifras .cifra-no .mdi { color: var(--danger); }

.aprobadores { display: flex; flex-direction: column; gap: 8px; }
.aprobador-tarjeta { border: 1px solid var(--border); border-left: 3px solid var(--c, var(--border)); border-radius: 10px; background: var(--panel); }
.aprobador-tarjeta.revocado { opacity: .7; }
.aprobador {
  display: grid; grid-template-columns: 40px minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr);
  align-items: center; gap: 12px; padding: 10px 12px;
}
.aprobador-quien { display: flex; flex-direction: column; min-width: 0; }
.aprobador-quien b { font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.aprobador-quien span { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.aprobador-quien .mdi-whatsapp { color: #25a244; }
.aprobador-decision { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; min-width: 0; }
.aprobador-decision .hint { font-size: 11.5px; }
.aprobador-envios { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.aprobador-envio { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.aprobador-envio .mdi { font-size: 15px; line-height: 1; }
.aprobador-envio.envio-ok { color: var(--ok); }
.aprobador-envio.envio-fallo { color: var(--danger); }
.aprobador-envio.envio-espera, .aprobador-envio.envio-nada { color: var(--muted); }
.aprobador-envio.envio-nada { font-style: italic; }
.aprobador-detalle { margin: 0 12px 10px 64px; }
/* What each person said, WHOLE: the label column fits its text and the comment (and every
   earlier answer) wraps instead of being cut with an ellipsis on one line */
.aprobador-detalle .ticket-de-ventana { grid-template-columns: minmax(5rem, max-content) minmax(0, 1fr); align-items: start; }
.aprobador-detalle .titulo-ticket { white-space: normal; overflow: visible; overflow-wrap: anywhere; }
.aprobador-detalle .aprobador-comentario { color: var(--text); line-height: 1.5; }
@media (max-width: 480px) {
  .aprobador-detalle .ticket-de-ventana { grid-template-columns: minmax(0, 1fr); gap: 2px; }
}

@media (max-width: 640px) {
  .aprobador { grid-template-columns: 40px minmax(0, 1fr); }
  .aprobador-decision, .aprobador-envios { grid-column: 2; }
  .aprobador-detalle { margin-left: 12px; }
}
/* The person's gestures, WITH A NAME (icons alone were not understood), at the foot of its card */
.aprobador-acciones {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  padding: 8px 12px; border-top: 1px solid var(--border); background: var(--neutral-bg); border-radius: 0 0 10px 10px;
}
.aprobador-acciones .spacer { flex: 1; }
button.btn-accion {
  display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; border-radius: 7px;
  border: 1px solid var(--border); background: var(--panel); color: var(--text); font: inherit; font-size: 12px; cursor: pointer;
}
button.btn-accion .mdi { font-size: 15px; line-height: 1; color: var(--accent); }
button.btn-accion:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
button.btn-accion.peligro .mdi, button.btn-accion.peligro:hover:not(:disabled) { color: var(--danger); }
button.btn-accion.peligro:hover:not(:disabled) { border-color: var(--danger); }

/* A tooltip that says several things, one per line (the DevOps chip's three gestures) */
/* `pre` and `max-content`: one gesture per line, each line whole. With `pre-line` the bubble took
   the narrow width of its chip and broke every word onto its own line */
.con-tooltip.tooltip-varias-lineas::after { white-space: pre; width: max-content; text-align: left; padding: 6px 10px; line-height: 1.6; }

/* The DevOps chip's card: fixed at its chip, like the row's ⋮ menu */
.tarjeta-devops {
  position: fixed; z-index: 60; max-width: calc(100vw - 16px); display: flex; flex-direction: column;
  border: 1px solid var(--border); border-radius: 12px; background: var(--panel); overflow: hidden;
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.2); font-size: 12.5px;
}
.tarjeta-devops-cabecera { display: flex; align-items: center; gap: 6px; padding: 8px 10px; border-bottom: 1px solid var(--border); }
.tarjeta-devops-cabecera .mdi-microsoft-azure-devops { color: var(--accent); font-size: 17px; }
.tarjeta-devops-cabecera .spacer { flex: 1; }
.tarjeta-devops-cuerpo { display: flex; flex-direction: column; gap: 10px; padding: 12px 14px 14px; max-height: min(60vh, 480px); overflow-y: auto; }
.tarjeta-devops-vacia { margin: 4px 0 0; }
/* Each work item (boceto B2): a grey strip with its number and «Abrir», then its title and data */
.devops-item { display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.devops-item-franja { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: var(--neutral-bg); }
.devops-item-franja .mono { font-weight: 700; font-size: 12px; }
.devops-item-franja .spacer { flex: 1; }
button.devops-item-abrir {
  display: inline-flex; align-items: center; gap: 2px; padding: 0; border: 0; background: none; cursor: pointer;
  color: var(--accent); font: inherit; font-size: 12px; font-weight: 600;
}
button.devops-item-abrir:hover { text-decoration: underline; }
.devops-item-cuerpo { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px 12px; }
.devops-item.eliminado { opacity: .7; }
/* The whole title, in two lines at most: it is what says which work item this is */
.devops-item-nombre {
  margin: 0; font-size: 13px; font-weight: 600; line-height: 1.4; color: var(--text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.devops-item-fila { display: flex; align-items: center; gap: 8px; min-width: 0; }
.devops-item-etiqueta { flex: none; width: 78px; color: var(--muted); font-size: 11.5px; }
.devops-estado { background: var(--accent-soft); color: var(--accent); font-weight: 600; white-space: nowrap; }
.devops-asignado { display: inline-flex; align-items: center; gap: 7px; min-width: 0; }
.devops-asignado > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.devops-asignado .destinatario-avatar { width: 22px; height: 22px; font-size: 9.5px; }
.devops-enlaces { display: flex; flex-direction: column; gap: 6px; }
.devops-enlace { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border: 1px solid var(--border); border-radius: 8px; }
.devops-enlace > .mdi { color: var(--muted); }
.devops-enlace-texto { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tarjeta-devops-pie { display: flex; align-items: center; gap: 6px; padding: 8px 14px; border-top: 1px solid var(--border); }
.tarjeta-devops-pie .spacer { flex: 1; }
/* While its card is open, the chip's tooltip would cover the card */
.con-tooltip.tooltip-oculto::after { display: none; }

/* ── EL EXPLORADOR DEL VISOR, como en VS Code (modules/docViewer/FileTree.js) ─────────────
   Sus clases son `visor-exp…` y no `explorador…`: esas son del explorador de «Descargar» (borde oscuro, filas propias) y se le colaban.
   Cabecera fija con sus acciones, una fila por carpeta o archivo con guías de sangría, y un
   icono con el color de su tipo. Su ancho lo da el visor (arrastrando el borde). */
:root {
  /* The colours each kind of file is known by (Office, Acrobat, the HTML5 logo…) */
  --tipo-word: #2b579a;
  --tipo-excel: #217346;
  --tipo-pdf: #d93025;
  --tipo-html: #e44d26;
  --tipo-imagen: #8e44ad;
  --tipo-codigo: #16a085;
}
.visor-lista.visor-exp { padding: 0; gap: 0; position: relative; }
.visor-lista.visor-exp.soltar-aqui { background: var(--accent-soft); box-shadow: inset 0 0 0 2px var(--accent); }
/* Boceto C: a grey strip «Archivos del ticket»; its actions show while the mouse is over the
   panel, with the keyboard on them, or while something is being written (`.fijas`) */
.visor-exp-cabecera {
  position: sticky; top: 0; z-index: 2; display: flex; align-items: center; gap: 4px; min-height: 38px;
  padding: 6px 6px 6px 10px; background: var(--neutral-bg); border-bottom: 1px solid var(--border);
}
.visor-exp-cabecera-icono { color: var(--accent); font-size: 15px; flex: none; }
.visor-exp-titulo { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; font-weight: 700; }
.visor-exp-acciones { display: inline-flex; gap: 2px; flex: none; opacity: 0; transition: opacity .12s; }
.visor-exp:hover .visor-exp-acciones,
.visor-exp-acciones:focus-within,
.visor-exp-acciones.fijas { opacity: 1; }
@media (hover: none) { .visor-exp-acciones { opacity: 1; } }
button.visor-exp-accion {
  width: 24px; height: 24px; border: 0; border-radius: 5px; background: transparent; color: var(--muted);
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer; font-size: 15px; padding: 0;
}
button.visor-exp-accion:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
button.visor-exp-accion:hover:not(:disabled) { background: var(--panel); color: var(--text); }
button.visor-exp-accion:disabled { opacity: .45; cursor: default; }
/* The eye while the generator files are shown: the standard blue, so the mode is seen */
button.visor-exp-accion.activa { color: var(--accent); }
/* Its tooltips go down: up they would leave the modal */
.visor-exp-acciones .con-tooltip::after { right: auto; left: 50%; top: calc(100% + 6px); transform: translateX(-50%); z-index: 20; }
.visor-exp-arbol { display: flex; flex-direction: column; padding: 4px 0 8px; }
/* One row: the guides of its level (a line every 14px), a chevron and an icon */
.visor-exp-fila {
  --nivel: 0;
  padding: 3px 8px 3px calc(8px + var(--nivel) * 14px) !important;
  border-radius: 0 !important; width: 100%;
  /* The indent guides, faint: a dark line read as a border */
  background-image: repeating-linear-gradient(90deg, transparent 0 13px, color-mix(in srgb, var(--border) 55%, transparent) 13px 14px);
  background-size: calc(var(--nivel) * 14px) 100%; background-repeat: no-repeat; background-position: 6px 0;
}
.visor-exp-fila.seleccionada { background-color: var(--neutral-bg); }
.visor-exp-fila.soltar-aqui { background-color: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent); }
.visor-exp-fila .visor-exp-chevron { width: 12px; font-size: 12px; color: var(--muted); flex: none; display: inline-block; opacity: .8; }
.visor-exp-fila .visor-exp-carpeta { font-size: 14px; color: var(--accent); }
.visor-carpeta.visor-exp-fila { color: var(--text); font-weight: 500; }
.visor-exp-fila .visor-exp-icono { font-size: 14px; }
/* No focus ring on a click (only with the keyboard): it drew a dark frame around the row */
.visor-exp-fila:focus { outline: none; }
.visor-exp-fila:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.visor-exp-icono.tipo-word { color: var(--tipo-word); }
.visor-exp-icono.tipo-excel { color: var(--tipo-excel); }
.visor-exp-icono.tipo-pdf { color: var(--tipo-pdf); }
.visor-exp-icono.tipo-html { color: var(--tipo-html); }
.visor-exp-icono.tipo-image { color: var(--tipo-imagen); }
.visor-exp-icono.tipo-code { color: var(--tipo-codigo); }
.visor-exp-icono.tipo-markdown,
.visor-exp-icono.tipo-text,
.visor-exp-icono.tipo-other { color: var(--muted); }
/* What was uploaded and is still on its way to R2 */
.visor-exp-fila.pendiente { opacity: .65; cursor: default; font-style: italic; }
.visor-exp-publicando { margin-left: auto; flex: none; font-size: 10.5px; color: var(--muted); display: inline-flex; align-items: center; gap: 2px; }
/* «Principal»: the file sent as the main document; discreet, the «⋯» stays right after it */
.visor-exp-principal {
  margin-left: auto; flex: none; display: inline-flex; align-items: center; gap: 2px;
  padding: 0 5px; border-radius: 8px; font-size: 10.5px; line-height: 16px;
  color: var(--accent); background: var(--accent-soft);
}
.visor-exp-principal .mdi { font-size: 11px; }
.visor-exp-principal + .visor-exp-mas, .visor-exp-principal + .visor-exp-publicando { margin-left: 4px; }
/* The new folder, typed in place */
.visor-exp-nueva { --nivel: 0; display: flex; align-items: center; gap: 6px; padding: 2px 8px 2px calc(22px + var(--nivel) * 14px); }
.visor-exp-nueva .mdi { color: var(--accent); font-size: 14px; flex: none; }
.visor-exp-nueva input { flex: 1; min-width: 0; height: 24px; padding: 0 6px; font-size: 12px; border: 1px solid var(--accent); border-radius: 4px; }
/* The «⋯» at the end of a row: shown on hover (and while its menu is open), as in VS Code */
.visor-exp-mas {
  margin-left: auto; flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 18px; border-radius: 4px; color: var(--muted); font-size: 15px;
  opacity: 0; transition: opacity .1s;
}
.visor-exp-fila:hover .visor-exp-mas, .visor-exp-fila:focus-visible .visor-exp-mas, .visor-exp-mas.abierto { opacity: 1; }
.visor-exp-mas:hover, .visor-exp-mas.abierto { background: color-mix(in srgb, var(--border) 70%, transparent); color: var(--text); }
@media (hover: none) { .visor-exp-mas { opacity: .6; } }
/* Renaming in place: the row becomes its input, at the same indent and with its icon */
.visor-exp-renombrar { --nivel: 0; display: flex; align-items: center; gap: 6px; padding: 2px 8px 2px calc(8px + var(--nivel) * 14px); }
.visor-exp-renombrar .visor-exp-chevron { width: 12px; flex: none; }
.visor-exp-renombrar .mdi { font-size: 14px; flex: none; }
.visor-exp-renombrar .visor-exp-carpeta { color: var(--accent); }
.visor-exp-renombrar input { flex: 1; min-width: 0; height: 22px; padding: 0 5px; font-size: 12px; border: 1px solid var(--accent); border-radius: 3px; outline: none; box-shadow: 0 0 0 2px var(--accent-soft); }

/* The explorer's right-click menu, like the system's: a floating card with a soft shadow,
   compact rows, the hovered one filled with the accent, separators as faint lines */
.menu-contextual {
  position: fixed; z-index: 1000; min-width: 210px; max-width: 280px; padding: 4px;
  background: var(--panel); color: var(--text);
  border: 1px solid color-mix(in srgb, var(--border) 85%, transparent); border-radius: 8px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .16), 0 2px 6px rgba(0, 0, 0, .08);
  font-size: 12.5px; user-select: none;
  animation: menu-contextual-entra .08s ease-out;
}
@keyframes menu-contextual-entra { from { opacity: 0; transform: scale(.98); } to { opacity: 1; transform: none; } }
.menu-contextual-item {
  display: flex; align-items: center; gap: 9px; width: 100%; min-height: 26px; padding: 3px 10px 3px 8px !important;
  border: 0 !important; border-radius: 5px !important; background: transparent !important; box-shadow: none !important;
  color: inherit !important; font: inherit; font-weight: 400 !important; text-align: left; cursor: default;
}
.menu-contextual-item .mdi { font-size: 15px; width: 16px; text-align: center; color: var(--muted); flex: none; }
.menu-contextual-texto { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.menu-contextual-pista { flex: none; margin-left: 18px; font-size: 11px; color: var(--muted); }
.menu-contextual-item.activa { background: var(--accent) !important; color: #fff !important; }
.menu-contextual-item.activa .mdi, .menu-contextual-item.activa .menu-contextual-pista { color: #fff; }
.menu-contextual-item.peligro, .menu-contextual-item.peligro .mdi { color: var(--danger) !important; }
.menu-contextual-item.peligro.activa { background: var(--danger) !important; color: #fff !important; }
.menu-contextual-item.peligro.activa .mdi { color: #fff !important; }
.menu-contextual-item.deshabilitada, .menu-contextual-item.deshabilitada .mdi { color: var(--muted) !important; opacity: .5; }
.menu-contextual-separador { height: 1px; margin: 4px 6px; background: var(--border); }
:root[data-theme="dark"] .menu-contextual { box-shadow: 0 12px 32px rgba(0, 0, 0, .5), 0 2px 6px rgba(0, 0, 0, .3); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .menu-contextual { box-shadow: 0 12px 32px rgba(0, 0, 0, .5), 0 2px 6px rgba(0, 0, 0, .3); }
}

/* The explorer's edge: dragged, it changes its width (double click: back to the usual) */
.visor-divisor { flex: 0 0 5px; margin-left: -3px; cursor: col-resize; position: relative; z-index: 3; }
.visor-divisor::after { content: ""; position: absolute; inset: 0 2px; transition: background .12s; }
.visor-divisor:hover::after { background: var(--accent); }
body.redimensionando { cursor: col-resize; user-select: none; }
body.redimensionando iframe { pointer-events: none; }
@media (max-width: 640px) {
  .visor-divisor { display: none; }
  .visor-lista.visor-exp { width: auto !important; }
}

/* ── A ticket's history (modules/ticketHistory): a timeline grouped by day ── */
.modal.modal-historial { width: 680px; max-width: calc(100vw - 32px); }
.modal-historial > .body { display: flex; flex-direction: column; gap: 12px; max-height: min(76vh, 760px); overflow-y: auto; padding-top: 14px; }
.modal-historial > .body > * { flex-shrink: 0; }

/* Filters: one line that scrolls sideways, soft pills; the chosen one filled with the brand */
.historial-filtros {
  display: flex; gap: 6px; overflow-x: auto; padding: 2px 2px 6px; margin: 0 -2px;
  scrollbar-width: thin; mask-image: linear-gradient(90deg, #000 92%, transparent);
}
.historial-filtro {
  flex: none; display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 10px !important;
  border: 1px solid var(--border) !important; border-radius: 999px !important; background: var(--panel) !important;
  color: var(--muted) !important; font-size: 12px; font-weight: 500 !important; white-space: nowrap; cursor: pointer;
  box-shadow: none !important; transition: background .12s, color .12s, border-color .12s;
}
.historial-filtro .mdi { font-size: 13px; }
.historial-filtro:hover { color: var(--text) !important; border-color: var(--border-strong) !important; }
.historial-filtro.activo { background: var(--accent) !important; border-color: var(--accent) !important; color: #fff !important; }

.historial-vacio {
  display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 28px 16px; text-align: center;
  color: var(--muted); border: 1px dashed var(--border); border-radius: 10px;
}
.historial-vacio .mdi { font-size: 28px; opacity: .6; }
.historial-vacio strong { color: var(--text); font-size: 13px; }
.historial-vacio span { font-size: 12px; max-width: 360px; }

/* The day: sticky while its events scroll, with how many there are */
.historial-dia-titulo {
  position: sticky; top: -14px; z-index: 2; display: flex; align-items: baseline; gap: 8px;
  margin: 0; padding: 8px 0 6px; background: var(--panel);
  font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--text);
}
.historial-dia-titulo small { font-size: 11px; font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--muted); }
.historial-dia + .historial-dia { margin-top: 4px; }

.historial-linea { list-style: none; margin: 0; padding: 0; position: relative; }
.historial-linea::before { content: ""; position: absolute; left: 15px; top: 18px; bottom: 18px; width: 2px; background: var(--border); border-radius: 1px; }
.historial-evento { position: relative; display: flex; gap: 12px; padding: 8px 8px 8px 0; border-radius: 8px; }
.historial-evento:hover { background: color-mix(in srgb, var(--neutral-bg) 70%, transparent); }

/* The point: the kind's icon, coloured by its group */
.historial-punto {
  position: relative; z-index: 1; flex: none; width: 32px; height: 32px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; font-size: 16px;
  background: var(--accent-soft); color: var(--accent); box-shadow: 0 0 0 3px var(--panel);
}
.historial-evento.grupo-sync .historial-punto,
.historial-evento.grupo-access .historial-punto { background: var(--neutral-bg); color: var(--muted); }
.historial-evento.grupo-approval .historial-punto { background: var(--info-bg); color: var(--info); }
.historial-evento.grupo-files .historial-punto,
.historial-evento.grupo-share .historial-punto { background: var(--warn-bg); color: var(--warn); }
.historial-evento.grupo-hours .historial-punto,
.historial-evento.grupo-billing .historial-punto { background: color-mix(in srgb, var(--ok) 14%, var(--panel)); color: var(--ok); }
.historial-evento.grupo-status .historial-punto,
.historial-evento.grupo-dates .historial-punto { background: var(--accent-soft); color: var(--accent); }

.historial-cuerpo { flex: 1; min-width: 0; padding-top: 1px; }
.historial-cabecera { display: flex; align-items: flex-start; gap: 10px; }
.historial-titulo { flex: 1; min-width: 0; font-size: 13px; font-weight: 600; line-height: 1.35; color: var(--text); overflow-wrap: anywhere; }
.historial-hora { flex: none; margin-top: 1px; font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* Who and what kind, under it */
.historial-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 4px; font-size: 12px; color: var(--muted); }
.historial-avatar {
  width: 18px; height: 18px; border-radius: 50%; flex: none; display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent); color: #fff; font-size: 9px; font-weight: 700; letter-spacing: .02em;
}
.historial-origen { font-size: 15px; }
.historial-quien { color: var(--text); font-weight: 500; }
.historial-via { display: inline-flex; align-items: center; gap: 3px; font-size: 11.5px; color: var(--muted); }
.historial-via .mdi { font-size: 13px; }
.historial-etiqueta {
  padding: 1px 7px; border-radius: 999px; background: var(--neutral-bg); color: var(--muted);
  font-size: 11px; font-weight: 500; white-space: nowrap;
}
.historial-enlace { display: inline-flex; align-items: center; gap: 2px; font-size: 12px; margin-left: auto; }

/* What changed: field, before (struck) → after */
.historial-cambios {
  display: grid; grid-template-columns: minmax(90px, max-content) 1fr; gap: 4px 12px; margin: 8px 0 0; padding: 8px 10px;
  background: var(--neutral-bg); border-radius: 8px; font-size: 12px;
}
.historial-cambios dt { color: var(--muted); }
.historial-cambios dd { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0; }
.historial-cambios .mdi { font-size: 12px; color: var(--muted); }
.historial-de { color: var(--muted); text-decoration: line-through; overflow-wrap: anywhere; }
.historial-a { padding: 0 6px; border-radius: 4px; background: var(--panel); color: var(--text); font-weight: 600; overflow-wrap: anywhere; }
.historial-a.vacio { background: transparent; color: var(--muted); font-weight: 400; font-style: italic; }

.historial-mas { display: flex; justify-content: center; padding-top: 4px; }
@media (max-width: 520px) {
  .historial-cambios { grid-template-columns: 1fr; }
  .historial-cambios dd { margin-bottom: 4px; }
}

/* «Traer ticket de DevOps» y «Novedades de DevOps» (modules/devopsImport, decisión D-30) */
.modal.traer-devops { max-width: 520px; width: calc(100vw - 32px); }
.traer-devops > footer .spacer, .devops-versiones-modal > footer .spacer { flex: 1; }
.traer-devops input[type="text"] { width: 100%; }
.traer-devops-pasos { list-style: none; margin: 4px 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.traer-devops-pasos li { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.traer-devops-pasos .paso-nombre { font-weight: 600; }
.traer-devops-pasos .paso-done .mdi { color: var(--ok); }
.traer-devops-pasos .paso-failed .mdi { color: var(--danger); }
.traer-devops-pasos .paso-pending .mdi, .traer-devops-pasos .paso-skipped .mdi { color: var(--muted); }
.traer-devops-referencias { margin: 0; padding-left: 18px; }
.devops-diff { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.65; font-size: 13.5px; border: 1px solid var(--border); border-radius: 8px; padding: 12px 14px; margin: 0; }
.devops-diff ins, .dv-comparar-leyenda ins { background: color-mix(in srgb, var(--ok) 16%, transparent); color: inherit; text-decoration: underline; text-decoration-color: var(--ok); border-radius: 3px; }
.devops-diff del, .dv-comparar-leyenda del { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); text-decoration: line-through; border-radius: 3px; }

/* «Ver DevOps» y el bloque DevOps de la ficha (DevopsNewsPanel → DevopsWorkItemCard). Prefijo
   `dv-`: `.devops-item` y `.devops-enlaces` son de la tarjeta del chip (DevopsChipCard) y no se
   pisan. El modal tiene alto fijo para que cambiar de pestaña no lo haga saltar; dentro, la
   cabecera del work item se va con el scroll y las pestañas se quedan pegadas arriba. */
.modal.devops-ver { position: relative; width: calc(100vw - 32px); max-width: 960px; height: min(88vh, 860px); overflow: hidden; }
.modal.devops-ver { display: flex; flex-direction: column; }
.dv-panel { display: flex; flex-direction: column; min-width: 0; }
.dv-panel-ventana { flex: 1; min-height: 0; overflow-x: hidden; overflow-y: auto; }
.dv-panel-ficha { gap: 10px; }
.dv-panel .spacer { flex: 1; }
/* `.modal header` (relleno, raya y negrita) no es para las cabeceras de dentro del bloque */
.dv-panel header { padding: 0; border-bottom: 0; font-weight: inherit; flex: initial; }
.dv-panel :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.dv-panel .dv-ficha-cabecera { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.dv-ficha-cabecera h4 { margin: 0; }
.dv-lista { display: flex; flex-direction: column; gap: 10px; }
.dv-panel-ventana .dv-lista { gap: 0; }

/* La cabecera del work item */
.dv-card { display: flex; flex-direction: column; min-width: 0; background: var(--panel); }
.dv-card-compacta { border: 1px solid var(--border); border-radius: 10px; }
.dv-panel .dv-hero { display: flex; flex-direction: column; gap: 8px; padding: 22px 24px 16px 24px; }
.dv-panel .dv-card-compacta .dv-hero { padding: 12px 14px; gap: 6px; }
.dv-hero-linea { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12px; min-width: 0; }
.dv-tipo-icono {
  --c: var(--muted);
  display: inline-flex; align-items: center; justify-content: center; flex: none; width: 28px; height: 28px; border-radius: 8px;
  background: color-mix(in srgb, var(--c) 14%, transparent); color: var(--c); font-size: 17px;
}
.dv-card-compacta .dv-tipo-icono { width: 24px; height: 24px; font-size: 15px; border-radius: 6px; }
.tipo-task { --c: var(--warn); }
.tipo-bug, .tipo-issue { --c: var(--danger); }
.tipo-story { --c: var(--accent); }
.tipo-feature { --c: var(--info); }
.tipo-epic { --c: color-mix(in srgb, var(--warn) 55%, var(--danger)); }
.tipo-test { --c: var(--ok); }
.dv-clave { font-family: var(--mono); font-size: 12px; font-weight: 600; color: var(--muted); letter-spacing: .01em; white-space: nowrap; }
.dv-origen {
  display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; border-radius: 999px; cursor: help;
  border: 1px solid var(--border); color: var(--muted); font-size: 11.5px; font-weight: 500; white-space: nowrap;
}
.dv-origen .mdi { font-size: 13px; }
.dv-origen.origen-imported { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); background: color-mix(in srgb, var(--ok) 8%, transparent); }
.dv-abrir {
  display: inline-flex; align-items: center; gap: 5px; padding: 5px 11px; border-radius: 7px; white-space: nowrap;
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); color: var(--accent); font-weight: 600; text-decoration: none;
}
.dv-abrir:hover { background: var(--accent-soft); border-color: var(--accent); }
/* 24-10-2026: the header reads top-down — the type's tile beside the key (with its role and origin)
   and the title; under a thin rule, one row of labelled facts (Estado · Tipo · Prioridad · Asignado
   a), each in its own column with the same label style, so the eye finds them in the same place on
   every work item. In the card of the ticket (compact) the labels hide and the facts are chips. */
.dv-hero-cuerpo { display: flex; align-items: flex-start; gap: 14px; min-width: 0; }
.dv-hero-cuerpo > .dv-tipo-icono { width: 40px; height: 40px; border-radius: 10px; font-size: 22px; margin-top: 1px; }
.dv-hero-texto { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
.dv-hero-meta { display: flex; flex-wrap: wrap; align-items: stretch; row-gap: 12px; margin: 8px 0 0; padding: 14px 0 0; border-top: 1px solid var(--border); }
.dv-hero-dato { display: flex; flex-direction: column; gap: 6px; min-width: 0; padding: 0 20px; border-left: 1px solid var(--border); }
.dv-hero-dato:first-child { padding-left: 0; border-left: 0; }
.dv-hero-dato dt { font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.dv-hero-dato dd { display: flex; align-items: center; min-height: 24px; min-width: 0; margin: 0; }
.dv-hero-persona { display: inline-flex; align-items: center; gap: 7px; min-width: 0; font-size: 12.5px; font-weight: 600; }
.dv-hero-persona .dv-avatar { width: 22px; height: 22px; font-size: 9.5px; }
.dv-hero-persona .dv-avatar-vacio .mdi { font-size: 14px; }
.dv-hero-nombre { max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dv-hero-sin { color: var(--muted); font-weight: 500; }
.dv-card-compacta .dv-hero-cuerpo { gap: 10px; }
.dv-card-compacta .dv-hero-cuerpo > .dv-tipo-icono { width: 24px; height: 24px; font-size: 15px; border-radius: 6px; margin-top: 0; }
.dv-card-compacta .dv-hero-texto { gap: 4px; }
.dv-card-compacta .dv-hero-meta { gap: 6px; margin-top: 2px; padding-top: 0; border-top: 0; }
.dv-card-compacta .dv-hero-dato { padding: 0; border-left: 0; }
.dv-card-compacta .dv-hero-dato dt { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.dv-card-compacta .dv-hero-dato dd { min-height: 0; }

/* THE ROLE of a work item (24-10-2026): Backend in the app's blue, Frontend in a teal of its own
   that reads apart from it (and from the green of «Hecho»), both ≥ 4.5:1 on their tint, in either theme */
:root { --rol-back: var(--brand); --rol-front: #0b7a6e; }
:root[data-theme="dark"]:not([data-presentacion]) { --rol-back: #3aa7e6; --rol-front: #3cc2b2; }
.dv-rol {
  --c: var(--rol-back);
  display: inline-flex; align-items: center; gap: 4px; height: 22px; padding: 0 9px; border-radius: 999px; white-space: nowrap;
  border: 1px solid color-mix(in srgb, var(--c) 40%, transparent); background: color-mix(in srgb, var(--c) 12%, transparent);
  color: color-mix(in srgb, var(--c) 82%, var(--text)); font: inherit; font-size: 11.5px; font-weight: 700; letter-spacing: .01em; line-height: 1;
}
.dv-rol.rol-frontend { --c: var(--rol-front); }
/* Subtarea en verde y Bug en rojo (03-11-2026): el chip y el NÚMERO del work item, en Ver DevOps y
   bajo el ticket en la tabla, para distinguirlos de un vistazo */
:root { --rol-subtarea: #15803d; --rol-bug: #c81e1e; }
:root[data-theme="dark"]:not([data-presentacion]) { --rol-subtarea: #4ade80; --rol-bug: #f87171; }
.dv-rol.rol-subtarea { --c: var(--rol-subtarea); }
.dv-rol.rol-bug { --c: var(--rol-bug); }
.dv-num-subtarea { color: var(--rol-subtarea) !important; font-weight: 700; }
.dv-num-bug { color: var(--rol-bug) !important; font-weight: 700; }
.dv-rol .mdi { font-size: 13px; }
button.dv-rol { cursor: pointer; }
button.dv-rol:hover:not(:disabled), button.dv-rol.abierto { border-color: var(--c); background: color-mix(in srgb, var(--c) 20%, transparent); }
button.dv-rol:disabled { cursor: progress; opacity: 1; }
.dv-rol-flecha { margin-left: -1px; opacity: .75; }
.dv-rol-mini { height: 18px; padding: 0 7px; font-size: 10.5px; letter-spacing: .02em; }
.dv-rol-caja { display: inline-flex; min-width: 0; }
.menu-rol-devops { min-width: 250px; overflow-y: auto; }
.menu-rol-motivo { display: flex; align-items: flex-start; gap: 6px; max-width: 290px; margin: 0; padding: 8px 14px 6px; color: var(--muted); font-size: 12px; white-space: normal; }
.menu-rol-motivo .mdi { font-size: 15px; line-height: 1.1; }
.menu-rol-devops .menu-acciones-item .menu-rol-marca { margin-left: auto; color: var(--accent); }
.menu-rol-devops .menu-acciones-item[aria-checked="true"] { font-weight: 600; }

.dv-titulo { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px; margin: 0; font-size: 21px; line-height: 1.28; font-weight: 650; letter-spacing: -.005em; overflow-wrap: anywhere; }
.dv-titulo > span { min-width: 0; }
.dv-card-compacta .dv-titulo { font-size: 14.5px; font-weight: 600; margin: 0; }
.dv-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 2px; }
.dv-chip {
  display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 10px; border-radius: 999px; white-space: nowrap;
  background: var(--neutral-bg); color: var(--text); font-size: 12px; font-weight: 500;
}
.dv-chip .mdi { font-size: 14px; color: var(--muted); }
.dv-estado, .dv-prioridad {
  --c: var(--muted);
  background: color-mix(in srgb, var(--c) 13%, transparent); color: color-mix(in srgb, var(--c) 82%, var(--text)); font-weight: 600;
}
.dv-prioridad .mdi { color: inherit; }
.dv-punto { width: 7px; height: 7px; border-radius: 50%; background: var(--c); flex: none; }
.estado-active { --c: var(--accent); }
.estado-done { --c: var(--ok); }
.estado-blocked { --c: var(--warn); }
.estado-removed { --c: var(--danger); }
.prioridad-high { --c: var(--danger); }
.prioridad-medium { --c: var(--warn); }
.dv-sync { display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 12px; color: var(--muted); }
.dv-sync-cuando { cursor: default; }
.dv-sync-estado { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 600; }
.dv-sync-estado .mdi { font-size: 15px; }
.dv-sync-estado.tono-ok { color: var(--ok); }
.dv-sync-estado.tono-info { color: var(--info); }
.dv-sync-estado.tono-warn { color: var(--warn); }
.dv-sync-estado.tono-muted { color: var(--muted); }
.dv-aviso-item { margin: 0; font-size: 12px; color: var(--warn); overflow-wrap: anywhere; }
.dv-detalle {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 2px; margin-top: 2px; padding: 2px 0;
  border: 0; background: none; color: var(--accent); font-weight: 600; font-size: 12.5px;
}
.dv-detalle .mdi { font-size: 17px; }
.dv-aviso {
  display: flex; align-items: flex-start; gap: 8px; padding: 10px 12px; border-radius: 8px; font-size: 12.5px; overflow-wrap: anywhere;
  background: var(--warn-bg); color: var(--warn); border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent);
}
.dv-aviso .mdi { font-size: 16px; line-height: 1.2; }
.dv-panel-ventana > .dv-aviso { margin: 16px 24px 0 24px; }

/* Ayuda al pasar o enfocar: varias líneas, a diferencia de `.con-tooltip` */
.dv-panel [data-tip] { position: relative; }
.dv-hero-linea { position: relative; }
.dv-panel .dv-origen[data-tip] { position: static; }
.dv-panel [data-tip]::after {
  content: attr(data-tip); position: absolute; top: calc(100% + 8px); left: 0; z-index: 10; display: none;
  width: max-content; max-width: min(340px, 100%); padding: 8px 10px; border-radius: 6px; box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
  background: var(--text); color: var(--panel); font-size: 12px; font-weight: 400; line-height: 1.45; text-align: left;
  white-space: normal; letter-spacing: 0; text-transform: none; pointer-events: none;
}
.dv-panel [data-tip]:hover::after, .dv-panel [data-tip]:focus-visible::after { display: block; }
.dv-panel .dv-ayuda[data-tip]::after { left: 50%; transform: translateX(-50%); width: 240px; max-width: none; }

/* Las pestañas */
.dv-cuerpo { display: flex; flex-direction: column; min-width: 0; }
.dv-card-compacta .dv-cuerpo { border-top: 1px solid var(--border); }
.dv-tabs-barra { border-bottom: 1px solid var(--border); background: var(--panel); }
.dv-tabs { display: flex; gap: 2px; padding: 0 24px; overflow-x: auto; scrollbar-width: none; }
.dv-tabs::-webkit-scrollbar { display: none; }
.dv-panel-ventana .dv-tabs-barra { position: sticky; top: 0; z-index: 3; }
.modal.devops-ver:focus { outline: none; }
.dv-card-compacta .dv-tabs { padding: 0 8px; }
.dv-tab {
  display: inline-flex; align-items: center; gap: 6px; flex: none; margin-bottom: -1px; padding: 11px 10px 10px;
  border: 0; border-bottom: 2px solid transparent; border-radius: 0; background: none; color: var(--muted); font-weight: 500; white-space: nowrap;
}
.dv-tab .mdi { font-size: 16px; }
.dv-tab:hover:not(.activa) { color: var(--text); border-bottom-color: var(--border-strong); }
.dv-tab.activa { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
.dv-panel .dv-tab:focus-visible { outline-offset: -3px; border-radius: 6px 6px 0 0; }
.dv-tab-cuenta {
  display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent); font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.dv-tab-cuenta.cero { background: var(--neutral-bg); color: var(--muted); }
.dv-pane { padding: 20px 24px 28px; min-width: 0; }
.dv-card-compacta .dv-pane { padding: 14px; }
.dv-panel .dv-pane:focus-visible { outline-offset: -2px; }

/* Resumen: one section per row, across the pane; inside, a property sheet (label | value) whose
   values all fall in the same column, section after section. */
.dv-resumen { --dv-etiqueta-ancho: 170px; display: flex; flex-direction: column; min-width: 0; }
.dv-card-compacta .dv-resumen { --dv-etiqueta-ancho: 130px; }
.dv-seccion { min-width: 0; padding: 14px 0; border-top: 1px solid var(--border); }
.dv-seccion:first-child { padding-top: 0; border-top: 0; }
.dv-seccion:last-child { padding-bottom: 0; }
.dv-grupo-titulo {
  display: flex; align-items: center; gap: 6px; margin: 0 0 12px;
  color: var(--muted); font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
}
.dv-seccion .dv-grupo-titulo { margin-bottom: 6px; }
.dv-grupo-titulo .mdi { font-size: 15px; }
.dv-props { display: flex; flex-direction: column; margin: 0; }
.dv-prop { display: grid; grid-template-columns: var(--dv-etiqueta-ancho) minmax(0, 1fr); gap: 2px 16px; align-items: center; min-height: 34px; padding: 4px 0; }
.dv-prop dt { color: var(--muted); font-size: 12.5px; line-height: 1.35; }
.dv-prop dd { margin: 0; min-width: 0; font-size: 13.5px; line-height: 1.4; overflow-wrap: anywhere; }
.dv-prop-tags { align-items: start; }
.dv-prop-tags dt { padding-top: 5px; }
.dv-persona { display: inline-flex; align-items: center; gap: 8px; min-width: 0; max-width: 100%; border-radius: 6px; }
.dv-persona-nombre { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.dv-panel .dv-persona[data-tip]::after { max-width: 340px; }
.dv-persona-vacia { color: var(--muted); font-weight: 400; }
.dv-avatar {
  --av: #017fc3;
  display: inline-flex; align-items: center; justify-content: center; flex: none; width: 24px; height: 24px; border-radius: 50%;
  background: var(--av); color: #fff; font-size: 10px; font-weight: 700; letter-spacing: .02em;
}
.dv-avatar-grande { width: 32px; height: 32px; font-size: 12px; }
.dv-avatar-vacio { --av: var(--muted); }
.dv-avatar.t1 { --av: #1a7f45; } .dv-avatar.t2 { --av: #a35c00; } .dv-avatar.t3 { --av: #4a3fb5; }
.dv-avatar.t4 { --av: #b3261e; } .dv-avatar.t5 { --av: #0f766e; } .dv-avatar.t6 { --av: #9d174d; } .dv-avatar.t7 { --av: #475569; }
.dv-ruta { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.dv-ruta-hoja { flex: none; max-width: 100%; font-weight: 600; overflow-wrap: anywhere; }
.dv-ruta-padre { min-width: 0; color: var(--muted); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dv-fecha { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 0 8px; font-variant-numeric: tabular-nums; }
.dv-fecha-hace { color: var(--muted); font-size: 12.5px; }
.dv-fecha-hace::before { content: "·"; margin-right: 8px; }
.dv-etiquetas { display: flex; flex-wrap: wrap; gap: 4px; }
.dv-etiqueta { padding: 2px 9px; border-radius: 999px; background: var(--info-bg); color: var(--info); font-size: 11.5px; font-weight: 500; }
/* The tags editor, inline in its row: chips and a small «Añadir…», no big dashed box */
.dv-resumen .dvw-etiquetas-caja { padding: 2px 4px; margin-left: -4px; border: 1px solid transparent; border-radius: 8px; }
.dv-resumen .dvw-etiquetas-caja:hover { border-color: var(--border); }
.dv-resumen .dvw-etiquetas-caja:focus-within { border-style: solid; border-color: var(--accent); }
.dv-resumen .dvw-etiquetas-campo { flex: 0 1 140px; min-width: 80px; padding: 2px 4px; }
.dv-resumen .dvw-etiquetas-acciones { justify-content: flex-start; }
.dv-relaciones { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.dv-relaciones li { min-width: 0; max-width: 100%; }
.dv-relacion {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%; padding: 3px 10px; border: 1px solid var(--border); border-radius: 999px;
  color: var(--text); font-size: 12.5px; text-decoration: none;
}
.dv-relacion .mdi { font-size: 15px; color: var(--muted); }
a.dv-relacion:hover { border-color: var(--accent); background: var(--accent-soft); }
.dv-relacion-tipo { color: var(--muted); }
.dv-relacion-tipo::after { content: "·"; margin-left: 6px; }
.dv-relacion-destino { min-width: 0; font-family: var(--mono); font-weight: 600; color: var(--accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 600px) {
  .dv-prop { grid-template-columns: minmax(0, 1fr); gap: 2px; padding: 6px 0; }
  .dv-prop-tags dt { padding-top: 0; }
  .dv-ruta { flex-wrap: wrap; gap: 0 8px; }
  .dv-ruta-padre { white-space: normal; overflow-wrap: anywhere; }
}

/* Descripción */
/* The texts (Descripción, criterios, pasos) use the whole width of the modal: a 74ch column left
   half the window empty beside long descriptions */
.dv-textos { display: flex; flex-direction: column; gap: 24px; }
.dv-panel .dv-texto-cabecera { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
.dv-texto-cabecera h4 { margin: 0; font-size: 14px; font-weight: 650; }
.dv-version {
  display: inline-flex; align-items: center; gap: 4px; padding: 1px 8px; border: 1px solid var(--border); border-radius: 999px;
  background: var(--neutral-bg); color: var(--muted); font-size: 11px; font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums;
}
button.dv-version-boton { cursor: pointer; font-family: inherit; line-height: 1.5; }
button.dv-version-boton:hover { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.dv-boton-suave {
  display: inline-flex; align-items: center; gap: 4px; padding: 3px 9px; border: 1px solid transparent; border-radius: 6px;
  background: none; color: var(--accent); font-size: 12px; font-weight: 600; white-space: nowrap;
}
.dv-boton-suave:hover:not(:disabled) { background: var(--accent-soft); border-color: transparent; }
.dv-prosa { font-size: 14px; line-height: 1.65; }
.dv-prosa p { margin: 0 0 10px; white-space: pre-wrap; overflow-wrap: anywhere; }
.dv-prosa ul { margin: 0 0 10px; padding-left: 22px; }
.dv-prosa li { margin: 3px 0; overflow-wrap: anywhere; }
.dv-prosa li::marker { color: var(--muted); }
.dv-prosa > :last-child { margin-bottom: 0; }
.dv-enlaces-texto { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; list-style: none; }
.dv-enlaces-texto a { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; color: var(--accent); text-decoration: none; }
.dv-enlaces-texto a:hover span { text-decoration: underline; }
.dv-enlaces-texto span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Comentarios */
.dv-hilo { display: flex; flex-direction: column; gap: 16px; margin: 0; padding: 0; list-style: none; }
.dv-comentario { display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: 12px; }
.dv-comentario.borrado { opacity: .65; }
.dv-comentario-cuerpo { padding: 10px 14px 12px; border-radius: 4px 12px 12px 12px; background: var(--neutral-bg); }
.dv-panel .dv-comentario-cabecera { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px; }
.dv-comentario-cabecera time { color: var(--muted); font-size: 12px; }
.dv-comentario-texto { margin: 6px 0 0; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; }
.dv-marca {
  --c: var(--muted);
  display: inline-flex; align-items: center; padding: 1px 8px; border-radius: 999px; white-space: nowrap;
  background: color-mix(in srgb, var(--c) 13%, transparent); color: color-mix(in srgb, var(--c) 85%, var(--text)); font-size: 11px; font-weight: 600;
}
.dv-marca.tono-ok { --c: var(--ok); }
.dv-marca.tono-warn { --c: var(--warn); }
.dv-marca.tono-danger { --c: var(--danger); }
.dv-marca.tono-neutral { --c: var(--accent); }

/* Adjuntos */
.dv-adjuntos { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(360px, 100%), 1fr)); gap: 10px; margin: 0; padding: 0; list-style: none; }
.dv-adjunto { display: flex; align-items: center; gap: 12px; min-width: 0; padding: 12px; border: 1px solid var(--border); border-radius: 10px; }
.dv-adjunto:hover { border-color: var(--border-strong); }
.dv-adjunto.ido { opacity: .7; }
.dv-adjunto-icono {
  --c: var(--muted);
  display: inline-flex; align-items: center; justify-content: center; flex: none; width: 40px; height: 40px; border-radius: 9px;
  background: color-mix(in srgb, var(--c) 13%, transparent); color: var(--c); font-size: 23px;
}
.archivo-pdf { --c: var(--danger); } .archivo-word { --c: var(--accent); } .archivo-excel { --c: var(--ok); }
.archivo-slides, .archivo-zip { --c: var(--warn); } .archivo-image, .archivo-video { --c: var(--info); }
.dv-adjunto-datos { display: flex; flex-direction: column; gap: 4px; flex: 1; min-width: 0; }
.dv-adjunto-nombre { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.dv-adjunto-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; color: var(--muted); font-size: 11.5px; }
.dv-ayuda { display: inline-flex; color: var(--muted); font-size: 15px; cursor: help; border-radius: 50%; }
.dv-ayuda:hover { color: var(--text); }
/* Each file's ⋮ (24-10-2026): «Abrir en DevOps», «Descargar» and «Eliminar» in the app's actions
   menu (`menu-acciones`), fixed at the button like the table cells' menus */
.dv-adjunto-menu { display: inline-flex; flex: none; }
.dv-adjunto-mas {
  display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0;
  border: 1px solid transparent; border-radius: 8px; background: transparent; color: var(--muted); font-size: 20px; cursor: pointer;
}
.dv-adjunto-mas:hover:not(:disabled) { border-color: var(--border-strong); background: var(--neutral-bg); color: var(--text); }
.dv-adjunto-mas.abierto { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.dv-adjunto-mas:disabled { cursor: progress; }
.menu-adjunto-devops { min-width: 200px; overflow-y: auto; }
.menu-adjunto-devops a.menu-acciones-item { text-decoration: none; }
.menu-adjunto-devops .menu-acciones-item:disabled { opacity: .55; cursor: not-allowed; }
.menu-adjunto-devops .menu-acciones-item:disabled:hover { background: transparent; }
.menu-adjunto-devops .menu-acciones-item.peligro,
.menu-adjunto-devops .menu-acciones-item.peligro .mdi { color: var(--danger); }
.menu-adjunto-devops .menu-acciones-item.peligro:hover:not(:disabled),
.menu-adjunto-devops .menu-acciones-item.peligro:focus-visible { background: var(--danger-bg); }
/* «Adjuntar archivos del ticket» under the list (`WorkItemAttachFiles`) */
/* «Adjuntar archivo» and «Adjuntar archivos del ticket» in one row, two equal columns aligned to
   the top; alone (or the token notice) it takes the whole row, and on a narrow screen they stack */
.dv-adjuntar { margin-top: 14px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; align-items: start; }
.dv-adjuntar-dos { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.dv-adjuntar-columna { display: grid; gap: 8px; min-width: 0; }
.dv-adjuntar > .hint { display: flex; align-items: center; gap: 6px; grid-column: 1 / -1; }
@media (max-width: 720px) { .dv-adjuntar-dos { grid-template-columns: minmax(0, 1fr); } }
/* «Adjuntar evidencia» (azureDevops/EvidenceAttachModal): the attach row alone, under its notice */
.evidencia-modal .evidencia-titulo { margin: 0; font-size: 15px; }
.evidencia-modal .dv-adjuntar { margin-top: 0; }
.evidencia-aviso {
  display: flex; align-items: center; gap: 8px; margin: 0; padding: 8px 12px;
  border-radius: 6px; background: var(--accent-soft); font-weight: 600;
}
/* Inside the modal its header lost the block's look (the modal styles its own <header>):
   the `.wi-sub` title bar, padded and ruled, the block as wide as the list */
.dv-adjuntar .wi-sub { overflow: hidden; }
.dv-adjuntar .wi-sub > header {
  display: flex; align-items: center; gap: 8px; margin: 0; padding: 9px 14px; border-bottom: 1px solid var(--border);
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
}
.dv-adjuntar .wi-sub-body { padding: 12px 14px; }
/* «Adjuntar archivo» (`DevopsAttachLocalFiles`): the drop zone, the queue and each one's progress */
.dv-local { display: grid; gap: 8px; }
.dv-local-zona {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px; padding: 14px;
  border: 1px dashed var(--border-strong); border-radius: 8px; text-align: center;
}
.dv-local-zona > .mdi { font-size: 20px; color: var(--muted); }
.dv-local-encima .dv-local-zona { border-color: var(--accent); background: var(--accent-soft); }
.dv-local-lista { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.dv-local-item { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; font-size: 12.5px; }
.dv-local-item .dv-local-nombre { flex: 1 1 160px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dv-local-item progress { flex: 1 1 100%; height: 6px; }
.dv-local-item.estado-sent > .mdi { color: var(--success, var(--accent)); }
.dv-local-item.estado-refused > .mdi, .dv-local-item.estado-failed > .mdi { color: var(--danger); }

/* «Interno»: the link and the movements of the relation (`modules/ticketRefs` blocks) as
   cards inside the pane (the modal resets every <header>, so the title bar is set here again) */
.dv-interno { display: grid; gap: 14px; min-width: 0; }
.dv-interno .wi-sub { overflow: hidden; }
.dv-interno .wi-sub > header {
  display: flex; align-items: center; gap: 8px; margin: 0; padding: 9px 14px; border-bottom: 1px solid var(--border);
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
}
.dv-interno .wi-sub > header label { font: inherit; color: inherit; margin: 0; }
.dv-interno .wi-sub-body { padding: 12px 14px; }
.dv-interno .refs-panel-link { display: flex; align-items: stretch; gap: 8px; }
.dv-interno .refs-panel-link input { flex: 1 1 auto; min-width: 0; height: 32px; font-size: 12.5px; }
.dv-interno .refs-panel-link .btn { flex: none; height: 32px; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.dv-interno .refs-panel-link .btn:first-of-type { margin-left: auto; }
.dv-interno .devops-history-box { max-height: 320px; border: 0; border-radius: 0; }
.dv-interno .devops-history-box .tabla-docs { table-layout: fixed; font-size: 12.5px; }
.dv-interno .devops-history-box .tabla-docs th {
  position: sticky; top: 0; z-index: 1; background: var(--panel); padding: 8px 12px;
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
}
.dv-interno .devops-history-box .tabla-docs td { padding: 9px 12px; vertical-align: middle; }
.dv-interno .devops-history-box .tabla-docs tr:last-child td { border-bottom: 0; }
.dv-interno .devops-history-box .tabla-docs th:nth-child(1) { width: 150px; }
.dv-interno .devops-history-box .tabla-docs th:nth-child(3) { width: 150px; }
.dv-interno .devops-history-box .tabla-docs th:nth-child(4) { width: 120px; }
.dv-interno .devops-history-box .tabla-docs th:nth-child(5) { width: 100px; }
.dv-interno .devops-history-file { max-width: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dv-interno .wi-sub > .hint.wi-sub-body { display: flex; align-items: center; gap: 8px; padding: 18px 14px; color: var(--muted); font-style: italic; }
/* The attachments one per row, as wide as the block under them: the name reads whole and the
   actions (Descargar, Abrir en DevOps) sit together on the right */
.dv-adjuntos { grid-template-columns: minmax(0, 1fr); }

/* Historial (y la lista del modal de versiones) */
.dv-linea { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
.dv-hito { position: relative; display: grid; grid-template-columns: 16px minmax(0, 1fr) auto; gap: 12px; align-items: start; padding-bottom: 18px; }
.dv-hito::before { content: ""; position: absolute; left: 7px; top: 16px; bottom: 0; width: 2px; background: var(--border); }
.dv-hito:last-child { padding-bottom: 0; }
.dv-hito:last-child::before { display: none; }
.dv-hito-punto { width: 12px; height: 12px; margin: 4px 0 0 2px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.dv-hito-punto.primero { background: var(--border-strong); box-shadow: 0 0 0 3px var(--neutral-bg); }
.dv-hito-titulo { display: flex; align-items: center; gap: 8px; margin: 0; }
.dv-hito-detalle { margin: 2px 0 0; color: var(--muted); font-size: 12px; overflow-wrap: anywhere; }
.dv-linea-compacta .dv-hito { padding-bottom: 12px; grid-template-columns: 16px minmax(0, 1fr); }

/* Novedades */
.dv-novedades {
  margin: 0 24px 16px; border: 1px solid color-mix(in srgb, var(--info) 30%, transparent); border-radius: 10px; overflow: hidden;
  background: var(--info-bg);
}
.dv-panel-ficha .dv-novedades { margin: 0; }
.dv-card-compacta .dv-novedades { margin: 0 14px 12px; }
.dv-panel .dv-novedades-cabecera { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 10px; padding: 10px 12px 10px 14px; }
.dv-novedades-cabecera strong { color: var(--info); font-size: 13.5px; }
.dv-novedades-icono {
  display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%;
  background: color-mix(in srgb, var(--info) 16%, transparent); color: var(--info); font-size: 16px;
}
.dv-boton-marcar {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px; border-radius: 7px;
  border: 1px solid color-mix(in srgb, var(--info) 45%, transparent); background: var(--panel); color: var(--info); font-size: 12px; font-weight: 600;
}
.dv-boton-marcar:hover:not(:disabled) { border-color: var(--info); }
.dv-boton-marcar:disabled { opacity: .7; cursor: progress; }
.dv-novedades-lista { display: flex; flex-direction: column; gap: 10px; max-height: 220px; overflow-y: auto; padding: 0 14px 12px 52px; }
.dv-novedades-de { margin: 0 0 4px; font-weight: 600; overflow-wrap: anywhere; }
.dv-lote + .dv-lote { margin-top: 6px; padding-top: 8px; border-top: 1px dashed color-mix(in srgb, var(--info) 25%, transparent); }
.dv-lote-cuando { margin: 0 0 4px; color: var(--muted); font-size: 11.5px; }
.dv-lote-lineas { display: flex; flex-direction: column; gap: 4px; margin: 0; padding: 0; list-style: none; }
.dv-lote-lineas li { display: flex; align-items: baseline; gap: 8px; overflow-wrap: anywhere; min-width: 0; }
.dv-lote-lineas li > span { min-width: 0; }
.dv-lote-lineas .mdi { flex: none; font-size: 15px; color: var(--info); }
.dv-lote-lineas .tono-ok .mdi { color: var(--ok); }
.dv-lote-lineas .tono-warn .mdi { color: var(--warn); }
.dv-lote-lineas .tono-neutro .mdi { color: var(--muted); }

/* Varios work items en «Ver DevOps»: se elige cuál se ve. Each pill is ONE button with only the
   number, the role and the news (24-10-2026): the titles are near twins, the whole one is the tooltip */
.dv-selector { display: flex; gap: 6px; padding: 14px 24px 2px 24px; overflow-x: auto; scrollbar-width: thin; flex: none; }
.dv-selector-pastilla {
  display: inline-flex; align-items: center; gap: 7px; flex: none; height: 32px; padding: 0 12px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--panel); color: var(--text); font: inherit; font-size: 12.5px; cursor: pointer;
}
.dv-selector-pastilla:hover { border-color: var(--border-strong); }
.dv-selector-pastilla > .mdi { font-size: 15px; color: var(--muted); }
.dv-selector-pastilla.activo { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.dv-selector-pastilla.activo .dv-clave, .dv-selector-pastilla.activo > .mdi { color: var(--accent); }
.dv-selector-nuevas { min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; background: var(--info); color: #fff; font-size: 11px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; }

/* Estados vacíos, error y carga */
.dv-vacio { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 40px 16px; text-align: center; }
.dv-panel-ventana > .dv-vacio { margin: auto 0; padding: 56px 24px; }
.dv-vacio-icono {
  display: inline-flex; align-items: center; justify-content: center; width: 52px; height: 52px; margin-bottom: 6px; border-radius: 50%;
  background: var(--neutral-bg); color: var(--muted); font-size: 26px;
}
.dv-error .dv-vacio-icono { background: var(--danger-bg); color: var(--danger); }
.dv-vacio-titulo { margin: 0; font-size: 14px; font-weight: 600; max-width: 52ch; overflow-wrap: anywhere; }
.dv-vacio .hint { margin: 0; max-width: 50ch; font-size: 12.5px; overflow-wrap: anywhere; }
.dv-vacio button { margin-top: 10px; }
.dv-vacio-linea { margin: 0; color: var(--muted); }
.dv-esqueleto { display: flex; flex-direction: column; gap: 18px; padding: 24px 24px 24px 24px; }
.dv-panel-ficha .dv-esqueleto { padding: 14px; border: 1px solid var(--border); border-radius: 10px; }
.dv-esqueleto-hero { display: flex; flex-direction: column; gap: 10px; }
.dv-esq-clave { width: 120px; height: 12px; }
.dv-esq-titulo { width: min(70%, 520px); height: 22px; }
.dv-panel-ficha .dv-esq-titulo { height: 16px; }
.dv-esq-chips { display: flex; gap: 8px; }
.dv-esq-tabs { display: flex; gap: 22px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.dv-esq-tabs .esqueleto-bloque { width: 84px; height: 12px; }
.dv-esq-grupos { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; }
.dv-esq-grupo { display: flex; flex-direction: column; gap: 12px; padding: 16px; border: 1px solid var(--border); border-radius: 10px; }
.dv-esq-grupo .corta { width: 40%; }

/* El modal de versiones */
.modal.devops-versiones-modal { width: calc(100vw - 32px); max-width: 760px; }
.dv-comparar { display: flex; align-items: flex-end; flex-wrap: wrap; gap: 10px 12px; }
.dv-comparar > .mdi { padding-bottom: 8px; color: var(--muted); }
.dv-comparar-campo { display: flex; flex-direction: column; gap: 4px; color: var(--muted); font-size: 11.5px; }
.dv-comparar-campo select { min-width: 96px; }
.dv-comparar-leyenda { display: inline-flex; gap: 8px; margin-left: auto; padding-bottom: 8px; font-size: 12px; }
.devops-versiones-modal .dv-grupo-titulo { margin: 8px 0 0; }

/* Una ventana estrecha: el modal ocupa la pantalla, todo en una columna, sin scroll horizontal */
@media (max-width: 600px) {
  .backdrop:has(> .modal.devops-ver) { padding: 0; }
  .modal.devops-ver { width: 100%; max-width: 100%; height: 100%; max-height: 100%; border-radius: 0; border: 0; }
  .dv-panel .dv-hero { padding: 16px 16px 12px 16px; }
  .dv-titulo { font-size: 17px; }
  .dv-meta > .spacer { display: none; }
  .dv-sync { flex-basis: 100%; margin-top: 2px; }
  .dv-hero-linea > .spacer { display: none; }
  .dv-hero-cuerpo { gap: 10px; }
  .dv-hero-cuerpo > .dv-tipo-icono { width: 32px; height: 32px; font-size: 18px; border-radius: 8px; }
  .dv-hero-meta { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 16px; }
  .dv-hero-dato { padding: 0; border-left: 0; }
  .dv-hero-nombre { max-width: 100%; }
  .dv-tabs { padding: 0 8px; }
  .dv-pane { padding: 16px 16px 24px; }
  .dv-novedades { margin: 0 16px 12px; }
  .dv-novedades-lista { padding-left: 14px; }
  .dv-panel-ventana > .dv-aviso { margin: 14px 16px 0 16px; }
  .dv-selector { padding: 14px 16px 4px 16px; }
  .dv-esqueleto { padding: 18px 16px 18px 16px; }
  .dv-resumen, .dv-card-compacta .dv-resumen { grid-template-columns: minmax(0, 1fr); }
  .dv-adjuntos { grid-template-columns: minmax(0, 1fr); }
  .dv-comentario { grid-template-columns: 28px minmax(0, 1fr); gap: 10px; }
  .dv-comentario .dv-avatar-grande { width: 28px; height: 28px; font-size: 11px; }
  .dv-comparar-leyenda { margin-left: 0; }
}

/* ---------------------------------------------------------------- escribir en DevOps (D-31) */

/* A confirmation toast: green, so it does not read as a warning */
.toast.ok { border-color: var(--ok); color: var(--ok); }
.dv-panel .spacer, .rte .spacer, .dvw-acciones .spacer, .dvw-conflicto-acciones .spacer { flex: 1; }

/* The rich text of DevOps (description, criteria, comments), built node by node */
.dv-rt { font-size: 14px; line-height: 1.65; overflow-wrap: anywhere; }
.dv-rt > :first-child { margin-top: 0; }
.dv-rt > :last-child { margin-bottom: 0; }
.dv-rt p { margin: 0 0 10px; white-space: pre-wrap; }
.dv-rt h3, .dv-rt h4, .dv-rt h5, .dv-rt h6 { margin: 16px 0 6px; line-height: 1.3; font-weight: 650; }
.dv-rt h3 { font-size: 17px; } .dv-rt h4 { font-size: 15.5px; } .dv-rt h5 { font-size: 14.5px; } .dv-rt h6 { font-size: 13.5px; color: var(--muted); }
.dv-rt ul, .dv-rt ol { margin: 0 0 10px; padding-left: 22px; }
.dv-rt li { margin: 3px 0; }
.dv-rt li::marker { color: var(--muted); }
.dv-rt blockquote { margin: 0 0 10px; padding: 6px 14px; border-left: 3px solid var(--border-strong); color: var(--muted); background: var(--neutral-bg); border-radius: 0 6px 6px 0; }
.dv-rt code { padding: 1px 5px; border-radius: 4px; background: var(--neutral-bg); font-family: var(--mono); font-size: 12.5px; }
.dv-rt pre { margin: 0 0 10px; padding: 10px 12px; border-radius: 8px; background: var(--neutral-bg); border: 1px solid var(--border); font-family: var(--mono); font-size: 12.5px; line-height: 1.5; overflow-x: auto; white-space: pre; }
.dv-rt pre code { padding: 0; background: none; }
.dv-rt a { color: var(--accent); }
.dv-rt hr { border: 0; border-top: 1px solid var(--border); margin: 14px 0; }
.dv-rt-tabla { max-width: 100%; margin: 0 0 10px; overflow-x: auto; }
.dv-rt table { border-collapse: collapse; font-size: 13px; }
.dv-rt th, .dv-rt td { padding: 6px 10px; border: 1px solid var(--border); text-align: left; vertical-align: top; }
.dv-rt th { background: var(--neutral-bg); font-weight: 600; }
.dv-rt-mencion { display: inline-flex; padding: 0 6px; border-radius: 999px; background: var(--accent-soft); color: var(--accent); font-weight: 600; white-space: nowrap; }
/* 20-10-2026: the image itself, at the text's width (never wider), as in Azure DevOps; a click enlarges it */
.dv-rt-imagen-caja { display: inline-block; max-width: 100%; vertical-align: top; }
.dv-rt-imagen { display: block; max-width: 100%; margin: 6px 0; padding: 0; border: 1px solid var(--border); border-radius: 8px; background: var(--neutral-bg); cursor: zoom-in; overflow: hidden; }
.dv-rt-imagen:hover, .dv-rt-imagen:focus-visible { border-color: var(--accent); }
.dv-rt-imagen img { display: block; max-width: 100%; height: auto; border-radius: 7px; }
.dv-rt-imagen-cargando {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%; margin: 2px 0; padding: 18px 14px; border: 1px dashed var(--border);
  border-radius: 8px; color: var(--muted); font-size: 12.5px; background: var(--neutral-bg);
}
.dv-rt-lightbox {
  position: fixed; inset: 0; z-index: 80; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  padding: 16px; background: rgba(0, 0, 0, 0.82); cursor: zoom-out;
}
.dv-rt-lightbox > img { max-width: 100%; max-height: calc(100vh - 90px); height: auto; border-radius: 6px; background: #fff; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5); }
.dv-rt-lightbox-barra { display: flex; align-items: center; gap: 10px; width: 100%; max-width: 1200px; color: #fff; cursor: default; }
.dv-rt-lightbox-nombre { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.dv-rt-lightbox-barra .btn-icono { display: inline-flex; align-items: center; gap: 4px; height: 30px; padding: 0 12px; font-size: 12px; text-decoration: none; color: #fff; border: 1px solid rgba(255, 255, 255, 0.5); border-radius: 6px; background: transparent; }
.dv-rt-lightbox-barra .modal-close { color: #fff; font-size: 26px; background: transparent; border: 0; cursor: pointer; }

/* The draggable divider of the documentation viewer's «Comparar» (`docViewer/CompareView.js`). The
   «Comparar» tab of «Ver DevOps» that also used it was removed on 24-10-2026, with its split. */
.dv-split-divider { flex: 0 0 6px; cursor: col-resize; position: relative; background: var(--border); }
.dv-split-divider:hover, .dv-split-divider:focus-visible { background: var(--accent); outline: none; }
/* The embedded documentation viewer: it fills its half; the modal's own header and footer rules
   (`.modal header`, `.dv-panel header`) would otherwise reach it from the DevOps modal around it */
.visor-embebido { display: flex; flex: 1 1 auto; min-height: 0; overflow: hidden; }
.visor-embebido-marco { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; min-height: 0; overflow: hidden; }
/* Header and footer keep their height; the tree and the document share the rest and scroll apart */
.visor-embebido-marco > header.modal-header, .visor-embebido-marco > footer { flex: none; }
.visor-embebido .visor { flex: 1 1 auto; min-height: 0; overflow: hidden; }
.visor-embebido .visor-lista, .visor-embebido .visor-cuerpo { min-height: 0; overscroll-behavior: contain; }
.dv-panel .visor-embebido-marco > header.modal-header { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--border); background: var(--panel); font-weight: 600; font-size: 13px; }
/* The explorer's own strip is a `header` too: `.dv-panel header` took its padding and its rule */
.dv-panel .visor-embebido .visor-exp-cabecera { padding: 6px 6px 6px 10px; border-bottom: 1px solid var(--border); }
.visor-embebido-marco > footer { display: flex; gap: 8px; padding: 8px 12px; border-top: 1px solid var(--border); background: var(--panel); }
.visor-embebido .visor-hoja, .visor-embebido .visor-codigo { height: 100%; min-height: 40dvh; }
.visor-embebido .visor-marco { min-height: 0; height: 100%; }
/* The explorer on the right: the edge and the border change sides */
.visor.visor-arbol-derecha { flex-direction: row-reverse; }
.visor-arbol-derecha .visor-lista { border-right: 0; border-left: 1px solid var(--border); }
.visor-arbol-derecha .visor-divisor { margin-left: 0; margin-right: -3px; }
@media (max-width: 900px) {
  /* Stacked: the description above, the documentation below, each with its own scroll */
  /* Still inside the modal's height: the description takes 40 % (the inline width share does not
     apply stacked, hence `!important`) and the documentation the rest; neither pushes the modal */
  .dv-split { flex-direction: column; }
  .dv-split-devops { flex: 0 0 40% !important; }
  .dv-split-docs { flex: 1 1 0; min-height: 0; }
  .visor-embebido .visor-lista { max-height: 35%; }
  .dv-split-divider { display: none; }
  .visor.visor-arbol-derecha { flex-direction: column; }
  .visor-arbol-derecha .visor-lista { border-left: 0; }
}
.dv-rt-imagen-enlace {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%; margin: 2px 0; padding: 5px 10px; border: 1px dashed var(--border-strong);
  border-radius: 8px; color: var(--accent); text-decoration: none; font-size: 12.5px; vertical-align: middle;
}
.dv-rt-imagen-enlace span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dv-rt-imagen-enlace small { color: var(--muted); }
.dv-rt-imagen-enlace:hover { border-style: solid; background: var(--accent-soft); }

/* The editor */
.rte { display: flex; flex-direction: column; min-width: 0; border: 1px solid var(--border-strong); border-radius: 10px; background: var(--panel); transition: border-color .15s, box-shadow .15s; }
.rte:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.rte-off { opacity: .75; }
.rte-barra { display: flex; flex-wrap: wrap; align-items: center; gap: 2px; padding: 5px 6px; border-bottom: 1px solid var(--border); background: var(--neutral-bg); border-radius: 10px 10px 0 0; }
.rte-boton {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 28px; padding: 0; border: 1px solid transparent;
  border-radius: 6px; background: none; color: var(--muted); font-size: 17px;
}
.rte-boton:hover:not(:disabled) { color: var(--text); background: var(--panel); border-color: var(--border); }
.rte-boton.activo { color: var(--accent); background: var(--accent-soft); border-color: transparent; }
.rte-boton:disabled { opacity: .45; cursor: default; }
.rte-separador { width: 1px; height: 18px; margin: 0 4px; background: var(--border-strong); opacity: .6; }
.rte-zona { position: relative; min-width: 0; }
.rte .ql-container.ql-snow { border: 0; font: inherit; font-size: 14px; color: var(--text); }
.rte .ql-editor { min-height: 92px; max-height: 340px; padding: 12px 14px; line-height: 1.6; overflow-y: auto; }
.rte-descripcion .ql-editor { min-height: 200px; max-height: max(220px, calc(100vh - 470px)); }
.rte .ql-editor.ql-blank::before { left: 14px; right: 14px; color: var(--muted); font-style: normal; }
.rte .ql-editor h1 { font-size: 19px; } .rte .ql-editor h2 { font-size: 16.5px; } .rte .ql-editor h3 { font-size: 15px; }
.rte .ql-editor h1, .rte .ql-editor h2, .rte .ql-editor h3 { margin: 10px 0 4px; font-weight: 650; }
.rte .ql-editor blockquote { margin: 6px 0; padding-left: 12px; border-left: 3px solid var(--border-strong); color: var(--muted); }
.rte .ql-editor code, .rte .ql-snow .ql-editor code { padding: 1px 5px; border-radius: 4px; background: var(--neutral-bg); color: var(--text); font-family: var(--mono); font-size: 12.5px; }
.rte .ql-snow .ql-editor .ql-code-block-container { margin: 6px 0; padding: 8px 12px; border-radius: 8px; background: var(--neutral-bg); color: var(--text); border: 1px solid var(--border); font-family: var(--mono); font-size: 12.5px; }
.rte .ql-editor a { color: var(--accent); }
.rte .ql-editor table { border-collapse: collapse; width: auto; margin: 6px 0; }
.rte .ql-editor td { min-width: 60px; padding: 5px 8px; border: 1px solid var(--border-strong); }
.rte .ql-editor li[data-list]::before { color: var(--muted); }
.rte-mencion { display: inline-block; padding: 0 6px; border-radius: 999px; background: var(--accent-soft); color: var(--accent); font-weight: 600; white-space: nowrap; }
.rte-imagen { display: inline-block; vertical-align: bottom; margin: 2px 0; }
.rte-imagen-cuerpo { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; }
.rte-imagen img { display: block; max-width: min(320px, 100%); max-height: 200px; border-radius: 6px; border: 1px solid var(--border); }
.rte-imagen.sin-miniatura .rte-imagen-cuerpo { padding: 3px 9px; border: 1px dashed var(--border-strong); border-radius: 7px; color: var(--muted); font-size: 12.5px; }
.rte-cargando { display: flex; flex-direction: column; gap: 10px; padding: 16px 14px; min-height: 92px; }
.rte-cargando-alto { min-height: 220px; border: 1px solid var(--border); border-radius: 10px; }
.rte-cargando .corta { width: 50%; }
.rte-error { margin: 0; padding: 10px 14px; color: var(--danger); }
.rte-pie { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; padding: 6px 12px; border-top: 1px solid var(--border); font-size: 11.5px; color: var(--muted); }
.rte-contador.tono-warn { color: var(--warn); } .rte-contador.tono-danger { color: var(--danger); font-weight: 600; }
.rte-subiendo { color: var(--accent); }
.rte-aviso { color: var(--warn); }
.rte-estado { display: inline-flex; align-items: center; gap: 4px; font-weight: 600; }
.rte-estado.tono-ok { color: var(--ok); } .rte-estado.tono-info { color: var(--accent); } .rte-estado.tono-danger { color: var(--danger); }
.rte-atajos kbd { font-size: 10.5px; }
.rte-enlace {
  position: absolute; left: 10px; right: 10px; top: 8px; z-index: 6; display: flex; align-items: center; gap: 6px; padding: 6px 8px;
  border: 1px solid var(--border-strong); border-radius: 8px; background: var(--panel); box-shadow: 0 8px 24px rgba(0, 0, 0, .16);
}
.rte-enlace input { flex: 1; min-width: 0; padding: 5px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); }
.rte-menciones, .dvw-pop {
  position: absolute; z-index: 8; width: min(320px, calc(100vw - 48px)); max-height: 300px; overflow-y: auto; padding: 6px;
  border: 1px solid var(--border-strong); border-radius: 10px; background: var(--panel); box-shadow: 0 12px 32px rgba(0, 0, 0, .18), 0 2px 6px rgba(0, 0, 0, .08);
}
:root[data-theme="dark"] .rte-menciones, :root[data-theme="dark"] .dvw-pop { box-shadow: 0 12px 32px rgba(0, 0, 0, .55); }
.rte-menciones-titulo, .dvw-pop-titulo { margin: 2px 6px 6px; font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.rte-menciones-nota, .dvw-pop-nota, .dvw-pop-cargando { margin: 6px; font-size: 11.5px; color: var(--muted); }
.rte-persona, .dvw-opcion {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 7px 8px; border: 0; border-radius: 7px; background: none;
  color: var(--text); text-align: left; cursor: pointer; list-style: none;
}
.rte-persona.elegida, .dvw-opcion.activa { background: var(--accent-soft); }
.rte-persona-avatar {
  display: inline-flex; align-items: center; justify-content: center; flex: none; width: 28px; height: 28px; border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); font-size: 11px; font-weight: 700;
}
.rte-persona-avatar.nadie { background: var(--neutral-bg); color: var(--muted); }
.rte-persona-datos { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.rte-persona-datos strong { font-weight: 600; overflow-wrap: anywhere; }
.rte-persona-datos small { color: var(--muted); font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rte-persona-origen { flex: none; font-size: 10.5px; color: var(--muted); }

/* Composer and description editor */
.dv-comentarios { display: flex; flex-direction: column; gap: 20px; }
.dvw-composer { display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: 12px; }
.dvw-composer.editando { grid-template-columns: minmax(0, 1fr); margin-top: 8px; }
.dvw-composer-cuerpo { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.dvw-yo { --av: var(--accent); }
.dvw-acciones { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.dvw-acciones .primary { display: inline-flex; align-items: center; gap: 6px; }
.dvw-autor { color: var(--muted); font-size: 12px; }
.dvw-recuperado { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 0; padding: 6px 10px; border-radius: 8px; background: var(--info-bg); color: var(--info); font-size: 12.5px; }
.dvw-error, .dvw-campo-fallo { margin: 0; color: var(--danger); font-size: 12.5px; }
.dvw-avisados { margin: 0; font-size: 12.5px; }
.dvw-avisados.tono-ok { color: var(--ok); } .dvw-avisados.tono-warn { color: var(--warn); }
.dvw-descripcion { display: flex; flex-direction: column; gap: 10px; }
.dv-comentario.propio .dv-comentario-cuerpo { background: color-mix(in srgb, var(--accent) 7%, var(--neutral-bg)); }
.dv-comentario-editado { color: var(--muted); font-size: 12px; }
.dv-comentario-texto.dv-prosa { margin-top: 6px; }
.dv-comentario-texto .dv-rt p { white-space: pre-wrap; }
.dvw-sin-token {
  display: flex; gap: 12px; align-items: flex-start; margin: 14px 64px 0 24px; padding: 10px 14px; border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--warn) 35%, transparent); background: var(--warn-bg); color: var(--text); font-size: 12.5px;
}
.dv-panel-ficha .dvw-sin-token { margin: 0 0 10px; }
.dvw-sin-token > .mdi { font-size: 20px; color: var(--warn); }
.dvw-sin-token p { margin: 2px 0 0; color: var(--muted); }

/* The revision conflict */
.dvw-conflicto { border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent); border-radius: 12px; background: var(--warn-bg); overflow: hidden; }
.dvw-conflicto-cabecera { display: flex; gap: 12px; align-items: flex-start; padding: 12px 14px; }
.dvw-conflicto-cabecera h5 { margin: 0; font-size: 14px; }
.dvw-conflicto-cabecera p { margin: 3px 0 0; color: var(--muted); font-size: 12.5px; }
.dvw-conflicto-icono { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 32px; height: 32px; border-radius: 50%; background: color-mix(in srgb, var(--warn) 18%, transparent); color: var(--warn); font-size: 18px; }
.dvw-conflicto-lados { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px; background: var(--border); border-top: 1px solid var(--border); }
.dvw-lado { min-width: 0; padding: 10px 14px 12px; background: var(--panel); }
.dvw-lado h6 { display: flex; align-items: center; gap: 6px; margin: 0 0 8px; font-size: 11.5px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.dvw-lado.mio h6 { color: var(--accent); }
.dvw-lado-texto { max-height: 220px; overflow-y: auto; font-size: 13px; }
.dvw-borrador { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.6; }
.dvw-conflicto-acciones { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 14px; border-top: 1px solid var(--border); background: var(--panel); }
.dvw-conflicto-acciones button { display: inline-flex; align-items: center; gap: 6px; }

/* Fields edited in place: state, assignee, tags */
.dvw-estado, .dvw-asignado, .dvw-asignado-envoltura { position: relative; display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; }
button.dvw-editable { cursor: pointer; border: 1px solid transparent; font-family: inherit; }
button.dv-chip.dvw-editable:hover:not(:disabled) { border-color: color-mix(in srgb, var(--c, var(--accent)) 55%, transparent); }
button.dvw-editable.guardando { cursor: progress; opacity: .8; }
.dv-chip .mdi-chevron-down { margin-right: -3px; color: inherit; opacity: .7; }
.dvw-asignado-boton { display: inline-flex; align-items: center; gap: 7px; min-width: 0; max-width: 100%; height: 26px; padding: 0 10px 0 3px; border-radius: 999px; background: var(--neutral-bg); color: var(--text); font-size: 12px; font-weight: 500; }
.dvw-asignado-boton.vacio { padding-left: 9px; color: var(--muted); }
.dvw-asignado-boton .dv-avatar { width: 20px; height: 20px; font-size: 9.5px; }
.dvw-asignado-nombre { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
button.dvw-asignado-boton:hover:not(:disabled) { border-color: var(--accent); }
.dvw-asignado.forma-fila { width: 100%; }
.dvw-asignado.forma-fila .dvw-asignado-boton { height: auto; min-height: 40px; padding: 4px 10px 4px 4px; border-radius: 10px; background: none; border: 1px dashed var(--border-strong); width: 100%; font-size: 13.5px; font-weight: 600; }
.dvw-asignado.forma-fila .dvw-asignado-nombre { white-space: normal; overflow-wrap: anywhere; text-align: left; flex: 1; }
.dvw-asignado.forma-fila .dv-avatar { width: 32px; height: 32px; font-size: 12px; }
.dvw-pop { top: calc(100% + 6px); left: 0; }
.dvw-pop-estados { width: 260px; outline: none; }
.dvw-opcion-punto { flex: none; width: 10px; height: 10px; border-radius: 50%; background: var(--muted); }
.dvw-opcion-nombre { flex: 1; min-width: 0; font-weight: 500; }
.dvw-opcion-nota { color: var(--muted); font-size: 11px; }
.dvw-opcion.actual .dvw-opcion-nombre { font-weight: 700; }
.dvw-opcion .mdi-check { color: var(--accent); }
.dvw-pop-busqueda { display: flex; align-items: center; gap: 6px; margin: 0 0 6px; padding: 0 8px; border: 1px solid var(--border); border-radius: 7px; background: var(--bg); }
.dvw-pop-busqueda input { flex: 1; min-width: 0; padding: 7px 0; border: 0; background: none; outline: none; }
.dvw-campo-fallo { flex-basis: 100%; }
.dvw-etiquetas { display: flex; flex-direction: column; gap: 6px; }
.dvw-etiquetas-caja { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 4px; padding: 4px; border: 1px dashed var(--border-strong); border-radius: 8px; }
.dvw-etiquetas-caja:focus-within { border-style: solid; border-color: var(--accent); }
.dvw-etiqueta { display: inline-flex; align-items: center; gap: 2px; padding-right: 3px; }
.dvw-etiqueta-quitar { display: inline-flex; padding: 0 2px; border: 0; background: none; color: inherit; opacity: .65; font-size: 13px; line-height: 1; }
.dvw-etiqueta-quitar:hover { opacity: 1; }
.dvw-etiquetas-campo { flex: 1; min-width: 90px; padding: 3px 4px; border: 0; background: none; outline: none; font-size: 12.5px; }
.dvw-pop-etiquetas { margin: 0; width: 240px; }
.dvw-pop-etiquetas .mdi { color: var(--muted); }
.dvw-etiquetas-acciones { display: flex; justify-content: flex-end; gap: 6px; }
button.dvw-mini { display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; font-size: 12px; }

/* Actividad: a vertical timeline, by day */
.dv-actividad { display: flex; flex-direction: column; gap: 18px; }
.dv-actividad-filtros { display: flex; gap: 6px; flex-wrap: wrap; }
.dv-filtro { display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px; border-radius: 999px; border: 1px solid var(--border); background: var(--panel); font-size: 12.5px; }
.dv-filtro.activo { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.dv-filtro-cuenta { min-width: 18px; padding: 0 5px; border-radius: 999px; background: var(--neutral-bg); color: var(--muted); font-size: 11px; text-align: center; }
.dv-filtro.activo .dv-filtro-cuenta { background: var(--panel); color: var(--accent); }
.dv-dia-titulo { position: sticky; top: 44px; z-index: 1; margin: 0 0 10px; padding: 2px 0; font-size: 11.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); background: var(--panel); }
.dv-dia-titulo::first-letter { text-transform: uppercase; }
.dv-tiempo { margin: 0; padding: 0; list-style: none; }
.dv-suceso { position: relative; display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: 12px; padding-bottom: 16px; }
.dv-suceso::before { content: ""; position: absolute; left: 15px; top: 34px; bottom: 2px; width: 2px; background: var(--border); border-radius: 1px; }
.dv-suceso:last-child { padding-bottom: 0; }
.dv-suceso:last-child::before { display: none; }
.dv-suceso-avatar { width: 32px; height: 32px; font-size: 12px; }
.dv-suceso-cuerpo { min-width: 0; padding-top: 3px; }
.dv-suceso-cabecera { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; margin: 0 0 4px; }
.dv-suceso-cabecera time, .dv-suceso-rev { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.dv-suceso-rev { font-size: 11px; }
.dv-suceso-acciones { display: flex; flex-direction: column; gap: 5px; margin: 0; padding: 0; list-style: none; }
.dv-suceso-acciones li { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 6px; align-items: start; }
.dv-suceso-acciones .mdi { font-size: 15px; line-height: 1.4; color: var(--muted); }
.dv-suceso-acciones .tono-accent .mdi { color: var(--accent); }
.dv-suceso-acciones .tono-ok .mdi { color: var(--ok); }
.dv-suceso-acciones .tono-info .mdi { color: var(--info); }
.dv-suceso-texto { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; min-width: 0; overflow-wrap: anywhere; line-height: 1.45; }
.dv-suceso-detalle { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.dv-desde-app { color: var(--accent); font-weight: 600; }
.dv-suceso-cita { flex-basis: 100%; margin: 2px 0 0; padding: 6px 10px; border-radius: 4px 10px 10px 10px; background: var(--neutral-bg); color: var(--text); font-size: 12.5px; white-space: pre-wrap; overflow-wrap: anywhere; }

@media (max-width: 600px) {
  .dvw-sin-token { margin: 12px 16px 0; }
  .dvw-conflicto-lados { grid-template-columns: minmax(0, 1fr); }
  .rte-atajos { display: none; }
  .rte-boton { width: 32px; height: 32px; }
  .rte .ql-editor { max-height: 46vh; }
  .dvw-composer { grid-template-columns: minmax(0, 1fr); }
  .dvw-yo { display: none; }
  .dvw-pop, .rte-menciones { width: calc(100vw - 48px); }
  .dvw-pop-estados { left: 0; }
  .dv-suceso { grid-template-columns: 28px minmax(0, 1fr); gap: 10px; }
  .dv-suceso-avatar { width: 28px; height: 28px; font-size: 11px; }
  .dv-suceso::before { left: 13px; top: 30px; }
  .dv-dia-titulo { top: 40px; }
}
.rte .ql-editor:focus, .rte .ql-editor:focus-visible { outline: none; }
.dvw-acciones .dvw-autor { flex: 1 1 260px; }
.dvw-acciones .dvw-autor + .spacer { display: none; }
/* Sistema → Proyectos: lo que propone «Crear también en Azure DevOps» (D-32) */
.defaults-devops { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; border: 1px dashed var(--border-strong); border-radius: 8px; }
.defaults-devops > legend { padding: 0 4px; font-weight: 600; }

/* «Restablecer contraseña» in «Editar usuario»: the button and what it does, side by side */
.restablecer-contrasena { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

/* Sessions of an account: «Sesiones activas» / «Histórico» */
.sesiones-pestanas { display: flex; border-bottom: 1px solid var(--border); padding: 0 16px; }
.sesiones-pestanas button { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 6px; border: 0; background: none;
  padding: 10px 12px; color: var(--muted); border-bottom: 2px solid transparent; cursor: pointer; font: inherit; }
.sesiones-pestanas button.activa { color: var(--brand); border-bottom-color: var(--brand); }
.sesiones-cuenta { font-size: 11px; padding: 0 6px; border-radius: 999px; background: color-mix(in srgb, var(--brand) 12%, transparent); }
.sesiones-historico td { white-space: nowrap; }

/* History of an account's changes */
.historial-usuario { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.historial-usuario li { display: flex; gap: 10px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; }
.historial-usuario-icono { flex: none; width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center;
  color: var(--brand); background: color-mix(in srgb, var(--brand) 10%, transparent); }
.historial-usuario-texto { flex: 1; min-width: 0; display: grid; gap: 2px; }
.historial-usuario-cabecera { display: flex; align-items: center; gap: 8px; }
.historial-usuario-cambios { margin-top: 6px; border-collapse: collapse; font-size: 12.5px; width: 100%; }
.historial-usuario-cambios td { padding: 3px 6px; vertical-align: top; }
.historial-usuario-cambios .campo { color: var(--muted); white-space: nowrap; width: 1%; }
.historial-usuario-cambios .antes { color: var(--muted); text-decoration: line-through; word-break: break-word; }
.historial-usuario-cambios .flecha { width: 1%; color: var(--muted); }
.historial-usuario-cambios .despues { word-break: break-word; }

/* Who is online (Sistema → Usuarios): a dot before the username */
.presencia { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 6px; vertical-align: middle; }
.presencia-online { background: #22c55e; box-shadow: 0 0 0 2px color-mix(in srgb, #22c55e 25%, transparent); }
.presencia-away { background: #f59e0b; }
.presencia-offline { background: transparent; border: 1.5px solid var(--muted); }
.etiqueta-tipo.en-uso { display: inline-flex; align-items: center; }
.etiqueta-tipo.en-uso .presencia { width: 7px; height: 7px; margin-right: 4px; }

/* «Aprobación de estimación» de varios tickets (BulkApprovalModal): la tanda y su resultado */
.modal-aprobacion-masiva .body { display: flex; flex-direction: column; gap: 16px; }
.tabla-masiva td:first-child { width: 110px; white-space: nowrap; }
.tabla-masiva .num { text-align: right; white-space: nowrap; width: 64px; }
.tabla-masiva tr.excluido td { color: var(--muted); }
.masiva-ok { color: var(--ok); }
.masiva-warn { color: var(--warn); }
.masiva-danger { color: var(--danger); }
.masiva-personas { margin: 4px 0 0; padding-left: 16px; font-size: 11.5px; color: var(--warn); }

/* Sistema → Bitácora (modules/requestLog) */
.bitacora-barra { flex-wrap: wrap; }
.bitacora-fecha { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--muted); }
.bitacora-fecha input { padding: 4px 6px; }
.bitacora-fila { cursor: pointer; }
.bitacora-fila:hover td, .bitacora-fila:focus-visible td { background: color-mix(in srgb, var(--brand) 6%, transparent); }
.bitacora-ruta { max-width: 420px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The «Token» filter: fluid like the others, but a long token name does not stretch the bar */
.bitacora-filtro-token { max-width: 28ch; text-overflow: ellipsis; }
.bitacora-token { max-width: 180px; overflow: hidden; text-overflow: ellipsis; }
.bitacora-metodo { font-family: var(--mono, monospace); font-size: 11.5px; font-weight: 700; padding: 1px 6px; border-radius: 4px;
  background: color-mix(in srgb, var(--muted) 14%, transparent); }
.bitacora-metodo.m-get { color: var(--brand); }
.bitacora-metodo.m-post { color: #16a34a; }
.bitacora-metodo.m-put, .bitacora-metodo.m-patch { color: #d97706; }
.bitacora-metodo.m-delete { color: #dc2626; }
.bitacora-estado { font-family: var(--mono, monospace); font-size: 12px; font-weight: 700; padding: 1px 7px; border-radius: 999px; }
.bitacora-estado.ok { color: #16a34a; background: color-mix(in srgb, #16a34a 12%, transparent); }
.bitacora-estado.info { color: var(--brand); background: color-mix(in srgb, var(--brand) 12%, transparent); }
.bitacora-estado.aviso { color: #d97706; background: color-mix(in srgb, #d97706 14%, transparent); }
.bitacora-estado.error { color: #dc2626; background: color-mix(in srgb, #dc2626 12%, transparent); }
.bitacora-detalle { display: grid; gap: 14px; }
.bitacora-modal-titulo { display: inline-flex; align-items: center; gap: 8px; }
.bitacora-linea { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px;
  background: color-mix(in srgb, var(--muted) 5%, transparent); }
.bitacora-linea .bitacora-metodo { font-size: 12.5px; padding: 3px 9px; }
.bitacora-linea-ruta { flex: 1; min-width: 0; font-size: 13.5px; word-break: break-all; }
.bitacora-resumen { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.bitacora-dato { display: grid; gap: 4px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; }
.bitacora-dato-eti { display: block; font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.bitacora-dato-valor { font-weight: 600; font-size: 13.5px; }
.bitacora-error { display: flex; align-items: flex-start; gap: 8px; margin: 0; }
.bitacora-quien { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.bitacora-quien-item { display: flex; gap: 10px; align-items: flex-start; font-size: 13px; min-width: 0; }
.bitacora-quien-item > .mdi { font-size: 18px; color: var(--brand); line-height: 1.6; }
.bitacora-quien-item > span { min-width: 0; overflow-wrap: anywhere; }
.bitacora-pestanas { display: flex; border-bottom: 1px solid var(--border); }
.bitacora-pestanas button { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 6px; border: 0; background: none;
  padding: 9px 12px; color: var(--muted); border-bottom: 2px solid transparent; cursor: pointer; font: inherit; font-weight: 600; }
.bitacora-pestanas button.activa { color: var(--brand); border-bottom-color: var(--brand); }
.bitacora-bloque { display: grid; gap: 6px; }
.bitacora-bloque > header { display: flex; align-items: center; justify-content: space-between; font-size: 12px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.bitacora-bloque > header small { text-transform: none; letter-spacing: 0; font-weight: 400; margin-left: 6px; }
.bitacora-json { margin: 0; max-height: 320px; overflow: auto; padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px;
  font-size: 12px; line-height: 1.5; background: color-mix(in srgb, var(--muted) 6%, transparent); white-space: pre-wrap; word-break: break-word; }
.bitacora-vacio { margin: 0; padding: 18px; text-align: center; color: var(--muted); border: 1px dashed var(--border); border-radius: 10px; font-size: 13px; }
.bitacora-nota { margin: 0; }
@media (max-width: 720px) { .bitacora-resumen { grid-template-columns: repeat(2, minmax(0, 1fr)); } .bitacora-quien { grid-template-columns: 1fr; } }


/* The account's menu, top right (SettingsMenu): the account's circle, the menu opens leftwards */
.cuenta-menu .ajustes-boton { display: inline-flex; align-items: center; gap: 6px; }
.cuenta-avatar { padding: 0; border: 0; border-radius: 50%; background: none; cursor: pointer; line-height: 0;
  box-shadow: 0 0 0 2px transparent; transition: box-shadow .15s; }
.cuenta-avatar:hover:not(:disabled), .cuenta-avatar.abierto { border: 0; box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent); }
body[data-bar="solid"] .topbar > div > button.cuenta-avatar,
body[data-bar="solid"] .topbar > div > button.cuenta-avatar:hover:not(:disabled) { background: none; border: 0; }
body[data-bar="solid"] .topbar > div > button.cuenta-avatar:hover:not(:disabled),
body[data-bar="solid"] .topbar > div > button.cuenta-avatar.abierto { box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.45); }
.dropdown-menu.dropdown-menu-derecha { left: auto; right: 0; min-width: 220px; }
.cuenta-cabecera { display: flex; align-items: center; gap: 10px; padding: 8px 10px 6px; }
.cuenta-datos { display: grid; min-width: 0; line-height: 1.3; }
.cuenta-datos b { font-size: 13.5px; }
.cuenta-datos small { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The account's circle (UserAvatar): the photo, or the initials; the app's colours until it picks others */
.user-avatar-circulo { display: inline-grid; place-items: center; flex: none; border-radius: 50%; overflow: hidden;
  background: var(--accent); color: #fff; font-weight: 700; letter-spacing: .02em; line-height: 1; user-select: none; }
.user-avatar-circulo img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* On the coloured bar the default circle goes white with the bar's colour, so it never melts into it */
body[data-bar="solid"] .topbar .cuenta-avatar .user-avatar-circulo:not(.con-foto) { background: #fff; color: var(--bar-fill); }
/* «Foto de perfil» inside «Actualizar» (AvatarSettings) */
.avatar-ajuste { display: grid; gap: 8px; margin-bottom: 6px; }
.avatar-tarjeta { display: grid; gap: 14px; padding: 16px; border: 1px solid var(--border); border-radius: 12px; background: var(--panel); }
.avatar-fila { display: flex; align-items: center; gap: 18px; }
.avatar-editable { position: relative; padding: 0; border: 0; background: none; border-radius: 50%; cursor: pointer; line-height: 0; }
.avatar-editable:hover:not(:disabled) { border: 0; }
.avatar-editable:hover .user-avatar-circulo { filter: brightness(.92); }
.avatar-insignia { position: absolute; right: -2px; bottom: -2px; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  background: var(--panel); color: var(--text); border: 1px solid var(--border-strong); font-size: 14px; line-height: 1; box-shadow: 0 1px 3px rgba(0,0,0,.12); }
.avatar-acciones { display: grid; gap: 6px; }
.avatar-botones { display: flex; align-items: center; gap: 12px; }
.avatar-colores { display: grid; gap: 10px; padding-top: 14px; border-top: 1px solid var(--border); }
.avatar-colores-titulo { font-size: 12.5px; font-weight: 600; color: var(--muted); }
.avatar-presets { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.avatar-preset { width: 28px; height: 28px; padding: 0; border-radius: 50%; border: 0; display: grid; place-items: center;
  font-size: 15px; line-height: 1; cursor: pointer; transition: transform .12s; }
.avatar-preset:hover:not(:disabled) { border: 0; transform: scale(1.08); }
.avatar-preset.activo { box-shadow: 0 0 0 2px var(--panel), 0 0 0 4px var(--accent); }
.avatar-preset-app { background: var(--accent); color: #fff; }
.avatar-preset-propio { background: none; color: var(--muted); border: 1.5px dashed var(--border-strong); }
.avatar-preset-propio:hover:not(:disabled) { border: 1.5px dashed var(--accent); color: var(--accent); }
.avatar-personalizado { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.avatar-color { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text); cursor: pointer; }
/* The colour pickers as round swatches: the global input styles squashed them to a line */
/* :not() twice so it outweighs the global field rule (`input:not(...)`, 0,4,1), which drew its own box around it */
.avatar-ajuste .avatar-color input[type="color"]:not(.swal2-input):not([hidden]) { -webkit-appearance: none; appearance: none; width: 30px; min-width: 30px; height: 30px;
  padding: 0; border: 1px solid var(--border-strong); border-radius: 50%; background: none; cursor: pointer; overflow: hidden; }
.avatar-ajuste .avatar-color input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
.avatar-ajuste .avatar-color input[type="color"]::-webkit-color-swatch { border: 0; border-radius: 50%; }
.avatar-ajuste .avatar-color input[type="color"]::-moz-color-swatch { border: 0; border-radius: 50%; }
.dropdown-item.dropdown-item-peligro { color: var(--danger); }

/* «Editar usuario» (Sistema → Usuarios): laid out like Perfil */
.modal.modal-usuario { max-width: 720px; }
.usuario-form { display: grid; gap: 12px; }
.usuario-form .settings-subtitle { margin-top: 6px; }
.usuario-form .field { margin: 0; }
.usuario-form .grid2 { gap: 14px; align-items: start; }
.usuario-contrasena { display: flex; align-items: center; gap: 14px; padding: 14px 16px; border: 1px solid var(--border); border-radius: 12px; }
.usuario-contrasena > .mdi { font-size: 22px; color: var(--accent); }
.usuario-contrasena-texto { flex: 1; display: grid; gap: 2px; min-width: 0; }
/* Every label of the form the same (the Phone one had its own, bigger style) */
.usuario-form .campo-con-etiqueta { margin: 0; }
.usuario-form .campo-con-etiqueta > span:first-child { font-size: 11px; color: var(--muted); font-weight: 600; }
/* Equipo (TeamField) wraps its select inside its label: stacked like the others, the select at full
   size and width, the «+» beside it at the input's height */
.usuario-form .field > label:has(.campo-con-boton) { display: flex; flex-direction: column; gap: 4px; }
.usuario-form .campo-con-boton { display: flex; align-items: stretch; gap: 8px; width: 100%; }
.usuario-form .campo-con-boton select { flex: 1; min-width: 0; width: 100%; font-size: 14px; font-weight: 400; color: var(--text); }
.usuario-form .campo-con-boton .btn-ver { flex: none; width: 38px; height: auto; display: grid; place-items: center; }

/* UserFormModal, create mode: a subtitle with its counter and note, and the roles' list */
.usuario-subtitulo-con-dato { display: flex; align-items: center; gap: 8px; }
.usuario-subtitulo-con-dato .hint { text-transform: none; letter-spacing: 0; font-weight: 400; }
.usuario-lista { display: grid; gap: 8px; }
.usuario-form > p.hint { margin: 0; }

/* Sistema → Usuarios: the account's circle in its row, with its presence as a dot on the corner */
.usuario-celda { display: inline-flex; align-items: center; gap: 10px; }
.avatar-con-presencia { position: relative; display: inline-flex; flex: none; }
.presencia.presencia-insignia { position: absolute; right: -1px; bottom: -1px; width: 10px; height: 10px; margin: 0;
  border: 2px solid var(--panel); box-sizing: content-box; }
.presencia.presencia-insignia.presencia-offline { background: var(--panel); border-color: var(--panel); box-shadow: inset 0 0 0 1.5px var(--muted); }

/* A colour in the account's history (avatar): its swatch before its code */
.historial-color { display: inline-block; width: 12px; height: 12px; border-radius: 50%; margin-right: 6px; vertical-align: -1px; border: 1px solid var(--border-strong); }

/* «Nuevo token» of Integración: «Todas las IPs» / «Solo estas IPs» as two selectable cards */
.opciones-tarjeta { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.opcion-tarjeta { position: relative; display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 12px; cursor: pointer; transition: border-color .15s, background .15s; }
.opcion-tarjeta:hover { border-color: var(--border-strong); }
.opcion-tarjeta.activa { border-color: var(--accent); background: var(--accent-soft); }
.opcion-tarjeta input { position: absolute; opacity: 0; pointer-events: none; }
.opcion-tarjeta:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.opcion-tarjeta > .mdi { font-size: 22px; color: var(--muted); }
.opcion-tarjeta.activa > .mdi { color: var(--accent); }
.opcion-tarjeta > span { display: grid; gap: 2px; }
@media (max-width: 560px) { .opciones-tarjeta { grid-template-columns: 1fr; } }

/* «Token creado» → «Enviar por correo» */
.token-envio { margin-top: 8px; align-items: center; }
.token-enviado { display: flex; align-items: center; gap: 6px; color: var(--ok); margin: 4px 0 0; }

/* Sistema → Integración: the tokens table */
.tabla-tokens td { vertical-align: middle; }
.token-consumidor { display: grid; gap: 2px; min-width: 0; }
.token-nota { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tabla-tokens .etiqueta-tipo { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.tabla-tokens .col-acciones { width: 1%; text-align: right; }
.tabla-tokens tr.fila-apagada td { opacity: .7; }


/* PaginationBar (design «C»): total in bold, «filtrados de N», page numbers, sizes as segments */
.paginacion-barra { flex-wrap: wrap; gap: 8px 12px; padding: 8px 2px 0; font-size: 13px; }
/* Count | page size (centred) | page numbers: a grid, so the size stays in the middle */
.paginacion.paginacion-barra { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; }
.paginacion-izquierda { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; min-width: 0; }
.paginacion-centro { display: flex; align-items: center; gap: 8px; justify-self: center; }
.paginacion-tamanos-etiqueta { font-size: 12px; color: var(--muted); white-space: nowrap; }
.paginacion-barra .paginacion-paginas { justify-self: end; }
@media (max-width: 720px) {
  .paginacion.paginacion-barra { grid-template-columns: minmax(0, 1fr); justify-items: center; }
  .paginacion-izquierda { justify-content: center; }
  .paginacion-barra .paginacion-paginas { justify-self: center; }
  .paginacion-derecha-vacia { display: none; }
}
.paginacion-total b { font-weight: 700; color: var(--text); }
.paginacion-filtro { padding: 1px 8px; border-radius: 999px; background: var(--bg); border: 1px solid var(--border); color: var(--muted); font-size: 12px; }
.paginacion-paginas { display: inline-flex; align-items: center; gap: 4px; }
.paginacion-paginas .btn-pag { min-width: 28px; height: 28px; padding: 0 6px; font-size: 13px; border: 1px solid var(--border); background: var(--panel); color: var(--text); }
.paginacion-paginas .btn-pag .mdi { font-size: 16px; }
.paginacion-paginas .btn-pag.actual { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
.paginacion-puntos { padding: 0 2px; color: var(--muted); }
.paginacion-tamanos { display: inline-flex; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.paginacion-tamanos button { border: 0; border-right: 1px solid var(--border); background: var(--panel); color: var(--muted); padding: 4px 10px; font: inherit; font-size: 12px; cursor: pointer; }
.paginacion-tamanos button:last-child { border-right: 0; }
.paginacion-tamanos button:hover { color: var(--accent); }
.paginacion-tamanos button.activo { background: var(--accent-soft); color: var(--accent); font-weight: 600; }

/* The Sistema tables, one look for all (Usuarios, Roles, Parámetros, Bitácora, Integración):
   rows centred, the main datum in bold with the secondary one under it, small chips for counts,
   and the actions pinned to the right. */
.tabla-sistema td { vertical-align: middle; }
.tabla-sistema .col-acciones { width: 1%; white-space: nowrap; }
.tabla-sistema .col-acciones .acciones { justify-content: flex-end; }
.celda-doble { display: grid; gap: 2px; min-width: 0; }
.celda-doble > b { font-weight: 600; }
.celda-doble > .hint { overflow: hidden; text-overflow: ellipsis; }
.celda-doble.recortada > .hint { white-space: nowrap; max-width: 520px; }
.chip-dato { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 999px; background: var(--bg); border: 1px solid var(--border); color: var(--muted); font-size: 11.5px; white-space: nowrap; }
.chip-dato .mdi { font-size: 13px; }
.chip-dato.fuerte { color: var(--text); }
.bitacora-peticion { display: inline-flex; align-items: center; gap: 8px; min-width: 0; max-width: 100%; }
.bitacora-peticion .bitacora-ruta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.texto-en-linea { color: var(--ok); font-weight: 600; }
.celda-doble .yo { margin-left: 4px; }

/* The notifications bell (top bar), live */
.notificaciones { position: relative; margin-right: 10px; }
.notificaciones-boton { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border: 0; border-radius: 50%; background: transparent; color: inherit; cursor: pointer; font-size: 22px; }
.notificaciones-boton:hover, .notificaciones-boton.abierto { background: rgba(255, 255, 255, 0.16); }
.notificaciones-contador { position: absolute; top: 1px; right: 0; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; background: var(--danger); color: var(--panel); font-size: 10.5px; font-weight: 700; line-height: 18px; text-align: center; box-shadow: 0 0 0 2px var(--bar-fill, var(--brand)); }
.notificaciones-menu { width: 400px; max-width: calc(100vw - 24px); padding: 0; color: var(--text); overflow: hidden; }
/* «Por decidir» in the bell (D-38): what waits for this account's decision, apart from the
   notifications. Its own counter, amber, at the bell's TOP LEFT and growing outwards (its right
   edge stops 1px into the button, well before the icon at 7px): the red one, top right, is
   «sin leer» and grows from the right edge (a «99+» reaches x≈7), so even «99+» beside «99+»
   keeps the rings apart, and the amber never covers the bell.
   Outside the button means over its neighbour: the button gets a left margin as wide as the
   counter (`margenDelContador`, set by the bell), so it steps on nothing. A fixed block at the top of the menu,
   above the tabs: at most about three rows in view, the rest scroll inside it. */
.notificaciones-por-decidir { position: absolute; top: 1px; right: calc(100% - 1px); min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; background: var(--warn); color: var(--panel); font-size: 10.5px; font-weight: 700; line-height: 18px; text-align: center; white-space: nowrap; box-shadow: 0 0 0 2px var(--panel); }
/* On the blue bar a ring of the bar's own colour is invisible, and amber (1.2:1) and red (1.5:1)
   barely differ from the blue: a white ring (4.4:1) draws the edge of both. In dark the red is a
   light salmon, where white digits read at 2.5:1: they go dark like the amber's (--panel). */
body[data-bar="solid"] .notificaciones-boton .notificaciones-contador,
body[data-bar="solid"] .notificaciones-boton .notificaciones-por-decidir { box-shadow: 0 0 0 2px #fff; }
.por-decidir { border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); background: var(--warn-bg); }
.por-decidir-cabecera { display: flex; align-items: center; gap: 8px; padding: 8px 14px 4px; }
.por-decidir-titulo-bloque { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 700; color: var(--warn); outline: none; }
.por-decidir-titulo-bloque:focus-visible { outline: 2px solid color-mix(in srgb, var(--warn) 50%, transparent); outline-offset: 2px; border-radius: 4px; }
.por-decidir-todas { border: 0; background: none; color: var(--accent); font: inherit; font-size: 12px; cursor: pointer; padding: 2px 4px; border-radius: 4px; }
.por-decidir-todas:hover { background: var(--accent-soft); }
.por-decidir-lista { list-style: none; margin: 0; padding: 0 8px 8px; display: grid; gap: 6px; max-height: 300px; overflow-y: auto; }
.por-decidir-fila { display: grid; gap: 6px; padding: 8px 10px; border-radius: 8px; background: var(--panel); border: 1px solid color-mix(in srgb, var(--warn) 30%, var(--border)); }
.por-decidir-ver { display: grid; gap: 2px; width: 100%; padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; min-width: 0; }
.por-decidir-ver:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.por-decidir-meta { display: flex; align-items: center; gap: 6px; font-size: 11.5px; }
.por-decidir-clave { color: var(--accent); font-weight: 600; }
.por-decidir-nombre { font-size: 12.5px; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.por-decidir-quien { font-size: 11px; color: var(--muted); }
/* «Ya aprobaron» (D-37, the anchor): only who approved, in the theme's «ok» green, discreet */
.por-decidir-ancla { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--ok); font-weight: 600; }
.por-decidir-botones { display: flex; justify-content: flex-end; gap: 6px; }
.por-decidir-botones button { height: 28px; padding: 0 10px; font-size: 12px; }
.por-decidir-estado { margin: 0; padding: 6px 14px; font-size: 11.5px; color: var(--muted); border-bottom: 1px solid var(--border); }
.por-decidir-reintentar { border: 0; background: none; color: var(--accent); font: inherit; cursor: pointer; padding: 0; text-decoration: underline; }
@media (max-width: 600px) {
  /* The bell's menu is anchored to the bell, and on a phone the account avatar to its right
     pushed its 100vw-wide box past the LEFT edge (it already did before «Por decidir», which
     just made it obvious). Pinned to the viewport with the 12px gutters instead, right under the
     top bar (`--menu-top`, measured by the bell when it opens, since the bar's height depends on
     how it wraps), and never taller than what is left of the screen: the rest scrolls inside. */
  .notificaciones .notificaciones-menu {
    position: fixed; top: var(--menu-top, 64px); left: 12px; right: 12px; width: auto; max-width: none;
    max-height: calc(100dvh - var(--menu-top, 64px) - 12px); overflow-y: auto; overscroll-behavior: contain;
  }
  /* On a phone the two buttons share the row's width: big enough for a thumb */
  .por-decidir-botones button { flex: 1 1 0; height: 34px; justify-content: center; }
  .por-decidir-lista { max-height: 40vh; }
}
.notificaciones-cabecera { display: flex; align-items: center; gap: 8px; padding: 12px 14px 8px; }
.notificaciones-cabecera > b { font-size: 14px; }
.notificaciones-todas { display: inline-flex; align-items: center; gap: 4px; border: 0; background: none; color: var(--accent); font: inherit; font-size: 12px; cursor: pointer; padding: 2px 4px; border-radius: 4px; }
.notificaciones-todas:hover { background: var(--accent-soft); }
.notificaciones-pestanas { display: flex; gap: 2px; padding: 0 10px; border-bottom: 1px solid var(--border); }
.notificaciones-pestanas button { border: 0; background: none; color: var(--muted); font: inherit; font-size: 12.5px; padding: 6px 8px 8px; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.notificaciones-pestanas button.activa { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
.notificaciones-lista { max-height: 440px; overflow-y: auto; }
.notificaciones-vacio { padding: 28px 16px; display: grid; justify-items: center; gap: 6px; color: var(--muted); text-align: center; }
.notificaciones-vacio .mdi { font-size: 28px; }
.notificacion { position: relative; display: flex; align-items: flex-start; gap: 12px; width: 100%; padding: 12px 14px 12px 16px; border: 0; border-bottom: 1px solid var(--border); background: none; text-align: left; cursor: pointer; color: inherit; font: inherit; }
.notificacion:last-child { border-bottom: 0; }
.notificacion:hover { background: var(--bg); }
.notificacion.sin-leer { background: color-mix(in srgb, var(--accent-soft) 45%, transparent); }
.notificacion.sin-leer::before { content: ""; position: absolute; left: 0; top: 10px; bottom: 10px; width: 3px; border-radius: 0 3px 3px 0; background: var(--accent); }
.notificacion-icono { flex: none; width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 17px; background: var(--accent-soft); color: var(--accent); }
.notificacion.tono-ok .notificacion-icono { background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ok); }
.notificacion.tono-danger .notificacion-icono { background: var(--danger-bg); color: var(--danger); }
.notificacion-texto { flex: 1; min-width: 0; display: grid; gap: 3px; font-size: 12.5px; }
.notificacion-meta { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--muted); }
.notificacion-tipo { font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; font-size: 10px; }
.notificacion.tono-ok .notificacion-tipo { color: var(--ok); }
.notificacion.tono-danger .notificacion-tipo { color: var(--danger); }
.notificacion-titulo { font-weight: 500; line-height: 1.35; }
.notificacion.sin-leer .notificacion-titulo { font-weight: 700; }
.notificacion-cuerpo { color: var(--muted); line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* Administración → Notificaciones: the recipients of a kind as a row of avatars */
.avatares-fila { display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap; }
/* A short modal whose content opens a floating list (the recipients picker of
   Administración → Notificaciones): the body does not scroll, so the list goes OVER the
   modal and its footer instead of being cut inside a tiny scroll box. */
.modal.modal-desplegable, .modal.modal-desplegable .body { overflow: visible; }
.modal.modal-desplegable .destinatarios-lista { z-index: 60; }
.modal.modal-desplegable .destinatarios-scroll { max-height: min(360px, 50vh); }
.notificacion-icono.tono-ok { background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ok); }
.notificacion-icono.tono-danger { background: var(--danger-bg); color: var(--danger); }
/* «Lanzar prueba» of Administración → Notificaciones: the button is wrapped so its tooltip still
   shows while it is disabled (a disabled button gets no pointer events of its own) */
.accion-con-tooltip { display: inline-flex; vertical-align: middle; }
.tabla-docs .acciones .btn-ver + .accion-con-tooltip { margin-left: 0.5rem; }
/* The channel matrix of the notification preferences (NotificationPrefsEditor): one row per
   kind, one switch per channel; on a phone the channel names shrink to their icons */
.matriz-canales-scroll { border: 1px solid var(--border); border-radius: 0.625rem; background: var(--panel); }
.matriz-canales { width: 100%; border-collapse: collapse; font-size: 0.8rem; }
.matriz-canales th, .matriz-canales td { padding: 0.6rem 0.75rem; text-align: left; vertical-align: middle; }
.matriz-canales thead th { font-size: 0.72rem; font-weight: 600; color: var(--muted); border-bottom: 1px solid var(--border); white-space: nowrap; }
.matriz-canales tbody tr + tr > * { border-top: 1px solid var(--border); }
.matriz-canales tbody th { font-weight: normal; }
.matriz-canales .matriz-canal { text-align: center; width: 5.5rem; }
.matriz-canales thead .matriz-canal .mdi { margin-right: 0.25rem; }
.matriz-canales .matriz-canal .interruptor { display: inline-block; vertical-align: middle; }
.matriz-tipo { display: flex; align-items: flex-start; gap: 0.6rem; }
.matriz-tipo-texto { display: grid; gap: 0.15rem; line-height: 1.35; }
@media (max-width: 560px) {
  .matriz-canales th, .matriz-canales td { padding: 0.5rem 0.4rem; }
  .matriz-canales .matriz-canal { width: auto; }
  .matriz-canales thead .matriz-canal span { display: none; }
  .matriz-canales thead .matriz-canal .mdi { margin-right: 0; font-size: 1rem; }
}
/* «Cambios de estado» rule form (`StateRuleForm`, Notificaciones → Tipos → «Reglas») */
.regla-estado-form { display: grid; gap: 0.75rem; padding: 0.75rem; border: 1px solid var(--accent); border-radius: 0.625rem; background: var(--panel); }
.regla-estado-campo { display: grid; gap: 0.35rem; font-size: 0.8rem; }
.regla-estado-campo > label { font-weight: 600; }
.regla-estado-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; max-height: 9rem; overflow-y: auto; }
.regla-estado-alcance { display: flex; flex-wrap: wrap; gap: 0.35rem 1rem; }
.regla-estado-opcion { display: inline-flex; align-items: center; gap: 0.35rem; font-weight: normal; cursor: pointer; }
.regla-estado-activa { display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.8rem; cursor: pointer; }
.regla-estado-error { margin: 0; color: var(--danger); font-size: 0.75rem; }
.regla-estado-botones { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 0.5rem; }
.regla-estado-botones .hint { margin-right: auto; }
/* The «Ver DevOps» / «Abrir en Azure DevOps» of a DevOps notice in its detail */
.detalle-notificacion-devops { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
/* The ticket detail opened from a notification: data chips and the main document inside */
.modal.modal-detalle-ticket { max-width: min(1100px, calc(100vw - 32px)); }
.detalle-ticket-datos { display: flex; flex-wrap: wrap; gap: 6px; }
/* Its header (key, title, description), fixed above the scrolling body: always in sight. A
   long description unfolded scrolls inside the header instead of eating the whole modal */
.detalle-ticket-cabecera { flex: none; padding: 14px 14px 0; max-height: 40vh; overflow-y: auto; }
/* Nothing in the body shrinks to make room: the body scrolls instead */
.modal-detalle-ticket > .body > * { flex: none; }
/* TicketCard `full`: title and description whole and wrapped */
.ticket-ficha.ticket-ficha-full { align-items: flex-start; }
.ticket-ficha-full .ticket-ficha-texto { flex: 1 1 auto; gap: 4px; }
.ticket-ficha-full .ticket-ficha-texto strong { font-size: 1rem; overflow-wrap: anywhere; }
.ticket-ficha-full .ticket-ficha-titulo { font-size: .9rem; font-weight: 600; color: var(--text); line-height: 1.4; }
.ticket-ficha-full .ticket-ficha-descripcion { font-size: .8125rem; color: var(--muted); line-height: 1.5; }
/* ExpandableText.js: a text whole and wrapped, folded at N lines with «Ver más» when long */
.expandable-text { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-width: 0; }
.expandable-text-body { max-width: 100%; white-space: pre-line; overflow-wrap: anywhere; word-break: break-word; }
.expandable-text-body.folded {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: var(--expandable-lines, 4);
  line-clamp: var(--expandable-lines, 4); overflow: hidden;
}
.expandable-text-toggle {
  display: inline-flex; align-items: center; gap: 2px; padding: 0; border: 0; background: none;
  color: var(--accent); font: inherit; font-size: .75rem; font-weight: 600; cursor: pointer;
}
.expandable-text-toggle:hover, .expandable-text-toggle:focus-visible { text-decoration: underline; outline: none; }
.expandable-text-toggle .mdi { font-size: 1rem; line-height: 1; }
.documento-previa { border: 1px solid var(--border); border-radius: 8px; background: var(--bg); min-height: 240px; max-height: 60vh; overflow: auto; }
.documento-previa .visor-marco { width: 100%; height: 60vh; border: 0; display: block; }
.documento-previa .visor-imagen { max-width: 100%; display: block; margin: 0 auto; }
.notificaciones-sonido { border: 0; background: none; color: var(--muted); cursor: pointer; font-size: 16px; padding: 2px 4px; border-radius: 4px; line-height: 1; }
.notificaciones-sonido:hover { color: var(--accent); background: var(--accent-soft); }
/* A bell row (`NotificationItem`): its body opens the detail, «⋯» on its right, and the
   approval gestures under the text. The row is a box, no longer a button: buttons inside. */
.notificacion.notificacion-fila { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: 0 0.25rem; padding: 0; cursor: default; }
.notificacion.notificacion-fila:hover { background: var(--bg); }
.notificacion.notificacion-fila.sin-leer:hover { background: color-mix(in srgb, var(--accent-soft) 65%, transparent); }
.notificacion-abrir { display: flex; align-items: flex-start; gap: 0.75rem; min-width: 0; width: 100%; padding: 0.75rem 0 0.75rem 1rem; border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.notificacion-abrir:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 0.375rem; }
.notificacion-mas { position: relative; padding: 0.5rem 0.5rem 0 0; }
.notificacion-mas-boton { display: inline-flex; align-items: center; justify-content: center; width: 1.75rem; height: 1.75rem; border: 0; border-radius: 50%; background: none; color: var(--muted); cursor: pointer; font-size: 1.1rem; opacity: 0.7; }
.notificacion-fila:hover .notificacion-mas-boton, .notificacion-mas-boton:focus-visible, .notificacion-mas-boton.abierto { opacity: 1; }
.notificacion-mas-boton:hover, .notificacion-mas-boton.abierto { color: var(--accent); background: var(--accent-soft); }
.notificacion-mas-menu { position: absolute; top: calc(100% - 0.25rem); right: 0.5rem; z-index: 30; min-width: 14rem; max-width: min(18rem, calc(100vw - 2rem)); padding: 0.25rem; border: 1px solid var(--border); border-radius: 0.5rem; background: var(--panel); box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.18); display: grid; }
.notificacion-mas-menu button { display: flex; align-items: flex-start; gap: 0.5rem; width: 100%; padding: 0.5rem 0.625rem; border: 0; border-radius: 0.375rem; background: none; color: var(--text); font: inherit; font-size: 0.8rem; text-align: left; cursor: pointer; }
.notificacion-mas-menu button:hover, .notificacion-mas-menu button:focus-visible { background: var(--bg); outline: none; }
.notificacion-mas-menu button .mdi { font-size: 1rem; line-height: 1.2; }
.notificacion-mas-menu button.peligro { color: var(--danger); }
.notificacion-mas-texto { display: grid; gap: 0.125rem; }
.notificacion-mas-texto small { color: var(--muted); font-size: 0.7rem; line-height: 1.3; }
.notificacion-decision { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 0.375rem; padding: 0 0.875rem 0.75rem 3.75rem; }
.notificacion-decision button { height: 1.75rem; padding: 0 0.625rem; font-size: 0.75rem; display: inline-flex; align-items: center; gap: 0.25rem; }
.notificacion-pregunta { flex: 1 1 100%; font-size: 0.78rem; font-weight: 600; text-align: right; }
.notificacion-decidida { display: inline-flex; align-items: center; gap: 0.25rem; font-size: 0.78rem; font-weight: 700; }
.notificacion-decidida.tono-ok { color: var(--ok); }
.notificacion-decidida.tono-danger { color: var(--danger); }
/* «Eliminar»: the row fades and folds away */
.notificacion-sale-leave-active { transition: opacity 0.22s ease, transform 0.22s ease, max-height 0.25s ease 0.05s; max-height: 20rem; overflow: hidden; }
.notificacion-sale-leave-to { opacity: 0; transform: translateX(1.5rem); max-height: 0; }
.notificacion-sale-move { transition: transform 0.22s ease; }
@media (prefers-reduced-motion: reduce) {
  .notificacion-sale-leave-active, .notificacion-sale-move { transition: none; }
}
@media (max-width: 600px) {
  .notificacion-decision { padding-left: 1rem; }
  .notificacion-decision button { flex: 1 1 0; height: 2.125rem; justify-content: center; }
  .notificacion-mas-boton { opacity: 1; }
}
/* The detail of one notification */
.modal.modal-detalle-notificacion { max-width: min(42rem, calc(100vw - 2rem)); }
.detalle-notificacion-meta { display: flex; flex-wrap: wrap; gap: 0.375rem; }
.detalle-notificacion-meta .chip-dato.tono-ok { color: var(--ok); }
.detalle-notificacion-meta .chip-dato.tono-danger { color: var(--danger); }
.detalle-notificacion-titulo { margin: 0.75rem 0 0.25rem; font-size: 1rem; line-height: 1.4; overflow-wrap: anywhere; }
.detalle-notificacion-cuerpo { margin: 0 0 0.5rem; white-space: pre-line; overflow-wrap: anywhere; line-height: 1.5; }
.detalle-notificacion-ticket { display: flex; align-items: center; gap: 0.5rem; width: 100%; padding: 0.5rem 0.75rem; border: 1px solid var(--border); border-radius: 0.5rem; background: var(--panel); color: inherit; font: inherit; text-align: left; cursor: pointer; }
.detalle-notificacion-ticket:hover, .detalle-notificacion-ticket:focus-visible { border-color: var(--accent); background: var(--accent-soft); outline: none; }
.detalle-notificacion-ticket .ticket-ficha { flex: 1 1 auto; min-width: 0; }
.detalle-aprobacion { display: grid; gap: 0.5rem; }
.detalle-aprobacion-fases, .detalle-aprobacion-personas { list-style: none; margin: 0; padding: 0; border: 1px solid var(--border); border-radius: 0.5rem; overflow: hidden; }
.detalle-aprobacion-fases li { display: flex; justify-content: space-between; gap: 1rem; padding: 0.375rem 0.75rem; font-size: 0.8rem; border-bottom: 1px solid var(--border); }
.detalle-aprobacion-fases li:last-child { border-bottom: 0; }
.detalle-aprobacion-fases li.total { background: var(--bg); font-weight: 600; }
/* «DOCS generado»: the bar of its change (en cola → generando → publicado → listo) */
.docs-progreso { border: 1px solid var(--border); border-radius: 0.5rem; padding: 0.625rem 0.75rem; margin: 0 0 0.75rem; display: grid; gap: 0.5rem; }
.docs-progreso-cabecera { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; font-size: 0.85rem; }
.docs-progreso-barra { height: 0.5rem; border-radius: 999px; background: var(--border); overflow: hidden; }
.docs-progreso-barra span { display: block; height: 100%; background: var(--brand); transition: width 0.3s ease; }
.docs-progreso-success .docs-progreso-barra span { background: var(--ok); }
.docs-progreso-failed .docs-progreso-barra span, .docs-progreso-canceled .docs-progreso-barra span { background: var(--danger); }
.docs-progreso-etapas { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr)); gap: 0.375rem; font-size: 0.78rem; }
.docs-progreso-etapas li { display: flex; align-items: center; gap: 0.25rem; color: var(--muted); }
.docs-progreso-etapas li.etapa-done { color: var(--ok-texto); }
.docs-progreso-etapas li.etapa-current { color: var(--brand); font-weight: 600; }
.docs-progreso-etapas li.etapa-failed { color: var(--danger); font-weight: 600; }
.docs-progreso-motivo { white-space: pre-line; overflow-wrap: anywhere; }
.detalle-aprobacion-personas li { display: grid; gap: 0.25rem; padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--border); font-size: 0.8rem; }
.detalle-aprobacion-personas li:last-child { border-bottom: 0; }
.detalle-aprobacion-personas li.tono-ok .chip-dato { color: var(--ok); }
.detalle-aprobacion-personas li.tono-danger .chip-dato { color: var(--danger); }
.detalle-aprobacion-persona { display: flex; flex-wrap: wrap; align-items: center; gap: 0.375rem; }
.detalle-aprobacion-comentario { overflow-wrap: anywhere; font-style: italic; }
.detalle-aprobacion-mia { margin: 0.5rem 0 0; }
.modal-detalle-notificacion footer .notificacion-pregunta { flex: 1 1 auto; text-align: left; }
/* Administración → Notificaciones: a kind whose recipients are the approvers of each request */
.destinatarios-auto { white-space: normal; }
/* Its test recipients: the chip and its «add» button side by side, wrapping when narrow */
/* Seven columns: the description wraps instead of pushing the rest out; below that the
   `.tabla-scroll` scrolls sideways like every other table */
.tabla-notificaciones { min-width: 60rem; }
.tabla-notificaciones td.hint { min-width: 12rem; max-width: 28rem; white-space: normal; }
.tabla-notificaciones td { white-space: normal; }
.tabla-notificaciones .col-acciones { white-space: nowrap; }
.tabla-notificaciones .acciones { flex-wrap: nowrap; gap: 0.375rem; }
/* The actions in FIXED slots (Reglas · Destinatarios por defecto · Histórico): a missing button
   keeps its gap, so the same button lines up from row to row */
.tabla-notificaciones .acciones.acciones-fijas { display: grid; grid-auto-flow: column; grid-auto-columns: 28px; gap: 0.375rem; justify-content: end; }
.accion-hueco { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; }
/* Every control of a row on the same middle line */
.tabla-notificaciones td { vertical-align: middle; }
/* «Reglas» carries how many there are as a small count on its corner */
.btn-ver.btn-con-cuenta { position: relative; }
.btn-cuenta { position: absolute; top: -6px; right: -7px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px; background: var(--accent); color: var(--panel); font-size: 10px; font-weight: 700; line-height: 16px; text-align: center; }
/* A kind switched off for everybody is dimmed; its power button (in «Medios») stays at hand and
   its channel buttons show disabled */
.tabla-notificaciones tr.notificacion-apagada > td:not(.col-medios):not(.col-acciones) { opacity: 0.5; }
/* «Medios»: the kind ON / OFF, then its channels for everybody, small toggles of one size */
.medios-globales { display: inline-flex; align-items: center; gap: 0.25rem; flex-wrap: nowrap; vertical-align: middle; }
.medios-globales > span { display: inline-flex; align-items: center; }
.medio-global.medio-encendido { margin-right: 0.25rem; }
.medio-global.medio-encendido.activo { background: var(--accent); color: var(--panel); }
.medio-global { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; padding: 0; border: 1px solid var(--border-strong); border-radius: 6px; background: transparent; color: var(--muted); cursor: pointer; }
.medio-global .mdi { font-size: 15px; line-height: 1; }
.medio-global.activo { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.medio-global:disabled { cursor: not-allowed; opacity: 0.45; }
.medio-global:not(:disabled):hover { border-color: var(--accent); }
/* «Mis notificaciones» / Usuarios: a kind switched off for everybody */
.matriz-canales tr.tipo-apagado > * { opacity: 0.55; }
.tipo-apagado-chip { margin-top: 0.15rem; width: fit-content; }
/* «Editar» of a kind: ONE view, the sections stacked as cards and walked with the scroll (no tabs,
   no side index), one «Guardar» in the footer with the count of unsaved changes */
.modal.editar-notificacion { max-width: min(66rem, calc(100vw - 2rem)); width: 100%; }
.editar-notificacion .body.editar-notificacion-cuerpo { display: grid; gap: 1.1rem; align-content: start; padding: 1.1rem 1.25rem; overflow-y: auto; min-height: 0; }
.editar-bloque { border: 1px solid var(--border); border-radius: 0.625rem; padding: 1rem 1.1rem; background: var(--panel); min-width: 0; }
.editar-bloque > h3 { margin: 0 0 0.15rem; font-size: 0.95rem; display: flex; align-items: center; gap: 0.5rem; }
.editar-bloque-sub { margin: 0 0 0.85rem; color: var(--muted); font-size: 0.78rem; }
.editar-notificacion-campos { display: grid; grid-template-columns: 1fr 1fr; gap: 0.85rem; }
.editar-notificacion-ancho { grid-column: 1 / -1; }
.editar-notificacion-fijo { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0.7rem; border: 1px dashed var(--border-strong); border-radius: 0.5rem; color: var(--muted); font-family: ui-monospace, Menlo, monospace; font-size: 0.85rem; }
.editar-notificacion-etiqueta-contador { display: flex; justify-content: space-between; gap: 0.5rem; }
.editar-notificacion-botones { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.5rem; }
.editar-notificacion textarea { resize: vertical; min-height: 4.5rem; }
.editar-notificacion .btn-pequeno { padding: 0.3rem 0.65rem; font-size: 0.75rem; justify-content: center; }
.editar-notificacion button.activo { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.editar-notificacion-error { margin: 0 1.25rem 0.75rem; }
.editar-bloque-problemas { list-style: none; margin: 0.75rem 0 0; padding: 0.5rem 0.7rem; display: grid; gap: 0.25rem; border-radius: 0.5rem; background: var(--danger-bg); color: var(--danger); font-size: 0.78rem; }
.editar-notificacion-error ul { margin: 0.35rem 0 0; padding-left: 1.1rem; }
.editar-notificacion-pie { align-items: center; }
.editar-notificacion-pie .spacer { flex: 1; }
.editar-notificacion .chip-dato.chip-aviso { background: var(--warn-bg); color: var(--warn); border-color: transparent; font-weight: 600; }
.editar-notificacion .chip-dato.chip-ok { background: color-mix(in srgb, var(--ok) 14%, var(--panel)); color: var(--ok); border-color: transparent; }
.editar-notificacion .chip-dato.chip-marca { background: var(--accent-soft); color: var(--accent); border-color: transparent; font-weight: 600; white-space: normal; }
/* The switches of «Editar»: `.interruptor` is a <span>, inline by default, so its size did not
   apply and only the knob showed. Inline-block and centred, always (`SwitchToggle`). */
.interruptor.notif-switch { display: inline-block; vertical-align: middle; position: relative; width: 36px; height: 20px; flex: none; }
/* «Medios»: the power switch and one card per channel */
.editar-notificacion-encendido { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.75rem; }
.medios-tarjetas { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.6rem; }
.medio-tarjeta { display: grid; gap: 0.45rem; align-content: start; padding: 0.75rem; border: 1px solid var(--border); border-radius: 0.625rem; background: var(--bg); min-width: 0; }
.medio-tarjeta-cabecera { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; font-weight: 600; }
.medio-tarjeta-nombre { display: inline-flex; align-items: center; gap: 0.5rem; min-width: 0; }
.medio-tarjeta-nombre .mdi { font-size: 1.1rem; color: var(--muted); }
.medio-tarjeta.bloqueado .medio-tarjeta-nombre { color: var(--muted); }
.medio-tarjeta-etiqueta { font-size: 0.7rem; color: var(--muted); margin-bottom: -0.2rem; }
.medio-tarjeta select { width: 100%; font-size: 0.8rem; }
.medio-tarjeta-motivo { display: flex; align-items: flex-start; gap: 0.3rem; font-size: 0.72rem; color: var(--muted); }
/* «Vista previa» of the e-mail: painted as the person receives it (light, like a mail client) */
.notif-preview { margin-top: 0.85rem; border: 1px solid var(--border); border-radius: 0.625rem; overflow: hidden; }
.notif-preview-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.6rem; padding: 0.6rem 0.85rem; border-bottom: 1px solid var(--border); background: var(--bg); color: var(--muted); font-size: 0.75rem; }
.notif-preview-bar b { color: var(--text); }
.notif-preview-bar.secundaria { background: var(--panel); }
.notif-preview-actions { display: inline-flex; align-items: center; gap: 0.5rem; }
.notif-preview-seg { display: inline-flex; border: 1px solid var(--border); border-radius: 0.5rem; overflow: hidden; }
.notif-preview-seg button { border: 0; border-radius: 0; background: transparent; padding: 0.25rem 0.65rem; font-size: 0.75rem; color: var(--muted); cursor: pointer; }
.notif-preview-seg button.activo { background: var(--accent); color: #fff; }
.notif-preview-bg { background: #eef1f5; padding: 1rem; }
.notif-preview-bg.actualizando { opacity: 0.6; }
.notif-preview-frame { display: block; width: 100%; height: 30rem; border: 0; border-radius: 0.5rem; background: #fff; }
.notif-preview-text { margin: 0; padding: 1rem; max-height: 30rem; overflow: auto; border-radius: 0.5rem; background: #fff; color: #1f2328; font-size: 0.8rem; white-space: pre-wrap; }
/* «Destinatarios» and «Pruebas» */
.editar-notificacion-destinatarios, .editar-notificacion-horario { display: grid; gap: 0.6rem; }
.editar-notificacion-prueba { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.5rem; }
/* «Reglas»: the two type cards, the groups by type and what is pending until «Guardar» */
.reglas-estado-admin { display: grid; gap: 0.6rem; }
.reglas-tipos { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
.regla-tipo { display: grid; gap: 0.25rem; text-align: left; padding: 0.85rem; border: 1px solid var(--border); border-radius: 0.625rem; background: var(--bg); color: var(--text); cursor: pointer; font: inherit; }
.regla-tipo.activo { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.regla-tipo:disabled { cursor: not-allowed; opacity: 0.45; }
.regla-tipo-titulo { display: flex; align-items: center; gap: 0.5rem; font-weight: 600; }
.regla-estado-resumen { border-left: 3px solid var(--accent); background: var(--accent-soft); padding: 0.6rem 0.75rem; border-radius: 0.375rem; font-size: 0.8rem; }
.reglas-grupo-titulo { display: flex; align-items: center; gap: 0.4rem; padding: 0.6rem 0.25rem 0.35rem; font-size: 0.72rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
.reglas-transicion { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; overflow-wrap: anywhere; }
.estado-chip { padding: 0.1rem 0.5rem; border-radius: 0.375rem; background: var(--neutral-bg); font-size: 0.75rem; }
.reglas-personas { display: inline-flex; align-items: center; gap: 0.35rem; }
.reglas-pendiente { margin-left: 0.4rem; }
.tabla-reglas-estado tr.pendiente-delete > td:not(.col-acciones) { text-decoration: line-through; opacity: 0.55; }
.tabla-reglas-estado tr.pendiente-create, .tabla-reglas-estado tr.pendiente-update { background: color-mix(in srgb, var(--warn) 7%, transparent); }
@media (max-width: 760px) {
  .editar-notificacion-campos, .reglas-tipos { grid-template-columns: 1fr; }
  .medios-tarjetas { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 480px) {
  .medios-tarjetas { grid-template-columns: 1fr; }
}
.recordatorio-horas-fila { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.recordatorio-horas { display: flex; flex-wrap: wrap; gap: 0.375rem; }
.recordatorio-horas .chip-quitar { border: 0; background: none; padding: 0 0 0 0.25rem; color: var(--muted); cursor: pointer; font: inherit; line-height: 1; }
.recordatorio-horas .chip-quitar:not(:disabled):hover { color: var(--danger); }
.recordatorio-horas-agregar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.recordatorio-horas-agregar select { width: auto; font-variant-numeric: tabular-nums; }
.recordatorio-dias { display: flex; flex-wrap: wrap; gap: 0.375rem; }
.recordatorio-dias .chip-tipo { min-width: 2.25rem; justify-content: center; }
.tabla-reglas-estado tr.inactiva > td:not(.col-acciones) { opacity: 0.6; }
.reglas-estado-transicion { overflow-wrap: anywhere; }
/* A TEST send («Probar») in the bell and in its detail */
.notificacion-prueba { display: inline-flex; align-items: center; gap: 0.2rem; padding: 0 0.375rem; border-radius: 999px; border: 1px dashed var(--warn); color: var(--warn); font-size: 0.65rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; line-height: 1.4; }
.chip-dato.notificacion-prueba { font-size: 0.72rem; text-transform: none; letter-spacing: 0; }

/* Bitácora: the date range as one control, the same height and border as the filters */
.rango-fechas { display: inline-flex; align-items: center; gap: 6px; flex: none; padding: 0 10px; border: 1px solid var(--border-strong); border-radius: 8px; background: var(--panel); }
.rango-fechas .mdi { color: var(--muted); font-size: 17px; }
.rango-fechas input[type="date"] { border: 0; background: transparent; padding: 7px 0; width: auto; min-width: 0; font: inherit; color: inherit; }
.rango-fechas input[type="date"]:focus { outline: none; }
.rango-fechas:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.rango-fechas-guion { color: var(--muted); }
/* Administración → Notificaciones: the recipients as a chip that opens their list */
.destinatarios-chip-menu { position: relative; display: inline-block; }
.chip-boton { cursor: pointer; font: inherit; font-size: 11.5px; }
.chip-boton:hover, .chip-boton.abierto { border-color: var(--accent); color: var(--accent); }
.destinatarios-menu { position: absolute; right: 0; left: auto; top: calc(100% + 6px); z-index: 40; min-width: 240px; max-height: 320px; overflow-y: auto; padding: 6px 0; }
.destinatarios-menu-titulo { padding: 4px 12px 8px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); border-bottom: 1px solid var(--border); margin-bottom: 4px; }
.destinatarios-menu-fila { display: flex; align-items: center; gap: 10px; padding: 6px 12px; font-size: 12.5px; }
/* «Mis notificaciones» (account menu): one row per kind with its switch on the right */
.modal.mis-notificaciones-modal { max-width: min(68rem, calc(100vw - 2rem)); width: 100%; }
.mis-notificaciones-lista { list-style: none; margin: 0; padding: 0; border: 1px solid var(--border); border-radius: 0.625rem; overflow: hidden; background: var(--panel); }
.mis-notificaciones-lista > li + li { border-top: 1px solid var(--border); }
.mis-notificaciones-fila { display: flex; align-items: flex-start; gap: 0.75rem; padding: 0.75rem 0.875rem; cursor: pointer; }
.mis-notificaciones-fila:hover { background: var(--bg); }
.mis-notificaciones-fila .interruptor { margin-top: 0.375rem; }
.mis-notificaciones-texto { flex: 1; min-width: 0; display: grid; gap: 0.2rem; font-size: 0.8rem; line-height: 1.35; }
.mis-notificaciones-texto .hint { white-space: normal; }
.mis-notificaciones-nota { display: inline-flex; align-items: baseline; gap: 0.3rem; font-size: 0.72rem; color: var(--accent); }

/* ------------------------------------------------------ Documentación, ajuste visual (16-10-2026) */
/* The «Herramientas» menu of the toolbar: the ⋮ menu's look, hung under its button */
.menu-herramientas { position: relative; }
.menu-herramientas > .menu-acciones { position: absolute; top: calc(100% + 4px); right: 0; }
.menu-herramientas > .btn.abierto { border-color: var(--accent); color: var(--accent); }
.acciones-docs > .btn.btn-solo-icono { width: 32px; height: 32px; }

/* The counters, compact: number and label on one line, the footnote after them */
.metricas-contadores .metrica {
  flex-direction: row; flex-wrap: wrap; align-items: baseline; column-gap: 10px; row-gap: 0;
  padding: 8px 12px;
}
.metricas-contadores .metrica-num { font-size: 22px; }
.metricas-contadores .metrica-eti { font-size: 13px; }
.metricas-contadores .metrica-pie { margin-left: auto; }

/* Zeros and unknown hours («—») faint, so the real hours stand out */
.tabla-docs td.horas-tenues,
.tabla-docs td.horas-tenues .despliegue-horas { color: color-mix(in srgb, var(--muted) 55%, var(--panel)); }

/* The totals row: grey fill and its short label, so it does not read as one more row */
.tabla-docs tfoot td { background: var(--neutral-bg); }

/* Ventana, Factura and Pago: mostly «—», so narrow and centred */
.tabla-docs th.col-ventana, .tabla-docs td.col-ventana,
.tabla-docs th.col-factura, .tabla-docs td.col-factura,
.tabla-docs th.col-mes-pago, .tabla-docs td.col-mes-pago { width: 1%; padding-left: 4px; padding-right: 4px; text-align: center; }
.tabla-docs th.col-ventana .th-orden,
.tabla-docs th.col-factura .th-orden,
.tabla-docs th.col-mes-pago .th-orden { justify-content: center; }

/* «Creación DevOps»: as narrow as its two-line date. Its label goes in two lines too
   (`.th-dos-lineas`), or the header alone would widen the column and push the table into a
   horizontal scroll, as «Mes de pago» once did. Colours come from the theme tokens. */
.tabla-docs th.col-devops-creado, .tabla-docs td.col-devops-creado { width: 1%; padding-left: 0.375rem; padding-right: 0.375rem; }
.tabla-docs th.col-devops-creado .th-orden { text-align: left; }
.tabla-docs .th-dos-lineas { display: inline-block; line-height: 1.15; white-space: normal; }

/* The dates: the day in the text colour, the time under it small and grey */
html:not([data-presentacion]) .tabla-docs td.two-line-date { color: var(--muted); }
html:not([data-presentacion]) .tabla-docs td.two-line-date::first-line { color: var(--text); font-size: 11px; }

/* Sorting: the arrow only on the sorted column, and on the others while hovering their header */
.tabla-docs th[aria-sort="none"] .th-orden .mdi { opacity: 0; transition: opacity 0.12s; }
.tabla-docs th[aria-sort="none"]:hover .th-orden .mdi,
.tabla-docs th[aria-sort="none"] .th-orden:focus-visible .mdi { opacity: 0.45; }

/* «Sin estado» as a grey pill as wide as the status ones, so the column reads as one block */
.tabla-docs .col-estado .select-estado:not(.con-estado) {
  min-width: 124px; justify-content: space-between; padding: 0 4px 0 0; border: 0; border-radius: 999px;
  background: var(--neutral-bg);
}
.tabla-docs .col-estado .select-estado:not(.con-estado):hover,
.tabla-docs .col-estado .select-estado:not(.con-estado).abierto { background: color-mix(in srgb, var(--muted) 18%, var(--panel)); }
.tabla-docs .col-estado .select-estado:not(.con-estado) .sin-estado { flex: 1; text-align: center; font-weight: 600; padding: 1px 8px; }

/* The project, soft: its catalogue colour as the text over a light tint of it */
.tabla-docs .col-proyecto .select-estado.con-estado,
.tabla-docs .col-proyecto > .tipo-doc.ficha-estado {
  background: color-mix(in srgb, var(--c-solid, #61686f) 14%, var(--panel));
  color: color-mix(in oklch, var(--c-solid, #61686f) 80%, var(--text));
  border-color: transparent;
}
.tabla-docs .col-proyecto .select-estado.con-estado:hover,
.tabla-docs .col-proyecto .select-estado.con-estado.abierto { background: color-mix(in srgb, var(--c-solid, #61686f) 24%, var(--panel)); }
.tabla-docs .col-proyecto .select-estado.con-estado .ficha-estado,
.tabla-docs .col-proyecto .select-estado.con-estado .mdi { color: inherit; }

/* Fecha de ventana and Mes de pago: the native select drawn like the Tipo or Estado control */
.filtros .campo-select select {
  appearance: none; -webkit-appearance: none; cursor: pointer;
  padding: 6px 30px 6px 10px;
  background: var(--panel) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2389919a' d='M7.41 8.58 12 13.17l4.59-4.59L18 10l-6 6-6-6z'/%3E%3C/svg%3E") no-repeat right 6px center / 18px;
}
.filtros .campo-select select:focus { outline: 0; border-color: var(--accent); }
@media (max-width: 640px) {
  /* On a phone the toolbar is a two-column grid: the menu's button fills its cell like the rest */
  .acciones-docs > .menu-herramientas > .btn { width: 100%; justify-content: center; }
}

/* Documentación's toolbar: what acts on the list on the left, the tools and «Crear ticket» on the right */
.acciones-docs > .acciones-separacion { flex: 1; }
@media (max-width: 640px) {
  .acciones-docs > .acciones-separacion { display: none; }
}

/* «Limpiar Filtros» as an icon only (its name in the tooltip): square, the icon centred */
.filtros .btn-limpiar { padding-left: 9px; padding-right: 9px; justify-content: center; }
.filtros .btn-limpiar .mdi { font-size: 16px; line-height: 1; }

/* The filter menus (Tipo, Estado, Sprint, Proyecto): one column as wide as the widest chip,
   every chip that width, so the list reads as one block */
.filtros .menu-tipos, .filtros-movidos .menu-tipos { display: grid; grid-template-columns: 1fr; width: max-content; }
.filtros .menu-tipos .chip-tipo, .filtros-movidos .menu-tipos .chip-tipo { white-space: nowrap; }
/* The number of each option («En desarrollo (12)», 23-10-2026): in the chip's own ink at full
   strength —the same contrast its colour was chosen for, in both themes and when pressed—, told
   apart from the name by its size (a point smaller), not by fading it. A «(0)» stays, in normal
   weight: still readable, only lighter in tone of voice. Tabular figures keep the width. */
.chip-cuenta { margin-left: 0.3em; color: inherit; font-size: 10px; font-weight: 600; font-variant-numeric: tabular-nums; }
.chip-cuenta.chip-cuenta-cero { font-weight: 400; }
/* A LONG list (the Estado filter brings every state of every DevOps type, 25+) stops at a
   height and scrolls inside, instead of running down over the table; «Todos» stays on top */
.filtros .menu-tipos, .filtros-movidos .menu-tipos { max-height: min(340px, 55vh); overflow-y: auto; overscroll-behavior: contain; }
.filtros .menu-tipos .chip-todos, .filtros-movidos .menu-tipos .chip-todos { position: sticky; top: -8px; z-index: 1; box-shadow: 0 -8px 0 var(--panel), 0 4px 6px -4px rgba(0, 0, 0, 0.25); }
/* The same cap for the cell menus (Estado / «Asignado a» of a row): measured by useCellMenu,
   never taller than this even when the window has room */
.menu-tipos.menu-estado-devops { max-height: min(340px, 55vh) !important; overflow-y: auto; overscroll-behavior: contain; }

/* The version at the foot of Documentación (components/AppVersionFooter.js): centred under
   the pagination bar, small and grey; the notice of a newer one in the accent colour */
.version-app { display: flex; justify-content: center; align-items: center; gap: 6px; font-size: 10.5px; color: var(--muted); padding: 0 2px; }
.layout-ancho .pantalla-docs > .version-app { margin-top: -10px; }
.version-app-nueva { display: inline-flex; align-items: center; gap: 4px; color: var(--accent); font-weight: 600; }
.version-app-nueva .mdi { font-size: 13px; line-height: 1; }
.version-app .btn-link.version-app-recargar { padding: 1px 8px; font-size: 10.5px; border-color: var(--accent); color: var(--accent); }
/* The compact variant at the foot of Sistema's side menu: never scrolls away with the menu.
   A newer build tints it with the accent; the reload button is always there. */
.version-app-menu {
  flex: none; display: flex; flex-direction: column; gap: 4px;
  padding: 8px 10px; border-top: 1px solid var(--border);
  font-size: 10.5px; color: var(--muted);
}
.version-app-menu-fila { display: flex; align-items: center; gap: 6px; min-width: 0; }
.version-app-menu-texto { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.version-app-menu .btn-ver.version-app-menu-recargar { width: 24px; height: 24px; margin-left: auto; flex: none; }
.version-app-menu-recargar .mdi { font-size: 14px; }
.version-app-menu.hay-nueva { background: var(--accent-soft); }
.version-app-menu.hay-nueva .version-app-menu-texto { color: var(--accent); }
.version-app-menu.hay-nueva .btn-ver.version-app-menu-recargar { color: var(--accent); border-color: var(--accent); }
/* Narrow screens: the menu is a row of tabs (see «Sistema» at 900px) and the version sits under
   it on one line. Here, after the base rules, so it wins over them. */
@media (max-width: 900px) {
  .version-app-menu { flex-direction: row; align-items: center; flex-wrap: wrap; padding: 6px 8px; }
  .version-app-menu-fila { flex: 1; }
}

/* ------------------------------------------------ «Pendientes de mi aprobación» (D-37)
   The notice is a STRIP IN THE FLOW, between the toolbar and the table: it takes one line
   from the table (whose box shrinks, `.tabla-scroll { flex: 1 }`) and covers nothing — not the
   last rows, not the pager, not the version footer, not the rows' «⋮». Amber like every
   «needs you» of the app (`--warn`, `--warn-bg`, both themes). One line on a desktop; on a
   phone, three: icon, title and «×»; the short text; the button. Dismissed, it folds into the toolbar's compact
   access («3 por aprobar», `.mis-aprob-acceso`). */
.mis-aprob-franja {
  display: flex; align-items: center; gap: 10px; min-width: 0;
  padding: 7px 8px 7px 12px; border-radius: 6px;
  background: var(--warn-bg); color: var(--text);
  border: 1px solid color-mix(in srgb, var(--warn) 35%, transparent); border-left: 4px solid var(--warn);
  animation: mis-aprob-entra 0.2s ease-out;
}
.mis-aprob-franja-icono { flex: none; font-size: 20px; line-height: 1; color: var(--warn); }
.mis-aprob-franja-texto {
  flex: 1 1 auto; min-width: 0; margin: 0; font-size: 13px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mis-aprob-franja-texto strong { color: var(--warn); margin-right: 8px; }
.mis-aprob-franja-hint { color: var(--muted); font-size: 12px; }
.mis-aprob-franja-revisar { flex: none; height: 30px; padding: 0 12px; font-size: 12px; }
.mis-aprob-franja-cerrar {
  flex: none; width: 30px; height: 30px; padding: 0; border: 0; border-radius: 6px;
  background: none; color: var(--muted); font-size: 18px; line-height: 1; cursor: pointer;
  display: grid; place-items: center;
}
.mis-aprob-franja-cerrar:hover { color: var(--text); background: color-mix(in srgb, currentColor 10%, transparent); }
.mis-aprob-franja-cerrar:focus-visible, .mis-aprob-acceso:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--warn) 45%, transparent); outline-offset: 2px;
}
@media (max-width: 600px) {
  /* A phone gets three rows on a grid: icon + the WHOLE title + «×» at the top right; the short
     text under them; «Revisar ahora» across the full width. The paragraph steps aside
     (`display: contents`) so its title and text become rows of their own: squeezed into one
     flex line, the title broke into a narrow column with «…» and the «×» floated mid-strip. */
  .mis-aprob-franja {
    display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "icono titulo cerrar" "hint hint hint" "revisar revisar revisar";
    align-items: start; column-gap: 10px; row-gap: 8px; padding: 10px 8px 10px 12px;
  }
  .mis-aprob-franja-icono { grid-area: icono; margin-top: 1px; }
  .mis-aprob-franja-texto { display: contents; }
  .mis-aprob-franja-texto strong { grid-area: titulo; margin: 0; white-space: normal; overflow-wrap: anywhere; align-self: center; }
  .mis-aprob-franja-hint { grid-area: hint; white-space: normal; }
  .mis-aprob-franja-cerrar { grid-area: cerrar; margin: -4px -2px 0 0; }
  .mis-aprob-franja-revisar { grid-area: revisar; width: 100%; height: 36px; }
}
/* The compact access: a toolbar button like its neighbours, in amber */
.acciones-docs > .btn.mis-aprob-acceso {
  color: var(--warn); border-color: color-mix(in srgb, var(--warn) 55%, transparent); background: var(--warn-bg); font-weight: 600;
}
.acciones-docs > .btn.mis-aprob-acceso:hover { border-color: var(--warn); }
@keyframes mis-aprob-entra { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .mis-aprob-franja { animation: none; } }

/* The attached document of an estimate: «Estimación v2 · 14/10 · TL-…-estimacion.docx» */
.mis-aprob-documento { display: flex; align-items: center; gap: 6px; min-width: 0; flex-wrap: wrap; }
.mis-aprob-documento .mdi { font-size: 14px; }
.mis-aprob-documento-nombre { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }

/* The list: one card per estimate, the decision buttons at its foot */
.modal-mis-aprobaciones .modal-header > span { display: inline-flex; align-items: center; gap: 8px; outline: none; }
.mis-aprob-cuenta {
  display: inline-grid; place-items: center; min-width: 22px; height: 22px; padding: 0 6px; border-radius: 11px;
  background: var(--warn-bg); color: var(--warn); font-size: 12px; font-weight: 700;
}
.mis-aprob-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.mis-aprob-item { border: 1px solid var(--border); border-radius: 8px; padding: 12px 14px; display: flex; flex-direction: column; gap: 6px; }
.mis-aprob-item[aria-busy="true"] { opacity: 0.7; }
.mis-aprob-cabeza { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.mis-aprob-clave { font-size: 12px; font-weight: 700; color: var(--accent); }
.mis-aprob-cabeza .chip-proyecto { font-size: 11px; padding: 1px 8px; border-radius: 999px; background: var(--neutral-bg); color: var(--muted); }
.mis-aprob-total { margin-left: auto; font-weight: 700; font-variant-numeric: tabular-nums; }
.mis-aprob-titulo { font-weight: 600; }
.mis-aprob-meta { display: flex; flex-wrap: wrap; gap: 4px 14px; }
.mis-aprob-meta .mdi { font-size: 13px; }
/* «Ya aprobaron» (D-37, the anchor): only who approved, never the rest. A quiet green line */
.mis-aprob-ancla { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--ok); font-weight: 600; }
.mis-aprob-fases { display: flex; flex-wrap: wrap; gap: 4px 6px; font-size: 12px; }
.mis-aprob-fases span { padding: 2px 8px; border-radius: 4px; background: var(--neutral-bg); }
.mis-aprob-notas summary { cursor: pointer; font-size: 12px; color: var(--muted); }
.mis-aprob-notas p { margin: 6px 0 0; white-space: pre-line; font-size: 12px; }
.mis-aprob-acciones { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.mis-aprob-acciones .spacer { flex: 1; }
.mis-aprob-vacio { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 28px 12px; text-align: center; }
.mis-aprob-vacio .mdi { font-size: 34px; color: var(--ok); }
/* The rejection: one small field per phase, wrapping on a phone */
.rechazo-mia-fases { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px 12px; }
.rechazo-mia-fases label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; }
.rechazo-mia-fases input { width: 100%; }
.modal-rechazo-mia .modal-header > span { display: inline-flex; align-items: center; gap: 6px; }
/* The mandatory observation: its counter («7/20») on the label's right, red until it is enough */
.rechazo-mia-observacion { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.rechazo-mia-observacion .rechazo-mia-falta { color: var(--danger); }
/* «Histórico» of an integration token (integration/TokenHistoryModal.js) */
.modal.modal-historico-token { max-width: 980px; height: calc(100vh - 64px); }
.modal-historico-token .historico-token-cuerpo { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 10px; }
.modal-historico-token .historico-token-cuerpo > .tabla-scroll { flex: 1; min-height: 0; }
.modal-historico-token .historico-motivo { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* «Histórico» of a notification kind (notifications/NotificationHistoryModal.js): the token's modal, wider for its 7 columns */
.modal.modal-historico-envios { max-width: min(1200px, 96vw); }
.modal-historico-envios .chip-estado-correo { white-space: nowrap; }
/* A route of the app reached with an integration token: what the history is for */
.chip-dato.chip-ruta-app { background: var(--warn-bg); color: var(--warn); border-color: transparent; font-weight: 600; }
.tabla-tokens .col-acciones { white-space: nowrap; }
.tabla-tokens .col-acciones .btn-ver + .btn-ver { margin-left: 6px; }

/* ── Imputar horas de gestión a tickets (D-40) ── */
.gestion-pestanas { margin-bottom: 12px; padding: 0; }
.chip-ticket.chip-imputada { cursor: pointer; padding: 2px 8px; background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }
.chip-ticket.chip-imputada:hover { filter: brightness(0.95); }
/* The modal is ONE screen (AllocationWizard): three numbered sections on the left, always in view,
   and the summary with the confirmation on the right, sticky inside the body's own scroll. The
   old step list read as tabs. Every colour is a token, so the dark theme comes for free */
.modal.modal-imputacion { max-width: 1180px; height: calc(100vh - 32px); max-height: calc(100vh - 32px); }
.modal-imputacion .imp-cabecera { align-items: flex-start; padding: 14px 18px; }
.imp-cabecera-textos { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.imp-cabecera h2 { margin: 0; font-size: 16px; font-weight: 600; display: flex; align-items: center; gap: 8px; }
.imp-cabecera h2 .mdi { color: var(--accent); font-size: 20px; }
.imp-cabecera .hint { margin: 0; font-size: 12px; font-weight: 400; }
.modal-imputacion .body.imp-cuerpo {
  display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 20px; align-items: start;
  padding: 18px; background: var(--bg);
}
.imp-secciones { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.modal-imputacion :is(button, a, summary, select, input, textarea):focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.modal-imputacion .num { font-variant-numeric: tabular-nums; }

/* A section: a card with its number, icon and title */
.imp-seccion { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 16px 18px 18px; transition: opacity .2s; }
/* `.modal header` gives every header inside a modal padding and a rule: a section's is not the modal's */
.modal .imp-seccion-cabecera { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; min-height: 28px; padding: 0; border: 0; font-weight: 400; }
.imp-seccion-numero {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 26px; height: 26px; border-radius: 50%; font-size: 13px; font-weight: 700;
  background: var(--accent-soft); color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
}
.imp-hecha .imp-seccion-numero { background: color-mix(in srgb, var(--ok) 14%, var(--panel)); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.imp-seccion-numero .mdi { font-size: 15px; line-height: 1; }
.imp-seccion-titulo { margin: 0; font-size: 14px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.imp-seccion-titulo .mdi { color: var(--muted); font-size: 17px; }
.imp-seccion-extra { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.imp-seccion-cuerpo { display: flex; flex-direction: column; gap: 14px; }
/* Pending: dimmed and saying what is missing, never hidden */
.imp-pendiente { background: color-mix(in srgb, var(--panel) 55%, var(--bg)); border-style: dashed; }
.imp-pendiente .imp-seccion-cabecera { opacity: .7; margin-bottom: 10px; }
.imp-pendiente .imp-seccion-numero { background: var(--neutral-bg); color: var(--muted); border-color: var(--border); }
.imp-seccion-falta { margin: 0 0 12px; font-size: 13px; color: var(--muted); display: flex; align-items: center; gap: 6px; }
.imp-fantasma { display: flex; flex-direction: column; gap: 8px; opacity: .55; }
.imp-fantasma span { display: block; height: 30px; border-radius: 6px; background: var(--neutral-bg); }
.imp-fantasma span:nth-child(2) { width: 88%; }
.imp-fantasma span:nth-child(3) { width: 72%; }
.imp-calculando { font-size: 12px; color: var(--accent); display: inline-flex; align-items: center; gap: 4px; }

/* Section 1 */
.imp-periodo { display: flex; flex-direction: column; gap: 16px; }
.imp-grupo { display: flex; flex-direction: column; gap: 6px; }
.imp-grupo .hint { margin: 0; font-size: 12px; display: flex; align-items: center; gap: 4px; }
.imp-fila { display: grid; gap: 12px; align-items: end; }
.imp-fila-fechas { grid-template-columns: minmax(130px, 1fr) minmax(130px, 1fr) auto minmax(140px, 1fr); }
/* The payment month of the allocation (Gerson, 20-10-2026): chosen in section 1, said in the summary and the preview */
.imp-mes-pago input, .imp-mes-pago select { width: 100%; }
.imp-mes-pago-vista b, .imp-resumen-mes-pago dd b { color: var(--accent); }
.imp-fila-dos { grid-template-columns: 1fr 1fr; align-items: start; }
.modal-imputacion .field > label { font-size: 12px; }
.modal-imputacion input:not([type="checkbox"]):not([type="radio"]), .modal-imputacion select { min-height: 34px; }
.imp-segmentos { display: inline-flex; border: 1px solid var(--border-strong); border-radius: 6px; overflow: hidden; height: 34px; }
.imp-segmentos button { border: 0; border-radius: 0; padding: 0 12px; background: var(--panel); font-size: 12px; white-space: nowrap; }
.imp-segmentos button + button { border-left: 1px solid var(--border-strong); }
.imp-segmentos button.activo { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
/* People, projects and types (D-44): each one a list of pills under its own header */
.imp-eleccion { display: flex; flex-direction: column; gap: 6px; }
.imp-eleccion > .hint { margin: 0; font-size: 12px; display: flex; align-items: center; gap: 4px; }
.imp-eleccion > .alert { margin: 0; }
.imp-eleccion-cabecera { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.modal-imputacion .imp-eleccion-cabecera > label { font-size: 12px; margin: 0; }
.imp-eleccion-cabecera .imp-contador { margin-left: auto; }
.imp-buscar.imp-buscar-personas { flex: none; width: 100%; max-width: 320px; }
.imp-pastillas-personas { max-height: 132px; overflow-y: auto; padding: 2px; }
.imp-pastilla .hint { font-weight: 400; font-size: 11px; }
.imp-pastilla:has(input:disabled) { opacity: 0.55; cursor: not-allowed; }
.modal-imputacion .field > label.imputacion-check { font-size: 13px; color: var(--text); font-weight: 400; }
.imp-pastillas { display: flex; flex-wrap: wrap; gap: 6px; }
.imp-pastilla {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px 4px 8px; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--panel); font-size: 12px; cursor: pointer; user-select: none;
}
.imp-pastilla input { width: auto; margin: 0; accent-color: var(--accent); }
.imp-pastilla:hover { border-color: var(--accent); }
.imp-pastilla:has(input:checked) { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 600; }
.imp-pastilla:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.imputacion-check { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; cursor: pointer; }
.imputacion-check input { width: auto; }
.modal-imputacion .imputacion-check input { accent-color: var(--accent); }

/* Section 2 */
.imp-tickets { display: flex; flex-direction: column; gap: 10px; }
.imp-barra { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center; }
.imp-buscar { position: relative; flex: 1 1 260px; }
.imp-buscar .mdi { position: absolute; left: 9px; top: 50%; transform: translateY(-50%); color: var(--muted); font-size: 16px; pointer-events: none; }
/* (0,4,1): the global input rule is (0,4,1) too, and this one comes later */
.modal-imputacion .imp-buscar input.imp-buscar-campo[type="search"] { padding-left: 30px; }
.imp-lista { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.imp-lista-cabecera {
  display: flex; align-items: center; gap: 12px; padding: 8px 12px; background: var(--neutral-bg);
  border-bottom: 1px solid var(--border); font-size: 12px;
}
.imp-lista-cabecera .imputacion-check { font-size: 12px; font-weight: 600; }
.imp-contador { margin-left: auto; color: var(--muted); }
.imp-contador b { color: var(--text); }
.imp-contador.lleno b { color: var(--warn); }
.imp-lista-filas { max-height: 300px; overflow-y: auto; }
/* Nothing in a row can overlap: the key has its own capped column and is cut with an ellipsis
   (the whole key in its `title`), the title takes the rest and is cut too, and the project chip
   and the payment month never shrink. Every child gets `min-width: 0`, or a long key without
   spaces (`3-Others/Piloto_gestion_horas_…`) pushes past its column onto the title */
.imp-ticket {
  display: grid; grid-template-columns: auto 132px minmax(0, 1fr) auto; align-items: center; gap: 10px;
  padding: 7px 12px; border-bottom: 1px solid var(--border); font-size: 12px; cursor: pointer;
}
.imp-ticket:last-child { border-bottom: 0; }
.imp-ticket:hover { background: var(--neutral-bg); }
.imp-ticket.elegido { background: var(--accent-soft); }
.imp-ticket:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: -2px; }
.imp-ticket input { width: auto; margin: 0; accent-color: var(--accent); }
.imp-ticket > * { min-width: 0; }
.imp-ticket-clave { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.imp-ticket-titulo { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.imp-ticket-datos { display: inline-flex; align-items: center; gap: 8px; flex: none; justify-self: end; }
.imp-ticket-datos > * { flex: none; }
.imp-etiqueta { font-size: 10px; padding: 1px 6px; border-radius: 4px; background: var(--neutral-bg); color: var(--muted); border: 1px solid var(--border); white-space: nowrap; }
.imp-etiqueta.ajena { background: var(--warn-bg); color: var(--warn); border-color: transparent; }
.imp-lista-vacia { margin: 0; padding: 18px 12px; text-align: center; color: var(--muted); font-size: 12px; }
.imp-lista-mas { margin: 0; padding: 8px 12px; }
.imp-ocultos { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; min-width: 0; }
.imp-ocultos .chip-ticket { max-width: 100%; min-width: 0; }
.imp-chip-clave { min-width: 0; max-width: 240px; overflow: hidden; text-overflow: ellipsis; }
.imp-ocultos .chip-ticket button { flex: none; }
.imp-mezcla { display: flex; flex-direction: column; gap: 6px; }
.modal-imputacion .alert { overflow-wrap: anywhere; }
.imp-mezcla p { margin: 0; }
.btn-link.imp-mini { padding: 3px 8px; font-size: 12px; gap: 4px; }

/* Section 3 */
.imp-aviso-accion { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.imp-aviso-accion .btn { flex: none; }
.imp-seccion-cuerpo > .recarga-linea { margin: -8px 0 -6px; }
.imp-reparto-caja { transition: opacity .2s; }
.imp-reparto-caja.recalculando { opacity: .55; }
.imp-reparto { display: flex; flex-direction: column; gap: 12px; }
.imp-reparto-datos { margin: 0; display: flex; flex-wrap: wrap; gap: 4px 0; font-size: 12px; color: var(--muted); }
.imp-reparto-datos span + span::before { content: "·"; margin: 0 8px; }
.imp-reparto-datos b { color: var(--text); }
.imp-desplegables { display: flex; flex-direction: column; gap: 6px; }
/* Shared with the detail modal (AllocationDetailModal): the base rule stays as it was, the look is scoped */
.imputacion-detalle summary { cursor: pointer; font-size: 13px; }
.modal-imputacion .imputacion-detalle summary { font-size: 12px; color: var(--accent); }
.imputacion-registros, .imputacion-fuera { margin: 6px 0 0; padding-left: 18px; font-size: 12px; max-height: 180px; overflow: auto; }
.imp-tabla { border: 1px solid var(--border); border-radius: 8px; overflow: auto; }
.imp-tabla table { font-size: 13px; }
.imp-tabla th, .imp-tabla td { padding: 8px 12px; }
.imp-tabla th.num, .imp-tabla td.num { text-align: right; }
.imp-tabla tbody tr:hover { background: transparent; }
.imp-tabla tr.editada td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
/* The ticket cell takes the width left by the two number columns and never more (`max-width: 0`
   with `width: 100%` is the table way of saying so): a long key wraps INSIDE it and the title is
   cut, instead of widening the table or running over «Propuesta» */
.imp-tabla td.imp-linea-ticket { white-space: normal; width: 100%; max-width: 0; }
.imp-tabla td.num { white-space: nowrap; }
.imp-linea-ticket > * { display: block; }
.imp-linea-clave { font-size: 12px; overflow-wrap: anywhere; }
.imp-linea-titulo { color: var(--muted); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.imputacion-lineas input[type="number"] { width: 96px; text-align: right; font-variant-numeric: tabular-nums; }
.imputacion-lineas tfoot td { border-top: 2px solid var(--border-strong); border-bottom: 0; background: var(--neutral-bg); white-space: normal; }
.imputacion-lineas .suma-cuadra b { color: var(--ok); }
.imputacion-lineas .suma-falta b, .imputacion-lineas .suma-sobra b { color: var(--warn); }
.imp-varias { display: flex; flex-direction: column; gap: 10px; }
.imp-varias > .hint { margin: 0; font-size: 12px; }
.imp-persona { border: 1px solid var(--border); border-radius: 8px; padding: 0 12px; }
.imp-persona > summary { display: flex; align-items: center; gap: 10px; padding: 10px 0; cursor: pointer; list-style: none; }
.imp-persona > summary::-webkit-details-marker { display: none; }
.imp-persona-flecha { transition: transform .15s; color: var(--muted); }
.imp-persona[open] > summary .imp-persona-flecha { transform: rotate(90deg); }
.imp-persona > summary .btn-link { margin-left: auto; flex: none; }
.imp-persona > summary > * { min-width: 0; }
.imp-persona > summary .badge, .imp-persona > summary .imp-persona-flecha { flex: none; }
.imp-persona-nombre { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.imp-persona[open] { padding-bottom: 12px; }
.imp-persona .badge .mdi { font-size: 12px; }

/* The summary column */
/* `z-index` above the table headers, which are sticky too (`.modal .tabla-scroll th`, z-index 1):
   stacked under 900 px, the reparto's header used to paint over the summary pinned at the bottom */
.imp-resumen {
  position: sticky; top: 0; z-index: 2; display: flex; flex-direction: column; gap: 14px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 16px;
}
.imp-resumen-titulo { margin: 0; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); display: flex; align-items: center; gap: 6px; }
.imp-resumen-datos { margin: 0; display: flex; flex-direction: column; gap: 10px; }
.imp-resumen-datos > div { display: grid; grid-template-columns: 104px minmax(0, 1fr); gap: 8px; font-size: 12px; }
.imp-resumen-datos dt { color: var(--muted); }
.imp-resumen-datos dd { margin: 0; font-weight: 600; overflow-wrap: anywhere; }
.imp-resumen-datos dd .hint { font-weight: 400; }
.imp-total { padding: 12px; border-radius: 8px; background: var(--neutral-bg); display: flex; flex-direction: column; gap: 6px; }
.imp-total-cifras { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.imp-total-eti { font-size: 12px; color: var(--muted); }
.imp-total-num { font-size: 13px; font-variant-numeric: tabular-nums; }
.imp-total-num b { font-size: 22px; font-weight: 700; }
.imp-total.suma-cuadra .imp-total-num b { color: var(--ok); }
.imp-total.suma-falta .imp-total-num b, .imp-total.suma-sobra .imp-total-num b { color: var(--warn); }
.imp-barra-progreso { height: 6px; border-radius: 999px; background: color-mix(in srgb, var(--border) 70%, transparent); overflow: hidden; }
.imp-barra-progreso span { display: block; height: 100%; background: var(--accent); border-radius: inherit; transition: width .25s; }
.imp-total.suma-cuadra .imp-barra-progreso span { background: var(--ok); }
.imp-total.suma-falta .imp-barra-progreso span, .imp-total.suma-sobra .imp-barra-progreso span { background: var(--warn); }
.imp-avisos { display: flex; flex-direction: column; gap: 8px; }
.imp-avisos .alert { margin: 0; }
.imp-resumen-acciones { display: flex; flex-direction: column; gap: 8px; padding-top: 4px; border-top: 1px solid var(--border); }
.imp-confirmar { width: 100%; padding: 10px 12px; font-size: 14px; display: inline-flex; align-items: center; justify-content: center; gap: 6px; margin-top: 10px; }
.imp-resumen-motivo { margin: 0; font-size: 12px; color: var(--muted); display: flex; gap: 6px; align-items: flex-start; }
.imp-resumen-motivo.listo { color: var(--ok); }
.imp-cancelar { justify-content: center; border-color: transparent; background: none; }

/* Under ~900 px the columns stack and the summary sticks to the bottom: the sections above it
   already say period, people and project, so only the total, the reason and the buttons stay */
@media (max-width: 900px) {
  .modal-imputacion .body.imp-cuerpo { grid-template-columns: minmax(0, 1fr); padding: 12px; gap: 12px; }
  .imp-resumen {
    top: auto; bottom: -12px; margin: 0 -12px -12px; border-radius: 10px 10px 0 0; border-bottom: 0;
    padding: 12px 14px; gap: 10px; box-shadow: 0 -8px 24px rgba(0, 0, 0, .14);
  }
  .imp-resumen-titulo, .imp-resumen-datos { display: none; }
  .imp-resumen-acciones { border-top: 0; padding-top: 0; display: grid; grid-template-columns: 1fr auto; align-items: center; }
  .imp-confirmar { margin-top: 0; grid-column: 1; }
  .imp-cancelar { grid-column: 2; grid-row: 1; }
  .imp-resumen-motivo { grid-column: 1 / -1; }
  .imp-fila-dos { grid-template-columns: 1fr; }
  .imp-seccion { padding: 14px; }
}
@media (max-width: 560px) {
  .modal.modal-imputacion { height: 100%; max-height: 100%; }
  .imp-fila-fechas { grid-template-columns: 1fr 1fr; }
  .imp-segmentos { grid-column: 1 / -1; justify-self: start; }
  .imp-mes-pago { grid-column: 1 / -1; }
  .imp-ticket { grid-template-columns: auto 96px minmax(0, 1fr); }
  .imp-ticket-datos { display: none; }
}

/* The person's colour (lib/nameColor.mjs, the same as their avatar) as a dot before the name in
   the «Asignado a» cell: the chips of its menu and of the filter wear it whole */
.punto-persona { display: inline-block; flex: none; width: 8px; height: 8px; margin-right: 6px; border-radius: 50%; vertical-align: middle; }

/* «Asignado a» editable inside «Ver DevOps»: it reads like «Creado por» (avatar + bold name on one
   line), the table cell's width cap and dot are the table's */
.dv-asignado-editable .select-asignado { max-width: 100%; gap: 8px; padding: 2px 4px 2px 0; }
.dv-asignado-editable .asignado-nombre { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }

/* «Gestión de Horas» of a DOCS (D-40, `modules/docsHours`): the modal, its phases and the
   «Generado desde la app» mark of the table and the viewer */
.modal.modal-horas-docs { width: 860px; max-width: calc(100vw - 32px); }
.modal-horas-docs > .body { display: flex; flex-direction: column; gap: 12px; max-height: min(74vh, 760px); overflow-y: auto; }
.modal-horas-docs > .body > * { flex-shrink: 0; }
.horas-doc-barra { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; min-width: 0; }
.horas-doc-barra select { flex: 1 1 280px; min-width: 0; max-width: 100%; }
.horas-fases { display: flex; flex-direction: column; gap: 14px; }
.horas-fase { border: 1px solid var(--border); border-radius: 6px; padding: 8px 10px; }
.horas-fase-cabecera { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
/* Its own table, NOT the Documentación one (`.tabla-docs` brings min widths, fixed columns and
   no wrapping, which pushed the phases out of the modal sideways): fixed layout, the text wraps,
   Actividad takes what is left, Detalle a share, the hours a narrow right column */
.modal-horas-docs > .body { overflow-x: hidden; }
.horas-fase { min-width: 0; }
.horas-tabla { width: 100%; table-layout: fixed; border-collapse: collapse; font-size: 12.5px; }
.horas-tabla th, .horas-tabla td { padding: 6px 8px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; overflow-wrap: anywhere; white-space: normal; overflow: hidden; }
.horas-tabla th { font-size: 10.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.horas-tabla tr:last-child td { border-bottom: 0; }
.horas-tabla th:nth-child(2), .horas-tabla td:nth-child(2) { width: 34%; }
.horas-col-horas, .horas-tabla td.horas-numero { width: 80px; }
.horas-tabla th.horas-col-horas { text-align: right; }
.horas-col-accion { width: 36px; }
.horas-input { width: 100%; box-sizing: border-box; font: inherit; resize: vertical; }
.horas-numero { text-align: right; }
.horas-agregar-fase { display: flex; gap: 8px; align-items: center; }
.horas-resumen { display: flex; gap: 18px; justify-content: flex-end; }
/* A document without hours file: phase | hours of the inventory, a compact table with its own buttons */
.horas-tiempo { display: flex; flex-direction: column; gap: 10px; }
.horas-tiempo .horas-tabla { width: 100%; }
.horas-tiempo .horas-tabla th:nth-child(2), .horas-tiempo .horas-tabla td:nth-child(2) { width: 120px; text-align: right; }
.horas-tiempo .horas-tabla tr:last-child td { border-top: 1px solid var(--border); }
.horas-tiempo-acciones { display: flex; gap: 10px; justify-content: flex-end; align-items: center; }
/* In the modal's footer, beside «Cerrar»: the footer's own spacing */
.horas-pie-tiempo { display: contents; }
.horas-tiempo-acciones.en-pie { gap: 8px; }
/* In the footer, beside «Guardar»: no box, just the two options (or the notice) */
.horas-version { border: 0; margin: 0; padding: 0; display: flex; align-items: center; gap: 16px; flex-wrap: wrap; font-size: 12.5px; }
.horas-version label { display: inline-flex; align-items: center; gap: 6px; margin: 0; cursor: pointer; white-space: nowrap; }
.horas-version input { margin: 0; }
.horas-pipeline a { margin-left: 6px; }
/* «Reintentar» of a failed regeneration, on the status line itself: small, not a footer button */
.horas-pipeline .horas-reintentar { margin-left: 8px; padding: 2px 10px; min-height: 0; font-size: 12px; vertical-align: middle; }
/* D-40: the change on its way inside the modal (generating → syncing), under the version select */
.horas-progreso { display: flex; flex-direction: column; gap: 6px; padding: 8px 10px; border: 1px solid var(--brand); border-radius: 6px; background: var(--accent-soft); }
.horas-progreso-linea { display: flex; align-items: center; gap: 8px; min-width: 0; }
.horas-progreso-linea .mdi { color: var(--accent); }
.horas-progreso-texto { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.horas-progreso-linea a { white-space: nowrap; }
.horas-progreso .cargando-barra { flex: none; width: 100%; }
/* D-40: the DOCS on their way, at the foot of the viewer's explorer (it stays in sight while the tree scrolls) */
.visor-generando {
  position: sticky; bottom: 0; z-index: 2; margin-top: auto; display: flex; flex-direction: column; gap: 8px;
  padding: 8px 10px; background: var(--neutral-bg); border-top: 1px solid var(--border);
}
.visor-generando-item { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 4px 6px; }
.visor-generando-item .cargando-barra { grid-column: 1 / -1; }
.visor-generando-texto { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11.5px; color: var(--muted); }
.visor-generando-texto .mdi { color: var(--accent); }
.visor-generando-enlace { color: var(--muted); font-size: 13px; line-height: 1; }
.visor-generando-enlace:hover { color: var(--accent); }
.horas-detalle { display: grid; grid-template-columns: max-content 1fr; gap: 4px 12px; margin: 0; }
.horas-detalle dt { color: var(--muted); }
.horas-detalle dd { margin: 0; }
.chip-generado-app, .horas-chip-app {
  display: inline-flex; align-items: center; gap: 4px; margin-left: 6px; padding: 1px 6px; border-radius: 10px;
  font-size: 11px; color: var(--brand); background: var(--accent-soft); border: 1px solid var(--brand); white-space: nowrap;
}
.fila-clicable { cursor: pointer; }

/* «Tiempo en cada estado», on top of the Resumen of «Ver DevOps» (19-10-2026). The categories'
   colours are the app's tokens, so the dark theme comes with them; `tabular-nums` as in the
   imputation modal, for durations that line up. */
.dvt { display: flex; flex-direction: column; gap: 12px; }
.dvt .num { font-variant-numeric: tabular-nums; }
.dvt-cabecera { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.dvt-cabecera .dv-grupo-titulo { margin: 0; }
.dvt-configurar { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: var(--accent); text-decoration: none; }
.dvt-configurar:hover { text-decoration: underline; }
.dvt-cat-nuevo { --c: var(--muted); }
.dvt-cat-desarrollo { --c: var(--accent); }
.dvt-cat-pruebas { --c: var(--info); }
.dvt-cat-bloqueado { --c: var(--warn); }
.dvt-cat-resuelto { --c: color-mix(in srgb, var(--ok) 55%, var(--accent)); }
.dvt-cat-hecho { --c: var(--ok); }
.dvt-cat-eliminado { --c: var(--danger); }
.dvt-cat-otro { --c: var(--border-strong); }
/* Two states of the same category (Nuevo, Aprobado) do not look the same: a lighter tone each, from the same token */
.dvt-tono-1 { --c-tono: color-mix(in srgb, var(--c) 62%, var(--panel)); }
.dvt-tono-2 { --c-tono: color-mix(in srgb, var(--c) 38%, var(--panel)); }
.dvt-punto.dvt-tono-1, .dvt-punto.dvt-tono-2, .dvt-total-relleno.dvt-tono-1, .dvt-total-relleno.dvt-tono-2,
.dvt-tramo.dvt-tono-1, .dvt-tramo.dvt-tono-2 { background: var(--c-tono); box-shadow: inset 0 0 0 1px var(--c); }
.dvt-marca.dvt-tono-1, .dvt-marca.dvt-tono-2 { border-color: var(--c-tono); }
.dvt-punto { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: var(--c); flex: none; }

.dvt-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px; }
.dvt-kpi { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding: 10px 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); }
.dvt-kpi-etiqueta { font-size: 11.5px; color: var(--muted); }
.dvt-kpi-valor { display: flex; align-items: center; gap: 7px; font-size: 17px; font-weight: 650; line-height: 1.3; overflow-wrap: anywhere; }
.dvt-kpi-valor .num, .dvt-kpi-valor small { color: var(--muted); font-weight: 600; font-size: 13px; }
.dvt-kpi-detalle { font-size: 12px; color: var(--muted); }
/* The longest state being a development one: said, not shouted */
.dvt-kpi-desarrollo { border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); background: color-mix(in srgb, var(--accent-soft) 55%, var(--panel)); }

.dvt-barra { display: flex; gap: 2px; height: 16px; border-radius: 6px; overflow: hidden; background: var(--neutral-bg); }
.dvt-tramo { flex-basis: 0; min-width: 4px; background: var(--c); }
.dvt-tramo.en-curso { background: repeating-linear-gradient(135deg, var(--c) 0 6px, color-mix(in srgb, var(--c) 72%, var(--panel)) 6px 12px); }
.dvt-vacio, .dvt-mayor-nota { margin: 0; display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--muted); }

.dvt-detalle { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px 24px; }
.dvt-bloque { min-width: 0; }
.dvt-subtitulo { margin: 0 0 6px; font-size: 12.5px; font-weight: 600; color: var(--text); }
.dvt-subtitulo-nota { margin-left: 6px; font-weight: 400; font-size: 11.5px; color: var(--muted); }
.dvt-totales, .dvt-cambios { list-style: none; margin: 0; padding: 0; }
/* The columns live on the list and each row takes them (subgrid): every bar starts at the same x */
.dvt-totales { display: grid; grid-template-columns: auto minmax(130px, 1.5fr) minmax(24px, 1fr) auto; column-gap: 10px; }
.dvt-total { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; align-items: center; row-gap: 4px; padding: 6px 8px; border-radius: 8px; }
.dvt-total + .dvt-total { border-top: 1px solid var(--border); border-radius: 0; }
.dvt-total-mayor .dvt-total-nombre, .dvt-total-mayor .dvt-total-cifras strong { font-weight: 700; }
.dvt-total-nombre { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dvt-veces { color: var(--muted); font-size: 12px; }
.dvt-total-medida { height: 6px; border-radius: 3px; background: var(--neutral-bg); overflow: hidden; }
.dvt-total-relleno { display: block; height: 100%; background: var(--c); border-radius: 3px; }
.dvt-total-cifras { display: inline-flex; align-items: baseline; gap: 8px; justify-content: flex-end; white-space: nowrap; }
.dvt-total-cifras strong { font-weight: 600; }
.dvt-calendario { font-size: 12px; color: var(--muted); }
.dvt-pct { min-width: 38px; text-align: right; font-size: 12px; color: var(--muted); }
.dvt-en-curso {
  margin-left: 6px; padding: 0 6px; border-radius: 999px; font-size: 10.5px; font-weight: 600; vertical-align: 1px;
  color: var(--accent); background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
}

.dvt-cambios { max-height: 320px; overflow-y: auto; padding-right: 4px; }
.dvt-cambio { position: relative; display: grid; grid-template-columns: 14px minmax(0, 1fr); gap: 10px; padding-bottom: 10px; }
.dvt-cambio:not(:last-child)::before { content: ""; position: absolute; left: 6px; top: 16px; bottom: 0; width: 2px; background: var(--border); }
.dvt-marca { width: 14px; height: 14px; margin-top: 3px; border-radius: 50%; background: var(--panel); border: 3px solid var(--c); box-sizing: border-box; position: relative; }
.dvt-cambio.en-curso .dvt-marca { background: var(--c); }
.dvt-cambio-cuerpo { min-width: 0; }
.dvt-cambio-linea { display: flex; align-items: center; gap: 4px; margin: 0; }
.dvt-cambio-linea strong { overflow-wrap: anywhere; }
.dvt-cambio-duracion { font-weight: 600; white-space: nowrap; }
.dvt-cambio-meta, .dvt-cambio-motivo { margin: 1px 0 0; font-size: 12px; color: var(--muted); }
.dvt-fuera { margin-left: 6px; padding: 0 6px; border-radius: 999px; font-size: 10.5px; color: var(--muted); border: 1px solid var(--border); }
.dvt-cambio.fuera-del-ciclo .dvt-cambio-duracion { color: var(--muted); font-weight: 500; }

.dvt-incompleto { display: flex; align-items: flex-start; gap: 8px; padding: 8px 12px; border-radius: 8px; font-size: 12.5px; color: var(--text); background: var(--warn-bg); border: 1px solid color-mix(in srgb, var(--warn) 35%, transparent); }
.dvt-incompleto > .mdi { color: var(--warn); font-size: 16px; line-height: 1.2; }

.dvt-base { font-size: 12px; color: var(--muted); border-top: 1px solid var(--border); padding-top: 8px; }
.dvt-base > summary { display: flex; align-items: baseline; gap: 6px; cursor: pointer; list-style: none; }
.dvt-base > summary::-webkit-details-marker { display: none; }
.dvt-base > summary::after { content: "Cómo se calcula"; margin-left: auto; flex: none; color: var(--accent); }
.dvt-base[open] > summary::after { content: "Ocultar"; }
.dvt-base-cuerpo ul { margin: 6px 0 0; padding-left: 20px; }
.dvt-base-cuerpo li + li { margin-top: 2px; }
.dvt-base-aviso { display: flex; align-items: flex-start; gap: 6px; margin: 0; padding: 8px 12px; border-radius: 8px; font-size: 12.5px; color: var(--text); background: var(--warn-bg); border: 1px solid color-mix(in srgb, var(--warn) 35%, transparent); }
.dvt-base-aviso > .mdi { color: var(--warn); }
.dvt-renombrado { display: flex; align-items: center; gap: 6px; margin: 0; font-size: 12px; color: var(--muted); }

.dvt-aviso { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 1px dashed var(--border-strong); border-radius: 10px; }
.dvt-aviso > .mdi { font-size: 22px; color: var(--muted); }
.dvt-aviso > div { flex: 1; min-width: 0; }
.dvt-aviso .hint { margin: 2px 0 0; }
.dvt-esqueleto { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.dvt-esq-kpi { height: 64px; border-radius: 10px; }
.dvt-esqueleto .dvt-esq-barra { grid-column: 1 / -1; height: 16px; border-radius: 6px; }
.dvt-esqueleto .esqueleto-linea { grid-column: 1 / -1; }

@media (max-width: 860px) {
  .dvt-detalle { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 600px) {
  .dvt-configurar { margin-left: 0; flex-basis: 100%; }
  .dvt-kpis { grid-template-columns: minmax(0, 1fr); }
  .dvt-totales { grid-template-columns: auto minmax(0, 1fr) auto; }
  .dvt-total-medida { display: none; }
  .dvt-calendario { display: none; }
  .dvt-base > summary { flex-wrap: wrap; }
  .dvt-base > summary::after { margin-left: 0; }
  .dvt-esqueleto { grid-template-columns: minmax(0, 1fr); }
}

/* El horario laboral del equipo (D-45), en «Editar parámetro»: una fila por día con sus tramos */
.modal.modal-parametro.modal-horario { max-width: 720px; }
.horario-editor { display: flex; flex-direction: column; gap: 12px; }
.horario-zona input { max-width: 320px; }
.horario-tabla { width: 100%; border-collapse: collapse; font-size: 13px; }
.horario-tabla th, .horario-tabla td { padding: 6px 8px; text-align: left; vertical-align: middle; border-bottom: 1px solid var(--border); }
.horario-tabla thead th { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.horario-tabla tbody th { width: 96px; font-weight: 600; font-size: 13px; text-transform: none; letter-spacing: normal; color: var(--text); background: none; }
.horario-tabla .horario-horas { width: 84px; text-align: right; white-space: nowrap; color: var(--muted); font-size: 12px; }
.horario-libre th { color: var(--muted); font-weight: 500; }
.horario-tramos { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.horario-tramo { display: inline-flex; align-items: center; gap: 4px; padding: 2px 4px 2px 6px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--neutral-bg); }
.horario-tramo input[type="time"] { width: auto; padding: 2px 4px; font-variant-numeric: tabular-nums; }
.horario-tramo .btn-icono-solo { border: 0; background: none; padding: 2px; line-height: 1; color: var(--muted); cursor: pointer; border-radius: 4px; }
.horario-tramo .btn-icono-solo:hover { color: var(--danger); background: var(--danger-bg); }
.horario-agregar { font-size: 12px; padding: 3px 8px; gap: 2px; }
.horario-editor .chip { display: inline-flex; align-items: center; gap: 6px; cursor: default; font-size: 12px; }
.horario-editor .chip-quitar { border: 0; background: none; padding: 0 2px; line-height: 1; font-size: 15px; color: var(--muted); cursor: pointer; }
.horario-editor .chip-quitar:hover { color: var(--danger); }
.horario-resumen { display: flex; align-items: baseline; gap: 6px; margin: 0; font-size: 12.5px; color: var(--muted); }
.horario-defecto { align-self: flex-start; font-size: 12px; padding: 4px 10px; }
@media (max-width: 600px) {
  .horario-tabla thead { display: none; }
  .horario-tabla tr { display: grid; grid-template-columns: 1fr auto; border-bottom: 1px solid var(--border); padding: 4px 0; }
  .horario-tabla th, .horario-tabla td { border-bottom: 0; }
  .horario-tabla tbody th { width: auto; }
  .horario-tabla td:not(.horario-horas) { grid-column: 1 / -1; grid-row: 2; }
}
.horario-invalido { display: flex; flex-direction: column; gap: 4px; }
.horario-invalido pre { margin: 2px 0 0; max-height: 160px; overflow: auto; padding: 6px 8px; border-radius: 4px; font-size: 11.5px; white-space: pre-wrap; overflow-wrap: anywhere; color: var(--text); background: var(--panel); border: 1px solid var(--border); }

/* «Descargar el inventario» → «Mes pago» (D-46): qué se baja, en dos segmentos, y los meses en
   fichas como el filtro de la tabla (selección múltiple, sin desplegable que abrir). */
.segmentos-inv { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
.segmento-inv { display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px; cursor: pointer; font-size: 0.9rem; margin: 0; }
.segmento-inv + .segmento-inv { border-left: 1px solid var(--border); }
.segmento-inv input { position: absolute; opacity: 0; pointer-events: none; }
.segmento-inv.activo { background: var(--accent); color: #fff; font-weight: 600; }
.segmento-inv:focus-within { outline: 2px solid var(--accent); outline-offset: -2px; }
.meses-inv { display: flex; flex-wrap: wrap; gap: 6px; max-height: 180px; overflow-y: auto; }

/* ---------------------------------------------------- Reparto por ticket (D-40, 20-10-2026) */

/* Lo que RECIBE cada ticket sumando a todas las personas: va arriba de la sección 3 y en el
   detalle de una imputación. La cifra que se busca —las horas recibidas— es la grande; el
   desglose por persona y la nota del cobro (D-41) van en tono secundario. */
.imp-por-ticket { display: flex; flex-direction: column; gap: 8px; }
.imp-por-ticket-titulo { margin: 0; font-size: 13px; font-weight: 600; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.imp-por-ticket-titulo .mdi { color: var(--accent); font-size: 16px; }
.imp-por-ticket-titulo .hint { font-weight: 400; font-size: 12px; }
.imp-tabla-por-ticket td.imp-recibe b { font-size: 16px; font-weight: 700; }
.imp-tabla-por-ticket td.imp-se-cobra { white-space: normal; min-width: 160px; font-size: 12px; }
.imp-tabla-por-ticket tfoot td { border-top: 1px solid var(--border-strong); background: var(--neutral-bg); }
.imp-nota-cobro { color: var(--muted); }
.imp-tabla tr.imp-fila-resaltada td { background: var(--accent-soft); }
.imp-tabla tr.imp-fila-resaltada td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
.imp-tabla tbody tr.imp-fila-resaltada:hover { background: var(--accent-soft); }
/* D-48: la bolsa de varias personas. Las personas son el ORIGEN de las horas, no una columna del reparto */
.imp-origen .mdi { color: var(--accent); margin-right: 2px; }
.imp-sin-horas { margin: 0; font-size: 12px; }
.imp-registros-persona { margin: 8px 0 2px; font-size: 12px; font-weight: 600; color: var(--text); }
.imp-reparto-facturado { margin: 8px 0; }
.imp-tabla-por-ticket.imputacion-lineas input[type="number"] { width: 90px; }
.imp-no-editar { display: flex; align-items: center; gap: 4px; }

/* La marca de reparto de la celda «Gestión»: el icono de división junto a la cifra, que abre
   el detalle de la imputación. Discreta pero visible: un clic, no un adorno. */
.marca-reparto {
  border: 0; background: transparent; padding: 0 0 0 4px; cursor: pointer; color: var(--accent);
  font-size: 14px; line-height: 1; vertical-align: middle;
}
.marca-reparto:hover, .marca-reparto:focus-visible { color: var(--text); }

/* La lista para elegir imputación cuando el ticket recibe de varias */
.imp-lista-reparto { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.imp-elegir-reparto {
  width: 100%; display: grid; grid-template-columns: auto 1fr auto auto; gap: 12px; align-items: center;
  padding: 8px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); text-align: left; cursor: pointer;
}
.imp-elegir-reparto:hover, .imp-elegir-reparto:focus-visible { border-color: var(--accent); background: var(--accent-soft); }

/* «Ver DevOps» of a synchronized row without documentation, and that row in the load-test
   sessions' ticket search: a dashed «sin DOCS» mark, like the chip of a ticket not documented yet */
/* «Ver DevOps»'s header (24-10-2026): the ticket on the left (overline + key), the actions of the work
   item being looked at on the right with the «×». It is the app's modal header, so with a solid bar
   it takes the bar's colour (`body[data-bar="solid"] .modal > header`) and its parts turn white */
.modal.devops-ver > header.dv-ver-cabecera { display: flex; align-items: center; gap: 12px; padding: 10px 12px 10px 18px; font-weight: inherit; }
.dv-ver-titulo { display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0; }
.dv-ver-icono {
  display: inline-flex; align-items: center; justify-content: center; flex: none; width: 34px; height: 34px; border-radius: 9px;
  background: var(--accent-soft); color: var(--accent); font-size: 20px;
}
.dv-ver-textos { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.dv-ver-sobre { color: var(--muted); font-size: 10.5px; font-weight: 700; letter-spacing: .08em; line-height: 1.3; text-transform: uppercase; }
.dv-ver-ticket { display: flex; align-items: center; flex-wrap: wrap; gap: 2px 8px; min-width: 0; margin: 0; font-size: 15px; font-weight: 700; line-height: 1.3; }
.dv-ver-clave { font-family: var(--mono); letter-spacing: .01em; white-space: nowrap; }
.dv-ver-clave-tl { font-weight: 600; opacity: .8; }
.dv-ver-sep { font-weight: 400; opacity: .5; }
.dv-ver-acciones { display: flex; align-items: center; gap: 6px; flex: none; }
.modal-header a.btn-icono.dv-ver-abrir { gap: 6px; border-radius: 7px; font-weight: 600; white-space: nowrap; }
body[data-bar="solid"] .modal > header .dv-ver-icono { background: rgba(255, 255, 255, 0.16); color: #fff; }
body[data-bar="solid"] .modal > header .dv-ver-sobre { color: #fff; opacity: 0.8; }
body[data-bar="solid"] .modal > header .dv-sin-docs { border-color: rgba(255, 255, 255, 0.65); color: #fff; }
@media (max-width: 600px) {
  .modal.devops-ver > header.dv-ver-cabecera { padding: 8px 8px 8px 14px; gap: 8px; }
  .dv-ver-icono { width: 30px; height: 30px; font-size: 18px; }
  .dv-ver-abrir-texto { display: none; }
  .modal-header a.btn-icono.dv-ver-abrir { width: 32px; padding: 0; justify-content: center; }
}
.dv-sin-docs {
  display: inline-flex; align-items: center; padding: 0.1em 0.6em; border: 1px dashed var(--border-strong);
  border-radius: 999px; color: var(--muted); font-size: 0.75em; font-weight: 600; white-space: nowrap;
}
.opcion-ticket.opcion-sin-docs { grid-template-columns: auto 100px minmax(0, 1fr) auto; }
.opcion-ticket.opcion-sin-docs .titulo-ticket { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ------------------------------------------------------------------ Notificaciones → Plantillas
   The template catalog (Correo / WhatsApp, `modules/messageTemplates/TemplatesPanel.js`): the type
   chip with the kinds it serves, Meta's status, «En uso por» and the two switches of each row. */
.tabla-plantillas td { vertical-align: middle; }
.tabla-plantillas tr.plantilla-apagada td:first-child b { color: var(--muted); }
.tabla-plantillas .chip-dato.tono-marca { background: var(--accent-soft); color: var(--accent); border-color: transparent; font-weight: 600; }
.tabla-plantillas .chip-dato.tono-ok { background: color-mix(in srgb, var(--ok) 14%, var(--panel)); color: var(--ok); border-color: transparent; }
.tabla-plantillas .chip-dato.tono-aviso { background: var(--warn-bg); color: var(--warn); border-color: transparent; }
.tabla-plantillas .chip-dato.tono-peligro { background: var(--danger-bg); color: var(--danger); border-color: transparent; }
.plantilla-tipo { display: grid; gap: 4px; justify-items: start; max-width: 22rem; }
.plantilla-uso { display: flex; flex-wrap: wrap; gap: 4px; max-width: 18rem; }
.plantilla-interruptor { display: inline-flex; align-items: center; gap: 8px; }
.plantilla-candado { color: var(--muted); font-size: 16px; }
/* Parametrización → Global: EMAIL_TEMPLATES / WHATSAPP_TEMPLATES are read-only there */
.chip-dato.parametro-solo-lectura { align-self: flex-start; margin-top: 2px; }

/* «Vista previa» of «Editar»: the DOCS attached to the e-mail (a sample, never a real file) */
.notif-preview-adjuntos { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 0.75rem; }
.notif-preview-adjunto { display: inline-flex; align-items: center; gap: 10px; padding: 8px 12px; border: 1px solid #d0d7de; border-radius: 6px; background: #f6f8fa; color: #1f2328; font-size: 13px; }
.notif-preview-adjunto .mdi { font-size: 26px; color: #2b579a; }
.notif-preview-adjunto small { display: block; color: #6b7280; font-size: 11px; }
/* …and the WhatsApp bubble: document header, text, time and buttons (WhatsApp's own dark colours) */
.wa-preview-bg { background: #0b141a; padding: 1.25rem; display: flex; justify-content: center; }
.wa-preview-bg.actualizando { opacity: 0.6; }
.wa-burbuja { width: 330px; max-width: 100%; background: #202c33; color: #e9edef; border-radius: 0 10px 10px 10px; overflow: hidden; font-size: 14px; line-height: 1.4; }
.wa-doc { display: flex; align-items: center; gap: 10px; margin: 6px; padding: 10px; border-radius: 8px; background: #1a2329; overflow-wrap: anywhere; }
.wa-doc .mdi { font-size: 30px; color: #4a90e2; }
.wa-doc small { display: block; color: #8696a0; font-size: 11px; }
.wa-cabecera { padding: 8px 10px 0; font-weight: 700; }
.wa-texto { padding: 4px 10px 6px; white-space: pre-line; overflow-wrap: anywhere; }
.wa-hora { text-align: right; font-size: 11px; color: #8696a0; padding: 0 10px 6px; }
.wa-botones { display: grid; border-top: 1px solid #2a3942; }
.wa-botones span { text-align: center; padding: 9px; color: #53bdeb; border-top: 1px solid #2a3942; }
.wa-botones span:first-child { border-top: 0; }

/* ------------------------------------------------------------------ Plantillas: CRUD
   Notificaciones → Plantillas → Correo / WhatsApp (boceto docs/propuestas/plantillas/): the
   list's actions, «Ver», «Nueva / Editar» (one view, form on the left and live preview on the
   right), «Nueva versión» and «Eliminar». Same tokens as «Editar» of Notificaciones. */
.plantillas-encabezado { flex-wrap: wrap; }
.plantillas-encabezado > .btn + .btn { margin-left: 0; }
.tabla-plantillas .col-activa { width: 64px; }
.tabla-plantillas .col-acciones { width: 112px; text-align: right; white-space: nowrap; }
.plantilla-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }
.tabla-plantillas tr.plantilla-apagada td:not(.col-activa):not(.col-acciones) { opacity: 0.55; }
.tabla-plantillas .plantilla-candado { color: var(--warn); margin-right: 4px; }
.plantilla-modal .chip-dato.tono-marca, .plantilla-dialogo .chip-dato.tono-marca, .plantilla-tags .chip-dato.tono-marca { background: var(--accent-soft); color: var(--accent); border-color: transparent; font-weight: 600; }
.plantilla-modal .chip-dato.tono-ok, .plantilla-dialogo .chip-dato.tono-ok { background: color-mix(in srgb, var(--ok) 14%, var(--panel)); color: var(--ok); border-color: transparent; }
.plantilla-modal .chip-dato.tono-aviso, .plantilla-tags .chip-dato.tono-aviso { background: var(--warn-bg); color: var(--warn); border-color: transparent; }
.plantilla-modal .chip-dato.tono-peligro { background: var(--danger-bg); color: var(--danger); border-color: transparent; }
.plantilla-aviso { display: flex; align-items: flex-start; gap: 8px; border-radius: 6px; line-height: 1.5; }
.plantilla-aviso p { margin: 0 0 6px; }
.plantilla-cuenta-wa { display: grid; gap: 8px; }
.plantilla-waba-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 4px; }
.plantilla-waba-form input { max-width: 22rem; }
.help-error { margin: 4px 0 0; color: var(--danger); font-size: 11.5px; }
.help-ok { margin: 4px 0 0; color: var(--ok); font-size: 11.5px; display: flex; align-items: center; gap: 4px; }

/* The modal: blue header, form | preview, footer with the pending changes */
.modal.plantilla-modal { max-width: min(78rem, calc(100vw - 2rem)); width: 100%; overflow: hidden; }
.plantilla-modal-cabecera { background: var(--brand, #017fc3); color: #fff; border-bottom: 0; }
.plantilla-modal-cabecera.gris { background: #3a3f4b; }
.plantilla-modal-cabecera.rojo { background: var(--danger-fill, #c9372c); }
.plantilla-modal-cabecera .modal-close { color: #fff; }
.plantilla-modal-titulo { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; }
.plantilla-modal-titulo .mdi { font-size: 18px; }
.plantilla-modal-estado { font-weight: 500; font-size: 11.5px; padding: 2px 8px; border-radius: 999px; background: rgba(255, 255, 255, 0.18); }
.plantilla-modal-rejilla { display: grid; grid-template-columns: minmax(0, 1fr) 420px; flex: 1 1 auto; min-height: 0; overflow: hidden; }
.plantilla-modal-form { padding: 16px 20px; display: grid; gap: 14px; align-content: start; overflow-y: auto; min-height: 0; }
.plantilla-modal-error { margin: 10px 20px 0; }
.plantilla-modal-pie { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; padding: 12px 18px; border-top: 1px solid var(--border); background: var(--panel); flex: none; }
.plantilla-modal-pie-izq { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; color: var(--muted); font-size: 12px; }
.plantilla-modal-pie-der { display: flex; flex-wrap: wrap; gap: 8px; }
.plantilla-modal-pie .btn .mdi, .plantilla-dialogo footer .btn .mdi { margin-right: 2px; }
.chip-dato.plantilla-chip-aviso { background: var(--warn-bg); color: var(--warn); border-color: transparent; font-weight: 600; }
/* A WhatsApp template that still carries a link button: no visible links in WhatsApp */
.plantilla-aviso-enlace, .medio-tarjeta-motivo.plantilla-aviso-enlace { color: var(--warn); font-weight: 600; }
.chip-dato.plantilla-chip-ok { background: color-mix(in srgb, var(--ok) 14%, var(--panel)); color: var(--ok); border-color: transparent; }
.plantilla-problemas { color: var(--danger); display: inline-flex; align-items: center; gap: 4px; }
.plantilla-etiqueta-contador { display: flex; justify-content: space-between; gap: 8px; }
.plantilla-etiqueta-bloque { display: block; margin: 12px 0 6px; font-size: 11px; color: var(--muted); font-weight: 600; }
.plantilla-campos-tres { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.plantilla-campo-arriba { margin-top: 12px; }
.plantilla-campo-copia { margin: 4px 0 10px; }
.plantilla-linea-interruptor { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 10px 0; border-top: 1px solid var(--border); }
.plantilla-linea-interruptor:first-of-type { border-top: 0; padding-top: 0; }
.plantilla-linea-interruptor > span:first-child { display: grid; gap: 2px; }
.plantilla-linea-interruptor b { font-weight: 600; }

/* «Tipo»: the two cards, the kinds it serves (incompatible ones greyed with the reason) */
.plantilla-tipo-bloque { display: grid; gap: 12px; }
.plantilla-tipos { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.plantilla-tipo-tarjeta { display: grid; gap: 4px; text-align: left; padding: 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg); color: var(--text); cursor: pointer; font: inherit; }
.plantilla-tipo-tarjeta.activo { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); background: var(--accent-soft); }
.plantilla-tipo-titulo { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-weight: 600; font-size: 13px; }
.plantilla-radio { width: 15px; height: 15px; border-radius: 50%; border: 2px solid var(--border-strong); flex: none; }
.activo > .plantilla-tipo-titulo .plantilla-radio { border-color: var(--accent); box-shadow: inset 0 0 0 3px var(--accent-soft), inset 0 0 0 8px var(--accent); }
.plantilla-elegibles { display: flex; flex-wrap: wrap; gap: 6px; }
.plantilla-elegible { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: 8px; border: 1px solid var(--border-strong); background: var(--bg); color: var(--text); font: inherit; font-size: 12.5px; cursor: pointer; }
.plantilla-elegible.activo { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.plantilla-elegible.no-casa { border-style: dashed; }
.plantilla-check { width: 15px; height: 15px; border-radius: 4px; border: 2px solid var(--border-strong); display: inline-grid; place-items: center; font-size: 11px; }
.plantilla-elegible.activo .plantilla-check { border-color: var(--accent); background: var(--accent); color: #fff; }

/* «Contenido»: variable chips, the toolbar and the body */
.plantilla-contenido { display: grid; gap: 12px; }
.plantilla-variables { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 4px 0 8px; }
.plantilla-vchip { display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px; border-radius: 6px; border: 1px solid var(--border-strong); background: var(--panel2, var(--bg)); color: var(--text); font: inherit; font-size: 12px; cursor: pointer; }
.plantilla-vchip:hover:not(:disabled) { border-color: var(--accent); }
.plantilla-vchip .mono { color: var(--accent); font-size: 11px; }
.plantilla-vchip .mdi { font-size: 14px; color: var(--muted); }
.plantilla-vchip.obligatoria { border-color: color-mix(in srgb, var(--accent) 55%, transparent); }
.plantilla-herramientas { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; padding: 4px; border: 1px solid var(--border-strong); border-bottom: 0; border-radius: 8px 8px 0 0; background: var(--bg); }
.plantilla-herramientas + textarea { border-radius: 0 0 8px 8px; }
.plantilla-herramienta { width: 28px; height: 26px; display: inline-grid; place-items: center; border: 0; border-radius: 5px; background: none; color: var(--muted); cursor: pointer; }
.plantilla-herramienta.ancha { width: auto; display: inline-flex; gap: 4px; padding: 0 8px; font: inherit; font-size: 12px; }
.plantilla-herramienta:hover:not(:disabled) { background: var(--panel); color: var(--text); }
.plantilla-herramientas-sep { width: 1px; height: 18px; background: var(--border-strong); margin: 0 4px; }
.plantilla-herramientas-nota { margin-left: auto; color: var(--muted); font-size: 11.5px; padding-right: 6px; }
.plantilla-cuerpo-texto { min-height: 10rem; line-height: 1.55; font-family: inherit; resize: vertical; }
.plantilla-var { display: inline-block; padding: 0 5px; border-radius: 4px; background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--accent); font-family: ui-monospace, Menlo, monospace; font-size: 12px; }

/* WhatsApp: header options, {{n}} mapping, buttons and the rules */
.plantilla-wa-contenido { display: grid; gap: 14px; }
.plantilla-opciones { display: flex; flex-wrap: wrap; gap: 8px; }
.plantilla-opcion { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border: 1px solid var(--border-strong); border-radius: 8px; background: var(--bg); color: var(--text); font: inherit; font-size: 12.5px; cursor: pointer; }
.plantilla-opcion.activo { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.plantilla-archivo { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 11px; border: 1px solid var(--border-strong); border-radius: 8px; background: var(--bg); }
.plantilla-archivo input[type="file"] { margin-left: auto; font-size: 12px; max-width: 100%; }
.plantilla-ejemplos { display: grid; grid-template-columns: 52px minmax(0, 1fr) minmax(0, 1fr); gap: 8px 10px; align-items: center; }
.plantilla-ejemplos-th { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.plantilla-ejemplos input.campo-error { border-color: var(--danger); }
.plantilla-boton-fila { display: grid; grid-template-columns: 150px 1fr 1fr 28px; gap: 8px; align-items: center; margin-bottom: 8px; }
.plantilla-reglas { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; font-size: 12.5px; }
.plantilla-reglas li { display: flex; align-items: flex-start; gap: 8px; }
.plantilla-reglas li .mdi { font-size: 16px; }
.plantilla-reglas li.tono-ok .mdi { color: var(--ok); }
.plantilla-reglas li.tono-warn .mdi { color: var(--warn); }
.plantilla-reglas li.tono-err .mdi { color: var(--danger); }

/* The preview column: the mail (light, like a mail client) or the phone */
.plantilla-previa { background: var(--bg); border-left: 1px solid var(--border); padding: 16px; display: flex; flex-direction: column; gap: 10px; min-width: 0; overflow-y: auto; }
.plantilla-previa-cabecera { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 8px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.plantilla-previa-cabecera .notif-preview-seg button { text-transform: none; letter-spacing: 0; }
.plantilla-previa-asunto { display: flex; gap: 6px; font-size: 12.5px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); overflow-wrap: anywhere; }
.plantilla-previa-asunto b { color: var(--muted); font-weight: 500; }
.plantilla-previa-variables { margin: 0; padding: 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); white-space: pre-wrap; overflow-wrap: anywhere; font-family: inherit; font-size: 13px; line-height: 1.55; }
.plantilla-previa .notif-preview-bg { border-radius: 8px; }
.plantilla-telefono { background: #0b141a; border-radius: 18px; border: 1px solid #222d34; padding: 12px; }
.plantilla-telefono-barra { display: flex; align-items: center; gap: 10px; padding: 2px 4px 10px; border-bottom: 1px solid #1d2a31; margin-bottom: 12px; color: #e9edef; }
.plantilla-telefono-barra small { display: block; color: #8696a0; font-size: 11px; }
.plantilla-telefono-avatar { width: 30px; height: 30px; border-radius: 50%; background: var(--brand, #017fc3); display: grid; place-items: center; color: #fff; flex: none; }
.wa-variable { color: #53bdeb; }
.wa-pie { padding: 0 10px 4px; color: #8696a0; font-size: 12px; }
.wa-botones .mdi { font-size: 14px; }

/* «Ver»: the read-only card */
.plantilla-ficha { display: grid; grid-template-columns: 140px minmax(0, 1fr); gap: 9px 14px; margin: 0; font-size: 12.5px; }
.plantilla-ficha dt { color: var(--muted); }
.plantilla-ficha dd { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0; overflow-wrap: anywhere; }
.plantilla-ficha .plantilla-ficha-sep { grid-column: 1 / -1; border-top: 1px solid var(--border); margin: 2px 0; }

/* Small dialogs: Eliminar and «Nueva versión» */
.modal.plantilla-dialogo { max-width: 520px; overflow: hidden; }
.modal.plantilla-dialogo.ancho { max-width: 760px; }
.plantilla-dialogo .body p { margin: 0; }
.plantilla-eleccion { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.plantilla-eleccion-opcion { display: grid; gap: 6px; text-align: left; padding: 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg); color: var(--text); font: inherit; cursor: pointer; }
.plantilla-eleccion-opcion.recomendada, .plantilla-eleccion-opcion.activo { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }

@media (max-width: 1000px) {
  .plantilla-modal-rejilla { grid-template-columns: 1fr; overflow-y: auto; }
  .plantilla-modal-form { overflow: visible; }
  .plantilla-previa { border-left: 0; border-top: 1px solid var(--border); overflow: visible; }
}
@media (max-width: 700px) {
  .plantilla-modal-form { padding: 12px; }
  .plantilla-tipos, .plantilla-campos-tres, .plantilla-eleccion { grid-template-columns: 1fr; }
  .plantilla-boton-fila { grid-template-columns: 1fr 1fr; }
  .plantilla-ejemplos { grid-template-columns: 44px minmax(0, 1fr); }
  .plantilla-ejemplos > input { grid-column: 2; }
  .plantilla-ficha { grid-template-columns: 1fr; gap: 2px; }
  .plantilla-ficha dd { margin-bottom: 8px; }
  .plantillas-encabezado > .btn { width: 100%; justify-content: center; margin-left: 0; }
  /* The table turns into blocks, each cell with its label */
  .tabla-plantillas, .tabla-plantillas tbody, .tabla-plantillas tr, .tabla-plantillas td { display: block; }
  .tabla-plantillas { min-width: 0; }
  .tabla-plantillas thead { display: none; }
  .tabla-plantillas tr { position: relative; margin-bottom: 8px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); }
  .tabla-plantillas tr.fila-relleno { display: none; }
  .tabla-plantillas td { border: 0; padding: 4px 0; }
  .tabla-plantillas td[data-l]::before { content: attr(data-l); display: block; margin-bottom: 2px; font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
  .tabla-plantillas .col-acciones, .tabla-plantillas .col-activa { width: auto; text-align: left; }
  .tabla-plantillas td.col-activa { position: absolute; top: 10px; right: 12px; padding: 0; }
  .tabla-plantillas td.col-activa::before { display: none; }
}

/* ---------- Metadata de las notificaciones: selector de variables, Campana / Push e histórico por evento ---------- */
.variables-selector { display: grid; gap: 8px; margin: 6px 0 8px; padding: 10px 12px; border: 1px dashed var(--border); border-radius: 10px; background: var(--panel2, var(--bg)); }
.variables-selector-cabecera { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; }
.variables-selector-buscar { flex: 0 1 240px; }
.variables-selector-grupos { display: grid; gap: 8px; max-height: 260px; overflow-y: auto; }
.variables-grupo { display: grid; gap: 2px; }
.variables-grupo-titulo { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.variables-grupo .plantilla-variables { margin: 2px 0 0; }
.plantilla-vchip.no-disponible, .plantilla-vchip-formatos.no-disponible { opacity: 0.45; cursor: not-allowed; }
.plantilla-vchip.secreta .mdi { color: var(--warn, #c58a1a); }
.plantilla-vchip-formatos { display: inline-flex; align-items: stretch; border: 1px solid var(--border-strong); border-radius: 6px; overflow: hidden; font-size: 12px; }
.plantilla-vchip-nombre { display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px; }
.plantilla-vchip-nombre .mono { color: var(--accent); font-size: 11px; }
.plantilla-vchip-nombre .mdi { font-size: 14px; color: var(--muted); }
.plantilla-vchip-formato { padding: 3px 8px; border: 0; border-left: 1px solid var(--border-strong); background: transparent; color: var(--accent); font: inherit; font-size: 11px; cursor: pointer; }
.plantilla-vchip-formato:hover:not(:disabled) { background: var(--accent-soft); }
.plantilla-vchip-formatos.no-disponible .plantilla-vchip-formato { cursor: not-allowed; }
.plantilla-mapeo-dato { display: flex; align-items: center; gap: 6px; min-width: 0; }
.plantilla-mapeo-dato > select { flex: 1; min-width: 0; }
.plantilla-mapeo-dato > .mdi { color: var(--warn, #c58a1a); }
.texto-previa { display: grid; align-content: start; gap: 10px; }
.texto-previa-quien { justify-self: start; }
.texto-previa-crudo { display: grid; gap: 6px; padding: 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg); white-space: pre-wrap; overflow-wrap: anywhere; }
.texto-previa-contadores { display: flex; gap: 14px; margin: 0; font-size: 12px; color: var(--muted); }
.telefono-previa { padding: 12px; border-radius: 14px; background: #0e1013; }
.telefono-aviso { display: grid; gap: 2px; padding: 10px 12px; border-radius: 12px; background: #2a2d33; color: #e6e8ec; overflow-wrap: anywhere; }
.telefono-aviso-app { display: flex; align-items: center; gap: 6px; font-size: 11px; color: #8a92a3; }
.telefono-aviso-titulo { font-weight: 700; }
.telefono-aviso-texto { font-size: 13px; white-space: pre-line; }
.campana-previa { display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: 10px; padding: 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); overflow-wrap: anywhere; }
.campana-previa-icono { width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; background: var(--accent-soft); color: var(--accent); }
.tabla-variables-grupo td { padding-top: 12px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.historico-filtros-datos { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 10px; padding: 8px 10px; border: 1px dashed var(--border); border-radius: 10px; }
.historico-filtros-datos-titulo { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.historico-filtros-datos .historico-filtro.activo { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.historico-entregas { display: flex; flex-wrap: wrap; gap: 4px; }
.historico-entregas .chip-estado-correo { white-space: nowrap; }
.evento-cuerpo { display: grid; gap: 14px; }
.evento-cabecera { display: flex; flex-wrap: wrap; gap: 18px; align-items: center; }
.evento-dato { display: grid; gap: 2px; }
.evento-dato > span:first-child { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.evento-meta-grupos { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 10px; }
.evento-meta-grupo { padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel2, var(--bg)); }
.evento-meta-grupo h4 { margin: 0 0 6px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.evento-meta-fila { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 10px; padding: 4px 0; border-top: 1px solid var(--border); font-size: 13px; }
.evento-meta-fila:first-of-type { border-top: 0; }
.evento-meta-valor { overflow-wrap: anywhere; }
.evento-matriz td { vertical-align: top; }
.evento-persona { max-width: 320px; }
.evento-contenidos { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.evento-contenido { display: grid; align-content: start; gap: 8px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel2, var(--bg)); }
.evento-contenido-cabecera { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 6px; font-size: 12px; }
.evento-correo { display: grid; gap: 6px; }
@media (max-width: 760px) {
  .evento-contenidos { grid-template-columns: 1fr; }
  .evento-meta-fila { grid-template-columns: 120px minmax(0, 1fr); }
  .variables-selector-buscar { flex: 1 1 100%; }
}

/* «Mes de pago» de un registro de gestión (21-10-2026): el resumen y sus botones en una línea, y la
   rejilla de la celda «Pago» debajo, dentro del modal. La columna de la tabla no se parte: un mes
   cortado en dos líneas hacía la fila más alta que sus vecinas. */
.campo-mes-pago-gestion .mes-pago-gestion-linea { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.tabla-gestion td.col-mes-pago,
.tabla-gestion th.col-mes-pago { white-space: nowrap; }

/* Notificaciones → Equipos: the team matrix (it was the «Por equipo» tab, 22-10-2026) */
.equipo-notificaciones { display: grid; gap: 14px; }
.equipo-notificaciones-cabecera { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.equipo-selector { display: inline-flex; align-items: center; gap: 6px; }
.equipo-selector .mdi { color: var(--muted); font-size: 18px; }
.equipo-selector select { min-width: 240px; }
.equipo-miembros { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); }
.equipo-avatares { display: inline-flex; align-items: center; }
.equipo-avatar { display: inline-flex; border-radius: 50%; box-shadow: 0 0 0 2px var(--panel); margin-left: -6px; }
.equipo-avatar:first-child { margin-left: 0; }
.equipo-avatar-mas { width: 24px; height: 24px; align-items: center; justify-content: center; font-size: 10px; font-weight: 700; background: var(--accent-soft); color: var(--accent); }
.matriz-equipo thead .hint { font-weight: normal; }
.matriz-equipo-columna { display: inline-grid; justify-items: center; gap: 6px; }
.matriz-equipo-columna .mdi { margin-right: 0.25rem; }
.matriz-equipo .interruptor-mixto { background: color-mix(in srgb, var(--accent) 45%, var(--border)); }
.matriz-equipo .matriz-tipo-texto .hint { font-size: 11.5px; }
/* The kind's name and description wrap: on one line they pushed the channel columns (and their
   switches) out of sight to the right, and the inherited header style shouted them in capitals */
.matriz-equipo tbody th { text-transform: none; letter-spacing: normal; white-space: normal; font-size: 0.8rem; color: var(--text); min-width: 260px; }
.matriz-equipo .matriz-tipo { display: flex; align-items: flex-start; gap: 10px; }
.matriz-equipo .matriz-tipo-texto { display: grid; gap: 2px; white-space: normal; }
.matriz-equipo .matriz-tipo-texto b { text-transform: none; letter-spacing: normal; font-weight: 600; }
.matriz-equipo .matriz-tipo-texto .hint { white-space: normal; max-width: 560px; line-height: 1.35; text-transform: none; letter-spacing: normal; }
.matriz-equipo thead th:first-child { width: auto; }
.matriz-equipo .matriz-canal { width: 6.5rem; white-space: nowrap; }
.celda-motivo-equipo-matriz { display: inline-grid; justify-items: center; gap: 3px; }
.celda-motivo-equipo-matriz .hint, .celda-motivo-equipo { font-size: 10.5px; max-width: 130px; line-height: 1.25; text-align: center; }
.celda-motivo-equipo { display: block; margin: 3px auto 0; }
.matriz-equipo-error { color: var(--danger); font-size: 11px; }
.equipo-notificaciones-pie { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 10px; }
.equipo-notificaciones-acciones { display: inline-flex; gap: 8px; }
.equipo-enlaces-whatsapp { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg); }
.equipo-enlaces-whatsapp > .mdi { font-size: 20px; color: var(--accent); }
.equipo-enlaces-whatsapp.apagado > .mdi { color: var(--warn); }
.equipo-enlaces-whatsapp-texto { display: grid; gap: 2px; flex: 1; min-width: 0; font-size: 0.82rem; }
.equipo-enlaces-whatsapp-texto .hint { white-space: normal; line-height: 1.35; }
/* «Mis notificaciones»: why some options are missing (the account's team switched them off) */
.aviso-equipo-notificaciones { display: flex; align-items: center; gap: 8px; margin: 0 0 12px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg); color: var(--muted); font-size: 12.5px; }
.aviso-equipo-notificaciones .mdi { font-size: 16px; }

/* ===== JIRA (22-10-2026): «Estado Jira», «Asignado Jira» y «Ver Jira» (modules/jira) ===== */
.menu-tipos.menu-estado-jira { width: 220px; max-height: min(340px, 55vh) !important; overflow-y: auto; overscroll-behavior: contain; }
.menu-tipos.menu-asignado-jira { width: 300px; max-height: min(380px, 60vh) !important; overflow-y: auto; overscroll-behavior: contain; }
.menu-asignado-jira input[type="search"] { width: 100%; box-sizing: border-box; margin-bottom: 4px; }
.menu-asignado-jira .chip-persona { --c: var(--muted); text-align: left; }
.jira-menu-nota { padding: 2px 4px; margin: 0; }
.jira-menu-error { margin: 0; padding: 4px 6px; font-size: 12px; color: var(--danger, #c9372c); }
.jira-menu-error a { color: inherit; text-decoration: underline; }
.jira-transicion-campos { display: flex; flex-direction: column; gap: 2px; }
.jira-transicion-campos a { font-size: 11px; padding: 0 4px; }
.chip-tipo.chip-apagado { opacity: 0.55; cursor: not-allowed; }
.jira-ver-cuerpo { display: flex; flex-direction: column; gap: 10px; min-height: 0; }
/* «Ver Jira» while Jira asks to wait: the stored copy, its countdown and why nothing can be changed */
.jira-ver-pausa { display: flex; flex-direction: column; gap: 4px; }
.jira-ver-pausa p { margin: 0; }
.jira-ver-pausa .hint { color: inherit; opacity: .85; }
.jira-no-disponible { margin: 0 0 8px; }
.jira-texto { white-space: pre-wrap; word-break: break-word; font: inherit; margin: 0; }
.jira-enlaces { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 12px; }
.jira-datos { display: grid; grid-template-columns: max-content 1fr; gap: 6px 14px; margin: 0; }
.jira-datos dt { color: var(--muted); font-size: 12px; }
.jira-datos dd { margin: 0; }
.jira-adjuntos ul { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
/* «Ver Jira» (23-10-2026): attachments that download, with a thumbnail for the images, and the images of a text */
.jira-adjuntos-lista { gap: 6px !important; }
.jira-adjunto { display: flex; align-items: center; gap: 8px; min-width: 0; }
.jira-adjunto-datos { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.jira-adjunto-datos > a, .jira-adjunto-datos > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jira-adjunto-miniatura { flex: none; width: 56px; display: flex; justify-content: center; }
.jira-adjunto-miniatura .dv-rt-imagen { margin: 0; }
.jira-adjunto-miniatura .dv-rt-imagen img { max-width: 56px; max-height: 56px; object-fit: cover; }
.jira-adjunto-miniatura .dv-rt-imagen-cargando, .jira-adjunto-miniatura .jira-imagen-sin { font-size: 0; }
.jira-adjunto-miniatura .dv-rt-imagen-cargando i, .jira-adjunto-miniatura .jira-imagen-sin i { font-size: 20px; }
.jira-adjunto-miniatura .jira-imagen-sin button, .jira-adjunto-miniatura .jira-imagen-sin small { display: none; }
.jira-adjunto-jira { flex: none; }
.jira-adjuntos-pausa { margin: 4px 0; }
.jira-texto .jira-imagen .dv-rt-imagen img { max-width: min(100%, 480px); }
.jira-icono-caja { display: inline-flex; align-items: center; vertical-align: -3px; margin: 0 3px 0 1px; }
.jira-icono { display: inline-block; width: 16px; height: 16px; object-fit: contain; }
.jira-icono-hueco { color: var(--muted); font-size: 14px; line-height: 16px; text-align: center; }
.jira-icono-texto { color: var(--muted); }
.jira-archivo-chip { display: inline-flex; align-items: center; gap: 4px; max-width: 100%; padding: 1px 8px; margin: 2px 0; border: 1px dashed var(--border); border-radius: 6px; background: transparent; color: var(--accent); font: inherit; cursor: pointer; }
.jira-archivo-chip:hover, .jira-archivo-chip:focus-visible { border-style: solid; background: var(--accent-soft); }
.jira-imagen-sin { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 2px 8px; border: 1px dashed var(--border); border-radius: 6px; color: var(--muted); }
/* «Adjuntar en Jira» and «Versiones» of «Ver Jira» (23-10-2026) */
.jira-adjuntar { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }
/* «adjuntado»: un archivo que un envío cortado a medias ya dejó en Jira */
.devops-explorer-row .hint.ok { color: var(--ok, #2e7d32); white-space: nowrap; }
.jira-versiones { display: flex; flex-direction: column; gap: 10px; min-height: 0; }
.jira-versiones-barra { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.jira-versiones-barra input[type="search"] { flex: 1 1 220px; max-width: 360px; }
.jira-version-cambios { list-style: none; margin: 4px 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.jira-origen { font-size: 11px; padding: 0 6px; margin-right: 4px; }
.jira-origen.app { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.jira-version-comentario { margin: 4px 0 0 0; padding: 4px 8px; border-left: 3px solid var(--border); white-space: pre-wrap; overflow-wrap: anywhere; }
.jira-version-diff { display: grid; grid-template-columns: max-content 1fr; gap: 4px 10px; margin: 6px 0 0; }
.jira-version-diff dt { font-weight: 600; }
.jira-version-diff dd { margin: 0; overflow-wrap: anywhere; white-space: pre-wrap; }
.jira-descripcion-cabecera { display: flex; align-items: center; margin-bottom: 6px; }
.jira-conflicto { margin-bottom: 8px; }
.jira-conflicto .jira-texto { margin-top: 6px; max-height: 220px; overflow: auto; }
.jira-cambios { list-style: none; margin: 4px 0 0; padding: 0; font-size: 12px; }
.jira-cambios li { display: flex; flex-wrap: wrap; gap: 4px; align-items: baseline; }
.jira-campo { font-weight: 600; }
.jira-de { color: var(--muted); text-decoration: line-through; }
.jira-actividad-item.fallida { border-left: 3px solid var(--warn, #e2b203); padding-left: 6px; }

/* ---------------------------------------------------------------- mobile app download
   (modules/mobileApp, boceto docs/propuestas/descarga-app/, variant A) */
/* «¡Llévala en tu celular!»: a yellow pill left of the bell; «NUEVO» and a soft pulse until the account downloads it */
.app-movil-cta {
  position: relative; display: inline-flex; align-items: center; gap: 8px; height: 34px; padding: 0 14px 0 6px;
  border: 1px solid #f2c230; border-radius: 999px; background: #ffd34d; color: #0b2a3f;
  font-size: 13px; font-weight: 600; white-space: nowrap; cursor: pointer;
}
.app-movil-cta:hover, .app-movil-cta:focus-visible { background: #ffdb6b; outline: none; box-shadow: 0 0 0 3px rgba(255, 211, 77, 0.35); }
.app-movil-cta-icono { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; background: #0b2a3f; color: #ffd34d; font-size: 15px; flex: none; }
.app-movil-cta-nuevo {
  position: absolute; top: -8px; right: -6px; padding: 1px 6px; border-radius: 999px;
  background: #e5534b; color: #fff; font-size: 10px; font-weight: 700; letter-spacing: 0.03em; line-height: 1.4;
}
.app-movil-cta.nuevo { animation: app-movil-pulso 2.2s infinite; }
/* A new version not clicked yet: the phone also shakes now and then */
.app-movil-cta.nuevo .app-movil-cta-icono { animation: app-movil-sacudida 4.4s ease-in-out infinite; }
@keyframes app-movil-sacudida {
  0%, 82%, 100% { transform: rotate(0); }
  85% { transform: rotate(-14deg); }
  88% { transform: rotate(12deg); }
  91% { transform: rotate(-9deg); }
  94% { transform: rotate(6deg); }
  97% { transform: rotate(-3deg); }
}
/* Already downloaded: the same button, quieter */
.app-movil-cta:not(.nuevo) { background: transparent; color: inherit; border-color: #f2c230; }
.app-movil-cta:not(.nuevo):hover { background: rgba(255, 211, 77, 0.16); }
@keyframes app-movil-pulso {
  0% { box-shadow: 0 0 0 0 rgba(255, 211, 77, 0.55); }
  70% { box-shadow: 0 0 0 10px rgba(255, 211, 77, 0); }
  100% { box-shadow: 0 0 0 0 rgba(255, 211, 77, 0); }
}
@media (prefers-reduced-motion: reduce) { .app-movil-cta.nuevo, .app-movil-cta.nuevo .app-movil-cta-icono { animation: none; } }
/* A narrow screen keeps only the icon (and «NUEVO») */
@media (max-width: 760px) {
  .app-movil-cta { padding: 0 5px; }
  .app-movil-cta-texto { display: none; }
}

/* ---------------------------------------------------------------- usuarios en línea
   (modules/users/OnlineUsersButton.js): «● 7 en línea» right of «¡Llévala en tu celular!», only
   with its permission. A quiet pill that follows the bar (white on the solid blue one, by the
   `.topbar > div > button` rule); the dot is the theme's «ok» green, with a ring to separate it
   from the blue. */
.en-linea-boton {
  display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 12px 0 10px;
  border: 1px solid var(--border-strong); border-radius: 999px; background: transparent; color: inherit;
  font: inherit; font-size: 13px; font-weight: 600; white-space: nowrap; cursor: pointer;
}
.en-linea-boton:hover, .en-linea-boton.abierto { background: var(--accent-soft); }
.en-linea-boton:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.en-linea-punto { width: 9px; height: 9px; border-radius: 50%; background: var(--ok); box-shadow: 0 0 0 2px color-mix(in srgb, var(--ok) 25%, transparent); flex: none; }
.en-linea-boton.vacio .en-linea-punto { background: var(--muted); box-shadow: none; }
body[data-bar="solid"] .en-linea-punto { background: #4ade80; box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.85); }
body[data-bar="solid"] .en-linea-boton.vacio .en-linea-punto { background: rgba(255, 255, 255, 0.6); }
.en-linea-texto { font-weight: 500; }
.en-linea-menu { width: 380px; max-width: calc(100vw - 24px); padding: 0; color: var(--text); overflow: hidden; }
.en-linea-cabecera { display: flex; align-items: baseline; gap: 8px; padding: 12px 14px 8px; }
.en-linea-cabecera > b { font-size: 14px; }
.en-linea-resumen { margin-left: auto; font-size: 12px; color: var(--muted); }
.en-linea-buscar { display: flex; align-items: center; gap: 6px; margin: 0 12px 8px; padding: 0 8px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); }
.en-linea-buscar:focus-within { border-color: var(--accent); }
.en-linea-buscar .mdi { color: var(--muted); }
.en-linea-buscar input { flex: 1; min-width: 0; height: 32px; border: 0; background: transparent; color: var(--text); font: inherit; font-size: 13px; outline: none; }
.en-linea-fallo { margin: 0 12px 8px; padding: 6px 8px; border-radius: var(--radius); background: var(--warn-bg); color: var(--warn); font-size: 12px; }
.en-linea-lista { max-height: min(60vh, 460px); overflow-y: auto; overscroll-behavior: contain; padding-bottom: 6px; }
.en-linea-vacio { margin: 0; padding: 16px 14px; color: var(--muted); font-size: 13px; text-align: center; }
.en-linea-grupo ul { list-style: none; margin: 0; padding: 0; }
.en-linea-grupo-titulo { margin: 0; padding: 8px 14px 4px; font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
.en-linea-grupo-titulo span { font-weight: 500; }
.en-linea-fila { display: flex; align-items: center; gap: 10px; padding: 6px 14px; }
.en-linea-fila:hover { background: var(--neutral-bg); }
.en-linea-avatar { position: relative; display: inline-flex; flex: none; }
.en-linea-avatar-punto { position: absolute; right: -1px; bottom: -1px; width: 10px; height: 10px; border-radius: 50%; background: var(--ok); box-shadow: 0 0 0 2px var(--panel); }
.en-linea-quien { display: grid; min-width: 0; flex: 1; }
.en-linea-nombre { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.en-linea-correo { font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.en-linea-estado { flex: none; font-size: 12px; color: var(--muted); white-space: nowrap; border-radius: 4px; }
.en-linea-estado.activo { color: var(--ok-texto); font-weight: 600; }
.en-linea-estado:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* The channel (web / app / both): icons and a short text next to «En línea», the channel of the last
   connection next to its time. Icons inherit the status colour (green when online), and the text and
   the tooltip say it too: never colour alone. */
.en-linea-estado { display: inline-flex; align-items: center; gap: 4px; }
.en-linea-canal { display: inline-flex; gap: 1px; font-size: 14px; line-height: 1; }
.en-linea-canal .mdi { line-height: 1; }
.en-linea-canal-texto { font-weight: 500; }
/* The panel is narrow and clips what overflows: its tooltips wrap instead of running off the left */
.en-linea-estado.con-tooltip::after { white-space: normal; width: max-content; max-width: min(240px, 60vw); text-align: left; }
.en-linea-canales-resumen { margin: -4px 14px 8px; font-size: 12px; color: var(--muted); }
.en-linea-filtros { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 12px 8px; }
.en-linea-filtros .chip { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
.en-linea-filtros .chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* A narrow screen keeps the dot and the number, like the yellow button keeps only its icon */
@media (max-width: 760px) {
  .en-linea-boton { padding: 0 9px; }
  .en-linea-texto { display: none; }
}
/* On a phone the menu is pinned under the top bar with the 12px gutters, like the bell's */
@media (max-width: 600px) {
  .en-linea .en-linea-menu {
    position: fixed; top: var(--menu-top, 64px); left: 12px; right: 12px; width: auto; max-width: none;
    max-height: calc(100dvh - var(--menu-top, 64px) - 12px); overflow-y: auto; overscroll-behavior: contain;
  }
  .en-linea .en-linea-lista { max-height: none; }
  /* Only the icons on a phone: the name column keeps its room */
  .en-linea-canal-texto { display: none; }
}

/* «Descarga la app»: the pitch on the left, the QR on the right */
.modal.descarga-app-modal { max-width: 760px; }
.descarga-app-cabecera .mdi { margin-right: 4px; }
.modal .body.descarga-app-cuerpo { display: grid; grid-template-columns: minmax(0, 1fr) 250px; gap: 24px; padding: 20px; }
.descarga-app-texto .hint { margin: 0; }
.descarga-app-gancho { margin: 0 0 6px; font-size: 20px; font-weight: 700; line-height: 1.25; }
.descarga-app-gancho em { font-style: normal; color: var(--accent); }
.descarga-app-beneficios { list-style: none; padding: 0; margin: 14px 0; display: grid; gap: 10px; }
.descarga-app-beneficios li { display: flex; gap: 10px; align-items: flex-start; }
.descarga-app-beneficios .mdi { color: var(--accent); font-size: 20px; line-height: 1.2; }
.descarga-app-pasos { list-style: none; padding: 0; margin: 8px 0 0; display: grid; gap: 6px; }
.descarga-app-pasos li { display: flex; gap: 8px; align-items: center; font-size: 13px; color: var(--muted); }
.descarga-app-num { width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; flex: none; background: var(--neutral-bg); color: var(--text); font-size: 11px; font-weight: 700; }
.descarga-app-qr-caja { align-self: start; display: grid; gap: 10px; justify-items: center; text-align: center; padding: 14px; border: 1px solid var(--border); border-radius: 12px; background: var(--bg); }
.descarga-app-qr { position: relative; width: 210px; min-height: 210px; display: grid; place-items: center; padding: 10px; border-radius: 10px; background: #fff; overflow: hidden; }
.descarga-app-qr.cargando { background: var(--panel); }
.descarga-app-svg, .descarga-app-svg svg { display: block; width: 190px; height: 190px; transition: filter 0.2s, opacity 0.2s; }
/* Expired or downloaded (as WhatsApp Web): the QR blurred and dimmed behind the cover */
.descarga-app-qr.tapado .descarga-app-svg { filter: blur(3px) grayscale(1); opacity: 0.35; }
.descarga-app-tapa { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 128px; height: 128px; border: 0; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 14px;
  background: rgba(17, 27, 33, 0.88); color: #fff; font: inherit; font-size: 12px; line-height: 1.3; text-align: center; cursor: pointer; }
.descarga-app-tapa .mdi { font-size: 30px; line-height: 1; }
.descarga-app-tapa:hover:not(:disabled), .descarga-app-tapa:focus-visible { background: rgba(17, 27, 33, 0.96); outline: none; box-shadow: 0 0 0 3px var(--accent-soft); }
.descarga-app-tapa:disabled { cursor: progress; }
.descarga-app-tapa.listo { width: 96px; height: 96px; background: #1a7f45; cursor: default; }
.descarga-app-tapa.listo .mdi { font-size: 52px; }
.descarga-app-version, .descarga-app-vence, .descarga-app-escaneado { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--muted); }
.descarga-app-version .mdi-android { color: #3ddc84; }
.descarga-app-vence b { color: var(--text); font-variant-numeric: tabular-nums; }
.descarga-app-escaneado { font-size: 13px; font-weight: 600; color: var(--text); }
.descarga-app-escaneado .mdi { color: var(--accent); }
.descarga-app-otro { border: 0; padding: 0; background: none; font: inherit; font-size: 12px; color: var(--accent); text-decoration: underline; cursor: pointer; }
.descarga-app-otro:disabled { color: var(--muted); cursor: progress; }
.descarga-app-descargada { font-size: 13px; font-weight: 600; color: #1a7f45; }
.descarga-app-error { display: flex; gap: 8px; align-items: flex-start; text-align: left; font-size: 13px; color: var(--danger); }
.descarga-app-error .mdi { font-size: 18px; line-height: 1.2; }
.modal footer.descarga-app-pie { justify-content: space-between; align-items: center; }
.descarga-app-pie .hint { display: inline-flex; align-items: center; gap: 5px; }
@media (max-width: 760px) { .modal .body.descarga-app-cuerpo { grid-template-columns: minmax(0, 1fr); } }

/* Parametrización → App móvil: a version brought from Google Play has no file, its size cell says so */
.chip-dato.app-movil-play-chip .mdi { color: #3ddc84; }
/* The Google Play notice: the line that says the service account is missing */
.app-movil-play-falta { display: block; margin-top: 4px; font-weight: 600; }

/* App móvil → «Ver descargas» of a version (it was Históricos → Descargas de la app) */
.modal.descargas-app-modal { max-width: 1040px; }
.descargas-app-cifra { border: 0; padding: 0; background: none; font: inherit; color: var(--accent); text-decoration: underline; cursor: pointer; font-variant-numeric: tabular-nums; }
.app-movil-play { display: flex; align-items: flex-start; gap: 8px; margin: 0 0 12px; font-size: 13px; line-height: 1.5; }
.app-movil-play .mdi { font-size: 18px; line-height: 1.2; }
.app-movil-play a { color: inherit; font-weight: 600; }
.descargas-app-escaneo { display: block; font-size: 12px; }
.descargas-app-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin: 12px 0 0; }
.descargas-app-kpi { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); }
.descargas-app-kpi b { font-size: 20px; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.descargas-app-kpi span { font-size: 12px; color: var(--muted); }
.descargas-app-estado { white-space: nowrap; }
.chip-estado-correo.warn { color: var(--warn); background: var(--warn-bg); }
@media (max-width: 760px) { .descargas-app-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* «Actualizar Jira» / «Actualizar DevOps»: the app's preload (index.html) over Documentos' screen
   only, not the whole window — the other tools stay at hand while the update runs on the server */
.layout-ancho .cuerpo-docs > .pantalla-docs { position: relative; }
.app-preload.app-preload-panel {
  position: absolute; inset: 0; z-index: 25;
  border-radius: 12px; min-height: 260px;
}
.app-preload.app-preload-panel .app-preload-logo { height: 48px; }

/* «Actualizar Jira»: the period is chosen in a small panel under the button, before launching */
.menu-periodo > .menu-acciones.menu-periodo-panel { left: 0; right: auto; min-width: 240px; padding: 8px 0; }
.menu-periodo-titulo { margin: 0; padding: 2px 14px 6px; font-size: 12px; font-weight: 600; color: var(--muted); }
.menu-periodo-panel .menu-acciones-item { height: 32px; cursor: pointer; }
.menu-periodo-panel .menu-acciones-item input { margin: 0; }
.menu-periodo-fecha { display: flex; flex-direction: column; gap: 4px; padding: 4px 14px 2px 38px; }
.menu-periodo-aviso { margin: 4px 14px 0; }
.menu-periodo-acciones { display: flex; justify-content: flex-end; padding: 8px 14px 2px; }
/* «Actualizar Jira» / «Actualizar DevOps» as items of «Herramientas»: Jira's period unfolds in place */
.menu-periodo-item { display: flex; flex-direction: column; }
.menu-periodo-item > .menu-acciones-item.abierto { color: var(--accent); }
.menu-periodo-item > .menu-acciones-item > .mdi:last-child:not(:first-child) { margin-left: auto; }
.menu-periodo-item > .menu-acciones.menu-periodo-panel {
  position: static; min-width: 0; padding: 4px 0 8px; border: 0; border-radius: 0;
  border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); box-shadow: none; background: var(--bg-soft, transparent);
}
.menu-acciones-separador { height: 1px; margin: 4px 0; background: var(--border); }

/* ── «COMPARAR» EN EL VISOR (modules/docViewer/CompareView.js) ───────────────────────────
   The viewer's area in two columns, the explorer folded: its own header (ticket · Comparar,
   swap, back), a selector per side and the divider of «Ver DevOps» → «Comparar» (`.dv-split-divider`).
   Under 900 px the columns stack, each with its own scroll. */
.visor-comparar { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; overflow: hidden; }
.visor-comparar-cabecera { flex: none; }
.visor-comparar-titulo { display: inline-flex; align-items: center; gap: 6px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.visor-comparar-cuerpo { display: flex; flex: 1 1 auto; min-height: 0; overflow: hidden; border-top: 1px solid var(--border); }
.visor-comparar-lado { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.visor-comparar-left { flex: 0 0 50%; }
.visor-comparar-right { flex: 1 1 0; }
.visor-comparar-lado-cabecera { flex: none; display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--border); background: var(--panel); }
.visor-comparar-lado-cuerpo { flex: 1 1 auto; min-height: 0; overflow: auto; overscroll-behavior: contain; padding: 14px 16px; background: var(--neutral-bg); }
.visor-comparar-devops { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 14px 18px 18px; }
.visor-comparar-devops-titulo { font-size: 17px; margin: 8px 0 6px; }

/* The selector of a side: closed, what it shows; open, its groups, folders and files */
.visor-comparar-select { position: relative; flex: 1 1 auto; min-width: 0; }
.visor-comparar-select-boton {
  display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; min-width: 0;
  padding: 6px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg); color: var(--text); font-size: 13px; cursor: pointer;
}
.visor-comparar-select-boton:hover:not(:disabled) { border-color: var(--accent); }
.visor-comparar-select-boton:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.visor-comparar-select-actual { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.visor-comparar-select-texto { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.visor-comparar-principal { flex: none; font-size: 11px; color: var(--muted); }
.visor-comparar-lista {
  position: absolute; top: calc(100% + 4px); left: 0; z-index: 30; width: min(420px, 100%); min-width: 260px; max-height: 60vh; overflow-y: auto;
  padding: 6px; background: var(--panel); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 10px 30px rgba(0, 0, 0, .25); font-size: 13px;
}
.visor-comparar-grupo { padding: 8px 10px 4px; font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.visor-comparar-carpeta,
.visor-comparar-opcion { --nivel: 0; display: flex; align-items: center; gap: 8px; width: 100%; padding: 6px 10px 6px calc(10px + var(--nivel) * 18px); border-radius: 6px; }
.visor-comparar-carpeta { color: var(--muted); font-weight: 600; }
.visor-comparar-carpeta .mdi { color: var(--accent); }
.visor-comparar-opcion { border: 0; background: none; color: var(--text); text-align: left; cursor: pointer; font-size: 13px; }
.visor-comparar-opcion:hover { background: var(--accent-soft); }
.visor-comparar-opcion:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.visor-comparar-opcion.activa { background: var(--accent-soft); color: var(--accent); }
.visor-comparar-opcion .visor-comparar-principal,
.visor-comparar-marca { margin-left: auto; }
.visor-comparar-opcion .visor-comparar-principal + .visor-comparar-marca { margin-left: 4px; }
.visor-exp-icono.tipo-devops { color: var(--ok); }

/* A file filling its side: the frames and the editor take the side's height */
.documento-previa.documento-previa-llena { border: 0; border-radius: 0; background: transparent; min-height: 0; max-height: none; height: 100%; overflow: visible; }
.documento-previa-llena .visor-marco { height: 100%; min-height: 60vh; }
.documento-previa-llena .visor-hoja,
.documento-previa-llena .visor-codigo { height: 100%; min-height: 50vh; }

@media (max-width: 900px) {
  .visor-comparar-cuerpo { flex-direction: column; overflow-y: auto; }
  /* The inline width share does not apply stacked, hence `!important` */
  .visor-comparar-lado { flex: 0 0 auto !important; min-height: 70vh; }
  .visor-comparar-right { border-top: 1px solid var(--border); }
  .visor-comparar-cuerpo .dv-split-divider { display: none; }
  .visor-comparar-lista { width: 100%; min-width: 0; }
}

/* «Comenzar desarrollo» (24-10-2026, modules/devRuns): the Desarrollo column, its confirmation and
   the detail of a run. `dr-` = desarrollo/runner. The tones are the app's (ok, warn, danger, info). */
/* Three sub-columns since 02-11-2026 («Estimar» · «Desarrollo» · «QA»): narrower each than the single column was, so
   the three together do not push the table into a horizontal scroll; the longest button («Comenzar QA de nuevo») fits */
.tabla-docs th.col-desarrollo, .tabla-docs td.col-desarrollo { min-width: 128px; max-width: 180px; }
.tabla-docs th.col-desarrollo-estimacion, .tabla-docs td.col-desarrollo-estimacion { border-left: 1px solid var(--border); }
/* The reason and the dossier's summary are sentences: they wrap inside the column (the generic `th, td { nowrap }`
   left them on one line that ran under the pinned Acciones cell and out the other side), three lines at most */
.tabla-docs td.col-desarrollo { white-space: normal; }
.dr-celda { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; max-width: 180px; min-width: 0; }
/* Another kind's run holds the row: a quiet note where the button would be */
.dr-motivo--espera { color: var(--muted); font-style: italic; }
.dr-celda :is(.dr-motivo, .dr-comprobado) { max-width: 100%; overflow-wrap: anywhere; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; }
.dr-estado-boton { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; padding: 0; border: 0; background: none; color: inherit; cursor: pointer; text-align: left; }
.dr-estado-boton--fijo { cursor: default; }
.dr-estado-boton:hover .dr-estado, .dr-estado-boton:focus-visible .dr-estado { outline: 1px solid currentColor; }
.dr-estado { display: inline-flex; align-items: center; padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; white-space: nowrap; border: 1px solid transparent; }
.dr-estado--ok { color: var(--ok); background: color-mix(in srgb, var(--ok) 12%, transparent); border-color: color-mix(in srgb, var(--ok) 35%, transparent); }
.dr-estado--warn { color: var(--warn); background: var(--warn-bg); border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
.dr-estado--danger { color: var(--danger); background: var(--danger-bg); border-color: color-mix(in srgb, var(--danger) 35%, transparent); }
.dr-estado--info { color: var(--info); background: var(--info-bg); border-color: color-mix(in srgb, var(--info) 35%, transparent); }
.dr-estado--neutral { color: var(--muted); background: var(--neutral-bg); border-color: var(--border); }
.dr-estado--grande { font-size: 13px; padding: 3px 12px; }
.dr-fase { font-size: 11px; color: var(--muted); }
.dr-simulacion-mini { display: inline-flex; padding: 0 6px; border-radius: 4px; font-size: 10px; font-weight: 700; letter-spacing: .02em; text-transform: uppercase; color: var(--info); border: 1px dashed var(--info); }
.dr-boton-caja { display: inline-flex; }
/* Its tooltip is the same sentence: wrapped at a readable width, never one line across the table */
.dr-boton-caja.con-tooltip::after { white-space: normal; width: max-content; max-width: 280px; text-align: left; z-index: 6; }
.dr-comenzar { display: inline-flex; align-items: center; gap: 4px; height: 26px; padding: 0 10px; font-size: 11.5px; border-radius: 6px; border: 1px solid var(--accent); color: var(--accent); background: var(--panel); white-space: nowrap; cursor: pointer; }
.dr-comenzar:hover:not(:disabled) { background: var(--accent-soft); }
.dr-comenzar--aviso { border-color: var(--warn); color: var(--warn); }
.dr-comenzar:disabled { border-color: var(--border); color: var(--muted); background: var(--neutral-bg); cursor: not-allowed; }
/* 02-11-2026 («Comenzar QA»): the second button of the row, and the result of a QA-only run beside the state */
.dr-comenzar--qa { border-color: var(--ok, #1b7f4b); color: var(--ok, #1b7f4b); margin-top: 4px; }
.dr-comenzar--qa:hover:not(:disabled) { background: var(--ok-bg, rgba(27, 127, 75, .08)); }
.dr-qa-mini { display: inline-flex; padding: 0 6px; border-radius: 4px; font-size: 10px; font-weight: 700; letter-spacing: .02em; text-transform: uppercase; color: var(--accent); border: 1px solid var(--accent); }
.dr-qa-mini--ok { color: var(--ok, #1b7f4b); border-color: var(--ok, #1b7f4b); }
.dr-qa-mini--falla { color: var(--danger); border-color: var(--danger); }
.dr-donde-qa .dr-cuenta { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; max-width: 520px; }
.dr-donde-qa .dr-cuenta input, .dr-donde-qa input.dr-rama-origen, .dr-donde-qa select { width: 100%; max-width: 520px; }
.dr-produccion-aviso { display: flex; gap: 8px; align-items: flex-start; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--danger); color: var(--danger); background: rgba(200, 40, 40, .06); margin-top: 6px; }
.dr-produccion-aviso label { display: flex; gap: 6px; align-items: center; font-weight: 600; }
.dr-motivo { font-size: 11px; color: var(--muted); line-height: 1.3; }
.dr-comprobar { font-size: 11px; }
.dr-comprobar:disabled { opacity: .6; cursor: progress; }
.dr-comprobado { font-size: 11px; color: var(--muted); line-height: 1.3; }
.dr-cargando { display: flex; align-items: center; gap: 8px; color: var(--muted); padding: 12px 0; }
.dr-cargando-claro { color: #fff; }
.dr-simulacion-banner { display: flex; align-items: flex-start; gap: 8px; padding: 8px 12px; border-radius: var(--radius); border: 1px dashed var(--info); background: var(--info-bg); color: var(--text); font-size: 12.5px; }
.dr-simulacion-banner .mdi { color: var(--info); font-size: 18px; line-height: 1; }
.dr-real-mini { display: inline-flex; padding: 0 6px; border-radius: 4px; font-size: 10px; font-weight: 700; letter-spacing: .02em; text-transform: uppercase; color: var(--warn); border: 1px solid var(--warn); }
/* N4 (TL-8913): over the solid bar of the detail's header the tinted labels (green on blue) did not
   reach AA. There they are opaque chips with their own pair of colours per theme, each ≥ 4.5:1
   (checked by scripts/verify-dev-runs-progreso.js). */
.dr-detalle > header { --dr-chip-bg: #ffffff; --dr-chip-ok: #166534; --dr-chip-warn: #92400e; --dr-chip-danger: #991b1b; --dr-chip-info: #1e40af; --dr-chip-neutral: #374151; }
:root[data-theme="dark"]:not([data-presentacion]) .dr-detalle > header { --dr-chip-bg: #0f172a; --dr-chip-ok: #86efac; --dr-chip-warn: #fcd34d; --dr-chip-danger: #fca5a5; --dr-chip-info: #93c5fd; --dr-chip-neutral: #e5e7eb; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-presentacion]) .dr-detalle > header { --dr-chip-bg: #0f172a; --dr-chip-ok: #86efac; --dr-chip-warn: #fcd34d; --dr-chip-danger: #fca5a5; --dr-chip-info: #93c5fd; --dr-chip-neutral: #e5e7eb; }
}
.dr-detalle > header :is(.dr-estado, .dr-real-mini, .dr-simulacion-mini) { background: var(--dr-chip-bg); border: 1px solid var(--dr-chip-bg); border-style: solid; }
.dr-detalle > header .dr-estado--ok { color: var(--dr-chip-ok); }
.dr-detalle > header .dr-estado--warn, .dr-detalle > header .dr-real-mini { color: var(--dr-chip-warn); }
.dr-detalle > header .dr-estado--danger { color: var(--dr-chip-danger); }
.dr-detalle > header .dr-estado--info, .dr-detalle > header .dr-simulacion-mini { color: var(--dr-chip-info); }
.dr-detalle > header .dr-estado--neutral { color: var(--dr-chip-neutral); }
.dr-real-banner { display: flex; align-items: flex-start; gap: 8px; padding: 8px 12px; border-radius: var(--radius); border: 1px solid var(--warn); background: var(--warn-bg); color: var(--text); font-size: 12.5px; }
.dr-real-banner .mdi { color: var(--warn); font-size: 18px; line-height: 1; }
.dr-preflight { margin: 6px 0 0; padding: 0; list-style: none; font-size: 12px; }
.dr-preflight li { margin: 2px 0; overflow-wrap: anywhere; }
.dr-despliegue { display: grid; gap: 8px; }
.dr-decision { display: grid; gap: 8px; }
.dr-decision .drd-elige legend { margin-bottom: 4px; font-size: 13px; }
/* 28-10-2026: «Base de datos de Development», los .sql que el runner aplica antes de la QA en localhost */
.dr-decision .drd-bd-lista { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.dr-decision .drd-bd-lista li { display: flex; align-items: center; gap: 6px; font-size: 13px; min-width: 0; }
.dr-decision .drd-bd-lista code { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dr-decision .drd-bd-lista small { color: var(--muted); }
.dr-decision textarea { width: 100%; box-sizing: border-box; font: inherit; }
/* 02-11-2026 («Estimar»): la tarjeta del borrador de la estimación, sus horas editables y «Publicar» */
.dre-grupo { border: 1px solid var(--border); border-radius: var(--radius); padding: 8px 12px; background: var(--panel); }
.dre-grupo > summary { cursor: pointer; font-size: 13px; }
.dre-grupo > summary + * { margin-top: 8px; }
.dre-horas { table-layout: auto; }
.dre-horas .dre-h { text-align: right; white-space: nowrap; width: 90px; }
.dre-horas .dre-fase { font-weight: 600; white-space: nowrap; vertical-align: top; }
.dre-horas .dre-subtotal td { color: var(--muted); font-size: 12px; }
.dre-horas .dre-total td { background: var(--neutral-bg); }
.dre-input { width: 68px; text-align: right; font: inherit; padding: 3px 6px; }
.dre-problemas { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 4px; color: var(--warn); font-size: 12.5px; }
.dre-problemas li { display: flex; gap: 6px; align-items: flex-start; overflow-wrap: anywhere; }
.dre-hallazgos { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.dre-hallazgos li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 10px; align-items: start; font-size: 13px; }
.dre-cita { color: var(--muted); font-style: italic; overflow-wrap: anywhere; }
.dre-ruta { overflow-wrap: anywhere; }
.dre-seccion h4 { margin: 10px 0 4px; font-size: 13px; }
.dre-seccion h5 { margin: 8px 0 4px; font-size: 12.5px; color: var(--muted); }
.dre-seccion p, .dre-seccion ul { margin: 4px 0; font-size: 13px; }
.dre-motivo { display: grid; gap: 4px; font-size: 13px; }
.dre-acciones { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.drx-chip--estimacion { color: var(--accent); background: var(--accent-soft); }
.dr-comenzar--estimacion { border-color: var(--accent); color: var(--accent); margin-top: 4px; }
/* 02-11-2026 (Gerson): a run on a DevOps that is not the row's representative says which one, in the cell */
.dr-devops-mini { display: inline-flex; padding: 0 6px; border-radius: 4px; font-size: 10px; font-weight: 700; letter-spacing: .02em; color: var(--muted); border: 1px solid var(--border-strong, var(--border)); font-family: var(--mono); }
/* «¿Sobre qué DevOps?»: the selector before the confirmation when the row has several work items (DevRunDevopsPicker) */
.modal.drp { max-width: 560px; width: 96vw; }
.drp header { display: flex; align-items: center; gap: 10px; }
.drp header > span:first-child { flex: 1; }
.drp-body { display: grid; gap: 10px; }
.drp-lista { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; border: 0; min-width: 0; }
.drp-item { display: flex; align-items: flex-start; gap: 8px; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); cursor: pointer; min-width: 0; }
.drp-item input[type="radio"] { margin-top: 3px; flex: none; }
.drp-item[data-habilitado="no"] { cursor: not-allowed; color: var(--muted); background: var(--neutral-bg); }
.drp-item[data-elegido="si"] { border-color: var(--accent); box-shadow: inset 3px 0 0 var(--accent); }
.drp-cuerpo { display: grid; gap: 3px; min-width: 0; font-size: 12.5px; }
.drp-linea { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.drp-rol, .drp-representante { display: inline-flex; padding: 0 6px; border-radius: 4px; font-size: 10px; font-weight: 700; letter-spacing: .02em; text-transform: uppercase; border: 1px solid currentColor; }
.drp-rol--backend { color: var(--info); }
.drp-rol--frontend { color: var(--ok, #1b7f4b); }
.drp-representante { color: var(--muted); border-style: dashed; text-transform: none; font-weight: 600; }
.drp-titulo { overflow-wrap: anywhere; }
.drp-azure { display: flex; flex-wrap: wrap; gap: 10px; font-size: 11px; color: var(--muted); }
.drp-estado { display: inline-flex; align-items: flex-start; gap: 4px; font-size: 11px; line-height: 1.3; overflow-wrap: anywhere; }
.drp-estado--ok { color: var(--ok, #1b7f4b); }
.drp-estado--no { color: var(--danger); }
.drp footer .dr-motivo { margin-right: auto; align-self: center; }
/* 28-10-2026: «Conversar con la QA» */
.drq { display: grid; gap: 12px; }
.drq-lista { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.drq-par { display: grid; gap: 6px; }
.drq-msg { border-radius: 10px; padding: 8px 12px; max-width: 85%; min-width: 0; }
.drq-msg p { margin: 4px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.drq-msg small { color: var(--muted); }
.drq-msg--persona { justify-self: end; background: var(--neutral-bg); }
.drq-msg--qa { justify-self: start; border: 1px solid var(--border); background: var(--panel); }
.drq-msg--espera, .drq-msg--error { color: var(--muted); }
.drq-escribir { display: grid; gap: 8px; }
.drq-escribir textarea { width: 100%; box-sizing: border-box; font: inherit; }
.drq-escribir button, .drq-acciones button { justify-self: start; }
.drq-acciones { display: flex; flex-wrap: wrap; gap: 8px; }
.dr-despliegue-fila { display: grid; grid-template-columns: minmax(140px, 1fr) minmax(120px, 1fr) minmax(90px, .7fr); gap: 6px 10px; align-items: center; font-size: 12.5px; }
.dr-despliegue-fila input { width: 100%; }
.runner-proyectos-fila { display: grid; grid-template-columns: 110px 90px 1fr 130px auto auto; gap: 6px 10px; align-items: center; margin-bottom: 6px; }
.runner-proyectos-fila input[type="text"] { width: 100%; }
.dr-ficha { display: grid; grid-template-columns: 110px 1fr; gap: 6px 12px; margin: 0; font-size: 13px; }
.dr-ficha dt { color: var(--muted); font-weight: 600; }
.dr-ficha dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.dr-ficha--compacta { grid-template-columns: 96px 1fr; font-size: 12.5px; }
.dr-criterios-lista { margin: 6px 0 0; padding-left: 18px; font-size: 12.5px; }
.dr-repo { display: inline-block; margin: 0 6px 4px 0; padding: 1px 6px; border-radius: 4px; background: var(--neutral-bg); font-size: 11.5px; }
.dr-rama { font-size: 12px; }
.dr-texto-ok { color: var(--ok); }
.dr-texto-error, .dr-texto-aviso { color: var(--danger); }
.dr-avisos { margin: 0; padding: 8px 12px; list-style: none; border-radius: var(--radius); background: var(--warn-bg); color: var(--warn); font-size: 12.5px; }
.dr-confirmar footer .dr-motivo { margin-right: auto; align-self: center; }
.dr-detalle-cuerpo { gap: 14px; }
.dr-detalle h3 { margin: 10px 0 6px; font-size: 13px; }
.dr-faltantes { margin: 0; padding-left: 18px; color: var(--warn); font-size: 12.5px; }
.dr-defectos { margin-top: 14px; }
.dr-despliegue-pedido { display: grid; gap: 8px; margin-bottom: 8px; }
.dr-sha { overflow-wrap: anywhere; }
.dr-defectos-lista { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 8px; }
.dr-defecto { padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius); }
.dr-defecto-cabeza { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.dr-defecto-texto { margin: 4px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; font-size: 12.5px; }
.dr-aviso-evidencia { display: flex; align-items: center; gap: 6px; margin: 0; font-size: 12px; color: var(--muted); font-style: italic; }
.dr-plan { padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius); }
.dr-plan-acciones { display: flex; gap: 8px; }
/* PLAN.md as written (27-10-2026): headings, lists and the criterion × file table, readable instead of one long paragraph */
.drp-cabeza { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 6px 12px; }
.drp-documento { font-size: 13px; line-height: 1.55; max-width: 110ch; }
.drp-documento p { margin: 6px 0; overflow-wrap: anywhere; }
.drp-documento ol, .drp-documento ul { margin: 4px 0 8px; padding-left: 22px; }
.drp-documento li { margin: 3px 0; overflow-wrap: anywhere; }
.drp-titulo { margin: 4px 0 8px; font-size: 15px; }
.drp-seccion { margin: 16px 0 6px; padding-bottom: 4px; font-size: 13.5px; border-bottom: 1px solid var(--border); }
.drp-subseccion { margin: 12px 0 4px; font-size: 13px; }
.drp-codigo { font-family: var(--mono); font-size: 11.5px; padding: 1px 4px; border-radius: 4px; background: var(--accent-soft); overflow-wrap: anywhere; }
.drp-bloque-codigo { font-family: var(--mono); font-size: 11.5px; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius); overflow-x: auto; }
.drp-tabla-caja { overflow-x: auto; max-width: 100%; margin: 6px 0 10px; }
.drp-tabla { border-collapse: collapse; width: 100%; font-size: 12.5px; }
.drp-tabla th, .drp-tabla td { white-space: normal; text-align: left; vertical-align: top; padding: 6px 8px; border: 1px solid var(--border); overflow-wrap: anywhere; }
.drp-tabla th { background: var(--bg); font-weight: 600; }
/* The table of «Proyectos locales»: cells wrap instead of inheriting the generic `th, td { white-space: nowrap }`
   and only this box scrolls on a narrow screen, never the page (the run detail's criteria use `.drd-tabla`) */
.dr-matriz-caja { overflow-x: auto; max-width: 100%; }
.dr-matriz { width: 100%; border-collapse: collapse; font-size: 12.5px; table-layout: fixed; min-width: 640px; }
.dr-matriz td { white-space: normal; overflow-wrap: anywhere; }
.dr-matriz th, .dr-matriz td { padding: 6px 8px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; }
.dr-matriz th { color: var(--muted); font-weight: 600; }
/* «Proyectos locales» (25-10-2026): the chip in the Desarrollo header and its modal */
.dr-proyectos-chip { display: flex; width: fit-content; align-items: center; gap: 4px; margin-top: 4px; padding: 1px 8px; border: 1px solid var(--border); border-radius: 999px; background: var(--neutral-bg); color: var(--muted); font-size: 11px; font-weight: 500; cursor: pointer; white-space: nowrap; }
.dr-proyectos-chip:hover, .dr-proyectos-chip:focus-visible { border-color: var(--accent); color: var(--accent); }
.dr-servicios-ayuda { margin: 0 0 8px; }
.dr-servicios-runner { margin: 0 0 8px; }
.modal.dr-servicios { max-width: min(1040px, calc(100vw - 32px)); }
.dr-servicios-tabla { min-width: 820px; }
.dr-servicios-col-proyecto { width: 200px; }
.dr-servicios-col-estado { width: 160px; }
.dr-servicios-col-puerto { width: 64px; }
.dr-servicios-col-desde { width: 84px; }
.dr-servicios footer .dr-motivo { margin-right: auto; align-self: center; }
.dr-entregas, .dr-documentos, .dr-registro, .dr-intentos { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; }
.dr-entregas li, .dr-intentos li { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* Progress of a run (24-10-2026): «NN %» and the phase in the column, one bar per phase in the detail,
   and «Qué lleva y qué falta» (✔ hecho, ◻ falta, ✖ falló, – no aplica). */
.dr-progreso-celda { display: flex; align-items: flex-start; gap: 4px; width: 100%; }
.dr-progreso { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.dr-progreso-fila { display: flex; align-items: center; gap: 6px; }
.dr-barra { position: relative; flex: 1; min-width: 60px; height: 8px; border-radius: 4px; background: var(--neutral-bg); border: 1px solid var(--border); overflow: hidden; }
.dr-barra-relleno { position: absolute; inset: 0 auto 0 0; background: var(--info); transition: width .4s ease; }
.dr-barra--ok .dr-barra-relleno { background: var(--ok); }
.dr-barra--warn .dr-barra-relleno { background: var(--warn); }
.dr-barra--danger .dr-barra-relleno { background: var(--danger); }
.dr-barra--neutral .dr-barra-relleno { background: var(--muted); }
.dr-barra--fina { height: 6px; }
.dr-progreso-texto { font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dr-progreso-fase { font-size: 11px; color: var(--muted); }
.dr-info { padding: 0 2px; line-height: 1; }
.dr-progreso--grande .dr-barra { height: 12px; }
.dr-progreso--grande .dr-progreso-texto { font-size: 14px; }
.dr-fases { margin: 8px 0 0; padding: 0; list-style: none; display: grid; grid-template-columns: minmax(140px, auto) 1fr auto; gap: 4px 10px; align-items: center; font-size: 12.5px; }
.dr-fases li { display: contents; }
.dr-fase-porcentaje { font-variant-numeric: tabular-nums; text-align: right; color: var(--muted); }
.dr-fase-item--hecho .dr-barra-relleno { background: var(--ok); }
.dr-fase-item--fallo .dr-barra-relleno, .dr-fase-item--incompleta .dr-barra-relleno { background: var(--danger); }
.dr-fase-item--no_aplica .dr-fase-nombre { color: var(--muted); text-decoration: line-through; }
.dr-lista { max-width: 640px; width: 100%; }
.dr-lista .body { max-height: 70vh; overflow-y: auto; }
.dr-lista-grupo h4 { margin: 12px 0 4px; font-size: 13px; }
.dr-lista-grupo ul { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 3px; }
.dr-lista-grupo li { display: flex; gap: 8px; align-items: baseline; font-size: 12.5px; }
.dr-item-marca { width: 1.2em; flex: none; text-align: center; font-weight: 700; }
.dr-item--hecho .dr-item-marca { color: var(--ok); }
.dr-item--pendiente .dr-item-marca { color: var(--muted); }
.dr-item--fallo .dr-item-marca, .dr-item--fallo .dr-item-texto { color: var(--danger); }
.dr-item--no-aplica { color: var(--muted); }
@media (max-width: 600px) { .dr-fases { grid-template-columns: 1fr auto; } .dr-fases .dr-barra { display: none; } }

/* «Comenzar desarrollo», the understanding gate (25-10-2026): clarification, matrix and the mockup | Development gallery */
.dr-entendimiento { padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius); display: flex; flex-direction: column; gap: 8px; }
.dr-entendimiento h3 { display: flex; align-items: center; gap: 8px; }
.dr-entendimiento h4 { margin: 6px 0 2px; font-size: 0.95em; }
.dr-aclaracion { display: flex; flex-direction: column; gap: 8px; padding: 8px 10px; border-left: 3px solid var(--warn); background: var(--warn-bg); }
.dr-violaciones, .dr-problemas { margin: 0; padding-left: 18px; }
.dr-problemas { font-size: 0.85em; }
.dr-pregunta { display: flex; flex-direction: column; gap: 4px; }
.drd-avisos { display: flex; flex-direction: column; gap: 6px; margin: 8px 0; padding: 8px 12px; border: 1px solid var(--border); border-radius: var(--radius); min-width: 0; }
.drd-avisos legend h4 { margin: 0; }
.drd-aviso { display: flex; align-items: flex-start; gap: 8px; font-size: 13px; overflow-wrap: anywhere; }
.drd-aviso input[type="checkbox"] { margin-top: 3px; flex: none; }
.drd-avisos > button { align-self: flex-start; }
.dr-pregunta textarea { width: 100%; resize: vertical; }
.dr-pregunta .btn-icono { align-self: flex-start; }
.dr-tabla-scroll { overflow-x: auto; max-width: 100%; }
.dr-matriz-entendimiento { width: 100%; border-collapse: collapse; font-size: 0.88em; }
.dr-matriz-entendimiento th, .dr-matriz-entendimiento td { border-bottom: 1px solid var(--border); padding: 4px 6px; vertical-align: top; text-align: left; }
.dr-literal { white-space: pre-wrap; }
.dr-checklist-visual { margin: 0; padding-left: 0; list-style: none; display: flex; flex-direction: column; gap: 3px; }

/* The detail of a run, redesigned (25-10-2026, after the first real run of TL-8913): header with the live indicator,
   one banner with one action, the stepper, the tabs with counts, cards, the criteria table, the understanding cards,
   the mockup ↔ Development grid, the timelines and the lightbox. `drd-` = desarrollo/runner, detalle. The tokens are
   the app's, so the dark theme follows by itself. */
.drd-cabecera { align-items: flex-start; flex-wrap: wrap; row-gap: 8px; }
.drd-titulo { display: flex; flex-direction: column; gap: 6px; min-width: 0; flex: 1 1 420px; }
.drd-titulo h2 { margin: 0; font-size: 15px; font-weight: 700; display: flex; align-items: baseline; gap: 6px; min-width: 0; }
.drd-titulo-texto { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; font-weight: 600; }
.drd-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; font-size: 12px; font-weight: 500; }
.drd-fase-actual, .drd-intento { display: inline-flex; align-items: center; gap: 3px; opacity: .92; }
.drd-vivo { display: inline-flex; align-items: center; gap: 6px; padding: 1px 8px; border-radius: 999px; border: 1px solid currentColor; font-size: 11px; opacity: .9; }
.drd-vivo-punto { width: 7px; height: 7px; border-radius: 50%; background: currentColor; opacity: .6; }
.drd-vivo--activo .drd-vivo-punto { opacity: 1; animation: drd-pulso 1.6s ease-out infinite; }
@keyframes drd-pulso { 0% { box-shadow: 0 0 0 0 currentColor; } 70% { box-shadow: 0 0 0 6px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
@media (prefers-reduced-motion: reduce) { .drd-vivo--activo .drd-vivo-punto { animation: none; } }
.drd-acciones { display: flex; flex-wrap: wrap; gap: 6px; }
.dr-detalle-cuerpo { gap: 12px; }
/* The body is a flex column with a fixed height: its children must not shrink (the tab bar, with overflow-x, collapsed to 0) */
.dr-detalle-cuerpo > * { flex: none; }
.drd-banner { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-radius: var(--radius); border: 1px solid; font-size: 13px; }
.drd-banner > .mdi { font-size: 22px; line-height: 1; flex: none; }
.drd-banner-texto { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; overflow-wrap: anywhere; }
.drd-banner > button { flex: none; }
.drd-banner[data-tono="danger"] { background: var(--danger-bg); border-color: color-mix(in srgb, var(--danger) 40%, transparent); }
.drd-banner[data-tono="danger"] > .mdi, .drd-banner[data-tono="danger"] b { color: var(--danger); }
.drd-banner[data-tono="warn"] { background: var(--warn-bg); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.drd-banner[data-tono="warn"] > .mdi, .drd-banner[data-tono="warn"] b { color: var(--warn); }
.drd-banner[data-tono="info"] { background: var(--info-bg); border-color: color-mix(in srgb, var(--info) 40%, transparent); }
.drd-banner[data-tono="info"] > .mdi, .drd-banner[data-tono="info"] b { color: var(--info); }
.drd-banner[data-tono="neutral"] { background: var(--neutral-bg); border-color: var(--border); }
.drd-avance { display: flex; flex-direction: column; gap: 10px; padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); }
.drd-stepper { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 0; margin: 0; padding: 0; list-style: none; counter-reset: paso; }
.drd-stepper li { position: relative; display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 0 4px; text-align: center; min-width: 0; cursor: default; }
.drd-stepper li + li::before { content: ""; position: absolute; top: 13px; right: calc(50% + 16px); left: calc(-50% + 16px); height: 2px; background: var(--border); }
.drd-stepper li[data-estado="hecho"] + li::before, .drd-stepper li[data-estado="hecho"] + li[data-estado]::before { background: var(--ok); }
.drd-paso-marca { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; border: 2px solid var(--border-strong); background: var(--panel); color: var(--muted); font-size: 12px; font-weight: 700; z-index: 1; }
.drd-paso-marca .mdi { font-size: 16px; line-height: 1; }
.drd-stepper li[data-estado="hecho"] .drd-paso-marca { border-color: var(--ok); background: var(--ok); color: #fff; }
.drd-stepper li[data-estado="actual"] .drd-paso-marca { border-color: var(--info); color: var(--info); box-shadow: 0 0 0 4px var(--info-bg); }
.drd-stepper li[data-estado="fallo"] .drd-paso-marca { border-color: var(--danger); background: var(--danger); color: #fff; }
.drd-stepper li[data-estado="no_aplica"] .drd-paso-marca { border-style: dashed; }
.drd-paso-texto { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.drd-paso-nombre { font-size: 12px; font-weight: 600; overflow-wrap: anywhere; }
.drd-stepper li[data-estado="pendiente"] .drd-paso-nombre, .drd-stepper li[data-estado="no_aplica"] .drd-paso-nombre { color: var(--muted); font-weight: 500; }
.drd-stepper li[data-estado="fallo"] .drd-paso-nombre { color: var(--danger); }
.drd-paso-tiempo { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.drd-avance-total { display: flex; align-items: center; gap: 12px; }
.drd-avance-total .dr-progreso { flex: 1; }
.drd-tabs { position: sticky; top: -14px; z-index: 2; display: flex; gap: 2px; margin: 0 -14px; padding: 0 14px; border-bottom: 1px solid var(--border); background: var(--panel); overflow-x: auto; scrollbar-width: thin; }
.drd-tab { display: inline-flex; align-items: center; gap: 6px; padding: 10px 12px; border: 0; border-bottom: 2px solid transparent; background: none; color: var(--muted); font-size: 13px; font-weight: 600; white-space: nowrap; cursor: pointer; }
.drd-tab:hover { color: var(--text); }
.drd-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.drd-tab--activa { color: var(--accent); border-bottom-color: var(--accent); }
.drd-cuenta { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 18px; padding: 0 6px; border-radius: 999px; background: var(--neutral-bg); color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }
.drd-tab--activa .drd-cuenta { background: var(--accent-soft); color: var(--accent); }
.drd-cuenta--aviso, .drd-tab--activa .drd-cuenta--aviso { background: var(--warn-bg); color: var(--warn); }
.drd-panel { min-width: 0; }
.drd-panel[hidden] { display: none !important; }
.drd-seccion-cabeza { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-bottom: 8px; }
.drd-seccion-cabeza h3 { margin: 0; font-size: 14px; }
.drd-vacio { display: flex; align-items: center; gap: 8px; margin: 0; padding: 18px; border: 1px dashed var(--border); border-radius: var(--radius); color: var(--muted); font-size: 13px; }
.drd-vacio .mdi { font-size: 20px; }
.drd-chip { display: inline-flex; align-items: center; padding: 0 7px; border-radius: 4px; background: var(--neutral-bg); color: var(--muted); font-size: 11px; font-weight: 600; white-space: nowrap; }
.drd-chip-ambito { background: var(--accent-soft); color: var(--accent); }
/* Resumen */
.drd-resumen { display: flex; flex-direction: column; gap: 14px; }
.drd-tarjetas { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 12px; }
.drd-tarjeta { display: flex; flex-direction: column; gap: 6px; padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); min-width: 0; font-size: 13px; }
.drd-tarjeta h3 { display: flex; align-items: center; gap: 6px; margin: 0 0 4px; font-size: 13px; color: var(--muted); text-transform: uppercase; letter-spacing: .03em; }
.drd-tarjeta p { margin: 0; overflow-wrap: anywhere; }
.drd-destacado { font-weight: 700; }
.drd-copiar { height: 22px !important; padding: 0 6px !important; margin-left: 4px; vertical-align: middle; }
.drd-sesion { display: flex; flex-direction: column; gap: 3px; padding-top: 6px; border-top: 1px dashed var(--border); }
.drd-sesion-nombre { font-weight: 600; font-size: 12.5px; }
.drd-consumo-fila { display: grid; grid-template-columns: 56px minmax(60px, 1fr) auto; gap: 8px; align-items: center; font-size: 12px; }
.drd-consumo-etiqueta { color: var(--muted); }
.drd-consumo-texto { font-variant-numeric: tabular-nums; white-space: nowrap; }
.drd-bloque { display: flex; flex-direction: column; gap: 6px; }
.drd-bloque h3 { margin: 0; }
/* Criterios */
.drd-filtros { display: inline-flex; gap: 4px; margin-left: auto; }
.drd-filtro { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; border: 1px solid var(--border); border-radius: 999px; background: var(--panel); color: var(--text); font-size: 12px; cursor: pointer; }
.drd-filtro--activo { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.drd-tabla-caja { overflow-x: auto; max-width: 100%; border: 1px solid var(--border); border-radius: var(--radius); }
.drd-tabla { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 12.5px; min-width: 680px; }
.drd-tabla th, .drd-tabla td { padding: 8px 10px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; white-space: normal; overflow-wrap: anywhere; }
.drd-tabla th { position: sticky; top: 0; background: var(--neutral-bg); color: var(--muted); font-weight: 600; }
.drd-tabla tbody tr:last-child td { border-bottom: 0; }
.drd-tabla tbody tr:hover td { background: color-mix(in srgb, var(--accent-soft) 45%, transparent); }
.drd-col-codigo { width: 64px; }
.drd-col-caso { width: 20%; }
.drd-col-resultado { width: 112px; }
.drd-col-evidencia { width: 200px; }
.drd-codigo { font-weight: 700; }
.drd-criterio-texto { line-height: 1.45; }
.drd-criterio-texto--corto { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.drd-ca { color: var(--muted); }
.drd-criterio-pie { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 4px; }
.drd-expandir { font-size: 12px; }
.drd-git-ver-codigo { display: inline-flex; align-items: center; gap: 3px; margin-top: 4px; font-size: 12px; white-space: nowrap; }
.drd-miniaturas { display: flex; flex-wrap: wrap; gap: 6px; }
.drd-miniatura { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 88px; height: 56px; padding: 0; border: 1px solid var(--border); border-radius: 6px; background: var(--neutral-bg); overflow: hidden; cursor: zoom-in; color: var(--muted); font-size: 11px; text-align: center; }
.drd-miniatura:hover, .drd-miniatura:focus-visible { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.drd-miniatura img { width: 100%; height: 100%; object-fit: cover; }
.drd-miniatura--grande { width: 100%; height: 180px; }
.drd-miniatura--grande img { object-fit: contain; background: var(--panel); }
.drd-miniatura--sin { cursor: default; padding: 6px; }
.drd-miniatura--equipo { font-size: 10px; line-height: 1.2; }
.drd-en-equipo .mdi { margin-right: 4px; }
.drd-miniatura-carga { position: absolute; inset: 0; border-radius: 0; }
/* Entendimiento */
.drd-entendimiento { display: flex; flex-direction: column; gap: 10px; }
.drd-entendimiento h4 { margin: 4px 0 0; font-size: 13px; }
.drd-pregunta-pie { display: flex; align-items: center; gap: 8px; }
.drd-puntos { display: flex; flex-direction: column; gap: 6px; }
.drd-punto { border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); }
.drd-punto--abierto { border-color: var(--border-strong); }
.drd-punto-cabeza { display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 12px; border: 0; background: none; color: var(--text); font-size: 13px; text-align: left; cursor: pointer; }
.drd-punto-cabeza:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.drd-punto-resumen { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drd-punto-cuerpo { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; padding: 4px 12px 12px; font-size: 12.5px; }
.drd-punto-col h5 { margin: 0 0 4px; font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .03em; }
.drd-punto-col p { margin: 0 0 4px; overflow-wrap: anywhere; }
.drd-punto-cuerpo .dr-problemas { grid-column: 1 / -1; color: var(--danger); }
.drd-ref-codigo { overflow-wrap: anywhere; font-size: 11.5px; }
/* Referencias visuales */
.drd-ref-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(420px, 1fr)); gap: 12px; }
.drd-ref { display: flex; flex-direction: column; gap: 8px; padding: 12px; border: 1px solid var(--border); border-radius: var(--radius); min-width: 0; }
.drd-ref header { padding: 0; border: 0; font-size: 13px; }
.drd-ref-par { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.drd-ref-contexto { display: flex; flex-direction: column; gap: 6px; font-size: 12px; }
.drd-ref-contexto .drd-chip-fuente { align-self: flex-start; max-width: 100%; white-space: normal; }
.drd-ref-lineas { display: grid; grid-template-columns: max-content 1fr; gap: 2px 8px; margin: 0; }
.drd-ref-lineas dt { color: var(--muted); font-weight: 600; }
.drd-ref-lineas dd { margin: 0; overflow-wrap: anywhere; }
.drd-ref-par figure { margin: 0; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.drd-ref-par figcaption { font-size: 11.5px; color: var(--muted); text-align: center; }
/* Registro / Auditoría */
.drd-linea { list-style: none; margin: 0; padding: 0; position: relative; }
.drd-linea::before { content: ""; position: absolute; left: 13px; top: 6px; bottom: 6px; width: 2px; background: var(--border); }
.drd-linea li { position: relative; display: grid; grid-template-columns: 28px minmax(0, 1fr) auto; gap: 10px; align-items: start; padding: 6px 0; font-size: 12.5px; }
.drd-linea-icono { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; background: var(--panel); border: 1px solid var(--border); color: var(--muted); z-index: 1; }
.drd-linea-item--ok .drd-linea-icono { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.drd-linea-item--info .drd-linea-icono { color: var(--info); border-color: color-mix(in srgb, var(--info) 40%, transparent); }
.drd-linea-item--warn .drd-linea-icono { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.drd-linea-item--danger .drd-linea-icono { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, transparent); background: var(--danger-bg); }
.drd-linea-texto { min-width: 0; padding-top: 4px; }
.drd-linea-titulo { font-weight: 600; }
.drd-linea-detalle { color: var(--muted); overflow-wrap: anywhere; }
.drd-linea-hora { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; padding-top: 4px; font-size: 11.5px; white-space: nowrap; }
.drd-ver-todo { margin-top: 6px; }
/* Skeleton */
.drd-esqueleto { display: flex; flex-direction: column; gap: 12px; }
.drd-esq-banner { height: 48px; }
.drd-esq-stepper { height: 96px; }
.drd-esq-tabs { height: 38px; }
.drd-esq-tarjeta { height: 150px; }
/* Lightbox */
.drd-lightbox { position: fixed; inset: 0; z-index: 90; display: flex; flex-direction: column; background: rgba(0, 0, 0, 0.88); color: #fff; }
.drd-lightbox-barra { display: flex; align-items: center; gap: 8px; padding: 10px 16px; background: rgba(0, 0, 0, 0.45); }
.drd-lightbox-leyenda { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.drd-lightbox-cuenta { margin-left: 8px; opacity: .75; font-variant-numeric: tabular-nums; }
.drd-lightbox-zoom { min-width: 52px; text-align: right; font-variant-numeric: tabular-nums; font-size: 12px; opacity: .85; }
.drd-lightbox-barra .btn-icono { display: inline-flex; align-items: center; justify-content: center; gap: 4px; height: 32px; min-width: 32px; padding: 0 8px; color: #fff; border: 1px solid rgba(255, 255, 255, 0.4); border-radius: 6px; background: transparent; font-size: 12px; text-decoration: none; cursor: pointer; }
.drd-lightbox-barra .btn-icono:hover, .drd-lightbox-barra .btn-icono:focus-visible { background: rgba(255, 255, 255, 0.14); outline: 2px solid #fff; outline-offset: 1px; }
.drd-lightbox-barra .btn-icono .mdi { font-size: 18px; line-height: 1; }
.drd-lightbox-barra .modal-close { color: #fff; background: transparent; }
.drd-lightbox-lienzo { position: relative; flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; overflow: hidden; padding: 16px 64px; touch-action: none; }
.drd-lightbox-lienzo--mover { cursor: grab; }
.drd-lightbox-lienzo--arrastrando { cursor: grabbing; }
.drd-lightbox-img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 4px; background: #fff; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5); transform-origin: center center; transition: transform .12s ease-out; user-select: none; }
.drd-lightbox-lienzo--arrastrando .drd-lightbox-img { transition: none; }
.drd-lightbox-estado { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; }
.drd-lightbox-flecha { position: absolute; top: 50%; transform: translateY(-50%); z-index: 1; display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.4); background: rgba(0, 0, 0, 0.45); color: #fff; font-size: 26px; cursor: pointer; }
.drd-lightbox-flecha:hover, .drd-lightbox-flecha:focus-visible { background: rgba(255, 255, 255, 0.18); outline: 2px solid #fff; }
.drd-lightbox-flecha--izq { left: 12px; }
.drd-lightbox-flecha--der { right: 12px; }
@media (prefers-reduced-motion: reduce) { .drd-lightbox-img { transition: none; } }
/* Narrow screens: the stepper wraps to rows, cards and pairs stack, the understanding card goes to two columns */
@media (max-width: 900px) {
  .drd-punto-cuerpo { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .drd-ref-grid { grid-template-columns: 1fr; }
  .drd-filtros { margin-left: 0; }
  .drd-stepper { grid-template-columns: repeat(4, minmax(0, 1fr)); row-gap: 12px; }
  .drd-stepper li:nth-child(5)::before { display: none; }
  .drd-lightbox-lienzo { padding: 12px; }
}
@media (max-width: 600px) {
  .drd-punto-cuerpo, .drd-ref-par { grid-template-columns: 1fr; }
  .drd-banner { flex-wrap: wrap; }
  .drd-linea li { grid-template-columns: 28px minmax(0, 1fr); }
  .drd-linea-hora { grid-column: 2; align-items: flex-start; }
}

/* «Git» of a run's detail (25-10-2026) */
.drd-git { display: flex; flex-direction: column; gap: 14px; }
.drd-git h4, .drd-git h5 { margin: 6px 0 4px; font-size: 13px; }
.drd-git-repo { display: flex; flex-direction: column; gap: 8px; padding-top: 10px; border-top: 1px solid var(--border); }
.drd-git-repo > header a { font-size: 12.5px; }
.drd-git-rama { overflow-wrap: anywhere; }
.drd-git-checkout { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 12px; }
.drd-git-checkout code { padding: 2px 6px; border-radius: 4px; background: var(--neutral-bg); overflow-wrap: anywhere; }
.drd-git-posicion { margin: 4px 0 0; padding-left: 18px; font-size: 12.5px; }
.drd-tono--ok { color: var(--ok); } .drd-tono--warn { color: var(--warn); font-weight: 600; } .drd-tono--danger { color: var(--danger); font-weight: 600; } .drd-tono--info { color: var(--info); } .drd-tono--neutral { color: var(--muted); }
.drd-git-marca { color: var(--warn); font-weight: 600; }
.drd-git-alerta, .drd-git-atribucion-texto { color: var(--danger); font-weight: 700; margin: 4px 0 0; }
.drd-git-atribucion td { background: var(--danger-bg) !important; }
.drd-git-cuerpo { margin: 0 0 6px; padding: 8px 10px; border-radius: 4px; background: var(--neutral-bg); white-space: pre-wrap; overflow-wrap: anywhere; font-size: 12px; max-height: 260px; overflow: auto; }
.drd-git-archivos-commit { margin: 0; padding-left: 18px; font-size: 12px; }
.drd-git-empujes { margin: 0; padding-left: 18px; font-size: 12.5px; }
.drd-git-mr-enlace { display: inline-block; margin-right: 10px; }
.drd-mas { color: var(--ok); font-variant-numeric: tabular-nums; } .drd-menos { color: var(--danger); font-variant-numeric: tabular-nums; }
.drd-col-sha { width: 130px; } .drd-col-autor { width: 150px; } .drd-col-cambio { width: 120px; } .drd-col-estado { width: 96px; } .drd-col-clase { width: 190px; }
.drd-fila-detalle td { background: var(--panel) !important; }

/* «Qué lleva y qué falta», redesigned (25-10-2026): frozen when the run ended, distinct icons per state */
.drl { max-width: 720px; }
.drl-cabecera { align-items: flex-start; }
.drl-titulo { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.drl-titular { margin: 0 0 6px; padding: 8px 12px; border-radius: var(--radius); border: 1px solid var(--border); background: var(--neutral-bg); font-size: 13px; }
.drl-titular[data-tono="danger"] { background: var(--danger-bg); border-color: color-mix(in srgb, var(--danger) 40%, transparent); }
.drl-titular[data-tono="danger"] b { color: var(--danger); }
.drl-titular[data-tono="warn"] { background: var(--warn-bg); } .drl-titular[data-tono="warn"] b { color: var(--warn); }
.drl-titular[data-tono="ok"] { background: var(--ok-bg, var(--neutral-bg)); } .drl-titular[data-tono="ok"] b { color: var(--ok); }
.drl-grupo { padding: 8px 0; border-top: 1px solid var(--border); }
.drl-grupo h4 { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.drl-grupo .dr-item-marca { font-size: 15px; line-height: 1; flex: none; }
.dr-item--no-alcanzado, .dr-item--no-alcanzado .dr-item-marca { color: var(--muted); }
.dr-item--no-alcanzado .dr-item-texto { font-style: italic; }
.dr-item--cancelado .dr-item-marca, .dr-item--cancelado .dr-item-texto { color: var(--warn); }
.drd-stepper li[data-estado="no_alcanzado"] .drd-paso-marca { border-style: dotted; color: var(--muted); }
.drd-stepper li[data-estado="no_alcanzado"] .drd-paso-nombre { color: var(--muted); font-weight: 500; }

/* «Evidencias» of a run's detail (25-10-2026): the storyboard of PRUEBAS.md */
.drd-evidencias { display: flex; flex-direction: column; gap: 12px; }
.drd-ev-problemas ul { margin: 6px 0 0; padding-left: 18px; font-size: 12.5px; }
.drd-ev-filtros { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
.drd-ev-filtro-codigo { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; }
.drd-ev-grupo h4 { display: flex; gap: 8px; align-items: baseline; margin: 4px 0 8px; font-size: 13px; }
.drd-ev-grupo-titulo { font-weight: 500; color: var(--muted); overflow-wrap: anywhere; }
.drd-ev-pasos { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 10px; }
.drd-ev-paso { display: grid; grid-template-columns: 168px minmax(0, 1fr); gap: 12px; padding: 10px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); }
.drd-ev-paso[data-resultado="falla"] { border-left: 3px solid var(--danger); }
.drd-ev-paso[data-resultado="pasa"] { border-left: 3px solid var(--ok); }
.drd-ev-paso .drd-miniatura { width: 160px; height: 100px; }
.drd-ev-cabeza { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 13px; }
.drd-ev-chip { margin-left: auto; }
.drd-ev-leyenda { margin: 4px 0; font-style: italic; overflow-wrap: anywhere; }
.drd-ev-faltas { margin: 4px 0 0; padding-left: 18px; color: var(--warn); font-size: 12px; }
@media (max-width: 640px) { .drd-ev-paso { grid-template-columns: 1fr; } }
.drd-lightbox-explicacion { margin: 0; padding: 6px 16px 8px; background: rgba(0, 0, 0, 0.45); color: #fff; font-size: 13px; overflow-wrap: anywhere; }

/* «Ahora» and «Actividad» of a run's detail (25-10-2026): what the session is doing, live */
.drd-ahora { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 6px; font-size: 13px; min-width: 0; }
.drd-ahora-frase { min-width: 0; overflow-wrap: anywhere; }
.drd-ahora-hace { color: var(--muted); }
.drd-salud { display: inline-flex; align-items: center; gap: 6px; padding: 2px 10px; border-radius: 999px; font-size: 12px; font-weight: 600; border: 1px solid currentColor; white-space: nowrap; }
.drd-salud-punto { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.drd-salud[data-tono="ok"] { color: var(--ok); }
.drd-salud[data-tono="warn"] { color: var(--warn); background: var(--warn-bg); }
.drd-salud[data-tono="danger"] { color: var(--danger); background: var(--danger-bg); }
.drd-salud[data-tono="info"] { color: var(--info); background: var(--info-bg); }
.drd-salud[data-tono="neutral"] { color: var(--muted); }
.drd-ahora[data-salud="trabajando"] .drd-salud-punto, .drd-ahora[data-salud="pensando"] .drd-salud-punto, .drd-ahora[data-salud="encendiendo_servicios"] .drd-salud-punto { animation: drd-pulso 1.6s ease-out infinite; }
@media (prefers-reduced-motion: reduce) { .drd-ahora .drd-salud-punto { animation: none !important; } }
.drd-ahora-accion { padding: 2px 10px; }
.drd-actividad .drd-uso { display: grid; gap: 6px; margin-bottom: 10px; }
.drd-uso-fila { display: grid; grid-template-columns: 70px 1fr auto; align-items: center; gap: 8px; font-size: 12px; }
.drd-uso-barra { height: 6px; border-radius: 3px; background: var(--border); overflow: hidden; }
.drd-uso-barra > span { display: block; height: 100%; background: var(--ok); }
.drd-uso-barra[data-tono="warn"] > span { background: var(--warn); }
.drd-uso-barra[data-tono="danger"] > span { background: var(--danger); }
.drd-uso-valor { color: var(--muted); white-space: nowrap; }
.drd-actividad-lista { max-height: 320px; overflow-y: auto; border: 1px solid var(--border); border-radius: var(--radius); padding: 6px 10px; }
.drd-act-fase { margin: 8px 0 4px; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.drd-act-grupo ol { list-style: none; margin: 0; padding: 0; }
.drd-act-item { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; padding: 3px 0; font-size: 12.5px; border-bottom: 1px dashed var(--border); }
.drd-act-item:last-child { border-bottom: 0; }
.drd-act-hora { color: var(--muted); font-size: 11.5px; }
.drd-act-agente { padding: 0 8px; border-radius: 999px; background: var(--info-bg); color: var(--info); font-size: 11.5px; font-weight: 600; }
.drd-act-agente--principal { background: var(--border); color: var(--text); }
.drd-act-objetivo { color: var(--muted); overflow-wrap: anywhere; min-width: 0; }

/* «Scripts por ambiente» of a run's detail (25-10-2026): three states, sub-tabs per environment, the script viewer */
.drd-amb { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.drd-amb-panel { display: flex; align-items: flex-start; gap: 12px; padding: 16px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); font-size: 13px; }
.drd-amb-panel > .mdi { font-size: 26px; line-height: 1; }
.drd-amb-panel strong { display: block; font-size: 14px; margin-bottom: 4px; }
.drd-amb-panel p { margin: 0 0 4px; }
.drd-amb-panel--pendiente { border-style: dashed; color: var(--muted); }
.drd-amb-panel--neutro { background: var(--neutral-bg); }
.drd-amb-panel--neutro > .mdi { color: var(--info); }
.drd-amb-panel--falta { border-color: color-mix(in srgb, var(--danger) 45%, transparent); background: var(--danger-bg); }
.drd-amb-panel--falta > .mdi, .drd-amb-panel--falta strong { color: var(--danger); }
.drd-amb-pie { margin-top: 8px !important; }
.drd-amb-discrepancias { margin: 6px 0 0; padding-left: 18px; font-size: 12.5px; }
.drd-amb-avisos { list-style: none; margin: 0; padding: 10px 12px; border-radius: var(--radius); background: var(--warn-bg); color: var(--warn); font-size: 12.5px; display: flex; flex-direction: column; gap: 4px; }
.drd-subtabs { display: flex; flex-wrap: wrap; gap: 6px; border-bottom: 1px solid var(--border); }
.drd-subtab { padding: 6px 12px; border: 1px solid transparent; border-bottom: 0; border-radius: var(--radius) var(--radius) 0 0; background: none; color: var(--muted); cursor: pointer; font-size: 13px; }
.drd-subtab--activa { border-color: var(--border); background: var(--panel); color: var(--text); font-weight: 600; margin-bottom: -1px; }
.drd-amb-ambiente { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.drd-amb-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.drd-amb-item-cabeza { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 0; border: 0; background: none; color: inherit; cursor: pointer; text-align: left; font: inherit; }
.drd-amb-orden { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 999px; background: var(--neutral-bg); font-size: 12px; font-weight: 700; }
.drd-amb-archivo { overflow-wrap: anywhere; min-width: 0; }
.drd-script { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.drd-script-comando, .drd-script-barra { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.drd-codigo { margin: 0; max-height: 420px; overflow: auto; padding: 8px 0; border: 1px solid var(--border); border-radius: var(--radius); background: var(--neutral-bg); font-size: 12px; line-height: 1.5; }
.drd-codigo-linea { display: block; padding-right: 12px; white-space: pre; }
.drd-codigo-n { display: inline-block; width: 3.5em; padding-right: 10px; text-align: right; color: var(--muted); user-select: none; }
.drd-codigo .tk-kw { color: var(--info); font-weight: 600; }
.drd-codigo .tk-str { color: var(--ok-texto); }
.drd-codigo .tk-com { color: var(--muted); font-style: italic; }
.drd-codigo .tk-num { color: var(--warn); }

/* «Insumos» of a run (25-10-2026): the inbox of NECESIDADES.md, blocking requests in red, the wait and «Reanudar» */
.drd-ins { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.drd-ins .drd-seccion-cabeza { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.drd-ins-espera { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 12px 14px; border-radius: var(--radius); background: var(--warn-bg); color: var(--warn); font-size: 13px; }
.drd-ins-espera > .mdi { font-size: 22px; }
.drd-ins-espera > span { flex: 1 1 240px; }
.drd-ins-espera[data-listo="si"] { background: var(--neutral-bg); color: inherit; }
.drd-ins-tarjeta { display: flex; flex-direction: column; gap: 6px; padding: 12px 14px; border: 1px solid var(--border); border-left-width: 4px; border-radius: var(--radius); background: var(--panel); font-size: 13px; min-width: 0; }
.drd-ins-tarjeta[data-bloqueante="si"] { border-left-color: var(--danger); background: var(--danger-bg); }
.drd-ins-tarjeta[data-bloqueante="no"] { border-left-color: var(--warn); }
.drd-ins-tarjeta--respondida { border-left-color: var(--ok); }
.drd-ins-tarjeta h4 { margin: 0; font-size: 14px; overflow-wrap: anywhere; }
.drd-ins-cabeza { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 12px; }
.drd-ins-codigo { font-weight: 600; }
.drd-ins-marca { padding: 1px 8px; border-radius: 999px; background: var(--neutral-bg); font-weight: 600; }
.drd-ins-marca--bloquea { background: var(--danger); color: #fff; }
.drd-ins-marca--ok { color: var(--ok); }
.drd-ins-tipo { color: var(--muted); }
.drd-ins-detalle { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.drd-ins-dada { margin: 0; padding: 8px 10px; border-left: 3px solid var(--border); background: var(--neutral-bg); white-space: pre-wrap; overflow-wrap: anywhere; }
.drd-ins-respuesta, .drd-ins-nuevo { display: flex; flex-direction: column; gap: 8px; }
.drd-ins-respuesta textarea, .drd-ins-nuevo textarea, .drd-ins-nuevo input[type="text"] { width: 100%; resize: vertical; box-sizing: border-box; }
.drd-ins-nuevo label { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; }
.drd-ins-fila { display: flex; flex-wrap: wrap; gap: 10px; }
.drd-ins-crece { flex: 1 1 220px; }
.drd-ins-archivos { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 12.5px; }
.drd-ins-archivos input[type="file"] { max-width: 100%; }
.drd-ins-elegidos, .drd-ins-adjuntos { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; font-size: 12.5px; overflow-wrap: anywhere; }
.drd-ins-acciones { display: flex; flex-wrap: wrap; gap: 8px; }
.drd-ins-cerradas summary { cursor: pointer; font-size: 12.5px; color: var(--muted); }
/* Choosing among options (26-10-2026): «Insumos» and «Entendimiento» */
.drd-ins-elegir { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 12px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--warn-bg, var(--neutral-bg)); font-size: 13px; }
.drd-elige { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; border: 0; min-width: 0; }
.drd-elige-tarjeta { display: flex; align-items: flex-start; gap: 8px; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); cursor: pointer; min-width: 0; }
.drd-elige-tarjeta input[type="radio"] { margin-top: 3px; flex: none; }
.drd-elige-tarjeta[data-elegida="si"] { border-color: var(--accent, var(--ok)); box-shadow: inset 3px 0 0 var(--accent, var(--ok)); }
.drd-elige-cuerpo { display: flex; flex-direction: column; gap: 2px; min-width: 0; overflow-wrap: anywhere; }
.drd-elige-titulo { font-size: 13px; }
.drd-elige-consecuencia { font-size: 12px; color: var(--muted); }
.drd-elige-recomendada { margin-left: 4px; padding: 0 6px; border-radius: 999px; background: var(--ok); color: #fff; font-size: 11px; font-weight: 600; }
.drd-elige-otra, .drd-elige-nota textarea { width: 100%; resize: vertical; box-sizing: border-box; }
.drd-elige-nota { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; color: var(--muted); }
/* «Commits de la rama» (25-10-2026, modules/devRuns/DevRunCommitsModal.js): the branch, its way to GitLab
   as four steps, the totals and the commits on a timeline by day. Everything from the theme's tokens. */
.modal.dr-c { max-width: 880px; width: 100%; height: min(86vh, 900px); overflow: hidden; box-shadow: 0 24px 60px -18px rgba(0, 0, 0, .45); }
.dr-c-header { align-items: center; gap: 12px; padding: 14px 18px; background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 10%, var(--panel)), var(--panel) 70%); }
.dr-c-logo { display: grid; place-items: center; width: 38px; height: 38px; border-radius: 10px; background: var(--accent); color: #fff; font-size: 22px; flex: none; box-shadow: 0 6px 14px -6px var(--accent); }
.dr-c-encabezado { min-width: 0; }
.dr-c-h { margin: 0; font-size: 16px; line-height: 1.2; }
.dr-c-sub { margin: 2px 0 0; font-size: 12px; font-weight: 400; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 52ch; }
.dr-c-body { padding: 16px 18px; gap: 14px; flex: 1 1 auto; }

.dr-c-rama { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.dr-c-rama-chip { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: 999px; border: 1px solid var(--border-strong); background: var(--neutral-bg); color: var(--text); font-size: 12px; cursor: pointer; max-width: 100%; }
.dr-c-rama-chip .mono { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dr-c-rama-chip:hover, .dr-c-rama-chip:focus-visible { border-color: var(--accent); color: var(--accent); }
.dr-c-rama-chip--destino { cursor: default; background: color-mix(in srgb, var(--ok) 10%, transparent); border-color: color-mix(in srgb, var(--ok) 40%, transparent); color: var(--ok-texto); }
.dr-c-rama-chip--destino:hover, .dr-c-rama-chip--destino:focus-visible { color: var(--ok-texto); border-color: var(--ok); }
.dr-c-copiar { opacity: .55; font-size: 13px; }
.dr-c-flecha { color: var(--muted); font-size: 20px; }

/* The way to GitLab: four steps joined by a line that fills as they are done */
.dr-c-camino { list-style: none; margin: 0; padding: 4px 0 0; display: grid; grid-template-columns: repeat(5, 1fr); counter-reset: paso; }
.dr-c-paso { position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; font-size: 11.5px; color: var(--muted); padding: 0 4px; border-radius: 8px; outline-offset: 2px; }
.dr-c-paso::before { content: ""; position: absolute; top: 15px; right: 50%; width: 100%; height: 2px; background: var(--border); z-index: 0; }
.dr-c-paso:first-child::before { display: none; }
.dr-c-paso--done::before, .dr-c-paso--current::before { background: var(--ok); }
.dr-c-paso.con-tooltip::after { right: auto; left: 50%; top: auto; bottom: calc(100% + 6px); transform: translateX(-50%); white-space: normal; width: 220px; text-align: left; z-index: 30; }
.dr-c-paso-icono { position: relative; z-index: 1; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; background: var(--panel); border: 2px solid var(--border-strong); font-size: 16px; transition: transform .2s ease, background .2s ease; }
.dr-c-paso--done { color: var(--text); }
.dr-c-paso--done .dr-c-paso-icono { background: var(--ok); border-color: var(--ok); color: #fff; }
.dr-c-paso--current { color: var(--accent); font-weight: 600; }
.dr-c-paso--current .dr-c-paso-icono { border-color: var(--accent); color: var(--accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent); animation: dr-c-latido 2s ease-in-out infinite; }
.dr-c-paso--failed .dr-c-paso-icono { border-color: var(--danger); color: var(--danger); background: var(--danger-bg); }
.dr-c-paso:hover .dr-c-paso-icono, .dr-c-paso:focus-visible .dr-c-paso-icono { transform: scale(1.08); }
@keyframes dr-c-latido { 50% { box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent) 8%, transparent); } }

/* Notices: what will happen and when, with their icon */
.dr-c-aviso { display: flex; align-items: flex-start; gap: 12px; padding: 12px 14px; border-radius: 10px; border: 1px solid var(--border); background: var(--neutral-bg); font-size: 12.5px; }
.dr-c-aviso > .mdi { font-size: 22px; line-height: 1; flex: none; }
.dr-c-aviso b { display: block; margin-bottom: 2px; font-size: 13px; }
.dr-c-aviso p { margin: 0; color: var(--muted); line-height: 1.45; }
.dr-c-aviso > div { flex: 1; }
.dr-c-aviso--info { background: var(--info-bg); border-color: color-mix(in srgb, var(--info) 30%, transparent); }
.dr-c-aviso--info > .mdi { color: var(--info); }
.dr-c-aviso--warn { background: var(--warn-bg); border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
.dr-c-aviso--warn > .mdi { color: var(--warn); }
.dr-c-aviso--danger { background: var(--danger-bg); border-color: color-mix(in srgb, var(--danger) 35%, transparent); }
.dr-c-aviso--danger > .mdi { color: var(--danger); }

/* The totals */
.dr-c-resumen { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin: 0; }
.dr-c-cifra { padding: 10px 12px; border-radius: 10px; border: 1px solid var(--border); background: var(--panel); transition: border-color .15s ease, transform .15s ease; }
.dr-c-cifra:hover, .dr-c-cifra:focus-visible { border-color: var(--accent); transform: translateY(-1px); }
.dr-c-cifra.con-tooltip::after { right: auto; left: 50%; top: auto; bottom: calc(100% + 6px); transform: translateX(-50%); }
.dr-c-cifra dt { font-size: 11px; color: var(--muted); display: flex; align-items: center; gap: 4px; text-transform: uppercase; letter-spacing: .04em; }
.dr-c-cifra dd { margin: 4px 0 0; font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; }
.dr-c-add { color: var(--ok-texto); font-weight: 600; }
.dr-c-del { color: var(--danger); font-weight: 600; }

/* Repos and search */
.dr-c-barra-herr { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; position: sticky; top: -16px; z-index: 3; background: var(--panel); padding: 6px 0; }
.dr-c-pestanas { display: inline-flex; gap: 2px; padding: 3px; border-radius: 10px; background: var(--neutral-bg); border: 1px solid var(--border); flex-wrap: wrap; }
.dr-c-pestanas [role="tab"] { border: 0; background: none; padding: 5px 10px; border-radius: 7px; font-size: 12px; color: var(--muted); display: inline-flex; align-items: center; gap: 6px; }
.dr-c-pestanas [role="tab"][aria-selected="true"] { background: var(--panel); color: var(--text); font-weight: 600; box-shadow: 0 1px 3px rgba(0, 0, 0, .12); }
.dr-c-pestanas [role="tab"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.dr-c-tab--sin { opacity: .65; }
.dr-c-cuenta { min-width: 18px; padding: 0 5px; border-radius: 999px; background: var(--border); color: var(--text); font-size: 10.5px; font-weight: 600; text-align: center; }
[aria-selected="true"] > .dr-c-cuenta { background: var(--accent); color: #fff; }
.dr-c-buscar { flex: 1; min-width: 200px; display: flex; align-items: center; gap: 6px; padding: 0 10px; border: 1px solid var(--border-strong); border-radius: 8px; background: var(--panel); }
.dr-c-buscar:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
.dr-c-buscar .mdi { color: var(--muted); font-size: 16px; }
.dr-c-buscar input { border: 0; outline: 0; background: none; flex: 1; padding: 7px 0; font-size: 12.5px; }

/* The commits by day, on a timeline */
.dr-c-lista { display: flex; flex-direction: column; gap: 14px; }
.dr-c-vacio { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 28px 10px; color: var(--muted); font-size: 12.5px; text-align: center; }
.dr-c-vacio .mdi { font-size: 34px; opacity: .6; }
.dr-c-dia-h { display: flex; align-items: center; gap: 8px; margin: 0 0 6px; font-size: 11.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.dr-c-dia-h::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.dr-c-dia-n { font-weight: 400; text-transform: none; letter-spacing: 0; }
.dr-c-linea { list-style: none; margin: 0; padding: 0 0 0 4px; position: relative; display: flex; flex-direction: column; gap: 8px; }
.dr-c-linea::before { content: ""; position: absolute; left: 15px; top: 6px; bottom: 6px; width: 2px; background: linear-gradient(var(--border-strong), var(--border)); border-radius: 2px; }
.dr-c-item { position: relative; display: flex; gap: 10px; align-items: flex-start; animation: dr-c-entra .25s ease both; }
.dr-c-nodo { position: relative; z-index: 1; flex: none; display: grid; place-items: center; width: 24px; height: 24px; margin-top: 10px; border-radius: 50%; background: var(--panel); border: 2px solid var(--border-strong); color: var(--muted); font-size: 13px; }
.dr-c-item--merge .dr-c-nodo { color: var(--info); border-color: var(--info); }
.dr-c-item--nuevo .dr-c-nodo { color: #fff; background: var(--accent); border-color: var(--accent); }
.dr-c-tarjeta { flex: 1; min-width: 0; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--border); background: var(--panel); transition: border-color .15s ease, box-shadow .15s ease; }
.dr-c-tarjeta:hover, .dr-c-tarjeta:focus-within { border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); box-shadow: 0 6px 18px -12px rgba(0, 0, 0, .35); }
.dr-c-item--nuevo .dr-c-tarjeta { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 5%, var(--panel)); }
.dr-c-cabeza { display: flex; gap: 10px; align-items: flex-start; }
.dr-c-avatar { --dr-c-hue: 210; flex: none; display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%; font-size: 11px; font-weight: 700; color: #fff; background: hsl(var(--dr-c-hue) 55% 38%); }
:root[data-theme="dark"]:not([data-presentacion]) .dr-c-avatar { background: hsl(var(--dr-c-hue) 45% 34%); }
.dr-c-texto { flex: 1; min-width: 0; }
.dr-c-titulo { margin: 0; font-size: 13px; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.dr-c-meta { margin: 3px 0 0; display: flex; flex-wrap: wrap; align-items: center; gap: 5px; font-size: 11.5px; color: var(--muted); }
.dr-c-cuando { text-decoration: underline dotted; text-underline-offset: 2px; cursor: help; }
.dr-c-chip { padding: 0 6px; border-radius: 999px; font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; background: var(--info-bg); color: var(--info); }
.dr-c-chip--nuevo { background: var(--accent); color: #fff; }
.dr-c-acciones { display: flex; align-items: center; gap: 8px; flex: none; }
.dr-c-barra { display: inline-flex; gap: 2px; }
.dr-c-bloque { width: 7px; height: 7px; border-radius: 2px; background: var(--border); }
.dr-c-bloque--add { background: var(--ok); }
.dr-c-bloque--del { background: var(--danger); }
.dr-c-lineas { font-size: 11px; font-variant-numeric: tabular-nums; }
.dr-c-sha { display: inline-flex; align-items: center; gap: 4px; padding: 3px 8px; border-radius: 6px; border: 1px solid var(--border); background: var(--neutral-bg); font-family: var(--mono); font-size: 11px; color: var(--text); }
.dr-c-sha:hover, .dr-c-sha:focus-visible { border-color: var(--accent); color: var(--accent); }
.dr-c-icono { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 6px; color: var(--muted); text-decoration: none; }
.dr-c-icono:hover, .dr-c-icono:focus-visible { color: var(--accent); background: var(--accent-soft); }
.dr-c-plegar { margin: 6px 0 0 40px; padding: 2px 6px; border: 0; background: none; color: var(--accent); font-size: 11.5px; display: inline-flex; align-items: center; gap: 2px; border-radius: 4px; }
.dr-c-plegar:hover { text-decoration: underline; }
.dr-c-mensaje { margin: 6px 0 0 40px; padding: 8px 10px; border-radius: 8px; background: var(--neutral-bg); border: 1px solid var(--border); font-family: var(--mono); font-size: 11.5px; white-space: pre-wrap; overflow-wrap: anywhere; max-height: 260px; overflow-y: auto; }
@keyframes dr-c-entra { from { opacity: 0; transform: translateY(4px); } }

/* Loading skeleton */
.dr-c-esqueleto { display: flex; flex-direction: column; gap: 10px; }
.dr-c-hueso { height: 54px; border-radius: 10px; background: linear-gradient(90deg, var(--neutral-bg) 25%, var(--esqueleto-brillo) 50%, var(--neutral-bg) 75%); background-size: 200% 100%; animation: dr-c-brillo 1.3s linear infinite; }
.dr-c-hueso--ancho { height: 36px; width: 60%; }
@keyframes dr-c-brillo { to { background-position: -200% 0; } }

/* Footer: when it was read and whether it keeps reading */
.dr-c-pie { align-items: center; flex-wrap: wrap; }
.dr-c-pie .spacer { flex: 1; }
.dr-c-pie a.btn-link { display: inline-flex; align-items: center; gap: 4px; text-decoration: none; }
.dr-c-vivo { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--muted); }
.dr-c-punto { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); }
.dr-c-punto--vivo { background: var(--ok); box-shadow: 0 0 0 0 color-mix(in srgb, var(--ok) 60%, transparent); animation: dr-c-pulso 2s ease-out infinite; }
@keyframes dr-c-pulso { 70% { box-shadow: 0 0 0 6px transparent; } }

@media (max-width: 720px) {
  .modal.dr-c { height: 94vh; }
  .dr-c-resumen { grid-template-columns: repeat(2, 1fr); }
  .dr-c-camino .dr-c-paso-texto { font-size: 10.5px; }
  .dr-c-acciones .dr-c-barra, .dr-c-acciones .dr-c-lineas { display: none; }
  .dr-c-sub { max-width: 30ch; }
}
@media (prefers-reduced-motion: reduce) {
  .dr-c-item, .dr-c-paso--current .dr-c-paso-icono, .dr-c-punto--vivo, .dr-c-hueso { animation: none; }
  .dr-c-cifra, .dr-c-paso-icono { transition: none; }
}
/* With a solid bar the header is the bar's blue: the subtitle, the icon and the state follow its white */
body[data-bar="solid"] .modal > header.dr-c-header { background: var(--bar-fill); }
body[data-bar="solid"] .dr-c-header .dr-c-sub { color: #fff; opacity: .9; }
body[data-bar="solid"] .dr-c-header .dr-c-logo { background: rgba(255, 255, 255, .18); border: 1px solid rgba(255, 255, 255, .45); box-shadow: none; }
body[data-bar="solid"] .dr-c-header .dr-estado { background: #fff; border-color: #fff; color: #1d2733; }

/* «Ver código» of a commit (DevRunCommitDiff.js): the files, then each one's unified diff as a table */
.dr-c-desplegables { display: flex; flex-wrap: wrap; gap: 4px; margin: 6px 0 0 40px; }
.dr-c-desplegables .dr-c-plegar { margin: 0; }
.dr-c-plegar--codigo { font-weight: 600; border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent); padding: 2px 8px; border-radius: 6px; }
.dr-c-plegar--codigo[aria-expanded="true"] { background: var(--accent-soft); }
.dr-c-plegar:disabled { opacity: .5; cursor: not-allowed; }
.dr-d { margin: 8px 0 0 40px; display: flex; flex-direction: column; gap: 8px; }
.dr-d-archivos { display: flex; flex-direction: column; gap: 8px; }
.dr-d-cargando { font-size: 12px; color: var(--muted); display: flex; align-items: center; gap: 6px; padding: 8px 0; }
.dr-d-indice { display: flex; align-items: center; gap: 6px; font-size: 12px; }
.dr-d-indice .spacer { flex: 1; }
.dr-d-indice-titulo { font-weight: 600; display: inline-flex; align-items: center; gap: 4px; }
.dr-d-lista-archivos { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.dr-d-ir { width: 100%; display: flex; align-items: center; gap: 6px; padding: 3px 6px; border: 0; border-radius: 6px; background: none; color: var(--text); font-size: 12px; text-align: left; }
.dr-d-ir:hover, .dr-d-ir:focus-visible { background: var(--neutral-bg); }
.dr-d-ir b { font-weight: 600; margin-right: auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dr-d-carpeta { color: var(--muted); font-family: var(--mono); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 45%; direction: rtl; text-align: left; }
.dr-d-tono--ok { color: var(--ok); }
.dr-d-tono--danger { color: var(--danger); }
.dr-d-tono--info { color: var(--info); }
.dr-d-tono--neutral { color: var(--muted); }
.dr-d-archivo { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; scroll-margin-top: 56px; }
.dr-d-cabecera { width: 100%; display: flex; align-items: center; gap: 6px; padding: 6px 10px; border: 0; border-bottom: 1px solid var(--border); background: var(--neutral-bg); color: var(--text); font-size: 12px; text-align: left; position: sticky; top: 0; z-index: 1; }
.dr-d-cabecera[aria-expanded="false"] { border-bottom: 0; }
.dr-d-cabecera .spacer { flex: 1; }
.dr-d-ruta { overflow-wrap: anywhere; font-size: 11.5px; }
.dr-d-cuerpo { overflow-x: auto; max-height: 520px; overflow-y: auto; }
.dr-d-tabla { border-collapse: collapse; width: 100%; font-family: var(--mono); font-size: 11.5px; line-height: 1.55; }
.dr-d-tabla td { padding: 0 8px; vertical-align: top; border: 0; }
.dr-d-num { width: 1%; min-width: 42px; text-align: right; color: var(--muted); user-select: none; border-right: 1px solid var(--border) !important; font-variant-numeric: tabular-nums; }
.dr-d-codigo { white-space: pre; tab-size: 4; }
.dr-d-marca { display: inline-block; width: 1.2em; user-select: none; color: var(--muted); }
.dr-d-fila--add { background: color-mix(in srgb, var(--ok) 12%, transparent); }
.dr-d-fila--add .dr-d-num { background: color-mix(in srgb, var(--ok) 18%, transparent); }
.dr-d-fila--add .dr-d-marca { color: var(--ok-texto); }
.dr-d-fila--del { background: color-mix(in srgb, var(--danger) 11%, transparent); }
.dr-d-fila--del .dr-d-num { background: color-mix(in srgb, var(--danger) 17%, transparent); }
.dr-d-fila--del .dr-d-marca { color: var(--danger); }
.dr-d-hunk { background: var(--info-bg); color: var(--info); padding: 3px 8px !important; font-size: 11px; }
.dr-d-meta { color: var(--muted); font-style: italic; }
.dr-d-nota { margin: 0; padding: 8px 10px; font-size: 12px; color: var(--muted); }

/* The merge requests of the branch (DevRunMrCard.js) */
.dr-mr-seccion { display: flex; flex-direction: column; gap: 8px; }
.dr-mr { display: flex; gap: 12px; align-items: flex-start; padding: 12px 14px; border-radius: 10px; border: 1px solid var(--border); border-left: 4px solid var(--muted); background: var(--panel); }
.dr-mr--ok { border-left-color: var(--ok); }
.dr-mr--info { border-left-color: var(--info); }
.dr-mr--danger { border-left-color: var(--danger); }
.dr-mr--warn { border-left-color: var(--warn); }
.dr-mr-icono { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; flex: none; font-size: 18px; background: var(--neutral-bg); color: var(--muted); }
.dr-mr--ok .dr-mr-icono { background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ok-texto); }
.dr-mr--info .dr-mr-icono { background: var(--info-bg); color: var(--info); }
.dr-mr--danger .dr-mr-icono { background: var(--danger-bg); color: var(--danger); }
.dr-mr-cuerpo { flex: 1; min-width: 0; }
.dr-mr-linea { margin: 0; display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.dr-mr-repo { color: var(--muted); }
.dr-mr-iid { color: var(--muted); font-weight: 600; }
.dr-mr-titulo { margin: 4px 0 0; font-size: 13.5px; font-weight: 600; overflow-wrap: anywhere; }
.dr-mr-listo { margin: 6px 0 0; display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 6px; font-size: 11.5px; font-weight: 600; }
.dr-mr-listo--ok { background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok-texto); }
.dr-mr-listo--warn { background: var(--warn-bg); color: var(--warn); }
.dr-mr-listo--neutral { background: var(--neutral-bg); color: var(--muted); }
.dr-mr-plegar { margin: 6px 0 0; padding-left: 0; display: flex; }
.dr-mr-descripcion { margin-left: 0; }
.dr-mr-acciones { display: flex; flex-direction: column; gap: 6px; flex: none; }
.dr-mr-acciones a.btn-link { display: inline-flex; align-items: center; gap: 4px; text-decoration: none; justify-content: flex-start; }
.dr-mr-ninguno { margin: 0; display: flex; align-items: center; gap: 8px; padding: 10px 12px; border: 1px dashed var(--border-strong); border-radius: 10px; color: var(--muted); font-size: 12.5px; }
.dr-mr-ninguno .mdi { font-size: 18px; }
@media (max-width: 720px) {
  .dr-mr { flex-wrap: wrap; }
  .dr-mr-acciones { flex-direction: row; width: 100%; }
  .dr-d, .dr-c-desplegables { margin-left: 0; }
}

/* «Comenzar desarrollo», the confirmation (26-10-2026): five blocks in plain words — what happens, what is
   developed, where, whether everything is ready, and the safety limits and the ticket's estimated hours */
.modal.dr-confirmar { max-width: 780px; width: 100%; }
.dr-confirmar-body { gap: 12px; background: var(--bg); }
.dr-modo-chip { padding: 1px 10px; border-radius: 999px; font-size: 11px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; background: rgba(255, 255, 255, .92); color: #1d2733; }
.dr-modo-chip--real { color: #8a4b00; }
.dr-confirmar .dr-real-banner { display: block; padding: 12px 14px; border-radius: 10px; }
.dr-pasos-titulo { margin: 0 0 6px; font-size: 13px; }
.dr-pasos { margin: 0; padding: 0; list-style: none; counter-reset: paso; display: grid; gap: 6px; }
.dr-pasos li { counter-increment: paso; display: flex; gap: 10px; align-items: flex-start; font-size: 12.5px; line-height: 1.45; }
.dr-pasos li::before { content: counter(paso); flex: none; display: grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; background: var(--warn); color: #fff; font-size: 11px; font-weight: 700; }
.dr-bloque { padding: 12px 14px; border-radius: 10px; border: 1px solid var(--border); background: var(--panel); }
.dr-bloque-h { margin: 0 0 10px; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); display: flex; align-items: center; gap: 6px; }
.dr-bloque-h .mdi { font-size: 16px; color: var(--accent); }
.dr-confirmar .dr-ficha { grid-template-columns: 120px 1fr; gap: 8px 14px; }
.dr-doc { display: inline-flex; align-items: center; gap: 4px; font-weight: 600; overflow-wrap: anywhere; }
.dr-doc .mdi { color: var(--accent); }
.dr-mini { padding: 0 6px; font-size: 12px; }
.dr-confirmar .dr-criterios-lista li { margin: 4px 0; line-height: 1.45; }
.dr-repos { display: flex; flex-wrap: wrap; gap: 4px; }
.dr-confirmar .dr-repo { margin: 0; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--border); }
.dr-confirmar #dr-proyecto { min-width: 200px; }
.dr-confirmar .dr-preflight { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 14px; padding: 8px 10px; border-radius: 8px; background: var(--neutral-bg); }
.dr-dos-bloques { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.dr-limites { margin: 0 0 8px; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 6px; }
.dr-limites li { display: inline-flex; align-items: center; gap: 4px; padding: 3px 10px; border-radius: 999px; background: var(--neutral-bg); border: 1px solid var(--border); font-size: 12px; cursor: help; }
.dr-limites li .mdi { color: var(--muted); }
.dr-limites li.con-tooltip::after { white-space: normal; width: 220px; z-index: 30; }
.dr-bloque .hint { font-size: 11.5px; line-height: 1.45; margin: 0; }
.dr-horas-cifra { margin: 0 0 4px; font-size: 22px; font-weight: 700; }
.dr-horas-filas { margin: 8px 0 0; padding: 0; list-style: none; font-size: 12px; display: grid; gap: 3px; }
.dr-horas-filas li { display: flex; justify-content: space-between; gap: 10px; color: var(--muted); }
.dr-horas-filas li.dr-horas-cuenta { color: var(--text); font-weight: 600; }
.dr-confirmar .dr-avisos { border: 1px solid color-mix(in srgb, var(--warn) 35%, transparent); border-radius: 10px; }
@media (max-width: 720px) {
  .dr-dos-bloques, .dr-confirmar .dr-preflight { grid-template-columns: 1fr; }
  .dr-confirmar .dr-ficha { grid-template-columns: 1fr; gap: 2px 0; }
  .dr-confirmar .dr-ficha dd { margin-bottom: 6px; }
}

/* «Skills del runner» (modules/devSkills, 27-10-2026): catalog, detail, version, editor and consumption */
.modal.skills-modal { max-width: min(1100px, calc(100vw - 32px)); }
.skills-modal .body { max-height: calc(100vh - 200px); overflow: auto; }
.skills-filtros { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 8px 0 12px; }
.skills-filtros input[type="search"] { flex: 1 1 260px; min-width: 0; }
.skills-tabla { margin: 6px 0 12px; }
.skills-tabla th, .skills-tabla td { text-align: left; vertical-align: top; padding: 8px 10px; border-bottom: 1px solid var(--border); }
.skills-tabla th { font-weight: 600; color: var(--muted); }
.skills-tabla tr.fila-clicable:hover, .skills-tabla tr.fila-clicable:focus-visible { background: var(--neutral-bg); outline: none; }
.skills-tabla .chip { margin: 0 4px 4px 0; }
.skills-descripcion { max-width: 520px; }
.skills-activa { background: color-mix(in srgb, var(--ok) 7%, transparent); }
.skills-acciones { white-space: nowrap; }
.skills-acciones .btn-link { margin-right: 8px; }
.skills-resumen { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 10px; }
.skills-auditoria ul { margin: 6px 0 0; padding-left: 18px; }
.skills-ficha { display: grid; grid-template-columns: max-content 1fr; gap: 4px 14px; margin: 0 0 12px; }
.skills-ficha dt { font-weight: 600; color: var(--muted); }
.skills-ficha dd { margin: 0; overflow-wrap: anywhere; }
.skills-ficha ul { margin: 0; padding-left: 18px; }
.skills-texto, .skills-diff { white-space: pre-wrap; overflow-wrap: anywhere; font-size: 12.5px; line-height: 1.55; border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; max-height: 420px; overflow: auto; margin: 6px 0 12px; }
.skills-diff span { display: block; }
.skills-diff .skills-add, td.skills-add { background: color-mix(in srgb, var(--ok) 14%, transparent); }
.skills-diff .skills-del, td.skills-del { background: color-mix(in srgb, var(--danger) 12%, transparent); }
.skills-diff .skills-same { color: var(--muted); }
.skills-campos { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 14px; }
.skills-campos .skills-ancho { grid-column: 1 / -1; }
.skills-editor textarea { width: 100%; }
.skills-opciones { display: flex; flex-wrap: wrap; gap: 6px 14px; border: 1px solid var(--border); border-radius: 8px; padding: 8px 12px; margin: 10px 0; }
.skills-opciones legend { padding: 0 4px; font-weight: 600; }
.skills-referencia { border: 1px solid var(--border); border-radius: 8px; padding: 8px; margin-bottom: 8px; }
.skills-referencia-cabecera { display: flex; gap: 8px; align-items: center; margin-bottom: 6px; }
.skills-referencia-cabecera input { flex: 1; }
@media (max-width: 720px) {
  .skills-campos { grid-template-columns: 1fr; }
  .skills-ficha { grid-template-columns: 1fr; }
  .skills-acciones { white-space: normal; }
}

/* One version of a skill (SkillVersionView): a side card with the manifest and the files, and a large viewer */
.modal.skills-modal--visor { max-width: min(1320px, calc(100vw - 32px)); width: 100%; }
.skills-modal--visor .body { max-height: none; overflow: visible; padding: 0; }
.skv { display: grid; grid-template-columns: 320px minmax(0, 1fr); height: calc(100vh - 150px); min-height: 420px; }
.skv-lateral { overflow: auto; padding: 16px; border-right: 1px solid var(--border); background: var(--neutral-bg); }
.skv-insignias { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.skv-nombre { margin: 0 0 4px; font-size: 15px; line-height: 1.3; }
.skv-descripcion { margin: 0 0 14px; color: var(--muted); font-size: 12.5px; line-height: 1.5; }
.skv-ficha { display: grid; grid-template-columns: 1fr; gap: 2px; margin: 0 0 14px; font-size: 12.5px; }
.skv-ficha dt { font-weight: 600; color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .04em; margin-top: 8px; }
.skv-ficha dd { margin: 0; overflow-wrap: anywhere; }
.skv-ficha ul { margin: 2px 0 0; padding-left: 16px; }
.skv-ficha .chip { margin: 2px 4px 2px 0; font-size: 11.5px; }
.skv-subtitulo { margin: 14px 0 6px; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.skv-archivos { display: flex; flex-direction: column; gap: 2px; }
.skv-archivos button { display: flex; align-items: center; gap: 6px; width: 100%; text-align: left; border: 1px solid transparent; background: none; border-radius: 6px; padding: 6px 8px; cursor: pointer; color: inherit; font: inherit; font-size: 12.5px; }
.skv-archivos button:hover { background: var(--accent-soft); }
.skv-archivos button.activo { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 600; }
.skv-archivos button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.skv-archivo-nombre { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.skv-runs { margin: 0; padding-left: 16px; font-size: 12.5px; }
.skv-visor { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.skv-barra { display: flex; align-items: center; gap: 10px; padding: 10px 16px; border-bottom: 1px solid var(--border); }
.skv-ruta { font-weight: 600; overflow-wrap: anywhere; }
.skv-codigo { flex: 1; overflow: auto; padding: 12px 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13.5px; line-height: 1.65; }
.skv-codigo:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.skv-linea { display: grid; grid-template-columns: 52px minmax(0, 1fr); }
.skv-linea:hover { background: var(--neutral-bg); }
.skv-n { text-align: right; padding-right: 14px; color: var(--muted); opacity: .6; user-select: none; }
.skv-t { white-space: pre-wrap; overflow-wrap: anywhere; padding-right: 16px; }
.skv-linea.skv-fm .skv-t { color: var(--muted); }
.skv-linea.skv-h .skv-t { font-weight: 700; color: var(--accent); }
.skv-linea.skv-li .skv-t { padding-left: 2px; }
.skv-linea.skv-code { background: color-mix(in srgb, var(--neutral-bg) 70%, transparent); }
@media (max-width: 860px) {
  .skv { grid-template-columns: 1fr; height: auto; }
  .skv-lateral { border-right: 0; border-bottom: 1px solid var(--border); }
  .skv-codigo { max-height: 70vh; }
}

/* «Entendimiento» (DevRunUnderstanding, 27-10-2026): header, summary tiles, the clarification panel as cards */
.ent { gap: 14px; }
.ent-cabeza { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.ent-cabeza h3 { margin: 0; font-size: 16px; display: flex; align-items: center; gap: 6px; }
.ent-cabeza h3 .mdi { color: var(--accent); }
.ent-cabeza p { margin: 2px 0 0; }
.ent-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.ent-kpi { display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto; column-gap: 10px; align-items: center; padding: 10px 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); border-left-width: 4px; }
.ent-kpi .mdi { grid-row: 1 / 3; font-size: 22px; }
.ent-kpi b { font-size: 18px; line-height: 1.1; }
.ent-kpi span { font-size: 12px; color: var(--muted); }
.ent-kpi--ok { border-left-color: var(--ok); } .ent-kpi--ok .mdi { color: var(--ok); }
.ent-kpi--warn { border-left-color: var(--warn); } .ent-kpi--warn .mdi { color: var(--warn); }
.ent-kpi--danger { border-left-color: var(--danger); } .ent-kpi--danger .mdi { color: var(--danger); }
.dr-aclaracion.ent-aclarar { gap: 12px; padding: 16px; border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent); border-left: 4px solid var(--warn); border-radius: 10px; background: var(--warn-bg); }
.ent-aclarar-cabeza { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ent-aclarar-cabeza > .mdi { font-size: 28px; color: var(--warn); }
.ent-aclarar-texto { flex: 1 1 280px; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ent-aclarar-texto b { font-size: 14px; }
.ent-progreso { height: 6px; border-radius: 999px; background: color-mix(in srgb, var(--warn) 18%, transparent); overflow: hidden; margin-top: 6px; max-width: 420px; }
.ent-progreso span { display: block; height: 100%; background: var(--ok); transition: width .35s ease; }
.ent-todo { display: inline-flex; align-items: center; gap: 6px; padding: 9px 16px; font-weight: 600; box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 30%, transparent); }
.ent-subtitulo { display: flex; align-items: center; gap: 6px; margin: 4px 0 0; font-size: 13px; }
.ent-subtitulo .mdi { color: var(--accent); font-size: 16px; }
.ent-subtitulo--danger, .ent-subtitulo--danger .mdi { color: var(--danger); }
.ent-codigo { display: inline-block; min-width: 26px; padding: 1px 6px; margin-right: 4px; border-radius: 6px; background: var(--accent-soft); color: var(--accent); font-size: 11.5px; font-weight: 700; text-align: center; }
.ent-tarjeta { padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); transition: border-color .2s, box-shadow .2s; }
.ent-tarjeta:hover { box-shadow: 0 2px 10px rgba(0, 0, 0, .06); }
.ent-tarjeta--hecha { border-color: color-mix(in srgb, var(--ok) 45%, transparent); }
/* 03-11-2026 (contrato de alcance): the «Añadidos» group — what the ticket does not ask for — and its help line */
.ent-grupo-ayuda { margin: -2px 0 0; }
.ent-tarjeta--anadido { border-left: 3px solid var(--warn); }
.ent-tarjeta > label { font-size: 13.5px; font-weight: 600; line-height: 1.45; }
.ent .drd-avisos { background: var(--panel); border-radius: 10px; padding: 12px 14px; gap: 4px; }
.ent .drd-aviso { padding: 8px 10px; border-radius: 8px; line-height: 1.5; cursor: pointer; transition: background .15s; }
.ent .drd-aviso:hover { background: var(--neutral-bg); }
.ent .drd-aviso--hecho { cursor: default; color: var(--muted); }
.ent .drd-aviso--hecho .mdi-check-circle { color: var(--ok); margin-top: 2px; }
.ent-avisos-acciones { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.ent-acciones { flex-wrap: wrap; align-items: center; padding-top: 10px; border-top: 1px solid color-mix(in srgb, var(--warn) 30%, transparent); }
.ent .drd-puntos { display: flex; flex-direction: column; gap: 8px; }
.ent .drd-punto { border-radius: 10px; border-left-width: 4px; transition: box-shadow .2s; }
.ent .drd-punto:hover { box-shadow: 0 2px 10px rgba(0, 0, 0, .06); }
.ent .drd-punto--ok { border-left-color: var(--ok); }
.ent .drd-punto--danger { border-left-color: var(--danger); }
.ent .drd-punto-cabeza { padding: 10px 14px; }
.ent .drd-punto-cuerpo { padding: 4px 14px 14px; gap: 14px; }
.ent .drd-punto-col { padding: 10px 12px; border-radius: 8px; background: var(--neutral-bg); }
.ent .drd-punto-col h5 { display: flex; align-items: center; gap: 4px; }
.ent-archivos { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 8px; }
.ent-archivo { padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); min-width: 0; }
.ent-archivo-cabeza { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ent-archivo-ruta { flex: 1 1 160px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
.ent-archivo-cambio { margin: 6px 0 0; font-size: 12.5px; line-height: 1.5; }
.ent-archivo .hint { margin: 4px 0 0; }
@media (max-width: 900px) {
  .ent-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ent-cabeza { flex-direction: column; }
}
@media (prefers-reduced-motion: reduce) { .ent-progreso span, .ent-tarjeta, .ent .drd-punto { transition: none; } }

/* «Plan adaptativo» (DevRunAdaptivePlan, 27-10-2026): the route, why, each phase planned vs done, the rises */
.dra { display: flex; flex-direction: column; gap: 10px; margin: 12px 0; }
.dra-cabeza { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.dra-cabeza h3 { margin: 0; display: flex; align-items: center; gap: 6px; }
.dra-cabeza h3 .mdi { color: var(--accent); }
.dra-politica { margin-left: auto; }
.dra-perfil { padding: 2px 12px; border-radius: 999px; font-weight: 700; font-size: 12px; letter-spacing: .05em; color: #fff; }
.dra-perfil--simple { background: var(--ok); }
.dra-perfil--medio { background: var(--warn); }
.dra-perfil--alto { background: var(--danger); }
.dra-senales { margin: 6px 0; padding-left: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; }
.dra-fases { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 8px; }
.dra-fase { display: flex; gap: 8px; align-items: flex-start; padding: 8px 10px; border: 1px solid var(--border); border-left-width: 4px; border-radius: 8px; background: var(--panel); }
.dra-fase .mdi { font-size: 18px; margin-top: 1px; }
.dra-fase-texto { display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 12.5px; }
.dra-fase-nombre { font-weight: 600; }
.dra-fase-estado { font-size: 12px; }
.dra-fase--ok { border-left-color: var(--ok); } .dra-fase--ok .mdi { color: var(--ok); }
.dra-fase--danger { border-left-color: var(--danger); } .dra-fase--danger .mdi { color: var(--danger); }
.dra-fase--neutral { border-left-color: var(--border-strong, var(--border)); } .dra-fase--neutral .mdi { color: var(--muted); }
.dra-fase--omitida { border-left-color: var(--muted); border-style: dashed; background: var(--neutral-bg); } .dra-fase--omitida .mdi, .dra-fase--omitida .dra-fase-estado { color: var(--muted); }
.dra-columnas { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.dra-columnas h4, .dra h4 { margin: 6px 0 4px; font-size: 12.5px; }
.dra-columnas ul, .dra-historial { margin: 0; padding-left: 18px; font-size: 12.5px; }
.dra .chip { margin: 0 4px 4px 0; }
@media (max-width: 720px) { .dra-columnas { grid-template-columns: 1fr; } .dra-politica { margin-left: 0; } }
.dr-ruta-prevista h4 { display: flex; align-items: center; gap: 6px; margin: 0 0 4px; } .dr-ruta-prevista ul { margin: 0; padding-left: 18px; }

/* Explorer of the ticket's files → «Información» (docViewer/FileInfoModal.js) */
.archivo-info { width: min(620px, 100%); }
.archivo-info .body { display: flex; flex-direction: column; gap: 14px; }
.archivo-info-seccion h4 { margin: 0 0 6px; font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted, #64748b); }
.archivo-info-seccion dl { display: grid; grid-template-columns: max-content 1fr; gap: 6px 14px; margin: 0; }
.archivo-info-seccion dt { font-weight: 600; font-size: 13px; }
.archivo-info-seccion dd { margin: 0; font-size: 13px; display: flex; align-items: flex-start; gap: 6px; min-width: 0; }
.archivo-info-seccion dd span { overflow-wrap: anywhere; }
.archivo-info-seccion dd.mono span { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
.archivo-info-copiar { padding: 0 6px; height: 22px; flex: none; }
.archivo-info-esqueleto { display: flex; flex-direction: column; gap: 10px; }
@media (max-width: 560px) { .archivo-info-seccion dl { grid-template-columns: 1fr; gap: 2px; } .archivo-info-seccion dd { margin-bottom: 8px; } }
/* «Información» de un archivo, pequeña: el archivo con su ícono y sus etiquetas, y debajo sus dos
   momentos (creado y modificado), cada uno con quién y cuándo */
.archivo-info.archivo-info-compacta { width: min(420px, 100%); }
.archivo-info-compacta .body { gap: 14px; padding-bottom: 18px; }
.archivo-info-cabeza { display: flex; align-items: flex-start; gap: 12px; }
.archivo-info-icono {
  flex: none; display: inline-flex; align-items: center; justify-content: center; width: 42px; height: 42px;
  border-radius: 10px; background: var(--accent-soft); color: var(--brand); font-size: 24px;
}
.archivo-info-nombre { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.archivo-info-nombre strong { font-size: 14px; line-height: 1.35; overflow-wrap: anywhere; }
.archivo-info-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.archivo-info-chip {
  display: inline-flex; align-items: center; height: 20px; padding: 0 8px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--neutral-bg); color: var(--muted); font-size: 11px; font-weight: 600;
}
.archivo-info-chip.chip-version { border-color: var(--accent); color: var(--brand); background: var(--accent-soft); }
.archivo-info-momentos { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: 8px; }
.archivo-info-momentos li { display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px; }
.archivo-info-momentos li + li { border-top: 1px solid var(--border); }
.archivo-info-momentos li > div { display: grid; grid-template-columns: 1fr auto; gap: 2px 10px; min-width: 0; flex: 1 1 auto; }
.archivo-info-momento-icono { flex: none; color: var(--muted); font-size: 18px; line-height: 1; padding-top: 1px; }
.archivo-info-momento-etiqueta { grid-column: 1 / -1; font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.archivo-info-momento-quien { font-size: 13px; font-weight: 600; overflow-wrap: anywhere; }
.archivo-info-momento-cuando { font-size: 12px; color: var(--muted); white-space: nowrap; }

/* «Horas acordadas» → la ronda de aprobación (components/RondasConsenso.js) */
.rondas-consenso { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 10px; }
.rondas-consenso .selector-ronda { max-width: 460px; }
.rondas-consenso .sobre-version { margin: 0; }
.rondas-consenso .sobre-version .mdi, .aviso-cambio-version .mdi { margin-right: 4px; }

/* App móvil → «Personas con la app» (AppPeoplePanel) and the KPIs of the people with the app: six
   cards in «Ver descargas», three here; they fit as many per row as the width allows */
.descargas-app-kpis { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.descargas-app-kpi .descargas-app-kpi-nota { font-size: 11px; }
.personas-app-nota { margin: 0; }
.personas-app-version { white-space: nowrap; }
.personas-app-desactualizada { margin-left: 6px; font-size: 11px; }

/* «Columnas» (DocsColumnPicker): the toolbar button and its floating list of checkboxes */
.selector-columnas { position: relative; }
.selector-columnas > .btn.abierto { border-color: var(--accent); color: var(--accent); }
.selector-columnas > .btn.activo { color: var(--accent); }
.menu-columnas {
  z-index: 60; display: flex; flex-direction: column; gap: 10px;
  width: 300px; padding: 12px 14px; overflow: auto;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
}
.menu-columnas-cabecera { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-weight: 600; }
.menu-columnas-nota { margin: 0; }
.menu-columnas-seccion { margin: 0; padding: 0; border: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 4px 12px; }
.menu-columnas-seccion > legend {
  grid-column: 1 / -1; padding: 0 0 4px; font-size: 11px; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted);
}
.menu-columnas-opcion { display: flex; align-items: center; gap: 8px; min-height: 28px; font-size: 13px; cursor: pointer; }
.menu-columnas-opcion input:disabled + span { color: var(--muted); }
@media (max-width: 640px) {
  .acciones-docs > .selector-columnas > .btn { width: 100%; justify-content: center; }
}

/* ================================================================================================================
   EL MODAL DEL RUN, REDISEÑADO (27-10-2026, mockup «Modal del run · rediseño» del equipo de diseño): cabecera blanca
   con el estado en palabras, cinco pestañas (Resumen, Requerimiento, Pruebas, Código, Actividad), tarjetas con borde
   fino sobre fondo gris, chips de estado y etiquetas en mayúsculas. Todo con los tokens de la app (tema oscuro incluido).
   ================================================================================================================ */
.modal.drx { padding: 0; overflow: hidden; }
.modal.drx > header.drx-cabecera { display: flex; flex-direction: column; gap: 12px; padding: 18px 24px 0; background: var(--panel); color: var(--text); border-bottom: 1px solid var(--border); font-weight: 400; }
.drx-cabecera-fila { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 12px 16px; }
.drx-identidad { display: flex; flex-direction: column; gap: 10px; min-width: 0; flex: 1 1 480px; }
.drx-titulo-fila { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.drx-titulo { margin: 0; font-size: 20px; line-height: 1.25; font-weight: 700; color: var(--text); }
.drx-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; font-size: 13px; }
.drx-meta strong { color: var(--text); font-weight: 600; }
.drx-acciones { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.drx-intentos select { height: 36px; padding: 0 10px; border: 1px solid var(--border-strong); border-radius: 8px; background: var(--panel); color: var(--text); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; }
.drx-cabecera .drd-ahora { margin: 0; }
.drx-tabs.drd-tabs { position: static; margin: 0 -24px; padding: 0 24px; gap: 0 24px; border-bottom: 0; background: transparent; }
.drx-tab.drd-tab { padding: 0; height: 44px; font-size: 14px; font-weight: 500; color: var(--muted); }
.drx-tab.drd-tab:hover { color: var(--text); }
.drx-tab.drd-tab.drd-tab--activa { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
.modal.drx .body.drx-cuerpo { padding: 24px; gap: 20px; background: var(--bg); }
.drx-cuerpo > .drd-panel { display: flex; flex-direction: column; }
.drx-cuerpo .drd-panel[hidden] { display: none !important; }

/* Piezas comunes */
.drx-chip { display: inline-flex; align-items: center; gap: 5px; min-height: 22px; padding: 0 9px; border-radius: 999px; font-size: 12px; font-weight: 600; white-space: nowrap; line-height: 1; }
.drx-chip .mdi { font-size: 13px; }
.drx-chip--ok { color: var(--ok-texto); background: color-mix(in srgb, var(--ok) 14%, transparent); }
.drx-chip--danger { color: var(--danger); background: var(--danger-bg); }
.drx-chip--warn { color: var(--warn); background: var(--warn-bg); }
.drx-chip--info { color: var(--info); background: var(--info-bg); }
.drx-chip--neutral { color: var(--text); background: var(--neutral-bg); }
.drx-chip--qa { color: var(--ok, #1b7f4b); background: var(--ok-bg, rgba(27, 127, 75, .1)); }
.drx-tenue { color: var(--muted); }
.drx-etiqueta { margin: 0; font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.drx-crece { flex: 1 1 auto; }
.drx-nowrap { white-space: nowrap; }
.drx-vacio { margin: 0; color: var(--muted); font-size: 13px; }
.drx-pie { margin: 0; font-size: 12px; }
.drx-btn { display: inline-flex; align-items: center; gap: 6px; height: 36px; padding: 0 14px; border-radius: 8px; border: 1px solid var(--border-strong); background: var(--panel); color: var(--text); font: inherit; font-size: 13px; font-weight: 600; white-space: nowrap; cursor: pointer; }
.drx-btn:hover:not(:disabled) { border-color: var(--accent); }
.drx-btn:disabled { opacity: .55; cursor: not-allowed; }
.drx-btn--pri { background: var(--brand); border-color: var(--brand); color: #fff; }
.drx-btn--pri:hover:not(:disabled) { background: var(--brand-strong); border-color: var(--brand-strong); }
.drx-btn--peligro { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 45%, transparent); }
.drx-btn--sm { height: 30px; padding: 0 10px; font-size: 12px; }
.drx-btn--icono { width: 36px; padding: 0; justify-content: center; }
.drx-btn--icono.drx-btn--sm { width: 30px; flex: none; }
.drx-btn .mdi { font-size: 16px; }
.drx-enlace { font-size: 13px; font-weight: 600; white-space: nowrap; }
.drx-enlace-bloque { display: block; }
.drx-tarjeta { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 18px 22px; display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.drx-tarjeta h3, .drx-seccion-cabeza h3 { margin: 0; font-size: 15px; font-weight: 700; }
.drx-tarjeta-cabeza { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; }
.drx-tarjeta-cabeza--base { align-items: baseline; }
.drx-cifra { font-size: 19px; font-weight: 700; }
.drx-seccion-cabeza { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 10px 16px; }
.drx-seccion-cabeza > div:first-child { display: flex; flex-direction: column; gap: 4px; }
.drx-icono-grande { width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; flex: none; font-size: 22px; }
.drx-hechos { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); gap: 10px; }
.drx-hecho { background: var(--panel); border: 1px solid var(--border); border-radius: 8px; padding: 12px 14px; display: flex; flex-direction: column; gap: 5px; min-width: 0; font-size: 14px; overflow-wrap: anywhere; }
.drx-hechos--cuatro .drx-hecho { background: var(--bg); }
.drx-bloque-lista { display: flex; flex-direction: column; gap: 6px; }
.drx-bloque-lista ol, .drx-bloque-lista ul { margin: 0; padding-left: 20px; font-size: 14px; line-height: 1.6; }
.drx-fila-acciones { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.drx-filtros { display: flex; flex-wrap: wrap; gap: 6px; }
.drx-filtro { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; border-radius: 999px; border: 1px solid var(--border); background: var(--panel); color: var(--text); font: inherit; font-size: 13px; cursor: pointer; }
.drx-filtro--activo { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.drx-aviso { display: flex; gap: 10px; align-items: flex-start; padding: 12px 16px; border-radius: 8px; border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent); background: var(--warn-bg); font-size: 14px; }
.drx-aviso > .mdi { color: var(--warn); font-size: 18px; }
.drx-aviso[data-tono="ok"] { border-color: color-mix(in srgb, var(--ok) 40%, transparent); background: var(--ok-bg, var(--neutral-bg)); }
.drx-aviso[data-tono="ok"] > .mdi { color: var(--ok); }
.drx-aviso summary { cursor: pointer; font-weight: 600; }
.drx-aviso ul { margin: 6px 0 0; padding-left: 20px; }
.drx-nota { display: flex; gap: 10px; align-items: baseline; padding: 10px 14px; border-radius: 8px; background: var(--panel); border: 1px dashed var(--border); font-size: 13px; }
.drx-tabla-caja { overflow-x: auto; max-width: 100%; border: 1px solid var(--border); border-radius: 8px; }
.drx-tabla { width: 100%; border-collapse: collapse; font-size: 13px; }
.drx-tabla th { text-align: left; padding: 9px 12px; background: var(--bg); color: var(--muted); font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; white-space: nowrap; border-bottom: 1px solid var(--border); }
.drx-tabla td { padding: 10px 12px; vertical-align: top; border-top: 1px solid var(--border); white-space: normal; overflow-wrap: anywhere; }
.drx-tabla tbody tr:first-child td { border-top: 0; }
.drx-tabla-simple { width: 100%; border-collapse: collapse; font-size: 13px; }
.drx-tabla-simple th { text-align: right; padding: 0 0 8px; color: var(--muted); font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }
.drx-tabla-simple th:first-child, .drx-tabla-simple td:first-child { text-align: left; }
.drx-tabla-simple td { text-align: right; padding: 9px 0; border-top: 1px solid var(--border); white-space: nowrap; font-variant-numeric: tabular-nums; }
.drx-kv { display: grid; grid-template-columns: 110px minmax(0, 1fr); gap: 9px 14px; margin: 0; font-size: 13px; }
.drx-kv dt { color: var(--muted); }
.drx-kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.drx-kv-copiar { display: flex; gap: 6px; align-items: center; }
.drx-recorte { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }

/* Resumen */
.drx-resumen, .drx-requerimiento, .drx-pruebas, .drx-codigo, .drx-actividad { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.drx-parada { display: flex; flex-direction: column; gap: 16px; padding: 22px; border-radius: 10px; background: color-mix(in srgb, var(--danger-bg) 65%, var(--panel)); border: 1px solid color-mix(in srgb, var(--danger) 30%, transparent); }
.drx-parada[data-estado="incomplete"] { background: color-mix(in srgb, var(--warn-bg) 65%, var(--panel)); border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
.drx-parada[data-estado="canceled"] { background: var(--panel); border-color: var(--border); }
.drx-parada-cabeza { display: flex; gap: 14px; align-items: flex-start; }
.drx-parada .drx-icono-grande { background: var(--danger-bg); color: var(--danger); }
.drx-parada[data-estado="incomplete"] .drx-icono-grande { background: var(--warn-bg); color: var(--warn); }
.drx-parada[data-estado="canceled"] .drx-icono-grande { background: var(--neutral-bg); color: var(--muted); }
.drx-parada-texto { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.drx-parada-texto .drx-etiqueta { color: var(--danger); }
.drx-parada[data-estado="incomplete"] .drx-parada-texto .drx-etiqueta { color: var(--warn); }
.drx-parada-texto h3 { margin: 0; font-size: 18px; line-height: 1.3; overflow-wrap: anywhere; }
.drx-parada-texto p:not(.drx-etiqueta) { margin: 0; font-size: 14px; line-height: 1.55; max-width: 760px; }
.drx-espera { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; padding: 18px 22px; border-radius: 10px; border: 1px solid color-mix(in srgb, var(--warn) 35%, transparent); background: color-mix(in srgb, var(--warn-bg) 70%, var(--panel)); }
.drx-espera[data-tono="danger"] { border-color: color-mix(in srgb, var(--danger) 35%, transparent); background: color-mix(in srgb, var(--danger-bg) 70%, var(--panel)); }
.drx-espera[data-tono="info"], .drx-espera[data-tono="neutral"] { border-color: var(--border); background: var(--panel); }
.drx-espera .drx-icono-grande { background: var(--warn-bg); color: var(--warn); }
.drx-espera[data-tono="danger"] .drx-icono-grande { background: var(--danger-bg); color: var(--danger); }
.drx-espera-texto { flex: 1 1 360px; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.drx-espera-texto h3 { margin: 0; font-size: 16px; }
.drx-espera-texto p:not(.drx-etiqueta) { margin: 0; font-size: 14px; }
.drx-espera--plan { padding: 12px 16px; }
.drx-recorrido { gap: 16px; }
.drx-pasos { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(min(120px, 100%), 1fr)); gap: 14px 6px; }
.drx-paso { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.drx-paso-linea { display: flex; align-items: center; }
.drx-paso-marca { width: 28px; height: 28px; border-radius: 50%; flex: none; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 700; background: var(--panel); border: 2px solid var(--border-strong); color: var(--muted); }
.drx-paso-tramo { flex: 1 1 auto; height: 2px; background: var(--border); }
.drx-paso-tramo[data-hecho="si"] { background: var(--ok); }
.drx-paso[data-estado="hecho"] .drx-paso-marca { background: var(--ok); border-color: var(--ok); color: #fff; }
.drx-paso[data-estado="actual"] .drx-paso-marca { background: var(--accent); border-color: var(--accent); color: #fff; }
.drx-paso[data-estado="fallo"] .drx-paso-marca { background: var(--danger); border-color: var(--danger); color: #fff; }
.drx-paso[data-estado="omitido"] .drx-paso-marca, .drx-paso[data-estado="no_aplica"] .drx-paso-marca, .drx-paso[data-estado="no_alcanzado"] .drx-paso-marca { border-style: dashed; }
.drx-paso-nombre { font-size: 14px; }
.drx-paso-detalle { font-size: 12px; color: var(--muted); }
.drx-paso[data-estado="fallo"] .drx-paso-nombre, .drx-paso[data-estado="fallo"] .drx-paso-detalle { color: var(--danger); }
.drx-paso[data-estado="omitido"] .drx-paso-nombre, .drx-paso[data-estado="no_alcanzado"] .drx-paso-nombre { color: var(--muted); }
.drx-avance { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
.drx-avance > :first-child { flex: 1 1 320px; }
.drx-decision { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; padding: 10px 14px; border-radius: 8px; background: var(--bg); font-size: 14px; }
.drx-columnas { display: flex; flex-wrap: wrap; gap: 18px; align-items: flex-start; }
.drx-principal { flex: 999 1 540px; min-width: 0; display: flex; flex-direction: column; gap: 18px; }
.drx-lateral { flex: 1 1 320px; min-width: 0; display: flex; flex-direction: column; gap: 18px; }
.drx-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.drx-lista > li { display: flex; gap: 12px; align-items: center; padding: 12px 0; border-top: 1px solid var(--border); }
.drx-lista > li:first-child { border-top: 0; padding-top: 4px; }
.drx-lista-texto { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; font-size: 14px; overflow-wrap: anywhere; }
.drx-lista-texto .drx-tenue { font-size: 13px; }
.drx-punto { width: 26px; height: 26px; border-radius: 50%; flex: none; display: flex; align-items: center; justify-content: center; font-size: 15px; }
.drx-punto--ok { background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ok-texto); }
.drx-punto--warn { background: var(--warn-bg); color: var(--warn); }
.drx-punto--danger { background: var(--danger-bg); color: var(--danger); }
.drx-punto--neutral { background: var(--neutral-bg); color: var(--muted); }
.drx-uso { display: flex; flex-direction: column; gap: 6px; }
.drx-intentos-lista { list-style: none; margin: 0; padding: 0; font-size: 13px; }
.drx-intentos-lista li { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-top: 1px solid var(--border); }
.drx-intentos-lista li:first-child { border-top: 0; }
.drx-intento-n { width: 26px; }
.drx-este { color: var(--accent); }
.drx-mas summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--accent); }
.drx-documentos { margin: 0; }

/* Requerimiento */
.drx-requerimiento .ent { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 18px 22px; }
.drx-requerimiento .ent-cabeza h3 { font-size: 16px; margin: 0 0 4px; }
.drx-criterio { display: flex; flex-direction: column; gap: 8px; padding: 14px 0; border-top: 1px solid var(--border); }
.drx-criterio:first-of-type { border-top: 0; padding-top: 2px; }
.drx-criterio-cabeza { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.drx-criterio-texto { margin: 0; font-size: 14px; line-height: 1.55; }
.drx-ejemplo { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; padding: 10px 14px; border-radius: 8px; background: var(--bg); font-size: 14px; }
/* 03-11-2026 (R8 del contrato de alcance): «Lo que pide el ticket», el texto literal del work item arriba de todo */
.drx-pedido { border-left: 3px solid var(--accent); }
.drx-pedido-aviso { display: flex; align-items: flex-start; gap: 6px; margin: 0; padding: 8px 12px; border-radius: 8px; background: color-mix(in srgb, var(--warn) 12%, var(--panel)); font-size: 13px; }
.drx-pedido-aviso .mdi { color: var(--warn); font-size: 16px; flex: none; }
.drx-pedido-bloque { display: flex; flex-direction: column; gap: 4px; }
.drx-pedido-bloque h5 { margin: 0; font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.drx-pedido-bloque > p, .drx-pedido-lista { margin: 0; padding: 10px 14px; border-radius: 8px; background: var(--bg); font-size: 14px; line-height: 1.55; overflow-wrap: anywhere; }
.drx-pedido-lista { padding-left: 34px; display: flex; flex-direction: column; gap: 6px; }
.drx-pedido-imagenes { display: flex; flex-wrap: wrap; gap: 12px 16px; }
.drx-pedido-imagenes figure { margin: 0; display: flex; flex-direction: column; gap: 4px; max-width: 260px; min-width: 0; }
.drx-pedido-imagenes figcaption { font-size: 12.5px; color: var(--text); overflow-wrap: anywhere; }
.drx-desplegar { display: inline-flex; align-items: center; gap: 6px; align-self: flex-start; }
.drx-punto-cuerpo { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); gap: 12px 16px; padding: 12px 14px; border-radius: 8px; background: var(--bg); font-size: 13px; }
.drx-punto-cuerpo h5 { margin: 0 0 4px; font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.drx-punto-cuerpo p { margin: 0 0 4px; }
.drx-punto-cuerpo .dr-problemas { grid-column: 1 / -1; margin: 0; }
.drx-archivo-cabeza { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 4px; }
.drx-ruta { display: block; font-size: 12px; }
.drx-repo { font-size: 12px; }
.drx-dos { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(440px, 100%), 1fr)); gap: 18px; align-items: start; }
.drx-dos > .drx-tarjeta > .drd-ins { display: flex; flex-direction: column; gap: 10px; }
.drx-requerimiento .dra { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 18px 22px; margin: 0; }

/* Pruebas */
.drx-qa { gap: 14px; }
.drx-qa-cabeza { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 12px; }
.drx-qa-titulo { flex: 1 1 320px; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.drx-qa-titulo h4 { margin: 0; font-size: 15px; line-height: 1.4; }
.drx-qa-titulo .drx-enlace { align-self: flex-start; }
.drx-qa-pasos { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.drx-qa-paso { display: grid; grid-template-columns: 32px minmax(0, 1fr) 190px; gap: 14px; padding: 14px 0; border-top: 1px solid var(--border); align-items: start; }
.drx-qa-n { width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background: var(--neutral-bg); font-weight: 700; font-size: 13px; }
.drx-qa-paso[data-resultado="pasa"] .drx-qa-n { background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ok-texto); }
.drx-qa-paso[data-resultado="falla"] .drx-qa-n { background: var(--danger-bg); color: var(--danger); }
.drx-qa-texto { display: flex; flex-direction: column; gap: 6px; min-width: 0; font-size: 14px; }
.drx-qa-texto p { margin: 0; }
.drx-qa-paso-cabeza { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.drx-qa-comparar { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); gap: 10px; }
.drx-qa-comparar > div { padding: 10px 12px; border-radius: 8px; background: var(--bg); font-size: 13px; }
.drx-qa-comparar p { margin: 4px 0 0; }
.drx-qa-captura { min-width: 0; }
.drx-sin-captura { display: flex; flex-direction: column; gap: 4px; align-items: center; justify-content: center; min-height: 96px; padding: 8px; border-radius: 8px; border: 1px dashed var(--border-strong); color: var(--muted); font-size: 12px; text-align: center; overflow-wrap: anywhere; }
.drx-sin-captura .mono { font-size: 11px; }
@media (max-width: 720px) { .drx-qa-paso { grid-template-columns: 32px minmax(0, 1fr); } .drx-qa-captura { grid-column: 2; } }

/* Código */
.drx-checkout { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 12px; border-radius: 8px; background: var(--bg); border: 1px solid var(--border); }
.drx-checkout code { flex: 1 1 320px; min-width: 0; font-size: 12px; overflow-wrap: anywhere; }
.drx-git-repo { display: flex; flex-direction: column; gap: 18px; }
.drx-git .drd-git-posicion { margin: 0; }
.drx-codigo .drd-amb { display: flex; flex-direction: column; gap: 10px; }

/* Actividad */
.drx-buscar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.drx-buscar input { height: 32px; min-width: 220px; padding: 0 10px; border: 1px solid var(--border-strong); border-radius: 8px; background: var(--panel); color: var(--text); font: inherit; font-size: 13px; }
.drx-linea { display: flex; flex-direction: column; gap: 14px; }
.drx-linea-fase { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.drx-linea-fase-cabeza { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 10px 16px; background: var(--bg); border-bottom: 1px solid var(--border); font-size: 14px; }
.drx-linea-fase-cabeza .drx-tenue { font-size: 13px; }
.drx-linea-items { list-style: none; margin: 0; padding: 0; }
.drx-linea-items > li { border-top: 1px solid var(--border); }
.drx-linea-items > li:first-child { border-top: 0; }
.drx-linea-fila, .drx-grupo > summary { display: grid; grid-template-columns: 96px 12px minmax(0, 1fr) auto; gap: 12px; align-items: start; padding: 10px 16px; font-size: 14px; }
.drx-grupo > summary { cursor: pointer; list-style: none; }
.drx-grupo > summary::-webkit-details-marker { display: none; }
.drx-hora { font-size: 12px; color: var(--muted); padding-top: 2px; }
.drx-linea-punto { width: 10px; height: 10px; margin-top: 5px; border-radius: 50%; background: var(--border-strong); }
.drl-item[data-tono="ok"] .drx-linea-punto { background: var(--ok); }
.drl-item[data-tono="info"] .drx-linea-punto { background: var(--info); }
.drl-item[data-tono="warn"] .drx-linea-punto { background: var(--warn); }
.drl-item[data-tono="danger"] .drx-linea-punto { background: var(--danger); }
.drl-item[data-tono="danger"] > .drx-linea-fila, .drl-item[data-tono="danger"] > .drx-grupo > summary { background: color-mix(in srgb, var(--danger-bg) 60%, transparent); }
.drx-linea-texto { display: flex; flex-direction: column; gap: 2px; min-width: 0; overflow-wrap: anywhere; }
.drx-linea-texto .drx-tenue { font-size: 13px; }
.drx-grupo-items, .drx-grupo-acciones { list-style: none; margin: 0; padding: 4px 16px 12px 136px; display: flex; flex-direction: column; gap: 6px; font-size: 13px; }
.drx-grupo-items li { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 12px; margin-left: -120px; }
.drx-grupo-acciones .mono { font-size: 12px; overflow-wrap: anywhere; }
.drx-verbo { display: inline-block; min-width: 64px; padding: 1px 8px; border-radius: 999px; background: var(--neutral-bg); font-size: 11px; font-weight: 600; text-align: center; }
@media (max-width: 720px) {
  .drx-linea-fila, .drx-grupo > summary { grid-template-columns: 70px 10px minmax(0, 1fr); }
  .drx-linea-fila > .drx-chip, .drx-grupo > summary > .drx-chip { display: none; }
  .drx-grupo-items, .drx-grupo-acciones { padding-left: 16px; }
  .drx-grupo-items li { margin-left: 0; grid-template-columns: 70px minmax(0, 1fr); }
  .modal.drx > header.drx-cabecera { padding: 14px 16px 0; }
  .drx-tabs.drd-tabs { margin: 0 -16px; padding: 0 16px; gap: 0 18px; }
  .modal.drx .body.drx-cuerpo { padding: 16px; }
}
/* Sin scroll horizontal en el modal del run (27-10-2026): el cuerpo solo se desplaza en vertical, las pestañas
   bajan de línea si no caben y las tablas reparten el ancho en vez de desbordar su caja. */
.modal.drx .body.drx-cuerpo { overflow-x: hidden; }
.drx-cuerpo > .drd-panel, .drx-cuerpo > .drd-panel > * { min-width: 0; max-width: 100%; }
.drx-tabs.drd-tabs { overflow: visible; flex-wrap: wrap; margin: 0; padding: 0; }
.drx-tabla-caja { overflow-x: visible; }
.drx-tabla { table-layout: auto; }
.drx-tabla td, .drx-tabla th { min-width: 0; }
.drx-tabla .drx-nowrap, .drx-tabla th { white-space: normal; }
.drx-tabla .mono, .drx-checkout code, .drx-git .mono { overflow-wrap: anywhere; word-break: break-word; }
.drx-cuerpo pre { white-space: pre-wrap; overflow-wrap: anywhere; }
/* Con la barra sólida (preferencia de la app) la cabecera del run va del color de la barra, como la de todo modal:
   su texto, el subtítulo, las pestañas y los botones pasan a blanco, y los chips de estado se apoyan en blanco. */
body[data-bar="solid"] .modal.drx > header.drx-cabecera { background: var(--bar-fill); color: #fff; border-bottom: 1px solid rgba(0, 0, 0, 0.22); }
body[data-bar="solid"] .modal.drx > header .drx-titulo,
body[data-bar="solid"] .modal.drx > header .drx-meta strong { color: #fff; }
body[data-bar="solid"] .modal.drx > header .drx-tenue,
body[data-bar="solid"] .modal.drx > header .drd-vivo { color: #fff; opacity: 0.88; }
body[data-bar="solid"] .modal.drx > header .drx-chip { background: #fff; }
body[data-bar="solid"] .modal.drx > header .drx-chip--neutral { color: var(--dr-chip-neutral); }
body[data-bar="solid"] .modal.drx > header .drx-chip--ok { color: var(--dr-chip-ok); }
body[data-bar="solid"] .modal.drx > header .drx-chip--warn { color: var(--dr-chip-warn); }
body[data-bar="solid"] .modal.drx > header .drx-chip--danger { color: var(--dr-chip-danger); }
body[data-bar="solid"] .modal.drx > header .drx-chip--info { color: var(--dr-chip-info); }
body[data-bar="solid"] .modal.drx > header .drx-chip { background: var(--dr-chip-bg); }
body[data-bar="solid"] .modal.drx > header .drx-tab.drd-tab { color: #fff; opacity: 0.8; }
body[data-bar="solid"] .modal.drx > header .drx-tab.drd-tab:hover { opacity: 1; }
body[data-bar="solid"] .modal.drx > header .drx-tab.drd-tab.drd-tab--activa { color: #fff; opacity: 1; border-bottom-color: #fff; }
body[data-bar="solid"] .modal.drx > header .drx-tab .drd-cuenta { background: rgba(255, 255, 255, 0.22); color: #fff; }
body[data-bar="solid"] .modal.drx > header .drx-tab .drd-cuenta--aviso { background: var(--dr-chip-bg); color: var(--dr-chip-warn); }
body[data-bar="solid"] .modal.drx > header .drx-btn { border-color: rgba(255, 255, 255, 0.65); background: rgba(255, 255, 255, 0.14); color: #fff; }
body[data-bar="solid"] .modal.drx > header .drx-btn:hover:not(:disabled) { background: rgba(255, 255, 255, 0.24); border-color: #fff; }
body[data-bar="solid"] .modal.drx > header .drx-btn--pri { background: #fff; border-color: #fff; color: var(--brand-strong); }
body[data-bar="solid"] .modal.drx > header .drx-btn--pri:hover:not(:disabled) { background: rgba(255, 255, 255, 0.9); color: var(--brand-strong); }
body[data-bar="solid"] .modal.drx > header .drx-intentos select { border-color: rgba(255, 255, 255, 0.65); background: rgba(255, 255, 255, 0.14); color: #fff; }
body[data-bar="solid"] .modal.drx > header .drx-intentos select option { color: var(--text); background: var(--panel); }
/* Las pestañas no saltan al elegir una: todas con el mismo peso, la activa se distingue por color y subrayado */
.drx-tab.drd-tab, .drx-tab.drd-tab.drd-tab--activa { font-weight: 600; }

/* ================================================================================================================
   EL MODAL DEL RUN, SEGUNDA PASADA (27-10-2026, «mal distribuido, sin guía visual, selectores planos, overflow, labels
   sin contraste»): enlaces que parecen enlaces, títulos con marca, etiquetas legibles, controles propios del modal,
   barra de avance del color del estado, plan y respuestas plegados, sin huecos vacíos.
   ================================================================================================================ */
/* Enlaces: sin borde ni caja, del color de la app; los que llevan a otra pestaña llevan flecha */
.drx .drx-link { display: inline-flex; align-items: center; gap: 4px; padding: 2px 0; border: 0; background: none; color: var(--accent); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap; text-decoration: none; }
/* The QA report delivered in volumes: one download per volume, in a row */
.drx-informe-tomos { display: inline-flex; flex-wrap: wrap; gap: 4px 14px; margin-left: 6px; }
.drx .drx-link:hover:not(:disabled) { text-decoration: underline; border: 0; background: none; }
.drx .drx-link:disabled { color: var(--muted); cursor: not-allowed; }
.drx .drx-link .mdi { font-size: 15px; }
.drx .drx-link--mono { font-family: var(--mono); font-size: 12px; font-weight: 500; color: var(--text); }
/* Los enlaces de los componentes que vienen de antes (quitar, cambiar respuesta, abrir archivo) en el mismo idioma */
.drx .btn-link { padding: 0; border: 0; background: none; color: var(--accent); font-size: 13px; font-weight: 600; }
.drx .btn-link:hover:not(:disabled) { text-decoration: underline; border: 0; }

/* Títulos de sección con una marca de color: dónde empieza cada bloque */
.drx .drx-tarjeta > h3, .drx .drx-tarjeta-cabeza > h3, .drx .drx-seccion-cabeza h3, .drx .ent-cabeza h3, .drx .drd-ins .drd-seccion-cabeza h3, .drx .dra-cabeza h3 { display: flex; align-items: center; gap: 10px; font-size: 16px; font-weight: 700; color: var(--text); letter-spacing: 0; text-transform: none; }
.drx .drx-tarjeta > h3::before, .drx .drx-tarjeta-cabeza > h3::before, .drx .drx-seccion-cabeza h3::before, .drx .ent-cabeza h3::before, .drx .drd-ins .drd-seccion-cabeza h3::before, .drx .dra-cabeza h3::before { content: ""; width: 4px; height: 18px; border-radius: 2px; background: var(--accent); flex: none; }
.drx .drx-tarjeta { padding: 20px 24px; gap: 14px; box-shadow: 0 1px 2px rgba(16, 24, 40, .04); }

/* Etiquetas con contraste y filas que se distinguen */
.drx .drx-etiqueta { color: color-mix(in srgb, var(--muted) 80%, var(--text)); }
.drx .drx-kv { gap: 0 14px; }
.drx .drx-kv dt, .drx .drx-kv dd { padding: 8px 0; border-top: 1px solid var(--border); }
.drx .drx-kv dt:first-of-type, .drx .drx-kv dt:first-of-type + dd { border-top: 0; }
.drx .drx-kv dt { color: color-mix(in srgb, var(--muted) 80%, var(--text)); font-size: 12px; font-weight: 600; }
.drx .drx-tabla tbody tr:nth-child(even) > td { background: color-mix(in srgb, var(--bg) 70%, transparent); }
.drx .drx-tabla-simple tbody tr:nth-child(even) > td { background: color-mix(in srgb, var(--bg) 70%, transparent); }
.drx .drx-tabla-simple td:first-child { padding-left: 6px; }
.drx .drx-tabla-simple td:last-child { padding-right: 6px; }

/* Parada: los datos en una línea, no en tres cajas grandes */
.drx .drx-datos-linea { display: flex; flex-wrap: wrap; gap: 8px 32px; margin: 0; padding: 12px 16px; border-radius: 8px; background: var(--panel); border: 1px solid var(--border); }
.drx .drx-datos-linea > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.drx .drx-datos-linea dt { font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: color-mix(in srgb, var(--muted) 80%, var(--text)); }
.drx .drx-datos-linea dd { margin: 0; font-size: 14px; font-weight: 600; }
.drx .drx-parada { padding: 20px 24px; gap: 14px; }
.drx .drx-parada-texto h3 { font-size: 17px; }

/* Barra de avance del color del estado, con la cifra al lado */
.drx .drx-avance { align-items: center; }
.drx .drx-barra { flex: 1 1 280px; height: 8px; border-radius: 999px; background: var(--neutral-bg); overflow: hidden; }
.drx .drx-barra > span { display: block; height: 100%; border-radius: 999px; background: var(--accent); transition: width .4s ease; }
.drx .drx-barra[data-estado="succeeded"] > span { background: var(--ok); }
.drx .drx-barra[data-estado="failed"] > span, .drx .drx-barra[data-estado="incomplete"] > span { background: var(--danger); }
.drx .drx-barra[data-estado="canceled"] > span { background: var(--border-strong); }
.drx .drx-barra-cifra { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; min-width: 42px; }
.drx .drx-avance > :first-child { flex: 1 1 280px; }

/* Sin huecos: los paneles de decisión y despliegue solo ocupan sitio cuando tienen algo */
.drx #drd-decision:empty, .drx #drd-despliegue:empty { display: none; }

/* Listas: el enlace a la derecha, el texto con aire */
.drx .drx-lista > li { gap: 14px; padding: 12px 0; }
.drx .drx-lista--compacta > li { padding: 10px 0; align-items: center; }
.drx .drx-lista--compacta .drx-lista-texto { font-size: 14px; }

/* Plan plegado: se ve el comienzo y se abre entero */
.drx .drx-plegable { position: relative; max-height: 280px; overflow: hidden; }
.drx .drx-plegable::after { content: ""; position: absolute; inset: auto 0 0 0; height: 80px; background: linear-gradient(to bottom, transparent, var(--panel)); pointer-events: none; }
.drx .drx-plegable--abierto { max-height: none; }
.drx .drx-plegable--abierto::after { display: none; }
.drx .drx-plegable-boton { align-self: flex-start; }

/* Archivos, trabajo y prueba: anchos que no aplastan la ruta */
.drx .drx-requerimiento .drx-tabla th:nth-child(1) { width: 24%; }
.drx .drx-requerimiento .drx-tabla th:nth-child(2) { width: 32%; }
.drx .drx-requerimiento .drx-tabla th:nth-child(3) { width: 26%; }
.drx .drx-ruta { overflow-wrap: normal; word-break: normal; }
.drx .drx-criterio { padding: 16px 0; }
.drx .drx-desplegar { font-size: 13px; }

/* Preguntas del equipo: tarjetas neutras con una franja de color, respondidas plegadas en una línea */
.drx .drd-ins-tarjeta { background: var(--panel); border: 1px solid var(--border); border-left: 4px solid var(--border-strong); border-radius: 8px; padding: 14px 16px; }
.drx .drd-ins-tarjeta[data-bloqueante="si"] { border-left-color: var(--danger); background: var(--panel); }
.drx .drd-ins-tarjeta[data-bloqueante="no"] { border-left-color: var(--warn); background: var(--panel); }
.drx .drd-ins-tarjeta--respondida { border-left-color: var(--ok); padding: 0; }
.drx .drd-ins-tarjeta--respondida > summary.drd-ins-resumen { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; padding: 12px 16px; cursor: pointer; list-style: none; }
.drx .drd-ins-tarjeta--respondida > summary::-webkit-details-marker { display: none; }
.drx .drd-ins-tarjeta--respondida > summary::before { content: "\F0142"; font-family: "Material Design Icons"; color: var(--muted); font-size: 16px; transition: transform .15s; }
.drx .drd-ins-tarjeta--respondida[open] > summary::before { transform: rotate(90deg); }
.drx .drd-ins-tarjeta--respondida[open] > summary { border-bottom: 1px solid var(--border); }
.drx .drd-ins-tarjeta--respondida > :not(summary) { margin-left: 16px; margin-right: 16px; }
.drx .drd-ins-tarjeta--respondida > :last-child { margin-bottom: 14px; }
.drx .drd-ins-resumen-titulo { font-weight: 700; font-size: 14px; }
.drx .drd-ins-resumen-eleccion { flex: 1 1 100%; color: var(--muted); font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-left: 26px; }
.drx .drd-ins-tarjeta h4 { font-size: 15px; margin: 8px 0 4px; }

/* Controles propios del modal: un solo estilo para elegir, escribir y adjuntar */
.drx select, .drx input[type="text"], .drx input[type="search"], .drx input[type="number"], .drx textarea {
  min-height: 36px; padding: 7px 10px; border: 1px solid var(--border-strong); border-radius: 8px; background: var(--panel); color: var(--text); font: inherit; font-size: 13px; box-shadow: none;
}
.drx textarea { line-height: 1.5; resize: vertical; width: 100%; }
.drx select { appearance: none; -webkit-appearance: none; padding-right: 32px; cursor: pointer; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 10px center; }
.drx select:focus, .drx input:focus, .drx textarea:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; border-color: var(--accent); }
.drx input[type="file"] { font-size: 12px; color: var(--muted); }
.drx input[type="file"]::file-selector-button { margin-right: 10px; height: 30px; padding: 0 12px; border: 1px solid var(--border-strong); border-radius: 8px; background: var(--panel); color: var(--text); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; }
.drx input[type="file"]::file-selector-button:hover { border-color: var(--accent); }
/* Los botones que traen los componentes de antes, con la forma de los del modal */
.drx button.primary, .drx .btn-icono, .drx button.danger { display: inline-flex; align-items: center; gap: 6px; min-height: 34px; padding: 0 14px; border-radius: 8px; font-size: 13px; font-weight: 600; }
.drx .btn-icono { border: 1px solid var(--border-strong); background: var(--panel); color: var(--text); }
.drx .btn-icono:hover:not(:disabled) { border-color: var(--accent); }

/* Actividad: buscador y descarga en una línea */
.drx .drx-buscar { flex-wrap: nowrap; }
.drx .drx-buscar input { width: 240px; min-width: 0; }
.drx .drx-linea-fila, .drx .drx-grupo > summary { grid-template-columns: 76px 12px minmax(0, 1fr) auto; }
.drx .drx-grupo-items li { grid-template-columns: 76px minmax(0, 1fr); margin-left: -100px; }
.drx .drx-grupo-items, .drx .drx-grupo-acciones { padding-left: 116px; }
@media (max-width: 720px) {
  .drx .drx-buscar { flex-wrap: wrap; }
  .drx .drx-buscar input { width: 100%; }
  .drx .drx-grupo-items li { margin-left: 0; }
  .drx .drx-grupo-items, .drx .drx-grupo-acciones { padding-left: 16px; }
}

/* Rejillas parejas (27-10-2026, «sin listas largas al lado de una lista con 3 items»): lado a lado solo tarjetas del mismo
   tipo, con la misma altura; lo demás, a todo el ancho y una debajo de otra */
.drx .drx-rejilla { display: grid; gap: 18px; align-items: stretch; min-width: 0; }
.drx .drx-rejilla--1 { grid-template-columns: minmax(0, 1fr); }
.drx .drx-rejilla--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.drx .drx-rejilla--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.drx .drx-rejilla > .drx-tarjeta { height: 100%; }
.drx .drx-ver-mas { align-self: flex-start; margin-top: 2px; }
.drx .drx-subbloque { display: flex; flex-direction: column; gap: 6px; padding-top: 12px; border-top: 1px solid var(--border); }
.drx .drx-subbloque .drx-documentos { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
@media (max-width: 1180px) { .drx .drx-rejilla--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 860px) { .drx .drx-rejilla--2, .drx .drx-rejilla--3 { grid-template-columns: minmax(0, 1fr); } }
/* Reglas del plan a todo el ancho: sus fases en rejilla de tres y las validaciones al lado de las skills */
.drx .dra .dra-fases { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; }
.drx .dra .dra-columnas { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
@media (max-width: 860px) { .drx .dra .dra-columnas { grid-template-columns: minmax(0, 1fr); } }

/* «Ver código» con color (27-10-2026, Gerson: «que se vea qué se agregó y qué se quitó»): el código coloreado por
   lenguaje (codeHighlight.mjs) sobre un fondo de editor, una franja a la izquierda de cada línea añadida o quitada y
   las palabras que cambiaron dentro de la línea resaltadas con más fuerza. */
:root {
  --codigo-bg: #fbfcfd; --codigo-num: #8c959f;
  --hl-kw: #a626a4; --hl-str: #0a6e5c; --hl-num: #b35900; --hl-fn: #3b49c6; --hl-type: #9a6700;
  --hl-attr: #0b67b5; --hl-tag: #0b67b5; --hl-com: #6e7781; --hl-op: #5d6670;
}
:root[data-theme="dark"]:not([data-presentacion]) {
  --codigo-bg: #15171b; --codigo-num: #6b737d;
  --hl-kw: #e08ef0; --hl-str: #6fd3b8; --hl-num: #f2a65a; --hl-fn: #9aa8ff; --hl-type: #e3c066;
  --hl-attr: #7cc4fa; --hl-tag: #7cc4fa; --hl-com: #8b949e; --hl-op: #9aa3ad;
}
.hl-kw { color: var(--hl-kw); font-weight: 600; }
.hl-str { color: var(--hl-str); }
.hl-num { color: var(--hl-num); }
.hl-fn { color: var(--hl-fn); }
.hl-type { color: var(--hl-type); }
.hl-attr { color: var(--hl-attr); }
.hl-tag { color: var(--hl-tag); font-weight: 600; }
.hl-com { color: var(--hl-com); font-style: italic; }
.hl-op, .hl-p { color: var(--hl-op); }

.dr-d-archivo { border-radius: 10px; box-shadow: 0 1px 2px color-mix(in srgb, var(--text) 6%, transparent); background: var(--codigo-bg); }
.dr-d-cabecera { padding: 9px 12px; gap: 8px; background: var(--panel); font-size: 12.5px; }
.dr-d-cabecera:hover { background: color-mix(in srgb, var(--accent) 5%, var(--panel)); }
.dr-d-ruta b { font-weight: 700; color: var(--text); }
.dr-d-carpeta-cab { color: var(--muted); }
.dr-d-lenguaje { font-size: 10.5px; font-weight: 600; letter-spacing: .03em; padding: 1px 7px; border-radius: 99px; background: var(--neutral-bg); color: var(--muted); white-space: nowrap; }
.dr-d-cifras { display: inline-flex; gap: 6px; font-family: var(--mono); font-size: 11.5px; font-variant-numeric: tabular-nums; }
.dr-d-cabecera .dr-c-barra { margin-left: 2px; }

.dr-d-cuerpo { background: var(--codigo-bg); }
.dr-d-tabla { font-size: 12px; line-height: 1.65; }
.dr-d-tabla td { padding: 0 10px; }
.dr-d-num { color: var(--codigo-num); background: color-mix(in srgb, var(--neutral-bg) 60%, transparent); border-right: 0 !important; font-size: 11px; }
.dr-d-codigo { position: relative; padding-left: 14px !important; }
.dr-d-marca { font-weight: 700; }
.dr-d-fila--add .dr-d-codigo { box-shadow: inset 3px 0 0 var(--ok); background: color-mix(in srgb, var(--ok) 10%, transparent); }
.dr-d-fila--del .dr-d-codigo { box-shadow: inset 3px 0 0 var(--danger); background: color-mix(in srgb, var(--danger) 9%, transparent); }
.dr-d-fila--add, .dr-d-fila--del { background: none; }
.dr-d-fila--add .dr-d-num { background: color-mix(in srgb, var(--ok) 16%, transparent); color: var(--ok-texto); }
.dr-d-fila--del .dr-d-num { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); }
.dr-d-fila--del .dr-d-codigo > span:not(.dr-d-marca):not(.sr-only) { opacity: .85; }
.dr-d-cambio { border-radius: 3px; padding: 1px 0; }
.dr-d-fila--add .dr-d-cambio { background: color-mix(in srgb, var(--ok) 30%, transparent); }
.dr-d-fila--del .dr-d-cambio { background: color-mix(in srgb, var(--danger) 28%, transparent); text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--danger) 55%, transparent); }
.dr-d-fila--del .dr-d-cambio { opacity: 1 !important; }
.dr-d-hunk { background: color-mix(in srgb, var(--info) 8%, var(--codigo-bg)); color: var(--info); padding: 5px 14px !important; font-size: 11px; border-block: 1px solid color-mix(in srgb, var(--info) 18%, transparent); }
.dr-d-fila--hunk:first-child .dr-d-hunk { border-top: 0; }
.dr-d-fila--ctx:hover .dr-d-codigo, .dr-d-fila--ctx:hover .dr-d-num { background: color-mix(in srgb, var(--accent) 5%, transparent); }

/* ================================================================================================================
   EL MODAL DEL RUN · PROPUESTA APROBADA (27-10-2026, Gerson: «atractivo, intuitivo, ágil de leer»): arriba la
   identidad del ticket; debajo la franja «Ahora» (DevRunHero), la única zona con el color del estado, que dice cómo
   está, qué pasa y UNA acción, con el recorrido de las siete fases; luego las pestañas con su contador. «Resumen» abre
   con una fila de cifras, pone lo hecho junto a lo que necesita atención y deja el detalle plegado.
   ================================================================================================================ */
.modal.drx > header.drx-cabecera { padding: 16px 24px; gap: 8px; }
.drx-identidad { gap: 6px; }
.drx-titulo { font-size: 18px; }
.drx-meta { font-size: 12.5px; gap: 6px 14px; }
.drx-btn--quieto { background: transparent; border-color: transparent; color: var(--muted); }
.drx-btn--quieto:hover:not(:disabled) { color: var(--danger); border-color: var(--border); background: transparent; }

/* La franja «Ahora»: el tono pone el tinte, el color de la etiqueta y el de la fase actual */
.drh {
  --drh-color: var(--accent); --drh-tinte: var(--accent-soft);
  flex: none; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 14px 28px; align-items: center;
  padding: 18px 24px 16px; border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, var(--drh-tinte), var(--panel) 92%);
}
.drh[data-tono="danger"] { --drh-color: var(--danger); --drh-tinte: var(--danger-bg); }
.drh[data-tono="warn"] { --drh-color: var(--warn); --drh-tinte: var(--warn-bg); }
.drh[data-tono="ok"] { --drh-color: var(--ok); --drh-tinte: color-mix(in srgb, var(--ok) 12%, var(--panel)); }
.drh[data-tono="neutral"] { --drh-color: var(--muted); --drh-tinte: var(--neutral-bg); }
.drh-texto { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.drh-estado { display: inline-flex; align-items: center; gap: 8px; font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--drh-color); }
.drh-estado::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor; box-shadow: 0 0 0 4px color-mix(in srgb, currentColor 18%, transparent); }
.drh-titulo { margin: 2px 0 0; font-size: 21px; line-height: 1.25; font-weight: 700; color: var(--text); text-wrap: balance; overflow-wrap: anywhere; }
.drh-explica { margin: 0; color: var(--muted); font-size: 13.5px; line-height: 1.5; max-width: 78ch; }
.drh-acciones { display: flex; flex-direction: column; align-items: stretch; gap: 6px; min-width: 210px; }
.drh-acciones .drx-link { justify-content: center; }
.drh-principal { justify-content: center; height: 40px; font-size: 14px; }
.drh-ahora { grid-column: 1 / -1; }
.drh .drd-ahora { margin: 0; background: color-mix(in srgb, var(--panel) 70%, transparent); }
.drh-pie { grid-column: 1 / -1; display: flex; flex-direction: column; gap: 10px; }

.drh-recorrido { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.drh-fase { position: relative; padding: 0 8px 0 0; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
/* 03-11-2026: the step is a button (dot + label + detail) that opens its tab; it carries the 26px the dot needs, the
   li keeps the line between steps. Same layout as before: the dot sits at the li's top-left, the texts under it. */
.drh-fase-boton {
  position: relative; display: flex; flex-direction: column; gap: 1px; min-width: 0; width: 100%; margin: 0; padding: 26px 0 0;
  border: 0; border-radius: 6px; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; -webkit-appearance: none; appearance: none;
}
.drh-fase-boton:hover .drh-fase-nombre { text-decoration: underline; }
.drh-fase-boton:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.drh-fase::before { content: ""; position: absolute; top: 8px; left: 18px; right: 0; height: 3px; border-radius: 2px; background: var(--border); }
.drh-fase:last-child::before { display: none; }
.drh-fase[data-estado="hecho"]::before { background: var(--ok); }
.drh-fase[data-estado="actual"]::before { background: linear-gradient(90deg, var(--drh-color) 45%, var(--border) 45%); }
.drh-marca {
  position: absolute; top: 0; left: 0; width: 19px; height: 19px; border-radius: 50%; display: grid; place-items: center;
  background: var(--panel); border: 2px solid var(--border-strong); color: #fff; font-size: 12px; line-height: 1;
}
.drh-fase[data-estado="hecho"] .drh-marca { background: var(--ok); border-color: var(--ok); }
.drh-fase[data-estado="fallo"] .drh-marca { background: var(--danger); border-color: var(--danger); }
.drh-fase[data-estado="actual"] .drh-marca { border: 5px solid var(--drh-color); box-shadow: 0 0 0 4px color-mix(in srgb, var(--drh-color) 20%, transparent); }
.drh-fase[data-estado="no_alcanzado"] .drh-marca, .drh-fase[data-estado="omitido"] .drh-marca, .drh-fase[data-estado="no_aplica"] .drh-marca { border-style: dashed; color: var(--muted); }
.drh-fase-nombre { font-size: 12.5px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.drh-fase-detalle { font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.drh-fase[data-estado="pendiente"] .drh-fase-nombre, .drh-fase[data-estado="no_alcanzado"] .drh-fase-nombre, .drh-fase[data-estado="no_aplica"] .drh-fase-nombre, .drh-fase[data-estado="omitido"] .drh-fase-nombre { color: var(--muted); font-weight: 500; }
.drh-fase[data-estado="actual"] .drh-fase-detalle { color: var(--drh-color); font-weight: 600; }
.drh-fase[data-estado="fallo"] .drh-fase-nombre, .drh-fase[data-estado="fallo"] .drh-fase-detalle { color: var(--danger); }
.drh-pie-fila { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 16px; font-size: 12.5px; }
.drh-decision { color: var(--text); }
.drh-lista { margin-left: auto; }

/* Pestañas fuera de la cabecera: sobre el panel, con su contador en píldora */
.modal.drx > nav.drx-tabs.drd-tabs { flex: none; display: flex; flex-wrap: nowrap; overflow-x: auto; margin: 0; padding: 0 24px; gap: 0 26px; background: var(--panel); border-bottom: 1px solid var(--border); scrollbar-width: none; }
.modal.drx > nav .drx-tab.drd-tab { height: 46px; font-weight: 600; gap: 7px; }
.modal.drx > nav .drx-tab .drd-cuenta { font-weight: 700; }

/* Resumen: cifras */
.drs-cifras { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin: 0; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
.drs-cifras[data-columnas="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.drs-cifra { padding: 14px 18px; min-width: 0; }
.drs-cifra + .drs-cifra { border-left: 1px solid var(--border); }
.drs-cifra dt { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.drs-cifra dd { margin: 4px 0 0; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.drs-cifra-valor { font-size: 22px; font-weight: 700; line-height: 1.2; font-variant-numeric: tabular-nums; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.drs-cifra[data-cifra="codigo"] .drs-cifra-valor { font-family: var(--mono); font-size: 19px; }
.drs-cifra small { font-size: 12px; color: var(--muted); }

/* Resumen: dos columnas de filas (icono · texto · destino) */
.drs-dos { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 20px; align-items: start; }
.drs-dos--uno { grid-template-columns: minmax(0, 1fr); }
.drs-dos > section { min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.drs-h { margin: 0; display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 700; color: var(--text); }
.drs-cuenta { font-size: 11px; font-weight: 700; padding: 1px 8px; border-radius: 999px; background: var(--neutral-bg); color: var(--muted); font-variant-numeric: tabular-nums; }
.drs-cuenta--ok { background: color-mix(in srgb, var(--ok) 14%, var(--panel)); color: var(--ok-texto); }
.drs-cuenta--warn { background: var(--warn-bg); color: var(--warn); }
.drs-cuenta--danger { background: var(--danger-bg); color: var(--danger); }
.drs-filas { list-style: none; margin: 0; padding: 0; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
.drs-filas > li { display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 11px 16px; }
.drs-filas > li + li { border-top: 1px solid var(--border); }
.drs-fila-texto { min-width: 0; display: flex; flex-direction: column; gap: 1px; font-size: 13px; }
.drs-fila-texto strong { font-weight: 600; overflow-wrap: anywhere; }
.drs-fila-texto small { font-size: 12px; color: var(--muted); overflow-wrap: anywhere; }
.drs-ico { width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; font-size: 13px; font-weight: 700; background: var(--neutral-bg); color: var(--muted); }
.drs-ico--ok { background: color-mix(in srgb, var(--ok) 15%, var(--panel)); color: var(--ok); }
.drs-ico--warn { background: var(--warn-bg); color: var(--warn); }
.drs-ico--danger { background: var(--danger-bg); color: var(--danger); }
.drs-ico--info { background: var(--info-bg); color: var(--info); }
.drs-ico--paso { background: var(--accent-soft); color: var(--accent); font-size: 11.5px; }
.drs-ir { border: 0; background: none; color: var(--accent); font: inherit; font-size: 12px; font-weight: 600; padding: 4px 8px; border-radius: 6px; white-space: nowrap; cursor: pointer; display: inline-flex; align-items: center; gap: 2px; }
.drs-ir:hover, .drs-ir:focus-visible { background: var(--accent-soft); }
.drs-vacio { margin: 0; padding: 14px 16px; font-size: 13px; color: var(--muted); background: var(--panel); border: 1px dashed var(--border); border-radius: 12px; }

/* Resumen: el detalle, plegado */
.drs-pliegue { background: var(--panel); border: 1px solid var(--border); border-radius: 12px; }
.drs-pliegue > summary { list-style: none; display: flex; align-items: baseline; gap: 10px; padding: 13px 18px; cursor: pointer; font-size: 13px; font-weight: 700; }
.drs-pliegue > summary::-webkit-details-marker { display: none; }
.drs-pliegue > summary small { font-weight: 400; color: var(--muted); font-size: 12px; }
.drs-pliegue > summary::after { content: "\F0140"; font-family: "Material Design Icons"; margin-left: auto; color: var(--muted); font-weight: 400; font-size: 18px; line-height: 1; transition: transform .15s; }
.drs-pliegue[open] > summary::after { transform: rotate(180deg); }
.drs-pliegue > summary:hover { color: var(--accent); }
.drs-pliegue-cuerpo { padding: 0 18px 18px; }
.drs-pliegue-cuerpo .drx-tarjeta { box-shadow: none; background: var(--bg); border-color: transparent; padding: 16px 18px; }

@media (max-width: 900px) {
  .drh { grid-template-columns: minmax(0, 1fr); padding: 16px; }
  .drh-acciones { flex-direction: row; flex-wrap: wrap; min-width: 0; }
  /* 03-11-2026 (H-3): with overflow-x the focus ring of a step was clipped above and on the left; 4px of room, given back by the margin */
  .drh-recorrido { grid-template-columns: repeat(7, minmax(92px, 1fr)); overflow-x: auto; padding: 4px 0 4px 4px; margin: -4px 0 -4px -4px; }
  .modal.drx > nav.drx-tabs.drd-tabs { padding: 0 16px; gap: 0 18px; }
  .drs-cifras, .drs-cifras[data-columnas="3"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .drs-cifra:nth-child(odd) { border-left: 0; }
  .drs-cifra:nth-child(n+3) { border-top: 1px solid var(--border); }
  .drs-dos { grid-template-columns: minmax(0, 1fr); }
}
@media (prefers-reduced-motion: reduce) { .drs-pliegue > summary::after { transition: none; } }

/* «PLAN», su propia pestaña (27-10-2026): la aprobación arriba —fija mientras espera, para tener los botones a
   mano mientras se lee—, un índice de secciones a la izquierda y el documento siempre abierto a su lado. */
.drpl { display: flex; flex-direction: column; gap: 18px; }
.drpl-estado {
  --drpl-color: var(--ok); --drpl-tinte: color-mix(in srgb, var(--ok) 10%, var(--panel));
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 14px 18px;
  padding: 16px 20px; border-radius: 12px; background: var(--drpl-tinte); border: 1px solid color-mix(in srgb, var(--drpl-color) 35%, var(--border));
}
.drpl-estado[data-tono="warn"] { --drpl-color: var(--warn); --drpl-tinte: var(--warn-bg); position: sticky; top: -24px; z-index: 3; box-shadow: 0 6px 16px -10px color-mix(in srgb, var(--text) 35%, transparent); }
.drpl-estado[data-tono="danger"] { --drpl-color: var(--danger); --drpl-tinte: var(--danger-bg); }
.drpl-estado-ico { width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; font-size: 22px; color: var(--drpl-color); background: color-mix(in srgb, var(--drpl-color) 14%, var(--panel)); }
.drpl-estado-texto { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.drpl-etiqueta { font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--drpl-color); }
.drpl-estado h3 { margin: 0; font-size: 16px; font-weight: 700; color: var(--text); text-wrap: balance; }
.drpl-estado p { margin: 0; font-size: 12.5px; color: var(--muted); }
.drpl-acciones { display: flex; gap: 8px; flex-wrap: wrap; }
.drpl-acciones .drx-btn { height: 38px; }

.drpl-cuerpo { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 20px; align-items: start; }
.drpl-cuerpo--sin-indice { grid-template-columns: minmax(0, 1fr); }
.drpl-indice { position: sticky; top: 72px; display: flex; flex-direction: column; gap: 6px; font-size: 13px; }
.drpl-indice-titulo { margin: 8px 0 2px; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.drpl-indice-titulo:first-child { margin-top: 0; }
.drpl-indice ol, .drpl-repos { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1px; }
.drpl-indice ol { counter-reset: s; border-left: 2px solid var(--border); }
.drpl-indice ol button {
  width: 100%; text-align: left; border: 0; background: none; color: var(--muted); font: inherit; font-size: 13px; line-height: 1.35;
  padding: 6px 10px; margin-left: -2px; border-left: 2px solid transparent; cursor: pointer; overflow-wrap: anywhere;
}
.drpl-indice ol button:hover, .drpl-indice ol button:focus-visible { color: var(--accent); border-left-color: var(--accent); background: var(--accent-soft); }
.drpl-repos li { font-size: 12px; color: var(--text); padding: 2px 0; overflow-wrap: anywhere; }
.drpl-documento { min-width: 0; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 22px 28px; }
.drpl-documento .drp-documento h4[id] { scroll-margin-top: 96px; }
.drpl-vacio { display: flex; gap: 14px; align-items: flex-start; padding: 22px; background: var(--panel); border: 1px dashed var(--border); border-radius: 12px; }
.drpl-vacio > .mdi { font-size: 28px; color: var(--muted); }
.drpl-vacio p { margin: 4px 0 0; color: var(--muted); font-size: 13px; }
@media (max-width: 900px) {
  .drpl-estado { grid-template-columns: auto minmax(0, 1fr); }
  .drpl-acciones { grid-column: 1 / -1; }
  .drpl-cuerpo { grid-template-columns: minmax(0, 1fr); }
  .drpl-indice { position: static; }
  .drpl-documento { padding: 18px; }
}
.drpl-documento .drp-documento { font-size: 14px; line-height: 1.65; max-width: 100ch; }
.drpl-documento .drp-titulo { font-size: 18px; margin: 0 0 12px; }
.drpl-documento .drp-seccion { font-size: 15.5px; margin: 26px 0 10px; padding-bottom: 6px; }

/* «Plan» sin el scroll del modal (27-10-2026, Gerson: el índice «sigue el scroll» y se mueve raro): en esta pestaña
   el cuerpo del modal no se desplaza; la aprobación queda arriba, el índice quieto en su columna y solo el documento
   se desplaza en su propio panel. En pantallas estrechas vuelve el scroll normal, todo en una columna. */
.modal.drx .body.drx-cuerpo.drx-cuerpo--plan { overflow: hidden; }
.drx-cuerpo--plan > .drd-panel:not([hidden]) { flex: 1 1 auto; min-height: 0; }
.drx-cuerpo--plan .drpl { flex: 1 1 auto; min-height: 0; }
.drx-cuerpo--plan .drpl-estado[data-tono="warn"] { position: static; box-shadow: none; }
.drx-cuerpo--plan .drpl-cuerpo { flex: 1 1 auto; min-height: 0; align-items: stretch; grid-template-rows: minmax(0, 1fr); }
.drpl-indice { position: static; top: auto; }
.drx-cuerpo--plan .drpl-indice { min-height: 0; overflow-y: auto; padding-right: 4px; scrollbar-width: thin; }
.drpl-lector { min-width: 0; display: flex; flex-direction: column; gap: 18px; }
.drx-cuerpo--plan .drpl-lector { min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding-right: 6px; scrollbar-width: thin; }
.drpl-lector:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 12px; }
.drpl-documento { position: relative; flex: none; }
.drpl-indice ol button[aria-current="location"] { color: var(--accent); font-weight: 600; border-left-color: var(--accent); background: var(--accent-soft); }
@media (max-width: 900px) {
  .modal.drx .body.drx-cuerpo.drx-cuerpo--plan { overflow-y: auto; }
  .drx-cuerpo--plan .drpl-lector, .drx-cuerpo--plan .drpl-indice { overflow: visible; }
  .drx-cuerpo--plan .drpl-cuerpo { grid-template-rows: none; }
}

/* Imagen generada por el agente (27-10-2026): se ve, pero se distingue de una captura del navegador */
.drx-generada { display: inline-flex; align-items: center; gap: 4px; margin-top: 6px; padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; background: var(--info-bg); color: var(--info); }
.drd-lightbox-generada { color: var(--info); font-weight: 600; }

/* «Fusionar y desplegar en Development» (27-10-2026): arriba de la pestaña Código mientras el run espera su despliegue */
.drm { --drm-color: var(--accent); --drm-tinte: var(--accent-soft); display: flex; flex-direction: column; gap: 14px; padding: 18px 22px; border-radius: 12px; border: 1px solid color-mix(in srgb, var(--drm-color) 35%, var(--border)); background: linear-gradient(180deg, var(--drm-tinte), var(--panel) 75%); }
.drm[data-tono="ok"] { --drm-color: var(--ok); --drm-tinte: color-mix(in srgb, var(--ok) 10%, var(--panel)); }
.drm[data-tono="danger"] { --drm-color: var(--danger); --drm-tinte: var(--danger-bg); }
.drm[data-tono="warn"] { --drm-color: var(--warn); --drm-tinte: var(--warn-bg); }
.drm[data-tono="info"] { --drm-color: var(--info); --drm-tinte: var(--info-bg); }
.drm-cabeza { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 14px; align-items: center; }
.drm-ico { width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; font-size: 22px; color: var(--drm-color); background: color-mix(in srgb, var(--drm-color) 14%, var(--panel)); }
.drm-texto h3 { margin: 0; font-size: 16px; font-weight: 700; color: var(--text); }
.drm-texto p { margin: 2px 0 0; font-size: 13px; color: var(--muted); max-width: 80ch; }
.drm-boton { height: 40px; font-size: 14px; white-space: nowrap; }
.drm-repos { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.drm-repos li { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 13px; padding: 8px 12px; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; }
.drm-repo { font-weight: 600; }
.drm-sha { padding: 1px 6px; border-radius: 6px; background: var(--neutral-bg); font-size: 12px; }
.drm-version { font-weight: 700; color: var(--ok-texto); font-variant-numeric: tabular-nums; }
.drm-motivo { margin: 0; padding: 10px 12px; border-radius: 8px; background: var(--danger-bg); color: var(--danger); font-size: 13px; font-weight: 600; overflow-wrap: anywhere; }
.drm-pasos { list-style: none; margin: 0; padding: 0 0 0 4px; display: flex; flex-direction: column; gap: 6px; border-left: 2px solid var(--border); }
.drm-pasos li { position: relative; padding-left: 16px; font-size: 13px; display: flex; flex-wrap: wrap; gap: 0 6px; }
.drm-paso-marca { position: absolute; left: -7px; top: 5px; width: 12px; height: 12px; border-radius: 50%; background: var(--drm-color); border: 2px solid var(--panel); }
.drm-pasos li[data-ultimo="si"] .drm-paso-marca { box-shadow: 0 0 0 4px color-mix(in srgb, var(--drm-color) 25%, transparent); animation: drm-latido 1.4s ease-in-out infinite; }
.drm-paso-texto { color: var(--muted); flex-basis: 100%; overflow-wrap: anywhere; }
.drm-registro { display: flex; flex-direction: column; gap: 6px; }
.drm-log { margin: 0; max-height: 320px; overflow: auto; padding: 12px 14px; border-radius: 8px; background: #0f1419; color: #d7dde3; font: 11.5px/1.55 var(--mono); white-space: pre-wrap; overflow-wrap: anywhere; }
@keyframes drm-latido { 50% { box-shadow: 0 0 0 7px color-mix(in srgb, var(--drm-color) 10%, transparent); } }
@media (prefers-reduced-motion: reduce) { .drm-pasos li[data-ultimo="si"] .drm-paso-marca { animation: none; } }
@media (max-width: 900px) { .drm-cabeza { grid-template-columns: auto minmax(0, 1fr); } .drm-boton { grid-column: 1 / -1; } }
/* 27-10-2026 (el MR primero): dos botones (aceptar / pedir cambios) y el cuadro de comentarios */
.drm-botones { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.drm-cambios { display: flex; flex-direction: column; gap: 8px; padding: 14px; border-radius: 10px; background: var(--panel); border: 1px solid var(--border); }
.drm-cambios label { font-size: 13px; color: var(--muted); }
.drm-cambios label b { color: var(--text); }
.drm-cambios textarea { width: 100%; min-height: 110px; resize: vertical; padding: 10px 12px; border: 1px solid var(--border-strong); border-radius: 8px; background: var(--panel); color: var(--text); font: inherit; font-size: 13px; line-height: 1.5; }
.drm-cambios textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.drm-cambios-acciones { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
@media (max-width: 900px) { .drm-botones { grid-column: 1 / -1; justify-content: flex-start; } }

/* «Mis filtros» (Herramientas, 28-10-2026), EXACTLY as its sketch (docs/propuestas/mis-filtros):
   row 1  Buscar · Tipo · Sprint · Proyecto · Fecha de ventana · Mes de pago · [DevOps/Jira] · [Más filtros]
   row 2  the «DevOps/Jira» panel under Buscar…Fecha de ventana, «Más filtros» under Mes de pago and the buttons,
   both UNFOLDED in place. The bar is the table's own component over a draft, laid out by this grid
   (`display: contents` lets each menu's button sit in row 1 and its panel in row 2). */
.modal-mis-filtros { width: min(1320px, 96vw); max-width: none; }
.modal-mis-filtros > .body { display: flex; flex-direction: column; gap: 14px; overflow: visible; }
.mis-filtros-acciones { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.modal-mis-filtros .filtros {
  display: grid;
  grid-template-columns: minmax(200px, 2fr) repeat(3, minmax(90px, 1fr)) minmax(130px, 1.3fr) minmax(90px, .9fr) auto auto;
  gap: 12px;
  align-items: end;
}
/* Every field of row 1 with its row fixed: placed in document order (a row-locked button alone would jump ahead) */
.modal-mis-filtros .filtros > .field { min-width: 0; margin: 0; grid-row: 1; }
.modal-mis-filtros .filtros > .campo-buscar { grid-column: 1; grid-row: 1; }
/* The row's own «Limpiar»: the modal has its own above */
.modal-mis-filtros .filtros > .acciones-filtro:not(.campo-menu-filtros) { display: none; }
.modal-mis-filtros .filtros > .campo-devops-jira,
.modal-mis-filtros .filtros > .campo-mas-filtros { display: contents; }
/* Their buttons: marked, in row 1, only a reference (the panels are always open here) */
.modal-mis-filtros .filtros .btn-devops-jira,
.modal-mis-filtros .filtros .btn-mas-filtros { grid-row: 1; align-self: end; pointer-events: none; }
.modal-mis-filtros .filtros .menu-filtros.panel-en-linea {
  position: static; width: 100%; max-width: none; max-height: none; overflow: visible; box-shadow: none; z-index: auto;
  margin: 0; box-sizing: border-box; padding: 14px 16px; gap: 14px; align-self: start;
}
/* DevOps/Jira down both rows; on the right «Más filtros» and, under it, «Ordenamiento» */
.modal-mis-filtros .filtros .menu-filtros.menu-devops-jira.panel-en-linea { grid-column: 1 / 6; grid-row: 2 / span 2; }
.modal-mis-filtros .filtros .menu-filtros.panel-orden.panel-en-linea { grid-column: 6 / 9; grid-row: 3; display: flex; flex-direction: column; align-items: stretch; background: var(--panel); }
.modal-mis-filtros .panel-orden select { width: 100%; }
.modal-mis-filtros .filtros .menu-filtros.panel-filtros.panel-en-linea {
  grid-column: 6 / 9; grid-row: 2; display: flex; flex-direction: column; align-items: stretch; background: var(--panel);
}
.panel-en-linea-titulo { font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
/* «DevOps/Jira»: each section's title in bold, no rules between them, its two fields wide */
.modal-mis-filtros .panel-en-linea .seccion-menu-filtros + .seccion-menu-filtros { border-top: 0; padding-top: 0; }
.modal-mis-filtros .panel-en-linea .seccion-menu-filtros > h4 { text-transform: none; letter-spacing: 0; font-size: 13px; font-weight: 700; color: var(--text); margin: 0 0 6px; }
.modal-mis-filtros .panel-en-linea .seccion-campos { gap: 12px; }
.modal-mis-filtros .panel-en-linea .select-tipos { width: 100%; }
/* «Más filtros»: each label above, its two dates in ONE row «fecha – fecha», Excluir full width */
.modal-mis-filtros .filtros .menu-filtros.panel-en-linea .rango-filtro {
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 4px 8px; align-items: center;
}
.modal-mis-filtros .filtros .menu-filtros.panel-en-linea .rango-filtro > label { grid-column: 1 / -1; min-width: 0; font-size: 11px; font-weight: 600; }
.modal-mis-filtros .filtros .menu-filtros.panel-en-linea .rango-filtro input[type="date"] { width: 100%; min-width: 0; }
.modal-mis-filtros .filtros .menu-filtros.panel-en-linea .rango-filtro.filtro-excluir input { grid-column: 1 / -1; width: 100%; }
.modal-mis-filtros .filtros .menu-filtros.panel-en-linea .rango-filtro > span.hint:not(.fecha-no-aplica) { font-size: 0; }
.modal-mis-filtros .filtros .menu-filtros.panel-en-linea .rango-filtro > span.hint:not(.fecha-no-aplica)::after { content: "–"; font-size: 13px; color: var(--muted); }
.modal-mis-filtros .filtros .menu-filtros.panel-en-linea .rango-filtro > .fecha-no-aplica { grid-column: 1 / -1; white-space: normal; }
.modal-mis-filtros .panel-en-linea .rango-filtro > label .hint { font-weight: 400; }
@media (max-width: 1000px) {
  .modal-mis-filtros .filtros { grid-template-columns: 1fr 1fr; }
  .modal-mis-filtros .filtros > .field { grid-row: auto; }
  .modal-mis-filtros .filtros > .campo-buscar { grid-column: 1 / -1; }
  .modal-mis-filtros .filtros .btn-devops-jira,
  .modal-mis-filtros .filtros .btn-mas-filtros { display: none; }
  .modal-mis-filtros .filtros .menu-filtros.menu-devops-jira.panel-en-linea,
  .modal-mis-filtros .filtros .menu-filtros.panel-filtros.panel-en-linea,
  .modal-mis-filtros .filtros .menu-filtros.panel-orden.panel-en-linea { grid-column: 1 / -1; grid-row: auto; }
}
/* 27-10-2026: un solo botón para responder todos los insumos */
.drd-ins-final { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 10px; padding: 14px 0 4px; border-top: 1px solid var(--border); }
.drd-ins-final .ent-falta { margin: 0 auto 0 0; }
/* 27-10-2026: aprendizajes propuestos por el cierre */
.drs-aprendizajes { display: flex; flex-direction: column; gap: 8px; }
.drs-aprendizajes-nota { margin: -4px 0 2px; font-size: 12.5px; color: var(--muted); }
.drs-aprendizajes li[data-estado="descartado"] .drs-fila-texto strong { color: var(--muted); text-decoration: line-through; font-weight: 500; }
.drs-aprendizaje-acciones { display: flex; gap: 4px; }

/* ───────────── «Preguntar a la documentación» (28-10-2026, modules/docsChat/ChatWidget.js) ─────────────
   A button in the bottom right corner on every screen, and its window above it. Below the modals (60), so a modal
   opened from a source covers it; the toasts move up to leave the button visible. */
.dchat-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.dchat ~ .toasts { bottom: 82px; }
.dchat-fab {
  position: fixed; right: 18px; bottom: 18px; z-index: 55; width: 52px; height: 52px; border-radius: 50%;
  border: 1px solid var(--brand-strong); background: var(--brand); color: #fff; font-size: 24px; cursor: pointer;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22); display: grid; place-items: center;
}
.dchat-fab:hover { background: var(--brand-strong); }
.dchat-fab:focus-visible { outline: 3px solid var(--accent-soft); outline-offset: 2px; }
.dchat-panel {
  position: fixed; right: 18px; bottom: 80px; z-index: 55; width: min(420px, calc(100vw - 32px));
  height: min(620px, calc(100vh - var(--topbar-h) - 100px)); display: flex; flex-direction: column;
  background: var(--panel); color: var(--text); border: 1px solid var(--border-strong); border-radius: 10px;
  box-shadow: 0 10px 32px rgba(0, 0, 0, 0.25); overflow: hidden;
}
.dchat-cabecera { display: flex; align-items: center; gap: 4px; padding: 10px 10px 10px 14px; background: var(--header-azul); color: #fff; }
.dchat-titulo { flex: 1; margin: 0; font-size: 14px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.dchat-icono { border: 0; background: transparent; color: #fff; font-size: 18px; width: 30px; height: 30px; border-radius: 6px; cursor: pointer; }
.dchat-icono:hover { background: rgba(255, 255, 255, 0.16); }
.dchat-cuerpo { flex: 1; overflow-y: auto; padding: 12px 14px; display: flex; flex-direction: column; gap: 14px; }
.dchat-vacio { color: var(--muted); font-size: 13px; line-height: 1.45; margin: 0; }
.dchat-turno { display: flex; flex-direction: column; gap: 6px; }
.dchat-pregunta {
  align-self: flex-end; max-width: 88%; margin: 0; padding: 8px 11px; border-radius: 10px 10px 2px 10px;
  background: var(--accent-soft); color: var(--text); font-size: 13px; white-space: pre-wrap; overflow-wrap: anywhere;
}
.dchat-respuesta {
  align-self: flex-start; max-width: 96%; padding: 9px 11px; border-radius: 10px 10px 10px 2px;
  background: var(--neutral-bg); border: 1px solid var(--border); font-size: 13px; line-height: 1.45; overflow-wrap: anywhere;
}
.dchat-parrafo, .dchat-item { margin: 0 0 4px; }
.dchat-item { padding-left: 14px; position: relative; }
.dchat-item::before { content: "•"; position: absolute; left: 3px; color: var(--muted); }
.dchat-fuera { color: var(--muted); font-style: italic; }
.dchat-aviso { color: var(--warn); background: var(--warn-bg); border-color: transparent; }
.dchat-aviso-docs { margin: 0; padding: 6px 12px; font-size: 12px; border-bottom: 1px solid var(--line, transparent); }
.dchat-esperando { display: flex; align-items: center; gap: 8px; color: var(--muted); }
.dchat-cancelar { margin-left: auto; border: 1px solid var(--border-strong); background: var(--panel); color: var(--text); border-radius: 6px; font-size: 12px; padding: 2px 8px; cursor: pointer; }
.dchat-puntos { display: inline-flex; gap: 3px; }
.dchat-puntos span { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); animation: dchat-pulso 1.2s infinite ease-in-out; }
.dchat-puntos span:nth-child(2) { animation-delay: 0.15s; }
.dchat-puntos span:nth-child(3) { animation-delay: 0.3s; }
@keyframes dchat-pulso { 0%, 80%, 100% { opacity: 0.25; transform: scale(0.8); } 40% { opacity: 1; transform: scale(1); } }
@media (prefers-reduced-motion: reduce) { .dchat-puntos span { animation: none; opacity: 0.7; } }
.dchat-codigo { font-family: var(--mono); font-size: 0.92em; padding: 1px 4px; border-radius: 4px; background: var(--accent-soft); overflow-wrap: anywhere; }
.dchat-marca {
  border: 0; background: var(--accent-soft); color: var(--accent); border-radius: 4px; padding: 0 4px; margin: 0 1px;
  font: inherit; font-size: 11px; font-weight: 600; cursor: pointer; vertical-align: baseline;
}
.dchat-fuentes { margin-top: 8px; padding-top: 7px; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 4px; }
.dchat-fuentes-titulo { font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.03em; }
.dchat-fuente {
  text-align: left; border: 1px solid var(--border); background: var(--panel); color: var(--text); border-radius: 6px;
  padding: 4px 7px; font-size: 12px; cursor: pointer; overflow-wrap: anywhere;
}
.dchat-fuente:hover:not(:disabled) { border-color: var(--accent); }
.dchat-fuente:disabled { cursor: default; opacity: 0.8; }
.dchat-fuente-marca { font-weight: 700; color: var(--accent); margin-right: 3px; }
.dchat-historial { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.dchat-historial-item {
  width: 100%; text-align: left; border: 1px solid var(--border); background: var(--panel); color: var(--text);
  border-radius: 8px; padding: 8px 10px; cursor: pointer; display: flex; flex-direction: column; gap: 2px;
}
.dchat-historial-item:hover { border-color: var(--accent); }
.dchat-historial-titulo { font-size: 13px; }
.dchat-historial-fecha { font-size: 11px; color: var(--muted); }
.dchat-pie { border-top: 1px solid var(--border); padding: 8px 10px 10px; display: flex; flex-direction: column; gap: 6px; }
.dchat-contexto { margin: 0; font-size: 11px; color: var(--muted); }
.dchat-error { margin: 0; font-size: 12px; color: var(--danger); background: var(--danger-bg); padding: 5px 8px; border-radius: 6px; }
.dchat-entrada { display: flex; gap: 6px; align-items: flex-end; }
.dchat-entrada textarea {
  flex: 1; resize: none; min-height: 40px; max-height: 120px; padding: 8px 10px; border: 1px solid var(--border-strong);
  border-radius: 8px; background: var(--panel); color: var(--text); font: inherit; font-size: 13px;
}
.dchat-entrada textarea:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
.dchat-enviar {
  width: 40px; height: 40px; border-radius: 8px; border: 1px solid var(--brand-strong); background: var(--brand); color: #fff;
  font-size: 18px; cursor: pointer;
}
.dchat-enviar:disabled { opacity: 0.45; cursor: default; }
/* Export (paso 4c): the buttons under an answer, and the screen's own question with its buttons */
.dchat-exportar { display: flex; align-items: center; gap: 4px; margin-top: 8px; font-size: 11px; color: var(--muted); }
.dchat-exportar > span { margin-right: 2px; }
.dchat-exportar-boton {
  border: 1px solid var(--border-strong); background: var(--panel); color: var(--text); border-radius: 5px;
  font-size: 11.5px; padding: 1px 8px; cursor: pointer;
}
.dchat-exportar-boton:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.dchat-exportar-boton:disabled { opacity: 0.5; cursor: default; }
.dchat-sistema { display: flex; flex-direction: column; gap: 6px; color: var(--muted); }
.dchat-opciones { display: flex; gap: 6px; flex-wrap: wrap; }
/* Opinion and curation (paso 5): 👍/👎 and «Corregir» under an answer, and the curators' panel with its three tabs */
.dchat-opinion { display: flex; align-items: center; gap: 4px; margin-top: 8px; flex-wrap: wrap; }
.dchat-opinion-boton {
  border: 1px solid var(--border-strong); background: var(--panel); border-radius: 5px; font-size: 13px; line-height: 1.3;
  padding: 0 6px; cursor: pointer; filter: grayscale(1); opacity: 0.75;
}
.dchat-opinion-boton:hover:not(:disabled), .dchat-opinion-activa { filter: none; opacity: 1; border-color: var(--accent); }
.dchat-opinion-activa { background: var(--accent-soft); }
.dchat-nota { font-size: 11.5px; color: var(--muted); margin: 0; }
.dchat-icono-activo { background: rgba(255, 255, 255, 0.24); }
.dchat-cura-form { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; font-size: 12px; color: var(--muted); }
.dchat-cura-form label { display: flex; flex-direction: column; gap: 3px; }
.dchat-cura-form textarea, .dchat-cura-form input, .dchat-cura-filtro select {
  border: 1px solid var(--border-strong); border-radius: 6px; background: var(--panel); color: var(--text); font: inherit; font-size: 12.5px; padding: 5px 7px;
}
.dchat-curaduria { display: flex; flex-direction: column; gap: 10px; }
.dchat-pestanas { display: flex; gap: 4px; border-bottom: 1px solid var(--border); }
.dchat-pestana { border: 0; background: transparent; color: var(--muted); font-size: 12.5px; padding: 6px 10px; cursor: pointer; border-bottom: 2px solid transparent; }
.dchat-pestana-activa { color: var(--text); border-bottom-color: var(--accent); font-weight: 600; }
.dchat-cura { border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; display: flex; flex-direction: column; gap: 4px; background: var(--panel); }
.dchat-cura .dchat-pregunta { align-self: stretch; max-width: none; }
.dchat-cura-meta { font-size: 11px; color: var(--muted); margin: 0; }
.dchat-cura-texto { font-size: 12.5px; margin: 0; white-space: pre-wrap; }
.dchat-cura-aviso { font-size: 12px; margin: 0; padding: 5px 8px; border-radius: 6px; color: var(--warn); background: var(--warn-bg); }
.dchat-cura-json { font-size: 11.5px; max-height: 320px; overflow: auto; margin: 6px 0 0; white-space: pre-wrap; word-break: break-word; }
.dchat-cura-filtro { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.dchat-glosario { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; }
.dchat-glosario li { display: flex; flex-direction: column; gap: 3px; border-bottom: 1px solid var(--border); padding-bottom: 6px; }
/* Images (paso 4b): the drop target, the attached ones before sending, and the thumbnails over a question */
.dchat-soltar { outline: 3px dashed var(--accent); outline-offset: -6px; }
.dchat-adjuntar {
  width: 40px; height: 40px; border-radius: 8px; border: 1px solid var(--border-strong); background: var(--panel); color: var(--text);
  font-size: 19px; cursor: pointer;
}
.dchat-adjuntar:hover { border-color: var(--accent); color: var(--accent); }
.dchat-adjuntos { list-style: none; margin: 0; padding: 0; display: flex; gap: 6px; flex-wrap: wrap; }
.dchat-documentos { list-style: none; margin: 0 0 6px; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.dchat-documento { display: flex; align-items: center; gap: 6px; padding: 4px 8px; border: 1px solid var(--border-strong); border-radius: 6px; background: var(--panel); color: var(--text); font-size: 12px; min-width: 0; }
.dchat-documento-nombre { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 0 1 auto; }
.dchat-documento-marca { font-weight: 700; opacity: .75; }
.dchat-documento-estado { opacity: .8; flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dchat-documento-error { border-color: var(--danger); }
.dchat-documento-error .dchat-documento-estado { color: var(--danger); opacity: 1; white-space: normal; }
.dchat-documento .dchat-adjunto-quitar { position: static; }
.dchat-adjunto {
  position: relative; width: 64px; height: 64px; border: 1px solid var(--border-strong); border-radius: 6px; overflow: hidden; background: var(--neutral-bg);
}
.dchat-adjunto img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dchat-adjunto-error { border-color: var(--danger); }
.dchat-adjunto-estado {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 1px 3px; font-size: 10px; line-height: 1.2; color: #fff;
  background: rgba(0, 0, 0, 0.6); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dchat-adjunto-error .dchat-adjunto-estado { background: var(--danger); }
.dchat-adjunto-quitar {
  position: absolute; top: 2px; right: 2px; width: 20px; height: 20px; border-radius: 50%; border: 0; padding: 0;
  background: rgba(0, 0, 0, 0.65); color: #fff; font-size: 13px; line-height: 20px; cursor: pointer;
}
.dchat-miniaturas { align-self: flex-end; display: flex; gap: 5px; flex-wrap: wrap; justify-content: flex-end; }
.dchat-miniatura {
  position: relative; width: 56px; height: 56px; padding: 0; border: 1px solid var(--border-strong); border-radius: 6px;
  overflow: hidden; background: var(--neutral-bg); cursor: pointer; display: grid; place-items: center; font-size: 11px; color: var(--muted);
}
.dchat-miniatura img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dchat-miniatura-marca { position: absolute; left: 2px; bottom: 2px; font-size: 9px; font-weight: 700; color: #fff; background: rgba(0, 0, 0, 0.6); border-radius: 3px; padding: 0 3px; }
.dchat-miniatura-ida { cursor: default; font-weight: 600; }
@media (max-width: 520px) {
  .dchat-panel { right: 8px; left: 8px; width: auto; bottom: 76px; height: calc(100vh - 140px); }
  .dchat-fab { right: 12px; bottom: 12px; }
}

/* «Aprobaciones» (29-10-2026, estimateApprovals/ApprovalBoardModal.js): the board by DevOps state as a
   spreadsheet. Ticket, Estado and Título stay put while scrolling sideways; the header stays on top.
   Approved cells green, missing ones white (the panel's colour, so the dark theme keeps reading). */
/* A pantalla completa (Gerson, 29-10-2026): la matriz crece con las personas y necesita todo el ancho */
.backdrop.tablero-aprob-fondo { padding: 0; }
.tablero-aprob-modal { width: 100vw; height: 100vh; max-width: none; max-height: none; border-radius: 0; border: none; }
.tablero-aprob-modal .body { flex: 1 1 auto; }
.tablero-aprob-barra { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.tablero-aprob-estados { display: flex; gap: 6px; flex-wrap: wrap; }
.tablero-aprob-buscar { flex: 0 1 280px; }
/* El color de cada estado de DevOps, en el orden del flujo (29-10-2026): pinta su chip, la franja y
   el tinte de su fila. Ni verde ni rojo, que ya dicen «Aprobado» y «Urgente». */
.tablero-aprob-modal .estado-0 { --c: var(--warn); }
.tablero-aprob-modal .estado-1 { --c: var(--info); }
.tablero-aprob-modal .estado-2 { --c: var(--accent); }
.tablero-aprob-modal .estado-3 { --c: #ad1457; }
.tablero-aprob-modal .estado-4 { --c: #00796b; }
.tablero-aprob-scroll { overflow: auto; flex: 1 1 auto; min-height: 0; border: 1px solid var(--border-strong); border-radius: var(--radius); }
.tablero-aprob { border-collapse: separate; border-spacing: 0; font-size: 13px; min-width: 100%; }
.tablero-aprob th, .tablero-aprob td { border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: 6px 8px; vertical-align: middle; }
.tablero-aprob thead th { position: sticky; background: var(--brand); color: #fff; font-weight: 600; text-align: center; z-index: 2; }
.tablero-aprob thead tr:first-child th { top: 0; }
.tablero-aprob thead tr:nth-child(2) th { top: 31px; }
.tablero-aprob thead th.area { background: var(--brand-strong); text-transform: uppercase; letter-spacing: .03em; font-size: 12px; }
.tablero-aprob thead th.persona { min-width: 118px; max-width: 160px; white-space: normal; font-weight: 500; }
.tablero-aprob .fija { position: sticky; background: var(--panel); z-index: 1; }
.tablero-aprob thead .fija { z-index: 3; background: var(--brand); }
.tablero-aprob .fija-1 { left: 0; width: 180px; min-width: 180px; }
.tablero-aprob .fija-2 { left: 180px; min-width: 260px; max-width: 360px; border-right: 2px solid var(--border-strong); }
.tablero-aprob td.fija-1 b { display: block; font-weight: 700; }
.tablero-aprob td.fija-1 .hint { display: block; font-size: 11px; }
/* Una solicitud urgente: la fila entera enmarcada en rojo y «Urgente» bajo el estado (29-10-2026) */
.tablero-aprob tr.urgente > td { border-top: 2px solid var(--danger); border-bottom: 2px solid var(--danger); }
.tablero-aprob tr.urgente > td:first-child { border-left: 3px solid var(--danger); }
.tablero-aprob tr.urgente > td:last-child { border-right: 3px solid var(--danger); }
.tablero-aprob .chip-urgente { display: inline-block; margin-top: 4px; padding: 0 6px; border-radius: 999px; font-size: 11px; font-weight: 700; color: var(--danger); background: var(--danger-bg); border: 1px solid var(--danger); }
.tablero-aprob td.fija-1 .estado-devops { display: block; margin-top: 4px; font-size: 12px; color: var(--c, var(--muted)); font-weight: 600; }
/* El asignado, solo tras cambiar el estado aquí: resaltado si la transición lo reasignó */
.tablero-aprob td.fija-1 .asignado-tras-cambio { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; margin-top: 4px; font-size: 12px; }
.tablero-aprob td.fija-1 .marca-reasignado { font-size: 11px; font-weight: 600; color: var(--warn); }
/* Las horas del ticket bajo su clave: el desglose va en el tooltip */
.tablero-aprob td.fija-1 .horas-ticket { display: inline-flex; align-items: center; gap: 3px; margin-top: 2px; font-size: 12px; font-weight: 600; color: var(--text); cursor: help; }
.tablero-aprob td.fija-1 .horas-ticket .mdi { color: var(--muted); }
/* La fila toma el tinte de su estado en lo que no es una respuesta (ticket, título, «—» y conteos):
   las celdas «Aprobado» y «Falta» conservan su verde y su blanco. Opaco, que las fijas tapan al desplazar. */
.tablero-aprob tr[class*="estado-"] > td.fija,
.tablero-aprob tr[class*="estado-"] > td.num,
.tablero-aprob tr[class*="estado-"] > td.celda.vacia { background: color-mix(in srgb, var(--c) 9%, var(--panel)); }
.tablero-aprob tr[class*="estado-"] > td.fija-1 { box-shadow: inset 4px 0 0 var(--c); padding-left: 12px; }
.tablero-aprob td.titulo { white-space: normal; line-height: 1.3; }
.tablero-aprob tbody tr:hover td:not(.fija-1) { filter: brightness(.97); }
/* Not on the ticket cell: a `filter` makes it the containing block of the state menu (`position: fixed`),
   which then opens inside the cell and gets cut. And with the menu open the cell goes above its
   neighbours, sticky cells with their own stacking context that would paint over it */
.tablero-aprob td.fija-1:has(.menu-estado-devops), .tablero-aprob td.fija-1:has(.menu-asignado-devops) { z-index: 5; }
.tablero-aprob td.celda { text-align: center; white-space: nowrap; }
.tablero-aprob td.celda.aprobado { background: color-mix(in srgb, var(--ok) 22%, var(--panel)); color: var(--ok-texto); font-weight: 600; }
.tablero-aprob td.celda.falta { background: var(--panel); color: var(--text); font-weight: 600; }
.tablero-aprob td.celda.vacia { background: var(--neutral-bg); }
.tablero-aprob td.celda.no-requerida { background: var(--neutral-bg); color: var(--muted); font-style: italic; }
.tablero-aprob .btn-no-requerida:hover:not(:disabled) { color: var(--danger); border-color: var(--danger); }
.tablero-aprob td.num { text-align: right; min-width: 70px; }
.tablero-aprob .recordar { display: inline-flex; gap: 2px; margin-left: 6px; }
.tablero-aprob .btn-recordar { border: 1px solid var(--border); background: var(--panel); color: var(--muted); border-radius: 4px; padding: 1px 4px; cursor: pointer; line-height: 1; }
.tablero-aprob .btn-recordar:hover:not(:disabled) { color: var(--brand); border-color: var(--brand); }
.tablero-aprob .btn-recordar .mdi-whatsapp { color: #1fa855; }
.tablero-aprob .btn-recordar:disabled { opacity: .5; cursor: default; }

/* EL MES DE PAGO POR DEVOPS (02-11-2026). Las celdas «DevOps Backend» / «DevOps Frontend» apilan
   una línea por work item de la fila (con su número cuando son varios); la celda «Pago» de una fila
   con varios DevOps dice los meses («oct 2026 ×2 · nov 2026») y, si a alguno le falta el mes, un
   distintivo que lo cuenta. */
.tabla-docs .wi-lineas { display: flex; flex-direction: column; gap: 2px; }
/* Una línea mide lo mismo en «N.º», «Asignado a» y «Estado»: cada número queda frente a su
   asignado y su estado (03-11-2026). */
.tabla-docs .wi-linea { display: flex; align-items: center; gap: 4px; white-space: nowrap; min-height: 22px; }
.tabla-docs .wi-numero { font-size: 11px; color: var(--muted); }
.tabla-docs th.col-wi-numero,
.tabla-docs td.col-wi-numero { width: 1%; white-space: nowrap; padding-right: 4px; }
/* La celda «Pago» apila lo que enseña: el mes en una línea y el distintivo en la siguiente,
   centrados como el resto de la celda. El `td` es `nowrap` y de ancho mínimo (`width: 1%`), y con
   los dos en una misma línea el distintivo se salía de la celda y pisaba «Sprint» (TL-10715,
   02-11-2026). La anchura mínima es la del distintivo con su icono («Faltan 3 de 3»), que es lo
   más ancho que cabe aquí; lo que no quepa se recorta DENTRO de la celda, con su tooltip entero. */
.tabla-docs td.col-mes-pago .mes-pago-celda {
  display: inline-flex; flex-direction: column; align-items: center; gap: 3px;
  max-width: 100%; vertical-align: middle; overflow: hidden;
}
.tabla-docs td.col-mes-pago:has(.mes-pago-faltan) { max-width: none; }
.tabla-docs td.col-mes-pago:has(.mes-pago-faltan) .mes-pago-celda { min-width: 116px; }
.mes-pago-faltan {
  display: inline-flex; align-items: center; gap: 2px; max-width: 100%; box-sizing: border-box;
  padding: 0 6px; border-radius: 999px; font-size: 11px; line-height: 16px; white-space: nowrap;
  overflow: hidden;
  color: var(--warn); border: 1px solid var(--warn); background: color-mix(in srgb, var(--warn) 12%, transparent);
}
.mes-pago-faltan .mdi { font-size: 13px; flex: none; }
/* La elipsis la hace el texto, no el `inline-flex` (ahí la declaración no actúa) */
.mes-pago-faltan .mes-pago-faltan-texto { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* Varios DevOps sin faltantes: los meses se parten solo antes del « · » (lib/tramosPorDevops.mjs) */
.tabla-docs .col-mes-pago .mes-pago-devops { white-space: normal; text-align: center; }

/* El modal «Mes de pago por DevOps» */
.modal.modal-tramos-devops { width: 860px; }
.tabla-tramos-devops .tramo-devops { max-width: 260px; }
.tabla-tramos-devops .tramo-devops-titulo { max-width: 250px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tabla-tramos-devops .tag-rol { font-size: 11px; color: var(--muted); border: 1px solid var(--border); border-radius: 999px; padding: 0 6px; }
.tabla-tramos-devops .tramo-acciones { white-space: nowrap; }

/* EL EMBUDO DE LA COLUMNA «PAGO» (D4): el mismo filtro «Mes de pago» de la barra, como popover
   anclado a la cabecera (useFilterPopover lo coloca con position: fixed). */
.tabla-docs .th-con-filtro { display: inline-flex; align-items: center; gap: 2px; }
.tabla-docs .th-embudo { display: inline-flex; }
.tabla-docs .btn-embudo {
  display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px;
  border: 0; border-radius: 4px; background: transparent; color: var(--muted); cursor: pointer; font-size: 15px; padding: 0;
}
.tabla-docs .btn-embudo:hover:not(:disabled) { color: var(--text); background: color-mix(in srgb, var(--text) 10%, transparent); }
.tabla-docs .btn-embudo:disabled { opacity: 0.4; cursor: default; }
.tabla-docs .btn-embudo.activo { color: var(--accent, var(--text)); }
.menu-embudo-mes-pago {
  z-index: 60; display: flex; flex-direction: column; gap: 4px; min-width: 200px; width: max-content;
  overflow: auto; overscroll-behavior: contain; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); color: var(--text);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.28); box-sizing: border-box; text-align: left; font-weight: normal; text-transform: none;
}
.menu-embudo-mes-pago .embudo-acciones { display: flex; gap: 12px; padding-bottom: 6px; border-bottom: 1px solid var(--border); margin-bottom: 4px; }
.menu-embudo-mes-pago .embudo-opcion { display: flex; align-items: center; gap: 8px; padding: 3px 4px; border-radius: 4px; cursor: pointer; font-size: 13px; }
.menu-embudo-mes-pago .embudo-opcion:hover { background: color-mix(in srgb, var(--text) 6%, transparent); }
.menu-embudo-mes-pago .embudo-opcion.marcada { font-weight: 600; }
.menu-embudo-mes-pago .embudo-sin-mes { color: var(--warn); font-weight: 600; border: 1px dashed var(--warn); margin-bottom: 4px; }
.menu-embudo-mes-pago .embudo-etiqueta { flex: 1; }
.menu-embudo-mes-pago .embudo-conteo { color: var(--muted); font-size: 12px; }

/* ---- Pestaña «Despliegue» del detalle de un run (02-11-2026): las seis imágenes de Development ---- */
.drdp { display: flex; flex-direction: column; gap: 14px; }
.drdp-cabeza { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 10px 16px; padding: 16px 20px; border-radius: 12px; border: 1px solid var(--border); background: var(--panel); }
.drdp-cabeza h3 { margin: 0 0 4px; font-size: 16px; font-weight: 700; display: flex; align-items: center; gap: 8px; }
.drdp-cabeza-texto { flex: 1 1 360px; min-width: 0; }
.drdp-cabeza-texto p { margin: 0; font-size: 13px; line-height: 1.45; }
.drdp-cabeza-acciones { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.drdp-motivo { color: var(--warn); font-weight: 600; margin-top: 4px !important; }
.drdp-lectura { margin: 0; padding: 8px 12px; border-radius: 8px; font-size: 13px; background: var(--info-bg); color: var(--info); display: flex; gap: 8px; align-items: center; }
.drdp-lectura[data-estado="fallo"] { background: var(--danger-bg); color: var(--danger); }
.drdp-lectura[data-estado="atascado"] { background: var(--warn-bg); color: var(--warn); }
.drdp-sin-permiso { margin: 0; font-size: 13px; color: var(--muted); display: flex; gap: 6px; align-items: center; }
.drdp-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.drdp-fila { display: grid; grid-template-columns: minmax(220px, 1.6fr) minmax(150px, 1fr) minmax(170px, 1fr) auto; gap: 10px 18px; align-items: start; padding: 14px 18px; border-radius: 12px; border: 1px solid var(--border); background: var(--panel); }
.drdp-fila[data-tocado="si"] { border-color: color-mix(in srgb, var(--warn) 45%, var(--border)); background: linear-gradient(180deg, color-mix(in srgb, var(--warn) 6%, var(--panel)), var(--panel) 70%); }
.drdp-fila[data-estado="hecho"] { border-color: color-mix(in srgb, var(--ok) 45%, var(--border)); }
.drdp-fila[data-estado="fallo"] { border-color: color-mix(in srgb, var(--danger) 45%, var(--border)); }
.drdp-celda { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.drdp-etiqueta { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.drdp-nombre { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 15px; }
.drdp-tocado { font-size: 11px; }
.drdp-repo { font-size: 12px; }
.drdp-aviso { margin: 4px 0 0; font-size: 12.5px; line-height: 1.4; color: var(--danger); display: flex; gap: 6px; align-items: flex-start; }
.drdp-aviso--suave { color: var(--muted); }
.drdp-tag { font-size: 16px; }
.drdp-detalle { font-size: 12px; overflow-wrap: anywhere; }
.drdp-sin { font-size: 13px; color: var(--muted); font-style: italic; }
.drdp-input { height: 36px; padding: 0 10px; border-radius: 8px; border: 1px solid var(--border-strong); background: var(--bg); color: var(--text); font-size: 14px; width: 100%; max-width: 170px; }
.drdp-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.drdp-input[aria-invalid="true"] { border-color: var(--danger); }
.drdp-problema { font-size: 12px; color: var(--danger); font-weight: 600; }
.drdp-accion { align-self: center; justify-self: end; }
.drdp-avance { grid-column: 1 / -1; display: flex; flex-direction: column; gap: 8px; padding-top: 10px; border-top: 1px dashed var(--border); }
.drdp-avance-cabeza { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; font-size: 13px; }
.drdp-resultado { margin: 0; font-size: 14px; font-weight: 600; display: flex; gap: 8px; align-items: flex-start; }
.drdp-resultado[data-tono="ok"] { color: var(--ok-texto); }
.drdp-resultado[data-tono="danger"] { color: var(--danger); }
.drdp-pasos { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
.drdp-pasos li { display: grid; grid-template-columns: 20px auto 1fr; gap: 8px; align-items: baseline; }
.drdp-pasos li[data-ultimo="si"] { color: var(--info); }
.drdp-paso-marca { color: var(--ok); font-size: 15px; }
.drdp-pasos li[data-ultimo="si"] .drdp-paso-marca { color: var(--info); }
.drdp-paso-texto { color: var(--muted); overflow-wrap: anywhere; }
.drdp-registro { display: flex; flex-direction: column; gap: 6px; }
.drdp-log { margin: 0; max-height: 260px; overflow: auto; padding: 10px 12px; border-radius: 8px; background: var(--neutral-bg); font-size: 12px; line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; }
@media (max-width: 900px) {
  .drdp-fila { grid-template-columns: 1fr 1fr; }
  .drdp-proyecto { grid-column: 1 / -1; }
  .drdp-accion { grid-column: 1 / -1; justify-self: stretch; }
  .drdp-accion .drx-btn { width: 100%; justify-content: center; }
}

/* La pestaña «Fusionar» del detalle de un run (Gerson, 03-11-2026): rama destino por repo, «Ver cambios» y «Combinar ramas» */
.drf { display: flex; flex-direction: column; gap: 14px; }
.drf-cabeza { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 10px 16px; padding: 16px 20px; border-radius: 12px; border: 1px solid var(--border); background: var(--panel); }
.drf-cabeza h3 { margin: 0 0 4px; font-size: 16px; font-weight: 700; display: flex; align-items: center; gap: 8px; }
.drf-cabeza-texto { flex: 1 1 360px; min-width: 0; }
.drf-cabeza-texto p { margin: 0; font-size: 13px; line-height: 1.45; }
.drf-cabeza-acciones { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.drf-motivo { color: var(--warn); font-weight: 600; margin-top: 4px !important; display: flex; gap: 6px; align-items: flex-start; }
.drf-tarjeta .drm-texto h3 { font-size: 15px; }
.drf-destino-hecho { font-weight: 700; color: var(--ok-texto); }
.drf-vacio { margin: 0; padding: 14px 18px; border-radius: 12px; border: 1px dashed var(--border); color: var(--muted); font-size: 13px; display: flex; gap: 8px; align-items: center; }
.drf-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.drf-repo { display: flex; flex-direction: column; gap: 12px; padding: 14px 18px; border-radius: 12px; border: 1px solid var(--border); background: var(--panel); }
.drf-repo-cabeza { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; }
.drf-repo-nombre { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 14px; }
.drf-repo-destino { display: grid; grid-template-columns: minmax(180px, 1fr) minmax(260px, 2fr) auto; gap: 10px 16px; align-items: end; }
.drf-campo { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.drf-etiqueta { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.drf-input, .drf-select { height: 36px; padding: 0 10px; border-radius: 8px; border: 1px solid var(--border-strong); background: var(--bg); color: var(--text); font-size: 13px; width: 100%; }
.drf-input:focus-visible, .drf-select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.drf-detalle { font-size: 12px; display: inline-flex; gap: 4px; align-items: center; }
.drf-problema { font-size: 12px; color: var(--danger); font-weight: 600; }
.drf-repo-acciones { display: flex; gap: 8px; align-items: center; }
.drf-cambios { display: flex; flex-direction: column; gap: 10px; padding-top: 12px; border-top: 1px dashed var(--border); }
.drf-aviso { display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px; border-radius: 8px; background: var(--info-bg); color: var(--info); font-size: 13px; }
.drf-aviso[data-tono="ok"] { background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok-texto); }
.drf-aviso[data-tono="warn"] { background: var(--warn-bg); color: var(--warn); }
.drf-aviso p { margin: 2px 0 0; }
.drf-resumen { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 13px; }
.drf-resumen-titulo { font-weight: 600; margin-right: 4px; }
.drf-commits { font-size: 13px; }
.drf-commits summary { cursor: pointer; font-weight: 600; }
.drf-commits ul { margin: 6px 0 0; padding-left: 18px; display: flex; flex-direction: column; gap: 3px; }
.drf-diff .dr-d-archivos { display: flex; flex-direction: column; gap: 8px; }
@media (max-width: 900px) {
  .drf-repo-destino { grid-template-columns: 1fr; }
  .drf-repo-acciones .drx-btn { width: 100%; justify-content: center; }
}

/* ── The viewer's left column as an accordion (03-11-2026): «Archivos del ticket» and «Ticket» ── */
.visor-columna { flex: 0 0 270px; display: flex; flex-direction: column; min-height: 0; min-width: 0; border-right: 1px solid var(--border); overflow: hidden; }
.visor-columna > .visor-lista { flex: 1 1 auto; min-height: 0; border-right: 0; width: auto !important; }
.visor-columna > .visor-lista.plegada { flex: 0 0 auto; overflow: hidden; }
.visor-columna > .visor-ticket { border-top: 1px solid var(--border); }
.visor-arbol-derecha .visor-columna { border-right: 0; border-left: 1px solid var(--border); }
.visor-embebido .visor-columna { min-height: 0; }
/* The header that folds a section: chevron, icon and title in one button */
button.visor-exp-plegar {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 4px; padding: 0; border: 0; background: none;
  color: inherit; font: inherit; text-align: left; cursor: pointer;
}
button.visor-exp-plegar:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.visor-exp-plegar-chevron { color: var(--muted); font-size: 15px; flex: none; }
.visor-ticket-cuenta {
  margin-left: auto; padding: 0 6px; border-radius: 9px; font-size: 11px; font-weight: 600; line-height: 16px;
  color: var(--muted); background: var(--neutral-bg);
}
.visor-ticket-origen { margin-left: auto; color: var(--muted); font-size: 12px; }
.visor-ticket-vacio { margin: 2px 0 4px; padding: 0 12px 0 36px; font-size: 12px; }
.visor-ticket-aviso { margin: 8px; }
/* The right pane: a requirement, a comment or an attachment */
.visor-ticket-vista { display: flex; flex-direction: column; gap: 16px; }
.visor-ticket-documento { background: var(--panel); border: 1px solid var(--border); border-radius: 8px; padding: 14px 18px; }
.visor-ticket-documento-cabecera { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.visor-ticket-documento-cabecera h3 { margin: 0; font-size: 15px; font-weight: 650; overflow-wrap: anywhere; }
.visor-ticket-adjunto { display: flex; flex-direction: column; gap: 10px; min-height: 0; flex: 1 1 auto; }
.visor-ticket-adjunto .visor-ticket-documento-cabecera { margin-bottom: 0; }
/* La barra de un adjunto de «Ticket»: delgada, como la del documento, sin botones grandes */
.visor-ticket-barra {
  display: flex; align-items: center; gap: 8px; min-width: 0; padding: 6px 6px 6px 10px;
  border: 1px solid var(--border); border-radius: 6px; background: var(--panel); font-size: 13px;
}
.visor-ticket-barra > .mdi { flex: none; color: var(--muted); font-size: 16px; }
.visor-ticket-barra-nombre { min-width: 0; flex: 0 1 auto; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.visor-ticket-barra-meta { flex: 1 1 auto; min-width: 0; color: var(--muted); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.visor-ticket-barra-boton {
  flex: none; display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px;
  border: 0; border-radius: 6px; background: none; color: var(--muted); font-size: 18px; cursor: pointer;
}
.visor-ticket-barra-boton:hover { background: var(--neutral-bg); color: var(--text); }
.visor-ticket-sin-vista { padding: 24px; text-align: center; }
:root[data-theme="dark"]:not([data-presentacion]) .visor-ticket-cuenta { background: var(--panel); }
@media (max-width: 640px) {
  .visor-columna { flex: 0 0 auto; width: auto !important; max-height: 40vh; border-right: 0; border-bottom: 1px solid var(--border); }
  .visor-columna > .visor-lista { max-height: none; border-bottom: 0; }
  .visor-arbol-derecha .visor-columna { border-left: 0; }
}

/* ===================================================== «Horas de holgura» (modules/slackHours) */
.holgura-celda { display: inline-flex; flex-direction: column; align-items: flex-end; gap: 3px; }
.holgura-chip {
  display: inline-flex; align-items: center; gap: 4px; padding: 1px 7px; border-radius: 999px;
  font-weight: 600; font-size: 12px; white-space: nowrap; font-variant-numeric: tabular-nums;
}
.holgura-chip .mdi { font-size: 13px; }
.holgura-chip.aprobada { background: color-mix(in srgb, var(--ok) 14%, var(--panel)); color: var(--ok-texto); }
.holgura-chip.negativa { background: var(--warn-bg); color: var(--warn); }
.holgura-chip.pendiente { background: var(--neutral-bg); color: var(--muted); border: 1px dashed var(--border-strong); }
.holgura-chip.tachada { text-decoration: line-through; }
button.holgura-chip { font: inherit; font-weight: 600; font-size: 12px; cursor: pointer; }
button.holgura-chip:hover { border-color: var(--accent); color: var(--accent); }
.tabla-docs .col-holgura { cursor: default; }

.modal.modal-holgura { max-width: 580px; }
.modal-holgura > .body { max-height: min(72vh, 680px); overflow-y: auto; gap: 14px; }
.modal-holgura > footer { display: flex; align-items: center; gap: 8px; }
.modal-holgura > footer .spacer, .holgura-seguimiento-cabecera .spacer { flex: 1; }
.holgura-resumen { display: flex; gap: 10px; flex-wrap: wrap; }
.holgura-dato { background: var(--neutral-bg); border-radius: 8px; padding: 8px 12px; min-width: 120px; }
.holgura-dato small { display: block; color: var(--muted); font-size: 11px; }
.holgura-dato b { font-size: 16px; font-variant-numeric: tabular-nums; }
.holgura-dato.destacado { background: var(--accent-soft); }
.holgura-campo { display: flex; flex-direction: column; gap: 4px; }
.holgura-campo textarea { width: 100%; resize: vertical; font: inherit; }
.holgura-campo textarea.con-error, .holgura-paso.con-error, .holgura-personas.con-error { border-color: var(--danger); }
.holgura-error { margin: 0; color: var(--danger); font-size: 12px; }
.holgura-paso { display: inline-flex; align-self: flex-start; border: 1px solid var(--border-strong); border-radius: var(--radius); overflow: hidden; }
.holgura-paso input { width: 80px; border: 0; border-radius: 0; text-align: center; font-weight: 700; font-size: 15px; }
.holgura-paso-btn { border: 0; background: var(--neutral-bg); color: var(--muted); padding: 0 12px; font-size: 16px; cursor: pointer; }
.holgura-paso-btn:hover:not(:disabled) { color: var(--accent); }
.holgura-personas { border: 1px solid var(--border); border-radius: 8px; max-height: 190px; overflow: auto; }
.holgura-persona { display: flex; align-items: center; gap: 10px; padding: 7px 10px; border-bottom: 1px solid var(--border); cursor: pointer; }
.holgura-persona:last-child { border-bottom: 0; }
.holgura-persona input { accent-color: var(--accent); width: 16px; height: 16px; }
.holgura-persona-nombre { flex: 1; }
.holgura-persona-nombre small { display: block; color: var(--muted); font-size: 11px; }
.holgura-canales { display: flex; gap: 8px; flex-wrap: wrap; }
.holgura-canal { position: relative; display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px; border: 1px solid var(--border-strong); cursor: pointer; }
.holgura-canal input { position: absolute; opacity: 0; pointer-events: none; }
.holgura-canal.elegido { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.holgura-canal:focus-within { box-shadow: 0 0 0 2px var(--accent-soft); }
.holgura-historial { border-top: 1px solid var(--border); padding-top: 12px; }
.holgura-historial h4 { margin: 0 0 6px; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.holgura-historial-item { display: flex; align-items: center; gap: 10px; padding: 5px 0; font-size: 12.5px; }
.holgura-historial-motivo { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.holgura-historial-cuando { color: var(--muted); font-size: 11.5px; white-space: nowrap; }
.holgura-seguimiento-cabecera { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.holgura-seguimiento-motivo { margin: 0 0 6px; color: var(--muted); }
.holgura-aprobador { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--border); }
.holgura-aprobador:last-child { border-bottom: 0; }
.holgura-aprobador-nombre { flex: 1; }
.holgura-aprobador-nombre small { display: block; font-size: 11.5px; }
.holgura-comentario { color: var(--muted); }
.holgura-marca { width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; font-size: 14px; flex: none; }
.holgura-marca.tono-ok { background: color-mix(in srgb, var(--ok) 14%, var(--panel)); color: var(--ok-texto); }
.holgura-marca.tono-pending { background: var(--warn-bg); color: var(--warn); }
.holgura-marca.tono-danger { background: var(--danger-bg); color: var(--danger); }
.holgura-aprobador small.tono-ok { color: var(--ok-texto); }
.holgura-aprobador small.tono-pending { color: var(--muted); }
.holgura-aprobador small.tono-danger { color: var(--danger); }
.holgura-aprobador .btn-accion .mdi + .mdi { margin-left: -2px; }
