/* =============================================================
   NóminasHub — Componentes y utilidades

   Este archivo existe para vaciar los `style=` de los templates.
   Hoy hay 240 estilos incrustados y 437 colores crudos escritos a
   mano en el HTML; ninguno de ellos cambia cuando cambia el tema.

   Cada clase de aquí reemplaza un patrón que ya estaba repetido en
   los templates. No se inventaron: se extrajeron.

   Depende de tokens.css. Cargar siempre después.
   ============================================================= */

/* =============================================================
   CIFRAS — lo más importante de un sistema de nómina

   Las columnas de dinero se comparan verticalmente. Con cifras de
   ancho variable, el ojo tiene que releer cada renglón; con ancho
   tabular, una diferencia de magnitud se ve sin leer.
   ============================================================= */

.num {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

.num-mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* Importe: siempre a la derecha, siempre tabular. */
.amount {
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.amount-negative { color: var(--state-danger); }
.amount-zero     { color: var(--content-tertiary); }

/* Identificadores que se cotejan a ojo: RFC, CURP, NSS, CLABE,
   UUID. Van en mono para que un carácter cambiado se note. */
.ident {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  letter-spacing: -0.01em;
}

/* =============================================================
   ESTADO — la regla de negocio deja de vivir en un `style=`

   Antes, el umbral «≥80 verde, ≥50 ámbar, si no rojo» estaba
   escrito con Jinja adentro del atributo style. Un estado tiene
   nombre; el color es una consecuencia, no la definición.
   ============================================================= */

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--badge-y) var(--badge-x);
  border-radius: var(--badge-radius);
  font-size: var(--badge-size);
  font-weight: var(--badge-weight);
  line-height: 1.4;
  white-space: nowrap;
  border: 1px solid transparent;
}

.chip--success { background: var(--state-success-soft); color: var(--state-success-content); border-color: var(--state-success-border); }
.chip--warning { background: var(--state-warning-soft); color: var(--state-warning-content); border-color: var(--state-warning-border); }
.chip--danger  { background: var(--state-danger-soft);  color: var(--state-danger-content);  border-color: var(--state-danger-border); }
.chip--info    { background: var(--state-info-soft);    color: var(--state-info-content);    border-color: var(--state-info-border); }
.chip--neutral { background: var(--state-neutral-soft); color: var(--state-neutral-content); border-color: var(--state-neutral-border); }
.chip--muted   { background: var(--surface-sunken);     color: var(--content-secondary);     border-color: var(--border-subtle); }

/* El punto delante del texto. El color solo nunca debe ser el
   único portador del significado: quien no distingue rojo de
   verde necesita la palabra, y la palabra ya está en el chip. */
.chip::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

.chip--no-dot::before { display: none; }

/* =============================================================
   UTILIDADES DE TEXTO
   Reemplazan los `style="color:#475569"` y `style="font-size: var(--text-xs)"`
   que aparecían 240 veces.
   ============================================================= */

.t-primary   { color: var(--content-primary); }
.t-secondary { color: var(--content-secondary); }
.t-tertiary  { color: var(--content-tertiary); }
.t-accent    { color: var(--accent-content); }
.t-success   { color: var(--state-success); }
.t-warning   { color: var(--state-warning); }
.t-danger    { color: var(--state-danger); }
.t-info      { color: var(--state-info); }
.t-neutral   { color: var(--state-neutral); }

.t-2xs  { font-size: var(--text-2xs); }
.t-xs   { font-size: var(--text-xs); }
.t-sm   { font-size: var(--text-sm); }
.t-base { font-size: var(--text-base); }
.t-md   { font-size: var(--text-md); }
.t-lg   { font-size: var(--text-lg); }
.t-xl   { font-size: var(--text-xl); }

.t-medium   { font-weight: var(--weight-medium); }
.t-semibold { font-weight: var(--weight-semibold); }
.t-bold     { font-weight: var(--weight-bold); }

/* Encabezado de grupo: mayúsculas pequeñas con tracking. Estaba
   repetido a mano con font-size: var(--text-2xs) en varios templates. */
.t-overline {
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--content-tertiary);
}

/* =============================================================
   PAR ETIQUETA / VALOR
   El patrón `field-item` que ya usaban 23 veces, ahora tokenizado.
   ============================================================= */

.field-item {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
}

.field-label {
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--content-tertiary);
}

.field-value {
  font-size: var(--text-base);
  color: var(--content-primary);
  word-break: break-word;
}

.field-value:empty::after,
.field-value.is-empty::after {
  content: '—';
  color: var(--content-placeholder);
}

/* Rejilla de campos que se adapta sin media queries. */
.field-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-6) var(--space-8);
}

/* =============================================================
   INDICADOR (KPI)
   ============================================================= */

.kpi-card {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  padding: var(--card-padding);
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
  transition: border-color var(--duration-base) var(--ease),
              transform var(--duration-base) var(--ease);
}

.kpi-card:hover { border-color: var(--border-strong); }

/* Solo los indicadores que llevan a algún lado se levantan al
   pasar el ratón. Animar lo que no es clicable es mentir. */
a .kpi-card:hover { transform: translateY(-2px); }

.kpi-icon {
  width: var(--kpi-icon-size);
  height: var(--kpi-icon-size);
  border-radius: var(--radius-md);
  display: grid;
  place-items: center;
  font-size: var(--text-md);
  flex: none;
}

.kpi-icon--info    { background: var(--state-info-soft);    color: var(--state-info); }
.kpi-icon--success { background: var(--state-success-soft); color: var(--state-success); }
.kpi-icon--warning { background: var(--state-warning-soft); color: var(--state-warning); }
.kpi-icon--danger  { background: var(--state-danger-soft);  color: var(--state-danger); }
.kpi-icon--neutral { background: var(--state-neutral-soft); color: var(--state-neutral); }
.kpi-icon--accent  { background: var(--accent-soft);        color: var(--accent); }

.kpi-value {
  font-size: var(--kpi-value-size);
  font-weight: var(--kpi-value-weight);
  line-height: var(--leading-tight);
  font-variant-numeric: tabular-nums;
  color: var(--content-primary);
}

/* La cifra hereda el color del estado solo cuando el estado
   importa. Un conteo de empleados no es una alarma. */
.kpi-value--info    { color: var(--state-info); }
.kpi-value--success { color: var(--state-success); }
.kpi-value--warning { color: var(--state-warning); }
.kpi-value--danger  { color: var(--state-danger); }

.kpi-label {
  font-size: var(--kpi-label-size);
  color: var(--kpi-label-color);
  line-height: var(--leading-snug);
}

/* Indicador que exige atención. Sin parpadeo: un dashboard que
   destella ocho horas se ignora a los diez minutos. */
.kpi-card--alert {
  border-color: var(--state-warning-border);
  background: linear-gradient(0deg, var(--state-warning-soft), var(--state-warning-soft)), var(--card-bg);
}

/* =============================================================
   ENCABEZADO DE PÁGINA
   ============================================================= */

.page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  margin-bottom: var(--space-8);
}

.page-title {
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--content-primary);
  margin: 0;
}

.page-subtitle {
  font-size: var(--text-sm);
  color: var(--content-secondary);
  margin: var(--space-2) 0 0;
}

/* =============================================================
   RESUMEN DEL PERÍODO (portada)

   El encabezado del home no es el título de una pantalla: es la
   respuesta a «¿cómo va este período?». Por eso va centrado y
   grande, y el resto de la portada lo desarrolla.

   🔑 `periodo-antetitulo`, `periodo-titulo` y `periodo-bajada`
   vivían en el HTML desde el 2-sep-2026 **sin una sola regla de
   CSS**: se pintaban con el estilo por defecto del navegador. De
   ahí que la línea de resumen saliera diminuta y a la izquierda.
   Guillermo, 6-sep-2026: «me gustaría que fuera más grande,
   centrado».
   ============================================================= */
.resumen-hero {
  text-align: center;
  margin-bottom: var(--space-9);
}

.periodo-antetitulo {
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--content-tertiary);
  margin: 0 0 var(--space-2);
}

.periodo-titulo {
  font-size: var(--text-3xl);
  font-weight: var(--weight-bold);
  line-height: var(--leading-tight);
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--content-primary);
  margin: 0;
}

/* Las cifras del período, en fila y centradas bajo su clave.
   Sustituyen a la vez a la línea «181 empleados · 4 altas · 0
   bajas» y a las cuatro tarjetas que repetían esos mismos cuatro
   números un centímetro más abajo. */
.periodo-cifras {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
  gap: var(--space-6) var(--space-10);
  margin: var(--space-7) 0 0;
}

.periodo-cifra {
  min-width: 5.5rem;
}

.periodo-cifra__valor {
  display: block;
  font-size: var(--text-2xl);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  font-variant-numeric: tabular-nums;
  color: var(--content-primary);
}

.periodo-cifra__etiqueta {
  display: block;
  font-size: var(--text-xs);
  color: var(--content-secondary);
  margin-top: var(--space-1);
}

/* La cifra toma color solo cuando el color significa algo: un
   conteo de empleados no es una alarma, un aviso pendiente sí. */
.periodo-cifra__valor--exito   { color: var(--state-success-content); }
.periodo-cifra__valor--peligro { color: var(--state-danger-content); }
.periodo-cifra__valor--aviso   { color: var(--state-warning-content); }

/* La cifra que lleva a algún lado se comporta como enlace, y solo
   ella: animar o subrayar lo que no es clicable es mentir. El área
   pulsable supera los 24 px que pide WCAG 2.5.8 por la altura de la
   cifra más su relleno. */
a.periodo-cifra {
  text-decoration: none;
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-5);
  margin: calc(var(--space-2) * -1) calc(var(--space-5) * -1);
  transition: background-color var(--duration-base) var(--ease);
}

a.periodo-cifra:hover { background: var(--surface-hover); }
a.periodo-cifra:hover .periodo-cifra__etiqueta { text-decoration: underline; }

/* Cuando no hay período, o cuando el almacén no se pudo leer, la
   portada explica qué pasa en lugar de enseñar ceros. */
.periodo-bajada {
  font-size: var(--text-md);
  line-height: var(--leading-snug);
  color: var(--content-secondary);
  max-width: 48ch;
  margin: var(--space-6) auto 0;
}

/* =============================================================
   TABLA DE DATOS
   Densidad alta a propósito: se comparan renglones.
   ============================================================= */

.data-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--text-sm);
}

.data-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--table-header-bg);
  color: var(--table-header-color);
  font-size: var(--table-header-size);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  text-align: left;
  padding: var(--space-4) var(--table-cell-x);
  border-bottom: 1px solid var(--table-border);
  white-space: nowrap;
}

.data-table tbody td {
  padding: var(--table-cell-y) var(--table-cell-x);
  border-bottom: 1px solid var(--table-border);
  color: var(--content-primary);
  vertical-align: middle;
}

.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover { background: var(--table-row-hover); }

.data-table th.is-numeric,
.data-table td.is-numeric {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Envoltura obligatoria: una tabla ancha desplaza dentro de su
   caja, nunca empuja la página entera. */
.table-scroll {
  overflow-x: auto;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-subtle);
}

/* =============================================================
   ESTADO VACÍO
   ============================================================= */

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-5);
  padding: var(--space-11) var(--space-7);
  text-align: center;
  color: var(--content-tertiary);
}

.empty-state i {
  font-size: var(--text-3xl);
  color: var(--content-placeholder);
  line-height: 1;
}

.empty-state p {
  margin: 0;
  font-size: var(--text-sm);
  max-width: 42ch;
}

/* =============================================================
   INTERRUPTOR DE TEMA
   ============================================================= */

.theme-toggle {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-subtle);
  background: transparent;
  color: var(--content-secondary);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease),
              color var(--duration-fast) var(--ease);
}

.theme-toggle:hover {
  background: var(--surface-hover);
  color: var(--content-primary);
}

.theme-toggle:focus-visible {
  outline: none;
  box-shadow: var(--ring-focus);
}

/* Se muestra el icono del tema al que se va a cambiar, no el
   actual: el botón anuncia su efecto. */
.theme-toggle .icon-to-dark  { display: none; }
.theme-toggle .icon-to-light { display: block; }

[data-theme="dark"] .theme-toggle .icon-to-dark  { display: block; }
[data-theme="dark"] .theme-toggle .icon-to-light { display: none; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) .theme-toggle .icon-to-dark  { display: block; }
  :root:not([data-theme="light"]):not([data-theme="dark"]) .theme-toggle .icon-to-light { display: none; }
}

/* =============================================================
   ACCESIBILIDAD
   ============================================================= */

/* Foco visible y consistente en todo lo que se navega con teclado.
   Un dashboard que se opera con las manos en el teclado necesita
   saber dónde está parado. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: none;
  box-shadow: var(--ring-focus);
  border-radius: var(--radius-xs);
}

/* Salto directo al contenido, para quien no usa ratón. */
.skip-link {
  position: absolute;
  left: var(--space-5);
  top: calc(-1 * var(--space-12));
  z-index: 100;
  padding: var(--space-4) var(--space-6);
  background: var(--accent);
  color: var(--content-on-accent);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  transition: top var(--duration-fast) var(--ease);
}

.skip-link:focus { top: var(--space-5); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* =============================================================
   IMPRESIÓN
   Los reportes de cierre acaban en papel o en PDF. Sin esto, el
   tema oscuro imprime una hoja negra.
   ============================================================= */

@media print {
  :root, [data-theme="dark"], [data-theme="light"] {
    --surface-base: #fff;
    --surface-raised: #fff;
    --surface-sunken: #fff;
    --content-primary: #000;
    --content-secondary: #333;
    --content-tertiary: #555;
    --border-subtle: #ccc;
    --border-default: #999;
    --card-shadow: none;
  }

  .sidebar, .topbar, .theme-toggle, .skip-link, .no-print { display: none !important; }
  .main-content { margin-left: 0 !important; }
  .data-table thead th { position: static; }
  .card, .kpi-card { break-inside: avoid; }
}

/* =============================================================
   BARRA DE PROGRESO

   Las clases `bg-success`/`bg-warning`/`bg-danger` de Bootstrap se
   reapuntaron al fondo SUAVE de cada estado, que es lo correcto para
   una etiqueta pero demasiado tenue para una barra: sobre la canaleta
   casi no se distingue. La barra necesita el tono sólido.
   ============================================================= */

.progress {
  background: var(--surface-sunken);
  border-radius: var(--radius-pill);
  height: 8px;
  overflow: hidden;
}

.progress-bar {
  height: 100%;
  border-radius: var(--radius-pill);
  transition: width var(--duration-base) var(--ease);
  background: var(--accent-solid);
}

.progress-bar.bg-success { background: var(--state-success) !important; }
.progress-bar.bg-warning { background: var(--state-warning) !important; }
.progress-bar.bg-danger  { background: var(--state-danger) !important; }
.progress-bar.bg-info    { background: var(--state-info) !important; }

/* =============================================================
   UTILIDADES QUE BOOTSTRAP NO TRAE
   ============================================================= */

/* Sin esto, un hijo de flex con texto largo se niega a encogerse y
   `text-truncate` no recorta nada: empuja el contenedor. */
.min-w-0 { min-width: 0; }

/* =============================================================
   ARMAZÓN — piezas de `base.html`

   Estaban escritas como `style=` dentro del layout, y una de ellas
   traía un `rgba()` a mano que no venía de ningún token: el borde
   del aviso de alertas. Eso hace que en tema claro el borde no
   acompañe al fondo.
   ============================================================= */

/* Selector de empresa de la barra superior. El ancho está topado
   porque el nombre de una sociedad puede ser larguísimo y no debe
   empujar el resto de la barra. */
.empresa-select {
  max-width: 220px;
  font-size: var(--text-xs);
}

/* Aviso de alertas pendientes. Es un enlace con forma de etiqueta,
   no un botón: lleva a la bandeja, no ejecuta nada. */
.topbar-alertas {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-5);
  border-radius: var(--radius-sm);
  border: 1px solid var(--state-warning-border);
  background: var(--state-warning-soft);
  color: var(--state-warning-content);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  text-decoration: none;
  transition: background var(--duration-fast) var(--ease);
}

.topbar-alertas:hover {
  background: var(--state-warning-border);
  color: var(--state-warning-content);
}

/* Zona de mensajes flash: hereda el mismo margen lateral que el
   contenido para que el aviso quede alineado con la página. */
.flash-zone {
  padding: var(--space-5) var(--space-8) 0;
}

.flash-zone .alert {
  margin-bottom: var(--space-4);
}

/* =============================================================
   UTILIDADES DE MEDIDA

   POR QUÉ EXISTEN

   Al inventariar los 215 `style=` de los templates, cinco patrones
   explicaban la mayoría: truncar una celda, topar el ancho de un
   formulario, hacer desplazable un bloque de log, dibujar un punto
   de estado y dibujar un avatar. Cada aparición traía su propio
   número: 120, 140, 150, 160, 250, 280 px de ancho de celda; 6, 8, 9
   y 12 px de punto; 22, 30, 48, 52 y 56 px de avatar.

   Esos números no eran decisiones, eran accidentes. Aquí se
   consolidan en una escala: 140 y 160 pasan a 150, 6 y 9 pasan a 8,
   22 pasa a 24. La diferencia no se ve; lo que se gana es que el
   siguiente que necesite truncar una celda no invente un sexto ancho.
   ============================================================= */

:root {
  /* Ancho tope de celda que se trunca */
  --col-xs: 120px;
  --col-sm: 150px;
  --col-md: 180px;
  --col-lg: 250px;
  --col-xl: 300px;

  /* Ancho de lectura para formularios y contenido centrado */
  --measure-sm: 480px;
  --measure-md: 600px;
  --measure-lg: 768px;
  --measure-xl: 900px;
}

/* ----- Celdas que truncan -----------------------------------
   Se combinan con `.text-truncate` de Bootstrap, que aporta el
   `overflow` y los puntos suspensivos. Sin un ancho tope, esa
   clase no recorta nada. */
.col-xs { max-width: var(--col-xs); }
.col-sm-w { max-width: var(--col-sm); }
.col-md-w { max-width: var(--col-md); }
.col-lg-w { max-width: var(--col-lg); }
.col-xl-w { max-width: var(--col-xl); }

/* ----- Contenido de ancho topado --------------------------- */
.measure-sm { max-width: var(--measure-sm); }
.measure-md { max-width: var(--measure-md); }
.measure-lg { max-width: var(--measure-lg); }
.measure-xl { max-width: var(--measure-xl); }

/* ----- Bloque de log o detalle crudo -----------------------
   Antes usaba `bg-light` de Bootstrap, que es un gris fijo: en tema
   oscuro quedaba un rectángulo blanco con texto claro encima,
   ilegible. Va sobre la superficie hundida, que sí cambia de tema. */
.log-block {
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  padding: var(--space-5);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: var(--leading-normal);
  color: var(--content-secondary);
  white-space: pre-wrap;
  word-break: break-word;
  overflow-y: auto;
  max-height: 300px;
  margin-bottom: 0;
}

.log-block--corto { max-height: 150px; }
.log-block--alto  { max-height: 340px; }

/* ----- Punto de estado -------------------------------------
   Para cuando el estado se marca junto a un texto que ya lo nombra.
   Nunca como único portador del significado: el color solo no
   comunica a quien no distingue rojo de verde. */
.dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  flex-shrink: 0;
  background: var(--content-tertiary);
}

.dot--lg { width: 12px; height: 12px; }

.dot--success { background: var(--state-success); }
.dot--warning { background: var(--state-warning); }
.dot--danger  { background: var(--state-danger); }
.dot--info    { background: var(--state-info); }
.dot--neutral { background: var(--state-neutral); }
.dot--muted   { background: var(--content-tertiary); }

/* ----- Avatar / icono circular -----------------------------
   El tamaño manda la tipografía: una inicial en un círculo de 24px
   con la fuente de uno de 56px se desborda. */
.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent-content);
  font-weight: var(--weight-semibold);
  line-height: 1;
}

.avatar--xs { width: 24px; height: 24px; font-size: var(--text-2xs); }
.avatar--sm { width: 32px; height: 32px; font-size: var(--text-xs); }
.avatar--md { width: 48px; height: 48px; font-size: var(--text-lg); }
.avatar--lg { width: 56px; height: 56px; font-size: var(--text-xl); }

.avatar--success { background: var(--state-success-soft); color: var(--state-success-content); }
.avatar--warning { background: var(--state-warning-soft); color: var(--state-warning-content); }
.avatar--danger  { background: var(--state-danger-soft);  color: var(--state-danger-content); }
.avatar--info    { background: var(--state-info-soft);    color: var(--state-info-content); }
.avatar--neutral { background: var(--state-neutral-soft); color: var(--state-neutral-content); }
.avatar--muted   { background: var(--surface-sunken);     color: var(--content-secondary); }

/* =============================================================
   PIEZAS QUE BOOTSTRAP TRAE SIN TEMATIZAR

   `custom.css` ya reapuntó tarjetas, tablas, formularios, botones,
   avisos, modales y menús. Faltaban estas tres, que aparecieron al
   migrar las pantallas de detalle: sin ellas quedan con la paleta
   por defecto de Bootstrap y en tema oscuro se ven como un parche
   claro.
   ============================================================= */

/* ----- Ruta de navegación ----------------------------------- */
.breadcrumb {
  margin-bottom: 0;
  font-size: var(--text-xs);
  --bs-breadcrumb-divider-color: var(--content-tertiary);
}

.breadcrumb-item + .breadcrumb-item::before {
  color: var(--content-tertiary);
}

.breadcrumb-item a {
  color: var(--content-secondary);
  text-decoration: none;
}

.breadcrumb-item a:hover {
  color: var(--accent-content);
  text-decoration: underline;
}

.breadcrumb-item.active {
  color: var(--content-primary);
  font-weight: var(--weight-medium);
}

/* ----- Casilla y selector de opción ------------------------- */
.form-check-input {
  background-color: var(--surface-input);
  border-color: var(--border-default);
}

.form-check-input:checked {
  background-color: var(--accent-solid);
  border-color: var(--accent-solid);
}

.form-check-input:focus {
  border-color: var(--field-border-focus);
  box-shadow: var(--ring-focus);
}

.form-check-label {
  color: var(--content-secondary);
  font-size: var(--text-sm);
}

/* ----- Casilla de dato suelto -------------------------------
   Un número con su etiqueta, sin la jerarquía de un KPI. Reemplaza
   al `bg-light rounded p-2 text-center` que salía blanco en oscuro. */
.stat-tile {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5);
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  text-align: center;
  min-width: 0;
}

.stat-tile .field-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* =============================================================
   PANTALLA DE ACCESO

   No extiende el layout, así que no hereda su barra superior: el
   interruptor de tema necesita su propia posición.
   ============================================================= */

.login-theme-toggle {
  position: fixed;
  top: var(--space-7);
  right: var(--space-7);
  z-index: 10;
}

/* El botón de mostrar contraseña vive dentro del grupo de campo, pero
   es interactivo: necesita cursor y foco propios, que `input-group-text`
   no trae por ser decorativo. */
.input-group-boton {
  cursor: pointer;
  background: var(--surface-sunken);
  transition: background var(--duration-fast) var(--ease);
}

.input-group-boton:hover {
  background: var(--surface-hover);
}

/* Área de toque cómoda: es el único botón de la pantalla. */
.login-submit {
  padding: var(--space-5) var(--space-6);
  font-size: var(--text-md);
}

/* =============================================================
   IMPORTE POR NATURALEZA — fiscal, resguardo, total

   POR QUÉ ESTÁ EN EL SISTEMA Y NO EN CADA PANTALLA

   Cuatro templates definían `.monto-fiscal`, `.monto-resguardo` y
   `.monto-total` en su propio bloque `<style>`, y no con los mismos
   valores. La distinción fiscal / resguardo es la columna vertebral de
   este producto —se paga en dos carriles— así que el color que la marca
   no puede depender de en qué pantalla estés parado.

   Verde para fiscal y azul para resguardo se conservan porque el
   contador ya los tiene aprendidos. Lo que cambia es de dónde salen:
   del token de estado, no de un hex, así que ahora funcionan en los
   dos temas.
   ============================================================= */

.monto-fiscal,
.monto-resguardo,
.monto-total {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-sm);
  white-space: nowrap;
}

.monto-fiscal    { color: var(--state-success-content); }
.monto-resguardo { color: var(--state-info-content); }
.monto-total     { color: var(--content-primary); font-weight: var(--weight-semibold); }

/* =============================================================
   BARRA DE FILTROS

   `custom.css` ya trae `.filter-card`. Faltaba el tratamiento de sus
   etiquetas, que cada pantalla resolvía por su cuenta con un `label`
   de 0.67rem en mayúsculas.
   ============================================================= */

.filter-bar {
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-5) var(--space-6);
  margin-bottom: var(--space-6);
}

.filter-bar label,
.filter-card label {
  display: block;
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--content-tertiary);
  margin-bottom: var(--space-3);
}

/* Los campos de un filtro son más bajos que los de un formulario: se
   leen de un barrido, no se llenan con cuidado. */
.filter-bar .form-select,
.filter-bar .form-control,
.filter-card .form-select,
.filter-card .form-control {
  font-size: var(--text-sm);
  padding: var(--space-3) var(--space-5);
}

/* =============================================================
   COMPLEMENTOS DEL INDICADOR
   ============================================================= */

/* Tercera línea del KPI: la unidad o el detalle de la cifra. */
.kpi-sub {
  font-size: var(--text-xs);
  color: var(--content-tertiary);
  margin-top: var(--space-1);
}

/* Variante en rejilla, para cuando los indicadores no llevan icono y
   la cifra manda. Se apila en pantallas angostas sin media queries. */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-5);
  margin-bottom: var(--space-6);
}

/* Indicador sin icono: la franja de color de arriba hace el trabajo de
   señalar de qué es la cifra. */
.kpi-card--plain {
  display: block;
  position: relative;
  overflow: hidden;
  padding: var(--space-6) var(--space-7);
}

.kpi-card--plain::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--border-default);
}

.kpi-card--success::before { background: var(--state-success); }
.kpi-card--danger::before  { background: var(--state-danger); }
.kpi-card--info::before    { background: var(--state-info); }
.kpi-card--warning::before { background: var(--state-warning); }
.kpi-card--neutral::before { background: var(--state-neutral); }

/* =============================================================
   ETIQUETA DE CATEGORÍA TRUNCADA

   Para valores libres que el usuario captura y pueden venir largos:
   plaza, sucursal, departamento. Corta con puntos suspensivos en lugar
   de romper la fila de la tabla.
   ============================================================= */

.tag-trunc {
  display: inline-block;
  max-width: var(--col-md);
  padding: var(--space-1) var(--space-4);
  border-radius: var(--radius-xs);
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
  color: var(--content-secondary);
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: middle;
}

/* =============================================================
   BOTÓN DE ICONO EN TABLA

   Una celda de acciones con un botón de texto rompe la densidad de la
   tabla. Este es cuadrado, discreto, y solo se tiñe al pasar el ratón.
   Lleva `aria-label` obligatorio: un icono sin texto no se anuncia.
   ============================================================= */

.btn-icono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-xs);
  border: 1px solid var(--border-subtle);
  background: transparent;
  color: var(--content-secondary);
  font-size: var(--text-sm);
  text-decoration: none;
  transition: background var(--duration-fast) var(--ease),
              color var(--duration-fast) var(--ease),
              border-color var(--duration-fast) var(--ease);
}

.btn-icono:hover {
  background: var(--accent-soft);
  border-color: var(--accent-border);
  color: var(--accent-content);
}

/* =============================================================
   ANCHO MÍNIMO DE COLUMNA

   POR QUÉ

   En la tabla de expedientes, con once columnas, el navegador repartía
   el ancho y la columna del nombre quedaba tan angosta que «Bruno
   Ibáñez Cuéllar» se partía en tres renglones. Una tabla que desplaza
   en horizontal se lee; una con nombres partidos en tres, no.

   Estos mínimos van con `.table-scroll`, que ya desplaza dentro de su
   caja: la tabla puede ser más ancha que la pantalla sin empujar nada.
   ============================================================= */

.data-table td.col-min-sm,
.data-table th.col-min-sm { min-width: 120px; }

.data-table td.col-min-md,
.data-table th.col-min-md { min-width: 180px; }

.data-table td.col-min-lg,
.data-table th.col-min-lg { min-width: 240px; }

/* Nombre de persona: no se parte nunca. Si no cabe, se trunca con
   puntos suspensivos y el nombre completo queda en el `title`. */
.nombre-persona {
  display: block;
  font-weight: var(--weight-medium);
  text-decoration: none;
  color: var(--content-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nombre-persona:hover {
  color: var(--accent-content);
  text-decoration: underline;
}

/* =============================================================
   DATATABLES CON LA INTEGRACIÓN DE BOOTSTRAP 5

   POR QUÉ HACEN FALTA ESTOS SELECTORES

   `custom.css` ya tematizaba `.paginate_button`, que es la paginación
   NATIVA de DataTables. Pero el proyecto carga
   `dataTables.bootstrap5.min.js`, y esa integración dibuja la
   paginación como una lista de Bootstrap: `.pagination > .page-item >
   .page-link`. Los selectores viejos nunca la tocaban, así que el
   botón de la página actual salía con el azul por defecto de Bootstrap
   —no con el índigo del sistema— en las cuatro tablas del dashboard.
   ============================================================= */

.dataTables_wrapper .pagination {
  margin-bottom: 0;
  gap: var(--space-2);
}

.dataTables_wrapper .page-link {
  background: transparent;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
  color: var(--content-secondary);
  font-size: var(--text-sm);
  padding: var(--space-3) var(--space-5);
  transition: background var(--duration-fast) var(--ease),
              color var(--duration-fast) var(--ease);
}

.dataTables_wrapper .page-link:hover {
  background: var(--surface-hover);
  border-color: var(--border-default);
  color: var(--content-primary);
}

.dataTables_wrapper .page-item.active .page-link {
  background: var(--accent-solid);
  border-color: var(--accent-solid);
  color: var(--content-on-accent);
}

.dataTables_wrapper .page-item.disabled .page-link {
  background: transparent;
  border-color: var(--border-subtle);
  color: var(--content-disabled);
}

.dataTables_wrapper .page-link:focus {
  box-shadow: var(--ring-focus);
  outline: none;
}

/* El selector de tamaño de página venía tan angosto que cortaba el
   «50». Se le da aire y se separa de su etiqueta. */
.dataTables_wrapper .dataTables_length select {
  min-width: 68px;
  margin: 0 var(--space-3);
}

.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter {
  font-size: var(--text-sm);
  color: var(--content-secondary);
}

.dataTables_wrapper .dataTables_filter input {
  margin-left: var(--space-3);
  min-width: 220px;
}

/* La tabla de DataTables vive dentro de `.table-scroll`, que ya pone
   borde y radio: el envoltorio no debe agregar otro. */
.table-scroll > .dataTables_wrapper {
  border: none;
  border-radius: 0;
}

/* Deducción y cifra sin peso: completan la familia de importes. Una
   deducción se lee en rojo porque resta; el ISR piramidado del carril
   de resguardo va tenue porque es un cálculo intermedio, no algo que
   alguien cobre. */
.monto-deduccion {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-sm);
  color: var(--state-danger-content);
  white-space: nowrap;
}

.monto-tenue {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-sm);
  color: var(--content-tertiary);
  white-space: nowrap;
}

/* Énfasis para el neto de cada carril, que es la cifra que alguien
   cobra. Se combina con `.monto-fiscal` / `.monto-resguardo`. */
.monto-fuerte { font-weight: var(--weight-semibold); }

/* =============================================================
   FILA DE TOTALES

   Una tabla de nómina termina en una suma, y esa suma tiene que
   distinguirse de los renglones sin gritar. Se separa con una línea
   más gruesa y una superficie hundida, no con negritas en todo.
   ============================================================= */

.data-table tfoot td {
  padding: var(--table-cell-y) var(--table-cell-x);
  background: var(--surface-sunken);
  border-top: 2px solid var(--border-default);
  font-weight: var(--weight-semibold);
  color: var(--content-primary);
  vertical-align: middle;
}

.data-table tfoot .td-etiqueta {
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--content-tertiary);
}

/* Que la fila de totales no se vaya con el desplazamiento vertical. */
.data-table tfoot tr {
  position: sticky;
  bottom: 0;
}

/* =============================================================
   ETIQUETA DE CIFRA CON UMBRAL

   Para un número que se juzga contra un rango: días trabajados de una
   quincena, porcentaje de avance. El nivel lo decide la plantilla; el
   color solo acompaña al número, que sigue siendo legible sin él.
   ============================================================= */

.tag-num {
  display: inline-block;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-xs);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  background: var(--surface-sunken);
  color: var(--content-secondary);
}

.tag-num--success { background: var(--state-success-soft); color: var(--state-success-content); }
.tag-num--warning { background: var(--state-warning-soft); color: var(--state-warning-content); }
.tag-num--danger  { background: var(--state-danger-soft);  color: var(--state-danger-content); }

/* =============================================================
   BOTONES DELINEADOS QUE FALTABAN

   `custom.css` tematizó `btn-primary`, `btn-outline-secondary` y
   `btn-outline-success`. Las pantallas que necesitaban las otras tres
   variantes se las inventaban con un `style=` incrustado: la de
   períodos tenía cinco botones así, cada uno con su propio `rgba()`.
   ============================================================= */

.btn-outline-info {
  border-color: var(--state-info-border);
  background: var(--state-info-soft);
  color: var(--state-info-content);
}
.btn-outline-info:hover {
  background: var(--state-info-border);
  border-color: var(--state-info);
  color: var(--state-info-content);
}

.btn-outline-warning {
  border-color: var(--state-warning-border);
  background: var(--state-warning-soft);
  color: var(--state-warning-content);
}
.btn-outline-warning:hover {
  background: var(--state-warning-border);
  border-color: var(--state-warning);
  color: var(--state-warning-content);
}

.btn-outline-danger {
  border-color: var(--state-danger-border);
  background: var(--state-danger-soft);
  color: var(--state-danger-content);
}
.btn-outline-danger:hover {
  background: var(--state-danger-border);
  border-color: var(--state-danger);
  color: var(--state-danger-content);
}

/* Un botón deshabilitado tiene que verse deshabilitado sin depender de
   la opacidad del navegador, que en tema oscuro casi no se nota. */
.btn:disabled,
.btn.disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* =============================================================
   TARJETA DE REGISTRO

   Una fila de lista que no cabe en una tabla: a la izquierda el
   identificador grande, en medio los datos, a la derecha las acciones.
   La usa la lista de períodos de nómina.

   El borde izquierdo de color marca el estado terminal del registro:
   verde cuando está aprobado, gris y atenuado cuando está cerrado. Es
   la única señal que se conserva de la versión anterior, porque
   funciona: se ve de un barrido cuál período sigue vivo.
   ============================================================= */

.record-grid {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.record-card {
  display: grid;
  /* 124px es lo que mide «01/08 — 15/08/2026» sin partirse: con 100 la
     fecha caía en dos renglones debajo de la clave. */
  grid-template-columns: 124px 1fr auto auto;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-6) var(--space-7);
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: var(--card-radius);
  transition: border-color var(--duration-base) var(--ease);
}

.record-card:hover { border-color: var(--border-strong); }

.record-card--done   { border-left: 3px solid var(--state-success); }
.record-card--closed { border-left: 3px solid var(--border-strong); opacity: 0.75; }

@media (max-width: 768px) {
  .record-card {
    grid-template-columns: 1fr;
    gap: var(--space-5);
  }
}

/* Identificador protagonista de la tarjeta: la clave del período. */
.record-clave {
  font-family: var(--font-mono);
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  color: var(--content-primary);
  line-height: var(--leading-tight);
}

.record-meta {
  font-size: var(--text-xs);
  color: var(--content-tertiary);
  margin-top: var(--space-1);
  white-space: nowrap;
}

.record-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
}

.record-row {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  flex-wrap: wrap;
}

.record-stat {
  font-size: var(--text-xs);
  color: var(--content-tertiary);
}

.record-stat strong { color: var(--content-secondary); }

.record-actions {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* Cuenta atrás a la derecha de la tarjeta. */
.record-cuenta {
  text-align: right;
  min-width: 64px;
}

.record-cuenta-label {
  font-size: var(--text-2xs);
  color: var(--content-tertiary);
}

.record-cuenta-valor {
  font-family: var(--font-mono);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  color: var(--content-secondary);
}

.record-cuenta-valor--urgente { color: var(--state-danger); }
.record-cuenta-valor--proximo { color: var(--state-warning); }

/* =============================================================
   AVISOS FLOTANTES

   Confirman que una acción de fondo terminó. Van abajo a la derecha,
   fuera del camino de la lectura, y se van solos.
   ============================================================= */

.toast-stack {
  position: fixed;
  bottom: var(--space-7);
  right: var(--space-7);
  z-index: 1080;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  max-width: min(90vw, 380px);
}

.toast-msg {
  padding: var(--space-5) var(--space-6);
  background: var(--surface-overlay);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  font-size: var(--text-sm);
  color: var(--content-primary);
  animation: nh-entra-lateral var(--duration-base) var(--ease);
}

.toast-msg--ok  { border-left: 3px solid var(--state-success); }
.toast-msg--err { border-left: 3px solid var(--state-danger); color: var(--state-danger-content); }

@keyframes nh-entra-lateral {
  from { transform: translateX(40px); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* Quien prefiere no ver movimiento, no lo ve. */
@media (prefers-reduced-motion: reduce) {
  .toast-msg { animation: none; }
}

/* =============================================================
   INDICADOR DE ESPERA EN BOTÓN

   Para una acción que tarda: calcular una nómina de 183 personas no
   es instantáneo, y sin señal el usuario vuelve a hacer clic.
   ============================================================= */

.spinner-sm {
  display: none;
  width: 12px;
  height: 12px;
  border: 2px solid var(--border-default);
  border-top-color: currentColor;
  border-radius: var(--radius-pill);
  animation: nh-gira 0.6s linear infinite;
}

.spinner-sm.is-activo { display: inline-block; }

@keyframes nh-gira { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .spinner-sm { animation-duration: 2s; }
}

/* =============================================================
   CALENDARIO DEL CRONOGRAMA

   POR QUÉ ESTÁ AQUÍ Y NO EN SU TEMPLATE

   Este bloque ya usaba variables —era el template más avanzado de los
   quince— pero mezclaba: los tonos de estado seguían escritos como hex
   y `rgba()` a mano, en la paleta vieja del tema oscuro (#3fb950,
   #58a6ff, #e3b341). En tema claro esos verdes y azules quedan casi
   invisibles sobre papel.

   Se movió al sistema completo por la misma razón que el resto: mientras
   el color viva dentro del template, el tema no lo alcanza.
   ============================================================= */

.cal-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--space-7);
}

.cal-month {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: var(--card-radius);
  overflow: hidden;
}

.cal-month-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-5) var(--space-6);
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--border-subtle);
}

.cal-month-name {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--content-primary);
}

.cal-legend {
  display: flex;
  gap: var(--space-4);
  align-items: center;
}

.cal-legend-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-2xs);
  color: var(--content-secondary);
}

/* ----- Rejilla de días ----- */
.cal-days-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 1px;
  padding: var(--space-5) var(--space-5) var(--space-3);
}

.cal-dow {
  text-align: center;
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  color: var(--content-tertiary);
  padding-bottom: var(--space-3);
}

.cal-day {
  text-align: center;
  font-size: var(--text-xs);
  padding: var(--space-2) var(--space-1);
  border-radius: var(--radius-xs);
  color: var(--content-secondary);
  line-height: var(--leading-snug);
}

.cal-day.empty { visibility: hidden; }

/* El día de hoy es un círculo lleno. `--content-on-accent` y no blanco
   fijo: sobre el índigo del tema claro el blanco puro deslumbra menos
   que el token, que ya está calibrado para ese fondo. */
.cal-day.today {
  background: var(--accent-solid);
  color: var(--content-on-accent);
  font-weight: var(--weight-bold);
  border-radius: var(--radius-pill);
  box-shadow: var(--ring-focus);
}

/* ----- Tarjeta de período dentro del mes ----- */
.cal-periods {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5) var(--space-5);
}

.cal-period-card {
  padding: var(--space-5);
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
  border-left: 3px solid var(--border-default);
  border-radius: var(--radius-md);
}

.cal-period-card--success { border-left-color: var(--state-success); }
.cal-period-card--info    { border-left-color: var(--state-info); }
.cal-period-card--warning { border-left-color: var(--state-warning); }
.cal-period-card--muted   { border-left-color: var(--border-default); }

.cal-p-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}

.cal-p-nombre {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  color: var(--content-primary);
}

/* ----- Par de fechas ----- */
.cal-dates-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.cal-date-box {
  padding: var(--space-3) var(--space-4);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.cal-date-label {
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--content-tertiary);
  margin-bottom: var(--space-1);
}

.cal-date-value {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--content-primary);
}

.cal-date-box--vencido {
  border-color: var(--state-danger-border);
  background: var(--state-danger-soft);
}
.cal-date-box--vencido .cal-date-value { color: var(--state-danger-content); }

.cal-date-box--ok { border-color: var(--state-success-border); }
.cal-date-box--ok .cal-date-value { color: var(--state-success-content); }

.cal-date-box--hoy { border-color: var(--accent-border); }
.cal-date-box--hoy .cal-date-value { color: var(--accent-content); }

/* ----- Acuse de insumos recibidos ----- */
.cal-checks {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.cal-delivery {
  font-size: var(--text-2xs);
  color: var(--content-tertiary);
  margin-top: var(--space-3);
}

/* =============================================================
   PÍLDORAS DE RESUMEN

   Cuatro conteos en una fila, sin la jerarquía de una tarjeta de KPI:
   son contexto, no el asunto de la pantalla.
   ============================================================= */

.kpi-bar {
  display: flex;
  gap: var(--space-5);
  flex-wrap: wrap;
  margin-bottom: var(--space-8);
}

.kpi-pill {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-6);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  font-size: var(--text-sm);
}

.kpi-pill .n {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-bold);
  font-size: var(--text-md);
  color: var(--content-primary);
}

.kpi-pill .l { color: var(--content-secondary); }

/* =============================================================
   PALETA CATEGÓRICA DEL CRONOGRAMA

   POR QUÉ EXISTE

   El calendario pinta cada período de un color distinto para que dos
   períodos contiguos en el mismo mes no se confundan. Eso NO es un
   color de estado —no dice si algo va bien o mal— es un color de
   categoría: solo tiene que ser distinguible del vecino.

   🔴 Esta paleta estaba en `dashboard/views/cronograma.py`, como seis
   diccionarios de hex y `rgba()` que la vista inyectaba en el HTML con
   `style=`. Un color que nace en Python es el único que el tema no
   puede alcanzar: quedaba calibrado para fondo oscuro y en tema claro
   los rellenos al 28 % desaparecían sobre papel.

   Ahora la vista pasa el ÍNDICE (`color_idx`) y el color se elige aquí.
   Los seis tonos mantienen el orden original —azul, morado, naranja,
   verde, rosa, cian— para que nadie tenga que reaprender el calendario.
   ============================================================= */

:root {
  --cat-0: #4f46e5;  /* azul índigo, el de la marca */
  --cat-1: #7c3aed;  /* morado */
  --cat-2: #ea580c;  /* naranja */
  --cat-3: #15803d;  /* verde */
  --cat-4: #be185d;  /* rosa */
  --cat-5: #0e7490;  /* cian */

  /* Relleno del día dentro del período. Sobre papel una transparencia
     baja se pierde, así que aquí sube. */
  --cat-alpha: 0.16;
}

[data-theme="dark"] {
  /* Sobre tinta, el mismo tono se ve apagado: los seis suben de
     luminosidad y el relleno baja, porque el contraste ya lo da el
     fondo. */
  --cat-0: #818cf8;
  --cat-1: #a78bfa;
  --cat-2: #fb923c;
  --cat-3: #4ade80;
  --cat-4: #f472b6;
  --cat-5: #22d3ee;
  --cat-alpha: 0.22;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) {
    --cat-0: #818cf8;
    --cat-1: #a78bfa;
    --cat-2: #fb923c;
    --cat-3: #4ade80;
    --cat-4: #f472b6;
    --cat-5: #22d3ee;
    --cat-alpha: 0.22;
  }
}

/* `color-mix` produce el relleno a partir del mismo tono, así que no
   hay una segunda lista de valores que pueda quedar desalineada. */
.cat-0 { --cat: var(--cat-0); }
.cat-1 { --cat: var(--cat-1); }
.cat-2 { --cat: var(--cat-2); }
.cat-3 { --cat: var(--cat-3); }
.cat-4 { --cat: var(--cat-4); }
.cat-5 { --cat: var(--cat-5); }

/* Punto de la leyenda y borde de la tarjeta del período. */
.cal-legend-dot {
  width: 9px;
  height: 9px;
  border-radius: var(--radius-xs);
  background: var(--cat, var(--border-default));
}

.cal-p-dot {
  width: 9px;
  height: 9px;
  border-radius: var(--radius-pill);
  background: var(--cat, var(--border-default));
  flex-shrink: 0;
}

.cal-period-card.cat-0,
.cal-period-card.cat-1,
.cal-period-card.cat-2,
.cal-period-card.cat-3,
.cal-period-card.cat-4,
.cal-period-card.cat-5 {
  border-left-color: var(--cat);
}

/* Día que cae dentro de un período. El texto toma el tono pleno y el
   fondo una mezcla del mismo tono con la superficie. */
.cal-day.en-periodo {
  background: color-mix(in srgb, var(--cat) calc(var(--cat-alpha) * 100%), transparent);
  color: var(--cat);
  font-weight: var(--weight-semibold);
}

/* Reserva para navegadores sin `color-mix`: se queda el tono como
   texto sobre la superficie hundida, que sigue siendo legible. */
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  .cal-day.en-periodo { background: var(--surface-sunken); }
}

/* =============================================================
   ANCHO FIJO DE COLUMNA

   Distinto de `.col-min-*`: aquí el ancho se fija para que la tabla no
   se reacomode al filtrar. Lo necesitan las columnas cortas y
   predecibles —un id, una clave de período, un estado— para que la
   columna larga se quede con el resto del espacio.
   ============================================================= */

.data-table th.w-40  { width: 40px; }
.data-table th.w-70  { width: 70px; }
.data-table th.w-90  { width: 90px; }
.data-table th.w-110 { width: 110px; }
.data-table th.w-160 { width: 160px; }

/* =============================================================
   CÓDIGO EN LÍNEA

   Para una clave técnica dentro de un texto: el tipo de una alerta, el
   nombre de un parámetro. Antes cada pantalla la vestía con un `style=`
   sobre `<code>`, y en tema claro el fondo salía del navegador.
   ============================================================= */

.code-inline {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-xs);
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
  color: var(--content-secondary);
  white-space: nowrap;
}

/* =============================================================
   INDICADOR QUE FILTRA

   Una tarjeta de KPI que al pulsarse filtra la tabla. Era un `<div>` con
   `onclick` y `cursor:pointer`: no se podía alcanzar con el teclado ni
   se anunciaba como algo pulsable. Ahora es un `<button>`, y esta clase
   le quita la apariencia de botón sin quitarle el comportamiento.
   ============================================================= */

.kpi-boton {
  display: block;
  width: 100%;
  padding: 0;
  border: none;
  background: none;
  text-align: left;
  cursor: pointer;
}

.kpi-boton:focus-visible {
  outline: none;
}

.kpi-boton:focus-visible .kpi-card {
  border-color: var(--accent);
  box-shadow: var(--ring-focus);
}

.kpi-boton:hover .kpi-card {
  border-color: var(--border-strong);
}

/* =============================================================
   RECUADRO DE CITA

   Muestra un texto que viene de otro lado —la descripción de la alerta
   que se está resolviendo— dentro de un formulario. Deja claro que es
   contexto y no algo que se edita.
   ============================================================= */

.quote-box {
  padding: var(--space-5) var(--space-6);
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  color: var(--content-secondary);
}

/* =============================================================
   SEPARADOR DE SECCIÓN

   Divide un formulario o una ficha larga en bloques con nombre. La
   línea sale del propio separador, así que no hace falta un `<hr>`
   aparte que luego se desalinea.

   El color lo pone quien lo usa con `.t-success` o `.t-danger` cuando la
   sección lo pide —«Baja» en rojo—, no un `style=` con un hex.
   ============================================================= */

.section-sep {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin: var(--space-8) 0 var(--space-6);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--content-secondary);
  white-space: nowrap;
}

.section-sep::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border-subtle);
}

/* Primera sección de una tarjeta: no necesita separarse de nada arriba. */
.section-sep:first-child { margin-top: 0; }

/* =============================================================
   LISTA DE METADATOS

   Pares clave-valor en renglones, para la columna lateral de una ficha.
   Distinto de `.field-item`, que apila la etiqueta sobre el valor: aquí
   van enfrentados porque son datos de registro que se consultan, no
   contenido que se lee.
   ============================================================= */

.meta-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--border-subtle);
}

.meta-row:last-child { border-bottom: none; }

.meta-key {
  font-size: var(--text-xs);
  color: var(--content-tertiary);
  white-space: nowrap;
}

.meta-val {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--content-secondary);
  text-align: right;
  word-break: break-word;
}

/* Un valor que no es un identificador se lee mejor en la fuente normal. */
.meta-val--texto { font-family: var(--font-sans); }

/* =============================================================
   VALOR ANTERIOR Y NUEVO

   Para un historial de cambios. El anterior se tacha además de teñirse:
   así se distingue del nuevo sin depender del rojo contra el verde, que
   es justo el par que no distingue quien tiene daltonismo.
   ============================================================= */

.val-antes {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--state-danger-content);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

.val-despues {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--state-success-content);
  font-weight: var(--weight-medium);
}

/* =============================================================
   FICHA DE EXPEDIENTE

   Dos columnas: el expediente y una barra lateral de contexto. En
   pantalla angosta la lateral pasa abajo.
   ============================================================= */

.exp-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: var(--space-6);
  align-items: start;
}

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

.exp-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  min-width: 0;
}

/* Bloque de cierre de una ficha: la suma, destacada del resto. */
.exp-total {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-top: var(--space-7);
  padding: var(--space-5) var(--space-6);
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

/* =============================================================
   DESGLOSE DE CÁLCULO PASO A PASO

   La pantalla que explica CÓMO se llegó a un importe. Es la más
   didáctica del sistema: cada renglón es un paso numerado con su
   fórmula, y el tipo de paso decide el color.

   Los cuatro tipos son del negocio, no del diseño:
     percepción → suma       deducción → resta
     total      → cierre     info      → dato de contexto, no opera
   ============================================================= */

.recibo-grid {
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr);
  gap: var(--space-6);
  align-items: start;
}

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

.desglose-section {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: var(--card-radius);
  overflow: hidden;
}

.desglose-header {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-6) var(--space-7);
  border-bottom: 1px solid var(--border-subtle);
}

.desglose-title {
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--content-primary);
}

.desglose-sub {
  font-size: var(--text-2xs);
  color: var(--content-tertiary);
  margin-top: var(--space-1);
}

/* ----- Un paso ----- */
.paso-row {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-4) var(--space-7);
  border-bottom: 1px solid var(--border-subtle);
}

.paso-row:last-child { border-bottom: none; }

/* El tinte de fondo es muy leve a propósito: son renglones seguidos y
   un fondo saturado por renglón convierte la lista en un semáforo. */
.paso-row--percepcion { background: color-mix(in srgb, var(--state-success) 5%, transparent); }
.paso-row--deduccion  { background: color-mix(in srgb, var(--state-danger) 5%, transparent); }
.paso-row--info       { color: var(--content-tertiary); }

.paso-row--total {
  background: var(--surface-sunken);
  border-top: 1px solid var(--border-default);
}

/* Número del paso: un círculo delineado, que se rellena en el total. */
.paso-num {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-default);
  background: var(--surface-sunken);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  color: var(--content-tertiary);
}

.paso-row--total .paso-num {
  background: var(--state-success);
  border-color: var(--state-success);
  color: var(--content-on-accent);
}

/* En el carril de resguardo el cierre es azul, no verde. */
.paso-row--total.es-resguardo .paso-num {
  background: var(--state-info);
  border-color: var(--state-info);
}

.paso-concepto {
  font-size: var(--text-sm);
  color: var(--content-secondary);
}

.paso-row--total .paso-concepto {
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--content-primary);
}

/* La fórmula es la razón de ser de esta pantalla: va en mono para que
   los operadores y los números se distingan del texto. */
.paso-formula {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--content-tertiary);
  margin-top: var(--space-1);
}

.paso-importe {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  white-space: nowrap;
  text-align: right;
}

.paso-row--percepcion .paso-importe { color: var(--state-success-content); }
.paso-row--deduccion  .paso-importe { color: var(--state-danger-content); }
.paso-row--info       .paso-importe { color: var(--content-tertiary); }

.paso-row--total .paso-importe {
  font-size: var(--text-md);
  color: var(--content-primary);
}

.paso-row--total.es-resguardo .paso-importe { color: var(--state-info-content); }

/* ----- Aviso de costo que absorbe la empresa ----- */
.nota-costo {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  margin: 0 var(--space-7) var(--space-6);
  padding: var(--space-5) var(--space-6);
  background: var(--state-info-soft);
  border: 1px solid var(--state-info-border);
  border-radius: var(--radius-md);
  font-size: var(--text-xs);
  color: var(--content-secondary);
}

.nota-costo-val {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  color: var(--state-info-content);
  white-space: nowrap;
}

/* ----- Neto a pagar: la cifra que cierra la pantalla ----- */
.neto-box {
  margin-top: var(--space-6);
  padding: var(--space-6);
  background: var(--state-success-soft);
  border: 1px solid var(--state-success-border);
  border-radius: var(--radius-md);
  text-align: center;
}

.neto-label {
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--content-secondary);
}

.neto-val {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  color: var(--state-success-content);
  line-height: var(--leading-tight);
  margin-top: var(--space-2);
}

/* ----- Aviso de que el registro ya es definitivo ----- */
.banner-aprobado {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-5) var(--space-6);
  margin-bottom: var(--space-6);
  background: var(--state-success-soft);
  border: 1px solid var(--state-success-border);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  color: var(--content-secondary);
}

.banner-aprobado > i { color: var(--state-success); font-size: var(--text-md); }

/* ----- Nota al pie de una tarjeta ----- */
.nota-pie {
  margin-top: var(--space-5);
  padding: var(--space-4) var(--space-5);
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  color: var(--content-secondary);
}

/* =============================================================
   FILAS CON MARCA

   `table-warning` y `table-light` de Bootstrap son colores fijos: en
   tema oscuro pintan la fila de un amarillo pálido o de blanco, y el
   texto claro encima queda ilegible.

   `.fila-recurrente` marca una excepción que ya se había visto antes —el
   dato que decide si vale la pena resolverla una por una— y `.fila-nota`
   es el renglón de continuación que cuelga del anterior.
   ============================================================= */

.data-table tbody tr.fila-recurrente {
  background: var(--state-warning-soft);
}

.data-table tbody tr.fila-recurrente:hover {
  background: var(--state-warning-border);
}

/* Renglón de continuación: sin borde arriba, para que se lea pegado al
   registro del que cuelga. */
.data-table tbody tr.fila-nota > td {
  background: var(--surface-sunken);
  border-top: none;
  padding-top: var(--space-3);
  padding-bottom: var(--space-4);
}

/* =============================================================
   FILA DE PARÁMETRO

   Un ajuste con su nombre, su explicación y su control, en un renglón.
   Para pantallas de configuración donde cada parámetro se guarda solo,
   sin un botón de «guardar todo» al final.
   ============================================================= */

.param-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
  padding: var(--space-5) var(--space-6);
  margin-bottom: var(--space-4);
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-md);
  transition: border-color var(--duration-base) var(--ease);
}

.param-row:hover { border-color: var(--border-strong); }

.param-texto {
  flex: 1 1 auto;
  min-width: 0;
}

.param-nombre {
  display: block;
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  color: var(--content-primary);
}

/* La explicación no es opcional en esta pantalla: varios parámetros
   cambian lo que se le paga a alguien, y su nombre técnico no alcanza
   para saber qué hacen. */
.param-desc {
  display: block;
  font-size: var(--text-xs);
  color: var(--content-tertiary);
  margin-top: var(--space-1);
}

.param-control {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-shrink: 0;
}

.param-control .form-control,
.param-control .form-select {
  width: auto;
  min-width: 140px;
}

/* Bloque de resultado que aparece después de ejecutar algo. Oculto
   hasta que haya algo que mostrar. */
.resultado-box {
  margin-top: var(--space-6);
  padding: var(--space-6);
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

.resultado-box[hidden] { display: none; }

/* Ancho mínimo antes de que un hijo de flex se colapse. El caso: el
   selector de período junto al botón de calcular, que sin esto se
   encoge hasta que la clave del período no cabe. */
.min-w-220 { min-width: 220px; }


/* =============================================================
   BARRA DE MÓDULOS — Fase 1 · Navegación

   Dos barras, no una. La estrecha es el **mapa de la plataforma**
   (Home, Recepción, Mesa de cálculo, Expedientes, Entregables, Más) y
   no crece: todo lo que sea detalle vive en el submenú del módulo.

   Por qué icono + etiqueta y no solo icono: una barra de iconos pelados
   obliga a adivinar qué hace cada uno, y esta gente entra a trabajar,
   no a explorar.
   ============================================================= */

.modulos {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 1031;   /* por encima del submenú, que es 1030 */
  width: var(--modulos-width);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-6) var(--space-3);

  /* Hundida a propósito. Las dos barras son blancas por defecto y se
     funden en una sola franja: sin este contraste no se distingue el
     mapa de módulos del submenú, que es justo lo que la doble barra
     viene a separar. */
  background: var(--surface-sunken);
  border-right: 1px solid var(--border-default);
  overflow-y: auto;
}

/* La empresa activa encabeza la barra. En multi-empresa, saber en cuál
   estás parado es lo primero que hay que poder responder. */
.modulos-empresa {
  width: 56px;
  height: 56px;
  border-radius: 16px;
  background: var(--state-success, #14b8a6);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-lg);
  font-weight: 700;
  letter-spacing: .02em;
  text-decoration: none;
  flex-shrink: 0;
  transition: transform var(--duration-fast, .15s) var(--ease, ease);
}

.modulos-empresa:hover { transform: scale(1.04); color: #fff; }

.modulo {
  position: relative;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 4px;
  border-radius: 12px;
  color: var(--text-secondary);
  text-decoration: none;
  text-align: center;
  font-size: var(--text-2xs);
  line-height: 1.25;
  transition: background var(--duration-fast, .15s) var(--ease, ease),
              color var(--duration-fast, .15s) var(--ease, ease);
}

.modulo i { font-size: var(--text-lg); }

.modulo:hover { background: var(--bg-hover); color: var(--text-primary); }

.modulo.is-activa {
  color: var(--accent-solid);
  background: var(--accent-soft);
  font-weight: 600;
}

/* Los módulos que aún no existen se muestran apagados en vez de
   esconderse: el mapa completo tiene que estar a la vista desde el
   primer día, y una entrada que desaparece no se puede preguntar. */
.modulo.is-pendiente {
  opacity: .38;
  cursor: not-allowed;
}

.modulo.is-pendiente:hover { background: none; color: var(--text-secondary); }

/* Punto de aviso. Acompañado de texto para lector de pantalla: el color
   por sí solo no comunica. */
.modulo-punto {
  position: absolute;
  top: 8px;
  right: 22px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--state-danger, #ef4444);
  box-shadow: 0 0 0 2px var(--surface-sunken);
}

.modulos-pie {
  margin-top: auto;
  padding-top: var(--space-5);
}

.modulos-avatar {
  position: relative;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent-solid), var(--accent-solid-hover));
  color: var(--content-on-accent, #fff);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
}

/* En pantallas chicas la barra de módulos pasa a horizontal arriba: en
   vertical se comería un tercio del ancho útil. */
@media (max-width: 991.98px) {
  .modulos {
    position: static;
    width: 100%;
    flex-direction: row;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3);
    border-right: 0;
    border-bottom: 1px solid var(--border-default);
    overflow-x: auto;
  }

  .modulos-empresa { width: 40px; height: 40px; border-radius: 12px; font-size: var(--text-md); }
  .modulo { width: auto; flex-direction: row; gap: 8px; padding: 8px 12px; white-space: nowrap; }
  .modulo-punto { position: static; margin-left: 2px; }
  .modulos-pie { margin-top: 0; margin-left: auto; padding-top: 0; }
}

/* En móvil la barra de módulos deja de ser fija y el contenido recupera
   el ancho completo. */
@media (max-width: 991.98px) {
  .main-content { margin-left: 0; }
  .app-wrapper { flex-direction: column; }
}


/* =============================================================
   SELECTOR DE EMPRESA — Fase 1 · Navegación

   Primera pantalla después de entrar. No hay menú todavía porque no
   hay empresa elegida, así que la pantalla se sostiene sola.

   Las empresas sin plataforma se muestran **apagadas y no ocultas**:
   igual que los módulos pendientes de la barra, el mapa completo tiene
   que estar a la vista. Una tarjeta que no aparece nadie la puede
   preguntar.
   ============================================================= */

.empresas-page {
  /* Fondo propio, no el del acceso: es el que Guillermo entregó para esta
     pantalla en `visily-profile-management.pdf`. Al ser una ilustración plana
     —y no una fotografía con detalle— el velo puede ser mucho más ligero. */
  --login-imagen: url('../img/empresas-fondo.jpg');

  margin: 0;
  min-height: 100vh;
  background-color: var(--bg-base);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 24px;
  overflow-x: hidden;
}

/* Misma capa fija que el acceso: elegir empresa es la continuación de entrar,
   así que comparten fondo. Es `fixed` con `inset: 0` por lo mismo que allí —
   una foto sobre el body con padding en `vw` deja franjas y provoca scroll. */
.empresas-page::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  background:
    linear-gradient(160deg,
      rgba(12, 26, 52, .34) 0%,
      rgba(12, 26, 52, .16) 45%,
      rgba(12, 26, 52, .30) 100%),
    var(--login-imagen) center center / cover no-repeat,
    var(--bg-base);
  pointer-events: none;
}



.empresas-marco {
  width: 100%;
  /* Da para cinco columnas de 148px con sus separaciones: es el reparto más
     ancho que puede elegir `columnas_sin_huerfanas()`. */
  max-width: 940px;
  text-align: center;
}

.empresas-isotipo {
  width: 116px;
  height: auto;
  margin-bottom: 28px;
}

.empresas-titulo {
  font-size: clamp(1.6rem, 3.4vw, 2.3rem);
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.02em;
  margin: 0;
}

.empresas-bajada {
  font-size: var(--text-md);
  color: var(--text-secondary);
  margin: 10px 0 0;
}

.empresas-aviso {
  max-width: 460px;
  margin: 20px auto 0;
  text-align: left;
  font-size: var(--text-base);
}

/* Rejilla, no flex.
   Con `flex-wrap` las tarjetas se repartían por ancho disponible y la última
   fila quedaba con una sola tarjeta flotando —seis empresas daban 5+1—. Una
   rejilla de columnas fijas reparte parejo, y el número de columnas lo decide
   el servidor para que nunca sobre una sola: ver `columnas_sin_huerfanas()`
   en `dashboard/views/... auth/routes.py`.

   `grid-auto-rows: 1fr` iguala el alto de todas: el nombre de «Come Más
   Plantas» ocupa dos líneas y sin esto su tarjeta era más alta que el resto. */
.empresas-lista {
  list-style: none;
  padding: 0;
  margin: 40px auto 0;
  display: grid;
  grid-template-columns: repeat(var(--empresas-columnas, 3), 148px);
  grid-auto-rows: 1fr;
  justify-content: center;
  gap: 20px;
}

.empresas-lista > li { display: flex; }

.empresa-tarjeta {
  width: 100%;
  padding: 22px 12px 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  border-radius: 18px;
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  text-decoration: none;
  color: var(--text-primary);
  transition: transform var(--duration-fast, .15s) var(--ease, ease),
              box-shadow var(--duration-fast, .15s) var(--ease, ease),
              border-color var(--duration-fast, .15s) var(--ease, ease);
}

.empresa-tarjeta:hover {
  transform: translateY(-4px);
  border-color: var(--accent-solid);
  box-shadow: 0 12px 28px -10px rgba(10, 12, 22, .28);
  color: var(--text-primary);
}

.empresa-tarjeta:focus-visible {
  outline: 3px solid var(--accent-solid);
  outline-offset: 3px;
}

.empresa-avatar {
  width: 72px;
  height: 72px;
  border-radius: 20px;
  background: linear-gradient(135deg, var(--accent-solid), var(--accent-solid-hover));
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-xl);
  font-weight: 700;
}

.empresa-nombre {
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1.3;
}

/* Apagada sin `opacity`: esa propiedad afecta a TODA la tarjeta, fondo
   incluido, así que la volvía translúcida y sobre el amarillo del edificio se
   teñía de crema. Se atenúa el contenido, no la superficie. */
.empresa-tarjeta.is-pendiente {
  cursor: not-allowed;
  color: var(--text-tertiary);
}

/* Sin hover ni elevación: no promete una acción que no ocurre. */
.empresa-tarjeta.is-pendiente:hover {
  transform: none;
  box-shadow: none;
  border-color: var(--border-default);
}

.empresa-tarjeta.is-pendiente .empresa-avatar {
  background: var(--surface-sunken);
  color: var(--text-tertiary);
}

/* El estado no se comunica solo con la opacidad: quien no distinga el
   contraste necesita leerlo. */
.empresa-etiqueta {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.empresas-salir {
  display: inline-block;
  margin-top: 44px;
  font-size: var(--text-sm);
  color: var(--text-tertiary);
  text-decoration: none;
}

.empresas-salir:hover { color: var(--text-secondary); text-decoration: underline; }

@media (max-width: 575.98px) {
  .empresa-tarjeta { padding: 18px 10px 14px; }
  .empresa-avatar { width: 60px; height: 60px; border-radius: 16px; font-size: var(--text-lg); }
}

/* Pantallas sin submenú: el contenido arranca justo después de la barra
   de módulos en vez de dejar el hueco vacío de un sidebar que no está. */
.main-content.sin-submenu {
  margin-left: var(--modulos-width);
}

@media (max-width: 991.98px) {
  .main-content.sin-submenu { margin-left: 0; }
}


/* =============================================================
   RECEPCIÓN — expediente por mes y período

   Estilo CRM: cada período es una tarjeta que se lee de un vistazo,
   como una oportunidad en un embudo. Lo que la hace útil no es lo que
   llegó sino **el hueco**: los papeles que faltan se muestran, no se
   omiten.
   ============================================================= */

.recepcion {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: var(--space-7);
  align-items: start;
}

.recepcion-titulo {
  font-size: var(--text-xl);
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--text-primary);
  margin: 0;
}

.recepcion-bajada {
  font-size: var(--text-base);
  color: var(--text-secondary);
  margin: 6px 0 0;
  max-width: 62ch;
}

.recepcion-cabecera { margin-bottom: var(--space-7); }

/* ----- Mes ----- */

.mes { margin-bottom: var(--space-7); }

.mes-titulo {
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  margin: 0 0 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border-default);
}

/* ----- Período: la tarjeta ----- */

.periodo {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg, 12px);
  background: var(--bg-surface);
  padding: 14px 16px;
  margin-bottom: 10px;
  transition: border-color var(--duration-fast, .15s) var(--ease, ease),
              box-shadow var(--duration-fast, .15s) var(--ease, ease);
}

.periodo:hover { box-shadow: 0 6px 18px -10px rgba(10, 12, 22, .28); }

.periodo.is-seleccionado {
  border-color: var(--accent-solid);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.periodo-cab {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.periodo-clave {
  font-size: var(--text-md);
  font-weight: 700;
  color: var(--text-primary);
  text-decoration: none;
  font-variant-numeric: tabular-nums;
}

.periodo-clave:hover { color: var(--accent-solid); }

.periodo-fechas {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}

.chip {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: .03em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--surface-sunken);
  color: var(--text-secondary);
}

.chip-cerrado   { background: var(--state-success-soft); color: var(--state-success); }
.chip-aprobado  { background: var(--state-info-soft);    color: var(--state-info); }
.chip-calculado { background: var(--state-info-soft);    color: var(--state-info); }
.chip-pendiente { background: var(--state-warning-soft); color: var(--state-warning); }

.periodo-progreso {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}

.progreso-barra {
  display: block;
  width: 64px;
  height: 5px;
  border-radius: 999px;
  background: var(--surface-sunken);
  overflow: hidden;
}

.progreso-relleno {
  display: block;
  height: 100%;
  background: var(--accent-solid);
}

/* ----- Papeles de trabajo -----
   Los ausentes NO se ocultan: son la información que hace útil la
   pantalla. Se muestran apagados y con borde punteado, que es la forma
   visual de decir «esto debería estar aquí». */

.papeles {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.papel {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 11px;
  border-radius: 8px;
  border: 1px solid var(--border-default);
  background: var(--bg-base);
  font-size: var(--text-xs);
}

.papel i { font-size: var(--text-base); }

.papel.is-recibido {
  border-color: var(--state-success-soft);
  background: var(--state-success-soft);
  color: var(--state-success);
}

.papel.is-error {
  border-color: var(--state-danger-soft);
  background: var(--state-danger-soft);
  color: var(--state-danger);
}

.papel.is-ausente {
  border-style: dashed;
  color: var(--text-tertiary);
  background: transparent;
}

.papel-nombre { font-weight: 600; }

.papel-estado,
.papel-de,
.papel-detalle,
.papel-fecha {
  font-weight: 400;
  opacity: .85;
}

.papel-fecha { font-variant-numeric: tabular-nums; }

/* ----- Lo que pasó ----- */

.periodo-sucesos {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border-subtle, var(--border-default));
}

.suceso {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  padding: 3px 8px;
  border-radius: 6px;
  background: var(--surface-sunken);
}

.suceso.is-pendiente { color: var(--state-warning); background: var(--state-warning-soft); }
.suceso-excepcion.is-pendiente { color: var(--state-danger); background: var(--state-danger-soft); }

/* ----- Panel de sucursales ----- */

.panel-sucursales {
  position: sticky;
  top: var(--space-6);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg, 12px);
  background: var(--bg-surface);
  padding: 16px;
}

.panel-titulo {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 6px;
}

.panel-periodo {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--accent-solid);
  text-transform: none;
  letter-spacing: 0;
}

.panel-nota,
.panel-vacio {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  margin: 0 0 12px;
  line-height: 1.5;
}

.sucursales { list-style: none; margin: 0; padding: 0; }

.sucursal {
  padding: 9px 0;
  border-bottom: 1px solid var(--border-subtle, var(--border-default));
}

.sucursal:last-child { border-bottom: 0; }

.sucursal-fila {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.sucursal-nombre {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-primary);
}

/* El número de incidencias es lo que se busca al mirar este panel. */
.sucursal-marca {
  font-size: var(--text-2xs);
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--state-warning-soft);
  color: var(--state-warning);
  font-variant-numeric: tabular-nums;
}

.sucursal-sociedad,
.sucursal-detalle {
  display: block;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}

.sucursal-sociedad { margin-top: 1px; }
.sucursal-detalle { margin-top: 2px; }

/* Bajo 1200px el panel deja de ser columna y pasa debajo: a menos ancho,
   apretarlo dejaría los nombres de sucursal ilegibles. */
@media (max-width: 1199.98px) {
  .recepcion { grid-template-columns: minmax(0, 1fr); }
  .panel-sucursales { position: static; }
}

.bandeja-vacia {
  text-align: center;
  padding: 64px 24px;
  border: 1px dashed var(--border-default);
  border-radius: var(--radius-lg, 12px);
  color: var(--text-tertiary);
}

.bandeja-vacia i { font-size: var(--text-3xl); opacity: .5; }
.bandeja-vacia-titulo { margin: 14px 0 4px; font-weight: 600; color: var(--text-secondary); }
.bandeja-vacia-texto { margin: 0; font-size: var(--text-base); }


/* ----- Filtro por período -----
   Recorta la pantalla a un período. No es un resaltado: con 14 períodos y
   creciendo, ver uno solo deja de ser cómodo y pasa a ser necesario. */

.filtros-periodo {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 16px;
}

.fp {
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  color: var(--text-secondary);
  font-size: var(--text-xs);
  font-weight: 600;
  text-decoration: none;
  font-variant-numeric: tabular-nums;
  transition: background var(--duration-fast, .15s) var(--ease, ease),
              color var(--duration-fast, .15s) var(--ease, ease);
}

.fp:hover { background: var(--bg-hover); color: var(--text-primary); }

.fp.is-activo {
  background: var(--accent-solid);
  border-color: var(--accent-solid);
  color: var(--content-on-accent, #fff);
}

/* ----- Documentos del período ----- */

.documentos {
  margin-top: var(--space-7);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg, 12px);
  background: var(--bg-surface);
  padding: 16px;
}

.documentos-titulo {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 12px;
}

.documentos-periodo {
  font-size: var(--text-sm);
  color: var(--accent-solid);
  text-transform: none;
  letter-spacing: 0;
}

.tabla-documentos {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.tabla-documentos th {
  text-align: left;
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  padding: 0 10px 8px 0;
  border-bottom: 1px solid var(--border-default);
}

.tabla-documentos td {
  padding: 9px 10px 9px 0;
  border-bottom: 1px solid var(--border-subtle, var(--border-default));
  color: var(--text-secondary);
  vertical-align: top;
}

.tabla-documentos tr:last-child td { border-bottom: 0; }

.doc-archivo {
  color: var(--text-primary);
  font-weight: 600;
}

.doc-archivo i { color: var(--state-success); margin-right: 6px; }

/* Cifras alineadas a la derecha y tabulares: se comparan en columna. */
.col-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.doc-errores {
  display: block;
  font-size: var(--text-2xs);
  color: var(--state-danger);
  font-weight: 600;
}

.doc-fecha {
  font-variant-numeric: tabular-nums;
  color: var(--text-tertiary);
  white-space: nowrap;
}

.documentos-vacio {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-tertiary);
  line-height: 1.55;
}

/* ----- Selector de sucursal del panel ----- */

.panel-filtro { margin-bottom: 12px; }

.panel-filtro .form-select {
  font-size: var(--text-xs);
  border-color: var(--border-default);
  background-color: var(--bg-base);
  color: var(--text-primary);
}

@media (max-width: 767.98px) {
  .tabla-documentos { display: block; overflow-x: auto; white-space: nowrap; }
}

/* El asunto del correo: es lo que identifica el envío para quien lo mandó,
   así que se muestra junto al papel y bajo el nombre del archivo. */
/* El asunto se muestra entero y envuelve. Es lo que distingue un envío de
   otro cuando llegan varios el mismo día, y recortarlo dejaba dos correos de
   sucursales distintas con exactamente el mismo aspecto. */
.papel-asunto {
  font-style: italic;
  opacity: .85;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* El papel deja de forzar una sola línea para que el asunto quepa. */
.papel {
  flex-wrap: wrap;
  max-width: 100%;
}

.doc-asunto {
  display: block;
  font-weight: 400;
  font-style: italic;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  margin-top: 2px;
}


/* ----- Selector de empresa sobre la foto -----
   Estas reglas van al FINAL a propósito. Colocadas junto al resto del bloque
   quedaban ANTES de las definiciones originales de `.empresas-titulo` y
   compañía, que las pisaban por orden de cascada: el velo se aplicaba pero el
   texto seguía en su color oscuro, ilegible sobre la imagen. */

.empresas-marco {
  position: relative;
  z-index: 1;
}

.empresas-titulo { color: #fff; }

.empresas-bajada { color: rgba(255, 255, 255, .82); }

.empresas-salir { color: rgba(255, 255, 255, .74); }
.empresas-salir:hover { color: #fff; }

/* Las tarjetas mantienen su superficie: son lo que se pulsa, así que no deben
   competir con la foto ni volverse translúcidas. */
.empresa-tarjeta {
  background: var(--bg-surface);
  box-shadow: 0 10px 30px -14px rgba(10, 12, 22, .55);
}

.empresa-tarjeta.is-pendiente {
  background: rgba(255, 255, 255, .82);
  border-color: rgba(255, 255, 255, .5);
}

/* ----- La tarjeta del período se abre al pulsarla -----
   El enlace vive en el título (teclado y lector de pantalla) y se estira sobre
   toda la tarjeta con un pseudo-elemento. Así el área de clic es la tarjeta
   entera sin anidar enlaces, que es HTML inválido. */

.periodo { position: relative; }

.periodo-enlace::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.periodo:has(.periodo-enlace) { cursor: pointer; }

.periodo:has(.periodo-enlace:hover) {
  border-color: var(--accent-solid);
  box-shadow: 0 8px 22px -12px rgba(10, 12, 22, .35);
}

/* Foco visible en la tarjeta, no solo en el texto del título. */
.periodo:has(.periodo-enlace:focus-visible) {
  outline: 3px solid var(--accent-solid);
  outline-offset: 2px;
}

/* El período abierto no se puede volver a pulsar: ya estás en él. */
.periodo.is-abierto {
  border-color: var(--accent-solid);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.volver {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 16px;
  padding: 6px 13px 6px 10px;
  border-radius: 999px;
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
}

.volver:hover { background: var(--bg-hover); color: var(--text-primary); }

/* Sin panel lateral, el contenido ocupa el ancho completo. */
.recepcion--sola { grid-template-columns: minmax(0, 1fr); }

/* ----- Pie de la barra de módulos -----
   Dos botones apilados: volver al selector de empresas (arriba, con las
   flechas) y el perfil, que cierra sesión.

   Sin menú desplegable a propósito. La barra lleva `overflow-y: auto` para
   que los módulos quepan en pantallas bajas, y eso recorta cualquier hijo
   posicionado que salga de ella: el menú se abría fuera del borde y quedaba
   invisible, así que el botón parecía no hacer nada. */

.modulos-pie {
  margin-top: auto;
  padding-top: var(--space-5);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.pie-boton {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  text-decoration: none;
  transition: background var(--duration-fast, .15s) var(--ease, ease),
              border-color var(--duration-fast, .15s) var(--ease, ease);
}

.pie-boton:focus-visible {
  outline: 3px solid var(--accent-solid);
  outline-offset: 2px;
}

/* Cambiar de empresa. Más pequeño que el perfil: es la acción secundaria. */
.pie-boton--empresa {
  width: 36px;
  height: 36px;
  color: var(--text-tertiary);
  border: 1px solid transparent;
  font-size: var(--text-md);
}

.pie-boton--empresa:hover {
  background: var(--accent-soft);
  border-color: var(--accent-border);
  color: var(--accent-solid);
}

/* Redondo y con silueta, como el diseño. Antes llevaba el isotipo, que es dos
   veces y media más ancho que alto y obligaba a un rectángulo; una silueta
   cabe en el círculo y además no finge ser una foto que no existe. */
.pie-boton--perfil {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  color: var(--text-tertiary);
  font-size: var(--text-lg);
}

.pie-boton--perfil:hover { color: var(--state-danger); }

.pie-boton--perfil:hover { border-color: var(--state-danger); }

@media (max-width: 991.98px) {
  .modulos-pie { flex-direction: row; margin-top: 0; margin-left: auto; padding-top: 0; }
}

.pie-boton--perfil .perfil-estado {
  right: -2px;
  bottom: -2px;
  border-color: var(--surface-sunken);
}

/* El título cruza el amarillo del edificio, donde el blanco por sí solo se
   pierde. Una sombra sutil lo sostiene sin ensuciar la ilustración. */
.empresas-titulo {
  text-shadow: 0 2px 14px rgba(10, 20, 44, .55);
}

.empresas-bajada {
  text-shadow: 0 1px 8px rgba(10, 20, 44, .5);
}

.empresas-salir {
  text-shadow: 0 1px 6px rgba(10, 20, 44, .5);
}

/* El isotipo cae justo sobre la cara amarilla del edificio, y su naranja y su
   gris se pierden ahí. Una placa blanca discreta lo despega del fondo sin
   convertirlo en un bloque: es la misma solución del acceso, pero aquí hace
   falta por contraste y no por transparencia. */
.empresas-isotipo {
  padding: 12px 20px;
  border-radius: 14px;
  background: rgba(255, 255, 255, .93);
  box-shadow: 0 8px 26px -12px rgba(10, 20, 44, .5);
}

/* Sobre el amarillo, un blanco translúcido se vuelve crema y las tarjetas
   apagadas parecían de otro color. Se opacan. */
.empresa-tarjeta.is-pendiente {
  background: rgba(255, 255, 255, .94);
  border-color: rgba(255, 255, 255, .7);
}

/* El contenido de una tarjeta apagada se atenúa por su cuenta. */
.empresa-tarjeta.is-pendiente .empresa-nombre { color: var(--text-secondary); }
.empresa-tarjeta.is-pendiente .empresa-avatar {
  background: var(--surface-sunken);
  color: var(--text-tertiary);
}

/* En pantallas chicas manda el ancho disponible, no el reparto ideal. */
@media (max-width: 575.98px) {
  .empresas-lista { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* =============================================================
   DETALLE DEL PERÍODO

   Solo existe dentro de un período abierto. En la lista, la primera
   vista son únicamente los períodos.
   ============================================================= */

.filtros-detalle {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: var(--space-7) 0 var(--space-6);
  padding-bottom: var(--space-6);
  border-bottom: 1px solid var(--border-default);
}

.fd-etiqueta {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  margin: 0;
}

.filtros-detalle .form-select {
  width: auto;
  min-width: 176px;
  font-size: var(--text-sm);
  border-color: var(--border-default);
  background-color: var(--bg-surface);
  color: var(--text-primary);
}

/* ----- Resumen de la hoja de instrucciones ----- */

.resumen-hi {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg, 12px);
  background: var(--bg-surface);
  padding: 18px;
  margin-bottom: var(--space-7);
}

.resumen-hi-titulo {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 16px;
}

.resumen-hi-donde {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--accent-solid);
  text-transform: none;
  letter-spacing: 0;
}

/* Los dos carriles del producto —fiscal y resguardo— se enseñan lado a lado
   porque la pregunta que responde esta pantalla es cuánto toca a cada uno. */
.carriles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  margin-bottom: 18px;
}

.carril {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 14px 16px;
  border-radius: 10px;
  border: 1px solid var(--border-default);
  background: var(--bg-base);
}

.carril-cifra {
  font-size: var(--text-2xl);
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}

.carril-nombre {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  line-height: 1.35;
}

/* Verde para fiscal y azul para resguardo: es el par que ya usa el resto del
   sistema para distinguir los dos carriles. No se inventa aquí. */
.carril--fiscal {
  border-color: var(--state-success-soft);
  background: var(--state-success-soft);
}
.carril--fiscal .carril-cifra { color: var(--state-success); }

.carril--resguardo {
  border-color: var(--state-info-soft);
  background: var(--state-info-soft);
}
.carril--resguardo .carril-cifra { color: var(--state-info); }

.carril--ambas .carril-cifra { color: var(--text-secondary); }

.carril--personas {
  border-color: var(--accent-border);
  background: var(--accent-soft);
}
.carril--personas .carril-cifra { color: var(--accent-content); }

/* ----- Tabla de incidencias ----- */

.tabla-incidencias {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.tabla-incidencias th {
  text-align: left;
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  padding: 0 10px 8px 0;
  border-bottom: 1px solid var(--border-default);
}

.tabla-incidencias td {
  padding: 9px 10px 9px 0;
  border-bottom: 1px solid var(--border-subtle, var(--border-default));
  color: var(--text-secondary);
}

.tabla-incidencias tr:last-child td { border-bottom: 0; }

/* Las informativas no descuentan: se apagan para que no compitan con las que
   sí mueven dinero. */
.fila-informativa td { color: var(--text-tertiary); }

.marca {
  display: inline-block;
  font-size: var(--text-2xs);
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 5px;
  margin-right: 4px;
}

.marca--fiscal    { background: var(--state-success-soft); color: var(--state-success); }
.marca--resguardo { background: var(--state-info-soft);    color: var(--state-info); }
.marca--info      { background: var(--surface-sunken);     color: var(--text-tertiary); }

/* ----- Documentos agrupados por asunto ----- */

.grupo-doc { margin-bottom: 22px; }
.grupo-doc:last-child { margin-bottom: 0; }

.grupo-doc-titulo {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--text-primary);
  margin: 0 0 8px;
}

.grupo-doc-conteo {
  font-size: var(--text-2xs);
  font-weight: 600;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--surface-sunken);
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 767.98px) {
  .tabla-incidencias { display: block; overflow-x: auto; }
}


/* =============================================================
   EL RECORTE DE LA COLA — pendientes / resueltas / todas

   Guillermo, 6-sep-2026: «aplica un filtro para que sea más rápido
   y sencillo ver qué está pendiente, y que vayan desapareciendo
   sería lo ideal».

   En P17 había 2 excepciones abiertas entre 42: cuarenta renglones
   de ruido entre el operador y las dos decisiones que quedaban.
   ============================================================= */

.cola-filtro {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

/* Enlaces, no botones: se abren en otra pestaña, quedan en el
   historial y funcionan sin JS. El área supera los 24 px de
   WCAG 2.5.8 por el relleno vertical. */
.cola-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-6);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  background: var(--bg-surface);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--text-secondary);
  text-decoration: none;
  transition: border-color var(--duration-base) var(--ease),
              background-color var(--duration-base) var(--ease);
}

.cola-chip:hover {
  border-color: var(--border-strong);
  color: var(--text-primary);
}

/* El activo no se marca solo con color: lleva borde de acento, fondo
   propio y `aria-current`, así que se distingue sin depender del tono. */
.cola-chip.is-activo {
  border-color: var(--accent-solid);
  background: var(--accent-soft);
  color: var(--accent-content);
  font-weight: var(--weight-semibold);
}

.cola-chip-num {
  font-variant-numeric: tabular-nums;
  padding: 0 var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  font-size: var(--text-2xs);
}

.cola-chip.is-activo .cola-chip-num {
  background: var(--surface-raised);
  color: var(--accent-content);
}

/* Cuando no queda nada pendiente la cola lo dice, en lugar de
   enseñar dos secciones vacías. Es lo que hace que «desaparecer»
   se lea como terminado y no como roto. */
.cola-limpia {
  border: 1px solid var(--state-success-soft);
  border-radius: var(--radius-lg, 12px);
  background: var(--bg-surface);
  padding: var(--space-9) var(--space-7);
  margin-bottom: var(--space-7);
  text-align: center;
}

.cola-limpia > .bi {
  font-size: var(--text-2xl);
  color: var(--state-success);
}

.cola-limpia-titulo {
  margin: var(--space-5) 0 0;
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  color: var(--text-primary);
}

.cola-limpia-pie {
  margin: var(--space-4) 0 0;
  font-size: var(--text-xs);
  color: var(--text-secondary);
}


/* =============================================================
   POR RESOLVER — las excepciones, dentro del período

   El operador arregla sin salir del período que está revisando. El
   formulario apunta a la ruta que ya existía, así que la regla de
   negocio —justificación obligatoria, alias que se registra— vive en
   un solo sitio.
   ============================================================= */

.arreglos {
  border: 1px solid var(--state-warning-soft);
  border-radius: var(--radius-lg, 12px);
  background: var(--bg-surface);
  padding: 18px;
  margin-bottom: var(--space-7);
}

.arreglos-titulo {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 14px;
}

.arreglos-conteo {
  font-size: var(--text-2xs);
  font-weight: 600;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--state-warning-soft);
  color: var(--state-warning);
  text-transform: none;
  letter-spacing: 0;
}

.excepciones { list-style: none; margin: 0; padding: 0; }

.exc {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 12px 0;
  border-bottom: 1px solid var(--border-subtle, var(--border-default));
}

.exc:last-child { border-bottom: 0; }

/* Lo resuelto se apaga: sigue visible como traza, pero no compite con lo que
   todavía pide una decisión. */
.exc.is-resuelta { opacity: .62; }

.exc-que {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 320px;
  flex: 1 1 420px;
}

.exc-tipo {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-primary);
}

.exc-quien {
  font-size: var(--text-xs);
  color: var(--accent-content);
  font-weight: 600;
}

/* Qué está pasando AHORA MISMO si nadie hace nada. Va antes del detalle y con
   más peso: es lo que decide si esto urge —el renglón no entró al cálculo— o
   solo hay que dejarlo bien. Ver `services/guia_excepciones.py`. */
.exc-hoy {
  font-size: var(--text-sm);
  color: var(--text-primary);
  line-height: 1.55;
  max-width: 72ch;
}

/* Qué frena, cuánto vale, cuánto lleva esperando y quién contesta, en una
   línea. Los cuatro datos que convertían «está abierta» en algo accionable. */
.exc-cuesta {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  line-height: 1.5;
}

.exc-cuesta .amount { font-weight: 600; }
.exc-cuesta strong { color: var(--text-primary); }

/* El detalle se muestra entero y envuelve: es la evidencia técnica de por qué
   hay que decidir algo, y cortada a mitad no sirve para decidir. Se le da
   medida de lectura para que no cruce toda la pantalla en una línea. */
.exc-detalle {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  line-height: 1.5;
  max-width: 68ch;
  white-space: normal;
  overflow-wrap: anywhere;
}

.exc-form {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.exc-form .form-select { width: auto; min-width: 210px; font-size: var(--text-sm); }
.exc-form .form-control { width: 230px; font-size: var(--text-sm); }

.exc-cerrada {
  display: flex;
  align-items: center;
  gap: 8px;
}

.exc-quien-cerro {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}

/* =============================================================
   EL PADRÓN DEL PERÍODO

   Se encoge y se amplía con el filtro de arriba: es el mismo recorte
   que alimenta el resumen de incidencias, así que las dos cifras
   siempre concuerdan. Si difirieran, una de las dos estaría mintiendo.
   ============================================================= */

.padron {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg, 12px);
  background: var(--bg-surface);
  padding: 18px;
  margin-bottom: var(--space-7);
}

.padron-titulo {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 14px;
}

.padron-conteo {
  font-size: var(--text-xs);
  font-weight: 700;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent-content);
  font-variant-numeric: tabular-nums;
  text-transform: none;
}

.padron-donde {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--accent-solid);
  text-transform: none;
  letter-spacing: 0;
}

.tabla-padron {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.tabla-padron th {
  text-align: left;
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  padding: 0 10px 8px 0;
  border-bottom: 1px solid var(--border-default);
  position: sticky;
  top: 0;
  background: var(--bg-surface);
}

.tabla-padron td {
  padding: 8px 10px 8px 0;
  border-bottom: 1px solid var(--border-subtle, var(--border-default));
  color: var(--text-secondary);
}

.tabla-padron tr:last-child td { border-bottom: 0; }
.tabla-padron tbody tr:hover { background: var(--bg-hover); }

.pad-nombre { color: var(--text-primary); font-weight: 600; }
.pad-rfc { font-variant-numeric: tabular-nums; color: var(--text-tertiary); }
.pad-suc { color: var(--text-tertiary); }

/* El punto medio marca «sin incidencia» sin gritar un cero en cada celda: con
   180 filas, una columna de ceros es ruido y esconde los datos que importan. */
.tabla-padron .col-num { color: var(--text-tertiary); }
.tabla-padron .col-num.es-dato {
  color: var(--text-primary);
  font-weight: 600;
}

/* Con 180 empleados la tabla no cabe en pantalla: se hace desplazable dentro
   de su tarjeta en vez de estirar la página. */
.padron .tabla-padron { display: block; max-height: 460px; overflow-y: auto; }
.padron .tabla-padron thead,
.padron .tabla-padron tbody { display: table; width: 100%; table-layout: fixed; }

@media (max-width: 767.98px) {
  .exc-form .form-control,
  .exc-form .form-select { width: 100%; }
}

/* Una excepción sin empleado asignado se muestra aunque haya filtro puesto:
   no se le puede adivinar la sucursal, y esconderla sería esconder el caso más
   problemático. Se marca para que no parezca que el filtro falló. */
.exc-sin-asignar {
  align-self: flex-start;
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: .03em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 5px;
  background: var(--surface-sunken);
  color: var(--text-tertiary);
}

/* La barra superior dice DÓNDE ESTÁS. Antes solo llevaba un contador de
   alertas, que no responde esa pregunta. */
.topbar-donde {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.topbar-modulo {
  font-size: var(--text-md);
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.2;
  letter-spacing: -.01em;
}

.topbar-descripcion {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 62ch;
}

/* El tamaño del archivo, cuando no hay cuenta de filas. */
.doc-tamano { color: var(--text-tertiary); font-variant-numeric: tabular-nums; }

@media (max-width: 767.98px) {
  .topbar-descripcion { display: none; }
}

/* A quién afecta el aviso, delante del texto: es lo primero que se busca al
   leer «cambió la empresa». El chip permite hasta dos líneas antes de recortar
   —un aviso de una línea y media no debería quedar a medias—. */
.suceso {
  max-width: 100%;
  white-space: normal;
  line-height: 1.4;
  align-items: flex-start;
}

.suceso-quien { margin-right: 4px; }

/* ----- Avisos del período -----
   Alertas y observaciones, dentro del período. Salieron de la tarjeta de la
   lista, donde competían con los papeles de trabajo por la misma mirada. */

.avisos {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg, 12px);
  background: var(--bg-surface);
  padding: 18px;
  margin-bottom: var(--space-7);
}

.avisos-titulo {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 12px;
}

.avisos-conteo {
  font-size: var(--text-2xs);
  font-weight: 600;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--state-warning-soft);
  color: var(--state-warning);
  text-transform: none;
  letter-spacing: 0;
}

.avisos-lista { list-style: none; margin: 0; padding: 0; }

.aviso {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border-subtle, var(--border-default));
  font-size: var(--text-sm);
}

.aviso:last-child { border-bottom: 0; }

.aviso > i { margin-top: 2px; color: var(--text-tertiary); font-size: var(--text-base); }
.aviso.is-pendiente > i { color: var(--state-warning); }

/* Lo resuelto se apaga: sigue siendo traza, pero no compite con lo pendiente. */
.aviso:not(.is-pendiente) { opacity: .6; }

.aviso-cuerpo {
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex: 1;
  min-width: 0;
}

.aviso-quien {
  font-weight: 600;
  color: var(--text-primary);
}

/* Entero y envolviendo: un aviso dice por qué hay que mirar algo, y cortado a
   mitad no cumple su función. */
.aviso-texto {
  color: var(--text-secondary);
  line-height: 1.45;
  max-width: 78ch;
  overflow-wrap: anywhere;
}

.aviso-fecha {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Cuántos correos de ese papel llegaron. Solo se muestra a partir de dos: un
   «1» junto a cada papel sería ruido en las cinco fichas de cada período. */
.papel-cuantos {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 0 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .6);
}

/* Sin detalle dentro, la ficha vuelve a ser una sola línea. */
.papel { flex-wrap: nowrap; white-space: nowrap; }


/* =============================================================
   MESA DE CÁLCULO

   Tres decisiones de Guillermo (3-sep) mandan sobre esta pantalla:
   se entra por período como en Recepción, se elige UN carril a la
   vez, y se agrupa por empresa fiscal —son cuatro— porque por
   sucursal serían diecisiete tablas para llegar al mismo sitio.

   Elegir el carril no es filtrar: cambia QUÉ COLUMNAS existen. Las
   incapacidades no tocan el resguardo y los hologramas no tocan el
   fiscal. Por eso el selector es lo primero y lo más grande de la
   pantalla, y no un `select` perdido entre otros filtros.

   Debajo, la tabla es densa a propósito —175 empleados— así que
   todo el trabajo va en que se pueda RECORRER: cifras tabulares que
   se comparan en columna, el nombre siempre visible, y el cero
   apagado para que los pocos datos que hay salten a la vista.
   ============================================================= */

.mesa { max-width: 100%; }

/* Las fichas de empresa de la lista de períodos son un CONTEO, no un estado.
   En Recepción el verde de `.papel.is-recibido` significa «este papel llegó»;
   reutilizarlo aquí diría que la empresa está lista cuando solo dice cuánta
   gente trae. Neutro a propósito. */
.papel--conteo {
  border-color: var(--border-default);
  background: var(--bg-surface);
  color: var(--text-secondary);
}

.papel--conteo i { color: var(--text-tertiary); }

.papel--conteo .papel-cuantos {
  background: var(--surface-sunken);
  color: var(--text-primary);
}

/* ----- El carril -----
   Dos opciones grandes, no un menú: es la decisión que define la
   pantalla y tiene que verse tomada de un vistazo. */

.carril-selector {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px;
  margin: 0 0 var(--space-6);
}

.carril-opcion {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 14px 18px;
  border-radius: var(--radius-lg, 12px);
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  text-decoration: none;
  transition: border-color .15s ease, background-color .15s ease;
}

.carril-opcion:hover { background: var(--bg-hover); }

.carril-opcion-nombre {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text-secondary);
}

.carril-opcion-pie {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}

/* El activo se llena; el otro se queda como lo que es: una salida.
   Verde fiscal y azul resguardo, el mismo par que usa el resto del
   sistema para distinguir los dos carriles. No se inventa aquí. */
.carril-opcion.is-activo {
  border-width: 2px;
  padding: 13px 17px;
}

.carril-opcion--fiscal.is-activo {
  border-color: var(--state-success);
  background: var(--state-success-soft);
}
.carril-opcion--fiscal.is-activo .carril-opcion-nombre { color: var(--state-success); }

.carril-opcion--resguardo.is-activo {
  border-color: var(--state-info);
  background: var(--state-info-soft);
}
.carril-opcion--resguardo.is-activo .carril-opcion-nombre { color: var(--state-info); }

/* ----- Las cuatro empresas -----
   Cada una calcula su propia nómina. Se abre una y aparece su tabla;
   verlas todas a la vez es la pared de tablas que se quiso evitar. */

.empresas-mesa {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin: 0 0 var(--space-5);
}

.empresa-caja {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 15px 17px;
  border-radius: var(--radius-lg, 12px);
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  text-decoration: none;
  transition: border-color .15s ease, background-color .15s ease;
}

a.empresa-caja:hover { background: var(--bg-hover); }

.empresa-caja-nombre {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.empresa-caja-cifra {
  font-size: var(--text-xl);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -.02em;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.empresa-caja-pie {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}

/* La abierta se marca por el borde, no por el fondo: el fondo ya lo
   usa el carril y dos señales de color compitiendo no dicen nada. */
.empresa-caja.is-abierta {
  border-color: var(--accent-border);
  border-width: 2px;
  padding: 14px 16px;
  background: var(--accent-soft);
}
.empresa-caja.is-abierta .empresa-caja-nombre { color: var(--accent-content); }

.empresa-caja--total {
  background: var(--surface-sunken);
  border-style: dashed;
}

/* ----- De dónde salen los números -----
   Un total sin su procedencia invita a confiar en él sin saber qué es. */

.mesa-origen {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px;
  font-size: var(--text-xs);
  color: var(--text-secondary);
  margin: 0 0 var(--space-6);
  padding: 9px 13px;
  border-radius: 8px;
  background: var(--surface-sunken);
}

.mesa-origen-error {
  color: var(--state-danger);
  font-weight: 600;
}

/* ----- Sin empresa elegida ----- */

.mesa-elige {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 44px 20px;
  border: 1px dashed var(--border-default);
  border-radius: var(--radius-lg, 12px);
  color: var(--text-tertiary);
  text-align: center;
}

.mesa-elige i { font-size: var(--text-2xl); opacity: .5; }
.mesa-elige p { margin: 0; font-size: var(--text-base); }

/* ----- La tabla ----- */

.mesa-tabla-marco {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg, 12px);
  background: var(--bg-surface);
  overflow-x: auto;
}

/* 🔴 SIN ALTURA MÁXIMA (3-sep-2026).
   Con `max-height: 68vh` la tabla tenía su propio scroll vertical, y eso hacía
   dos cosas malas a la vez: el cursor quedaba atrapado dentro —Guillermo:
   «si mi cursor lo pongo dentro de la tabla hace scroll, pero cuando termino la
   tabla se mueve»— y la tabla se veía más pequeña de lo que es, con 175 filas
   metidas en dos tercios de pantalla.

   Ahora crece con la página y scrollea la ventana entera, que es lo natural.
   Lo que de verdad hacía falta era que el encabezado no se perdiera, y eso lo
   da `position: sticky` en el `th`, no el recorte. */
.mesa-tabla-marco--libre { max-height: none; }

.mesa-tabla {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--text-xs);
}

.mesa-tabla th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--bg-surface);
  text-align: left;
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  padding: 10px 8px;
  border-bottom: 1px solid var(--border-default);
  white-space: nowrap;
}

.mesa-tabla td {
  padding: 7px 8px;
  border-bottom: 1px solid var(--border-subtle, var(--border-default));
  color: var(--text-secondary);
  white-space: nowrap;
}

.mesa-tabla tbody tr:hover td { background: var(--bg-hover); }

/* El nombre acompaña siempre: con las columnas de incidencias,
   perderlo al desplazarse a la derecha deja las cifras sin dueño. */
.col-fija {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--bg-surface);
  min-width: 210px;
  box-shadow: 1px 0 0 var(--border-default);
}

.mesa-tabla thead .col-fija { z-index: 3; }
.mesa-tabla tbody tr:hover .col-fija { background: var(--bg-hover); }

.mesa-nombre {
  display: block;
  font-weight: 600;
  color: var(--text-primary);
}

.mesa-puesto {
  display: block;
  font-size: var(--text-2xs);
  color: var(--text-tertiary);
}

.mesa-suc { color: var(--text-tertiary); }

/* ----- Las incidencias -----
   Columnas estrechas y cifras tabulares: se comparan en vertical. */

.col-inc {
  min-width: 62px;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--text-tertiary);
}

/* El punto de «sin incidencia» se apaga; el dato se enciende. Con 175
   filas, una pared de ceros esconde lo poco que hay que mirar. */
.col-inc.es-dato { font-weight: 700; }
.col-inc.es-descuenta { color: var(--state-danger); }
.col-inc.es-suma { color: var(--state-success); }
.col-inc.es-informativa { color: var(--text-secondary); }

/* En el encabezado, una marca de qué hace cada columna. */
.col-inc--descuenta   { border-top: 2px solid var(--state-danger-soft); }
.col-inc--suma        { border-top: 2px solid var(--state-success-soft); }
.col-inc--informativa { border-top: 2px solid var(--border-default); }

/* ----- Los importes del carril -----

   Se fijan a la DERECHA, igual que el nombre a la izquierda. La razón la
   enseñó el primer render: con catorce columnas de incidencia la tabla
   desborda, y lo primero que se sale de pantalla es justo el dinero —que es
   a lo que se entra a la mesa. Nombre a un lado, importe al otro, y las
   incidencias se recorren en medio. */

.col-num { text-align: right; font-variant-numeric: tabular-nums; }

.col-carril,
.col-total {
  position: sticky;
  z-index: 1;
  background: var(--bg-surface);
}

.col-carril {
  right: 116px;
  width: 108px;
  min-width: 108px;
  color: var(--text-secondary);
  box-shadow: -1px 0 0 var(--border-default);
}

.col-total {
  right: 0;
  width: 116px;
  min-width: 116px;
  font-weight: 700;
  color: var(--text-primary);
}

.mesa-tabla thead .col-carril,
.mesa-tabla thead .col-total { z-index: 3; }

.mesa-tabla tbody tr:hover .col-carril,
.mesa-tabla tbody tr:hover .col-total { background: var(--bg-hover); }

/* La fila con incidencias se marca por el borde, no por el fondo: teñirla
   entera competiría con el color que ya distingue descuento de percepción. */
.tiene-incidencias .col-fija {
  box-shadow: inset 3px 0 0 var(--state-warning), 1px 0 0 var(--border-default);
}

/* ----- Totales ----- */

.mesa-tabla tfoot td {
  position: sticky;
  bottom: 0;
  background: var(--surface-sunken);
  border-top: 2px solid var(--border-default);
  border-bottom: 0;
  font-weight: 700;
  color: var(--text-primary);
}

.mesa-tabla tfoot .col-fija,
.mesa-tabla tfoot .col-carril,
.mesa-tabla tfoot .col-total { background: var(--surface-sunken); z-index: 2; }

.mesa-nota {
  display: flex;
  align-items: baseline;
  gap: 7px;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  margin: var(--space-6) 0 0;
  line-height: 1.5;
}

@media (max-width: 991.98px) {
  .col-fija,
  .col-carril,
  .col-total { position: static; box-shadow: none; }
  .mesa-tabla-marco { max-height: none; }
}


/* =============================================================
   BASE DE EMPLEADOS

   El Excel del cliente vuelto pantalla. A diferencia de Recepción y
   la mesa, aquí NO se entra por período: no se trabaja una quincena,
   se mantiene un padrón. Guillermo lo pidió explícitamente como
   «una tabla con filtros por nombre, empresa, sucursales».

   Las dos decisiones que la gobiernan:

   1. **Se edita donde se lee.** Un clic sobre el nombre, la sucursal
      o el puesto los convierte en campo. Viene de una hoja de
      cálculo: obligar a abrir una ficha para cambiar un puesto sería
      pedirle a alguien que desaprenda cómo trabaja.

   2. **El sueldo real manda y los otros se apagan.** Los seis
      importes del Excel tienen un solo grado de libertad. El real es
      un botón; el fiscal y el resguardo se enseñan en gris porque
      son consecuencia, no captura.
   ============================================================= */

.padron { max-width: 100%; }

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

.padron-filtros {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: var(--space-5);
}

.padron-buscar {
  position: relative;
  flex: 1 1 260px;
  min-width: 220px;
}

.padron-buscar i {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-tertiary);
  font-size: var(--text-base);
  pointer-events: none;
}

.padron-buscar input {
  width: 100%;
  padding: 9px 13px 9px 34px;
  border-radius: 999px;
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  color: var(--text-primary);
  font-size: var(--text-base);
}

.padron-buscar input:focus,
.padron-filtros .form-select:focus {
  outline: 2px solid var(--accent-border);
  outline-offset: 1px;
}

.padron-filtros .form-select {
  width: auto;
  min-width: 165px;
  font-size: var(--text-sm);
  border-color: var(--border-default);
  background-color: var(--bg-surface);
  color: var(--text-primary);
}

.btn-filtrar,
.btn-limpiar {
  padding: 8px 16px;
  border-radius: 999px;
  font-size: var(--text-sm);
  font-weight: 600;
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  color: var(--text-secondary);
  text-decoration: none;
  cursor: pointer;
}

.btn-filtrar:hover,
.btn-limpiar:hover { background: var(--bg-hover); color: var(--text-primary); }

/* ----- Barra de conteo y acciones ----- */

.padron-barra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: var(--space-4);
}

.padron-cuenta {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.padron-cuenta strong { color: var(--text-primary); font-size: var(--text-md); }

.padron-acciones { display: flex; gap: 8px; flex-wrap: wrap; }

.btn-primario,
.btn-secundario,
.btn-peligro {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 16px;
  border-radius: 999px;
  font-size: var(--text-sm);
  font-weight: 600;
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
}

.btn-primario {
  background: var(--accent-solid);
  color: #fff;
}
.btn-primario:hover { filter: brightness(1.07); color: #fff; }

.btn-secundario {
  background: var(--bg-surface);
  border-color: var(--border-default);
  color: var(--text-secondary);
}
.btn-secundario:hover { background: var(--bg-hover); color: var(--text-primary); }

/* La baja es la acción destructiva de esta pantalla, y se ve como tal. */
.btn-peligro {
  background: var(--state-danger);
  color: #fff;
}
.btn-peligro:hover { filter: brightness(1.07); color: #fff; }

/* ----- La tabla ----- */

.padron-marco {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg, 12px);
  background: var(--bg-surface);
  overflow: auto;
  max-height: 70vh;
}

.padron-tabla {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--text-sm);
}

.padron-tabla th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--bg-surface);
  text-align: left;
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  padding: 11px 10px;
  border-bottom: 1px solid var(--border-default);
  white-space: nowrap;
}

.padron-tabla td {
  padding: 9px 10px;
  border-bottom: 1px solid var(--border-subtle, var(--border-default));
  color: var(--text-secondary);
  vertical-align: middle;
}

.padron-tabla tbody tr:hover td { background: var(--bg-hover); }

.col-n {
  width: 44px;
  text-align: right;
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}

/* El nombre acompaña al desplazarse: es lo que le da dueño a cada cifra. */
.padron-tabla .col-fija {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--bg-surface);
  min-width: 230px;
  box-shadow: 1px 0 0 var(--border-default);
}

.padron-tabla thead .col-fija { z-index: 3; }
.padron-tabla tbody tr:hover .col-fija { background: var(--bg-hover); }

.padron-nombre {
  display: block;
  font-weight: 600;
  color: var(--text-primary);
}

.padron-id,
.padron-tenue { color: var(--text-tertiary); }

.padron-id { display: block; font-size: var(--text-2xs); }

.padron-empresa {
  font-weight: 600;
  font-size: var(--text-xs);
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  white-space: nowrap;
}

/* ----- Lo editable -----
   Se insinúa, no se grita: un subrayado punteado que solo se afirma al pasar
   por encima. Marcar cada celda con un icono llenaría la tabla de ruido. */

.padron-nombre,
.padron-editable {
  cursor: text;
  border-bottom: 1px dashed transparent;
}

.padron-nombre:hover,
.padron-editable:hover,
.padron-nombre:focus-visible,
.padron-editable:focus-visible {
  border-bottom-color: var(--accent-border);
  outline: none;
}

.padron-campo {
  width: 100%;
  min-width: 140px;
  padding: 4px 7px;
  border-radius: 6px;
  border: 1px solid var(--accent-border);
  background: var(--bg-base);
  color: var(--text-primary);
  font-size: var(--text-sm);
  font-family: inherit;
}

/* ----- El dinero -----
   El real se toca; el fiscal y el resguardo se leen. */

.col-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

.col-real {
  border-left: 1px solid var(--border-default);
  border-right: 1px solid var(--border-default);
}

.padron-sueldo {
  display: block;
  width: 100%;
  padding: 2px 4px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: none;
  text-align: right;
  font: inherit;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--text-primary);
  cursor: pointer;
}

.padron-sueldo:hover,
.padron-sueldo:focus-visible {
  border-color: var(--accent-border);
  background: var(--accent-soft);
  outline: none;
}

.padron-sueldo-diario {
  display: block;
  font-size: var(--text-2xs);
  font-weight: 400;
  color: var(--text-tertiary);
}

/* ----- Bajas -----
   La fila se apaga en vez de desaparecer: sigue siendo consultable, y su
   estado se lee sin buscar la columna. */

.padron-tabla tr.es-baja td { opacity: .62; }
.padron-tabla tr.es-baja .padron-nombre { text-decoration: line-through; }

.chip-baja {
  display: inline-block;
  margin-top: 3px;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: var(--text-2xs);
  font-weight: 600;
  background: var(--state-danger-soft);
  color: var(--state-danger);
}

/* ----- Acciones por fila ----- */

.col-acciones { width: 84px; white-space: nowrap; text-align: right; }

.padron-inline { display: inline; }

.padron-accion {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  border: 1px solid transparent;
  background: none;
  color: var(--text-tertiary);
  cursor: pointer;
  text-decoration: none;
}

.padron-accion:hover {
  background: var(--bg-base);
  border-color: var(--border-default);
  color: var(--text-primary);
}

.padron-accion.es-baja-btn:hover {
  color: var(--state-danger);
  border-color: var(--state-danger-soft);
}

.padron-pista {
  display: flex;
  align-items: baseline;
  gap: 7px;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  margin: var(--space-5) 0 0;
  line-height: 1.5;
}

/* ----- Las hojas (dialog nativo) -----
   `<dialog>` en vez del modal de Bootstrap: trae el foco atrapado, el cierre
   con Escape y el fondo inerte sin JavaScript propio. Menos código y mejor
   comportamiento con lector de pantalla. */

.hoja {
  width: min(560px, calc(100vw - 32px));
  padding: 0;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg, 12px);
  background: var(--bg-surface);
  color: var(--text-primary);
}

.hoja::backdrop { background: rgba(15, 23, 42, .45); }

.hoja-cab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-default);
}

.hoja-cab h2 { margin: 0; font-size: var(--text-md); font-weight: 600; }

.hoja-cerrar {
  border: 0;
  background: none;
  color: var(--text-tertiary);
  cursor: pointer;
  font-size: var(--text-md);
  line-height: 1;
  padding: 4px;
}
.hoja-cerrar:hover { color: var(--text-primary); }

.hoja-cuerpo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px;
  padding: 20px;
}

.hoja-texto,
.campo--ancho,
.reparto { grid-column: 1 / -1; }

.hoja-texto { margin: 0; font-size: var(--text-base); }

.hoja-nota {
  display: block;
  margin-top: 5px;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  line-height: 1.5;
}

.campo { display: flex; flex-direction: column; gap: 5px; }

.campo > span {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--text-secondary);
}

.campo > span small { font-weight: 400; color: var(--text-tertiary); }

.campo input,
.campo select {
  padding: 9px 11px;
  border-radius: 8px;
  border: 1px solid var(--border-default);
  background: var(--bg-base);
  color: var(--text-primary);
  font-size: var(--text-base);
  font-family: inherit;
}

.campo input:focus,
.campo select:focus {
  outline: 2px solid var(--accent-border);
  outline-offset: 1px;
}

/* ----- El reparto del sueldo -----
   Aparece mientras se teclea. Es lo que convierte un número abstracto en una
   decisión: se ve a dónde va antes de guardarlo. */

.reparto {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  padding: 13px 15px;
  border-radius: 10px;
  background: var(--surface-sunken);
}

.reparto-parte { display: flex; flex-direction: column; gap: 1px; }

.reparto-etiqueta {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.reparto-parte strong {
  font-size: var(--text-md);
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}

.reparto-diario { font-size: var(--text-2xs); color: var(--text-tertiary); }

.reparto-aviso {
  grid-column: 1 / -1;
  margin: 0;
  font-size: var(--text-xs);
  line-height: 1.45;
  color: var(--state-warning-content);
}

.hoja-pie {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 14px 20px;
  border-top: 1px solid var(--border-default);
  background: var(--surface-sunken);
}

@media (max-width: 767.98px) {
  .padron-tabla .col-fija { position: static; box-shadow: none; }
  .padron-marco { max-height: none; }
  .padron-filtros .form-select,
  .btn-filtrar { flex: 1 1 auto; }
}


/* =============================================================
   MÁS

   Un índice, no un menú. Cada tarjeta dice PARA QUÉ sirve el módulo,
   no solo cómo se llama: quien llega aquí está buscando algo que no
   encontró en la barra, y un nombre suelto no lo resuelve.
   ============================================================= */

.mas-rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 14px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.mas-tarjeta {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  gap: 2px 14px;
  height: 100%;
  padding: 17px 19px;
  border-radius: var(--radius-lg, 12px);
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  text-decoration: none;
  transition: border-color .15s ease, background-color .15s ease;
}

.mas-tarjeta:hover {
  background: var(--bg-hover);
  border-color: var(--accent-border);
}

.mas-icono {
  grid-row: 1 / 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: var(--accent-soft);
  color: var(--accent-content);
  font-size: var(--text-md);
}

.mas-nombre {
  align-self: end;
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text-primary);
}

.mas-para-que {
  font-size: var(--text-xs);
  line-height: 1.45;
  color: var(--text-tertiary);
}


/* ----- Los que vienen en la hoja pero están de baja -----
   Ámbar, no rojo: no es un error del sistema, es una discrepancia entre dos
   fuentes que alguien tiene que resolver. Y se enumeran con nombre: «3
   personas de baja» sin decir quiénes no se puede revisar. */

.mesa-bajas {
  margin: 0 0 var(--space-6);
  padding: 14px 17px;
  border-radius: var(--radius-lg, 12px);
  border: 1px solid var(--state-warning-border);
  background: var(--state-warning-soft);
}

.mesa-bajas-titulo {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--state-warning-content);
}

.mesa-bajas-texto {
  margin: 3px 0 0;
  font-size: var(--text-xs);
  line-height: 1.5;
  color: var(--text-secondary);
}

.mesa-bajas-lista {
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.mesa-bajas-lista li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.mesa-bajas-lista strong { color: var(--text-primary); }

.mesa-bajas-lista span {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}


/* =============================================================
   MOVIMIENTOS DE PERSONAL

   Va lo PRIMERO dentro de un período. Que un correo haya llegado
   no es la pregunta —eso ya lo dice la lista de papeles—: la
   pregunta es si su contenido está en el padrón. Un alta recibida
   y no aplicada es una persona que no va a cobrar, y en la bandeja
   los dos casos se ven idénticos.

   El color va en el ESTADO, no en la fila: teñir el renglón entero
   por «pendiente» compite con la distinción alta/baja, que es la
   otra cosa que hay que leer de un vistazo.
   ============================================================= */

.movs {
  margin: 0 0 var(--space-6);
  padding: 16px 18px;
  border-radius: var(--radius-lg, 12px);
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
}

.movs-cab {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
}

.movs-titulo {
  margin: 0;
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text-primary);
}

.movs-marcadores { display: flex; gap: 6px; flex-wrap: wrap; }

.marcador {
  padding: 2px 10px;
  border-radius: 999px;
  font-size: var(--text-xs);
  font-weight: 600;
}

.marcador--pendiente {
  background: var(--state-warning-soft);
  color: var(--state-warning-content);
}
.marcador--revisar {
  background: var(--state-info-soft);
  color: var(--state-info);
}
.marcador--aplicada {
  background: var(--state-success-soft);
  color: var(--state-success);
}

.movs-pie {
  margin: 6px 0 12px;
  font-size: var(--text-xs);
  line-height: 1.5;
  color: var(--text-tertiary);
}

.movs-pie--ok { color: var(--state-success); }

.movs-lista {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
}

.mov {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 10px;
  padding: 8px 0;
  border-top: 1px solid var(--border-subtle, var(--border-default));
  font-size: var(--text-sm);
}

.mov:first-child { border-top: 0; }

/* Alta y baja se distinguen por la etiqueta, que es lo primero que se lee. */
.mov-tipo {
  flex: 0 0 46px;
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.mov-tipo--alta { color: var(--state-success); }
.mov-tipo--baja { color: var(--state-danger); }

.mov-nombre { font-weight: 600; color: var(--text-primary); }

.mov-datos {
  flex: 1 1 200px;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}

.mov-estado {
  flex: 0 0 auto;
  padding: 1px 9px;
  border-radius: 999px;
  font-size: var(--text-2xs);
  font-weight: 600;
  white-space: nowrap;
}

.mov-estado--pendiente {
  background: var(--state-warning-soft);
  color: var(--state-warning-content);
}
.mov-estado--revisar {
  background: var(--state-info-soft);
  color: var(--state-info);
}
.mov-estado--aplicada {
  background: transparent;
  color: var(--text-tertiary);
  font-weight: 400;
}

/* Lo ya aplicado se apaga: está para poder comprobarlo, no para llamar la
   atención. Lo que falta es lo que tiene que saltar. */
.mov--aplicada .mov-nombre { font-weight: 400; color: var(--text-secondary); }

.movs-ilegibles {
  margin: 12px 0 0;
  font-size: var(--text-xs);
  line-height: 1.5;
  color: var(--state-danger);
}


/* ----- Movimientos por aplicar (en la Base de empleados) -----
   Encabeza la pantalla porque es trabajo pendiente, no información. Ámbar y no
   rojo: nada está roto, hay algo que hacer. */

.pendientes {
  margin: 0 0 var(--space-5);
  padding: 15px 18px;
  border-radius: var(--radius-lg, 12px);
  border: 1px solid var(--state-warning-border);
  background: var(--state-warning-soft);
}

.pendientes-titulo {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--state-warning-content);
}

.pendientes-pie {
  margin: 3px 0 10px;
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

.pendientes-lista {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.pendiente {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--bg-surface);
  font-size: var(--text-sm);
}

.pendiente-nombre { font-weight: 600; color: var(--text-primary); }

.pendiente-datos {
  flex: 1 1 180px;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}

/* El botón dice el VERBO, no «aplicar»: quien lo pulsa tiene que saber qué va
   a pasar antes de pulsarlo, y «dar de baja» y «dar de alta» no se confunden. */
.btn-aplicar {
  flex: 0 0 auto;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid var(--accent-border);
  background: var(--bg-surface);
  color: var(--accent-content);
  font-size: var(--text-xs);
  font-weight: 600;
  cursor: pointer;
}

.btn-aplicar:hover {
  background: var(--accent-solid);
  border-color: var(--accent-solid);
  color: #fff;
}


/* ----- Historial de movimientos -----
   Una línea por cambio, agrupadas por período. Lo que se busca aquí es una
   explicación —«¿por qué no está esta persona?»— así que la fila entera se lee
   como una frase: cuándo, quién, qué pasó, y quién lo hizo. */

.hist-periodo {
  margin: 0 0 var(--space-6);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg, 12px);
  background: var(--bg-surface);
  overflow: hidden;
}

.hist-cab {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  padding: 13px 17px;
  border-bottom: 1px solid var(--border-default);
  background: var(--surface-sunken);
}

.hist-clave {
  margin: 0;
  font-size: var(--text-md);
  font-weight: 700;
  color: var(--text-primary);
}

.hist-marcadores { display: flex; gap: 6px; flex-wrap: wrap; }

.marcador--alta { background: var(--state-success-soft); color: var(--state-success); }
.marcador--baja { background: var(--state-danger-soft); color: var(--state-danger); }
.marcador--sueldo { background: var(--accent-soft); color: var(--accent-content); }

.hist-lista { margin: 0; padding: 0; list-style: none; }

.hist-fila {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 12px;
  padding: 9px 17px;
  border-top: 1px solid var(--border-subtle, var(--border-default));
  font-size: var(--text-sm);
}

.hist-fila:first-child { border-top: 0; }

.hist-cuando {
  flex: 0 0 110px;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}

.hist-quien { flex: 0 0 230px; }
.hist-quien a { font-weight: 600; color: var(--text-primary); text-decoration: none; }
.hist-quien a:hover { text-decoration: underline; }

.hist-donde {
  display: block;
  font-size: var(--text-2xs);
  color: var(--text-tertiary);
}

.hist-que { flex: 1 1 240px; color: var(--text-secondary); }

.hist-alta { color: var(--state-success); }
.hist-baja { color: var(--state-danger); }

/* El valor anterior va tachado, no en rojo: el par rojo/verde es el que no
   distingue quien tiene daltonismo, y aquí la diferencia es lo único que
   importa. */
.hist-antes { color: var(--text-tertiary); }
.hist-despues { font-weight: 600; color: var(--text-primary); }

.hist-por {
  flex: 0 0 auto;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}

.hist-tope {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  text-align: center;
}


/* ----- La mesa editable -----
   La tabla viene de una hoja de cálculo, así que se edita donde se lee. Lo
   editable se insinúa con un subrayado punteado que solo se afirma al pasar
   por encima: marcar catorce columnas con un icono llenaría la pantalla de
   ruido justo donde hace falta leer números. */

.col-editable { cursor: cell; }

.col-editable:hover,
.col-editable:focus-visible {
  outline: none;
  box-shadow: inset 0 -2px 0 var(--accent-border);
  background: var(--accent-soft);
}

.mesa-campo {
  width: 100%;
  min-width: 52px;
  padding: 2px 4px;
  border: 1px solid var(--accent-solid);
  border-radius: 4px;
  background: var(--bg-base);
  color: var(--text-primary);
  font: inherit;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.mesa-campo[type="checkbox"] { width: auto; min-width: 0; }

/* Mientras el servidor recalcula. Sin esto, un clic seguido de otro sobre la
   misma celda parece que no hizo nada. */
.col-editable.esta-guardando { opacity: .45; }

/* La fila que acaba de cambiar se enciende un instante: es la confirmación de
   que el total de la derecha se movió por lo que se acaba de teclear. */
.mesa-tabla tbody tr.recien-cambiada td {
  background: var(--state-success-soft);
  transition: background-color .9s ease-out;
}

/* El motivo del rechazo va PEGADO a la celda, no en una alerta que tapa la
   tabla: «los días se capturan en números enteros» solo se entiende viendo
   dónde se tecleó. */
.mesa-aviso {
  position: absolute;
  z-index: 5;
  margin-top: 22px;
  margin-left: -120px;
  width: 190px;
  padding: 7px 10px;
  border-radius: 8px;
  background: var(--state-danger);
  color: #fff;
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.35;
  text-align: left;
  white-space: normal;
  box-shadow: 0 4px 12px rgba(15, 23, 42, .25);
}

/* ⚠️ El globo de aviso necesita un ancla posicionada, pero `position: relative`
   sobre TODAS las celdas pisa el `sticky` de las columnas fijas —nombre a la
   izquierda, percepción y total a la derecha— y el dinero desaparecía debajo de
   las incidencias. Lo enseñó el render, no el código.

   Solo lo necesitan las celdas editables, que no son sticky. */
.col-editable { position: relative; }

/* El subtítulo del encabezado: «antes de descuentos» / «ya con descuentos».
   Guillermo pidió que la columna diga qué es para no confundir al operador. */
.col-pie {
  display: block;
  font-size: var(--text-2xs);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-tertiary);
}


/* El cambio que pide un movimiento: «de esto a esto». Es lo único que hay que
   leer para aprobarlo, así que va en lugar de los datos generales. */
.mov-tipo--movimiento { color: var(--state-info); }

.mov-cambio {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  margin-right: 12px;
  font-size: var(--text-xs);
}

.mov-cambio-que {
  font-weight: 600;
  color: var(--text-secondary);
}

/* El valor anterior tachado, no en rojo: el par rojo/verde es el que no
   distingue quien tiene daltonismo, y aquí la diferencia es todo. */
.mov-cambio s { color: var(--text-tertiary); }
.mov-cambio strong { color: var(--text-primary); }


/* =============================================================
   LAS EMPRESAS DE UN PERÍODO

   La única decisión de esta pantalla es en cuál se entra, así que
   las tarjetas son grandes y van centradas. Guillermo: «solo que
   aparezcan las empresas… que venga cuántos empleados tiene…
   necesito que esté más grande, centrado».

   El carril se elige DENTRO. Ofrecerlo aquí obligaba a decidir dos
   cosas a la vez para dar un paso.
   ============================================================= */

.mesa-empresas { max-width: 1100px; margin: 0 auto; }

.mesa-empresas-cuenta {
  margin: 0 0 var(--space-6);
  text-align: center;
  font-size: var(--text-base);
  color: var(--text-secondary);
}

/* =============================================================
   RESUMEN GLOBAL DE LAS CUATRO EMPRESAS

   Guillermo, 6-sep-2026: «aquí estaría bien implementar gráficas
   o resúmenes de las 4 empresas en global».

   Jerarquía deliberada: **lo que se paga va arriba y solo**, es la
   cifra por la que existe esta pantalla. Las otras tres tejas la
   explican —cuánto se descontó, quién entró y salió, a quién le
   cambió el sueldo— y por eso son más pequeñas. Cuatro cifras del
   mismo tamaño no serían un resumen, serían cuatro datos.
   ============================================================= */

.resumen-mesa {
  margin-bottom: var(--space-9);
  padding-bottom: var(--space-8);
  border-bottom: 1px solid var(--border-subtle);
  text-align: center;
}

.resumen-mesa-ante {
  margin: 0 0 var(--space-2);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.resumen-mesa-cifra {
  margin: 0;
  font-size: var(--text-3xl);
  font-weight: var(--weight-bold);
  line-height: var(--leading-tight);
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}

.resumen-mesa-tejas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-5);
  margin-top: var(--space-7);
  text-align: left;
}

.teja {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-6) var(--space-7);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
}

.teja-valor {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}

/* Dos cifras en una teja —altas y bajas, subieron y bajaron— llevan
   su palabra en la etiqueta, así que el color refuerza pero no es lo
   único que las distingue. */
.teja-valor--exito   { color: var(--state-success-content); }
.teja-valor--peligro { color: var(--state-danger-content); }
.teja-barra          { color: var(--border-strong); font-weight: var(--weight-normal); }

.teja-etiqueta {
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

/* El pie es lo que evita que la cifra se lea mal: dice contra qué se
   compara, o por qué no hay comparación. */
.teja-pie {
  font-size: var(--text-2xs);
  color: var(--text-tertiary);
  line-height: var(--leading-snug);
}

/* ── El reparto por empresa ───────────────────────────────────────────────
   Es tabla y gráfico a la vez: cada barra lleva su cifra escrita
   al lado, así que no hace falta pasar el ratón ni interpretar una
   longitud, y un lector de pantalla la recorre como lo que es. */
.mesa-reparto {
  width: 100%;
  margin-top: var(--space-8);
  border-collapse: collapse;
  text-align: left;
}

.mesa-reparto-titulo {
  caption-side: top;
  padding-bottom: var(--space-5);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  text-align: left;
}

/* 🔴 Las separaciones se declaran DENTRO del mismo alcance `.mesa-reparto td/th`.
   Escritas como `.mesa-reparto-nombre { padding-right }` perdían por especificidad
   contra `.mesa-reparto th { padding: … 0 }` —(0,1,1) gana a (0,1,0)— y el nombre
   de la empresa salía pegado a su barra. */
.mesa-reparto td,
.mesa-reparto th { padding: var(--space-3) 0; vertical-align: middle; }

.mesa-reparto-cab th {
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  color: var(--text-tertiary);
  border-bottom: 1px solid var(--border-subtle);
  padding-bottom: var(--space-4);
}

.mesa-reparto-cab th:nth-child(3),
.mesa-reparto-cab th:nth-child(4) { text-align: right; }

.mesa-reparto .mesa-reparto-nombre {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--text-primary);
  white-space: nowrap;
  padding-right: var(--space-7);
}

/* La celda de la barra se come el ancho sobrante: los nombres y las cifras
   miden lo suyo y la proporción usa todo lo que queda. */
.mesa-reparto .mesa-reparto-celda { width: 100%; min-width: 80px; }
.mesa-reparto-pista               { height: 10px; }

.mesa-reparto .mesa-reparto-importe {
  font-size: var(--text-sm);
  color: var(--text-primary);
  text-align: right;
  white-space: nowrap;
  padding-left: var(--space-9);
}

.mesa-reparto .mesa-reparto-pct {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  text-align: right;
  white-space: nowrap;
  padding-left: var(--space-7);
  min-width: 3.5rem;
}

.empresas-rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px;
  /* Cada tarjeta mide lo suyo. Estiradas a la altura de la más alta, las que no
     tienen aviso de bajas quedaban con un tercio de blanco. */
  align-items: start;
}

.empresa-tarjeta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 28px 22px 24px;
  border-radius: var(--radius-lg, 12px);
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  text-align: center;
  text-decoration: none;
  transition: border-color .15s ease, transform .15s ease;
}

.empresa-tarjeta:hover {
  border-color: var(--accent-border);
  transform: translateY(-2px);
}

.empresa-tarjeta-nombre {
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

/* La cifra es el número de personas, no un importe: es lo que Guillermo pidió
   ver de un vistazo, y lo que dice el tamaño de cada nómina. */
.empresa-tarjeta-cifra {
  font-size: var(--text-3xl);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -.03em;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.empresa-tarjeta-pie {
  font-size: var(--text-sm);
  color: var(--text-tertiary);
}

.empresa-tarjeta-datos {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  margin-top: 12px;
}

.dato {
  padding: 2px 10px;
  border-radius: 999px;
  background: var(--surface-sunken);
  font-size: var(--text-2xs);
  color: var(--text-secondary);
}

.dato--incidencias {
  background: var(--state-warning-soft);
  color: var(--state-warning-content);
}

/* El aviso de bajas vive DENTRO de su empresa: una discrepancia de CALENDRE no
   le dice nada a quien está mirando ARGAB. */
.empresa-tarjeta-baja {
  margin-top: 14px;
  padding: 9px 12px;
  border-radius: 8px;
  background: var(--state-warning-soft);
  font-size: var(--text-xs);
  line-height: 1.4;
  color: var(--state-warning-content);
}

.empresa-tarjeta-baja-quien {
  display: block;
  margin-top: 3px;
  font-weight: 600;
  color: var(--text-secondary);
}

.empresa-tarjeta-revisada {
  margin-top: 12px;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--state-success);
}

/* ----- Filtros de la tabla -----
   Filtran en el navegador: se está trabajando la tabla, y recargar a cada
   filtro perdería la posición y rompería el ritmo de captura. */

.mesa-filtros {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0 0 var(--space-5);
}

.mesa-buscar { position: relative; flex: 1 1 240px; min-width: 200px; }

.mesa-buscar i {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-tertiary);
  font-size: var(--text-base);
  pointer-events: none;
}

.mesa-buscar input {
  width: 100%;
  padding: 8px 13px 8px 34px;
  border-radius: 999px;
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  color: var(--text-primary);
  font-size: var(--text-sm);
}

.mesa-filtros .form-select {
  width: auto;
  min-width: 160px;
  font-size: var(--text-sm);
  border-color: var(--border-default);
  background-color: var(--bg-surface);
  color: var(--text-primary);
}

.conmutador {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 14px;
  border-radius: 999px;
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  font-size: var(--text-sm);
  color: var(--text-secondary);
  cursor: pointer;
}

.conmutador:has(input:checked) {
  border-color: var(--state-warning-border);
  background: var(--state-warning-soft);
  color: var(--state-warning-content);
  font-weight: 600;
}

.mesa-cuantos {
  margin-left: auto;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-secondary);
}

/* ----- Cerrar la revisión ----- */

.mesa-cierre {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: var(--space-6);
}

.mesa-cierre .mesa-nota { flex: 1 1 320px; margin: 0; }

.mesa-revisada {
  margin: 0 0 6px;
  font-size: var(--text-sm);
  color: var(--state-success);
}


/* Quien está a UN retardo de perder un día. Es la única razón de que la columna
   de retardos exista: por sí sola no descuenta nada, pero al tercero sí.
   Medido en P17: 57 personas traen retardos y 46 no pierden ningún día. */
.col-inc.es-a-punto {
  color: var(--state-warning-content);
  box-shadow: inset 0 0 0 1px var(--state-warning-border);
  border-radius: 4px;
}


/* Una columna que se calcula sola. Se ve, pero no invita a teclear: el cursor
   no cambia y no toma el foco. Pedir el conteo Y la falta que produce es pedir
   un dato de más, y deja capturarlos incongruentes. */
.col-derivada {
  cursor: default;
  font-style: italic;
  opacity: .8;
}


/* ----- Los tres sueldos -----
   Guillermo, 3-sep: «que sea una sola tabla, con la diferencia que percepción y
   total a pagar sea Sueldo Real, Sueldo Fiscal, Sueldo Resguardo».

   El real va primero y en negro: es lo que la persona recibe. Los otros dos lo
   explican, y por eso van más apagados y con el color de su carril — el mismo
   verde y azul que el resto del sistema usa para distinguirlos. */

.col-sueldo {
  position: sticky;
  z-index: 1;
  background: var(--bg-surface);
  white-space: nowrap;
}

/* Los anchos son fijos y los `right` se apilan a partir de ellos: con `sticky`
   no hay forma de que el navegador los deduzca. Y son holgados a propósito —el
   primer render cortó «Sueldo fiscal» y comió los centavos de la cifra. */
.col-sueldo--real {
  right: 244px;
  width: 124px;
  min-width: 124px;
  font-weight: 700;
  color: var(--text-primary);
  box-shadow: -1px 0 0 var(--border-default);
}

.col-sueldo--fiscal {
  right: 122px;
  width: 122px;
  min-width: 122px;
  color: var(--state-success);
}

.col-sueldo--resguardo {
  right: 0;
  width: 122px;
  min-width: 122px;
  color: var(--state-info);
}

.mesa-tabla thead .col-sueldo { z-index: 3; }
.mesa-tabla tbody tr:hover .col-sueldo { background: var(--bg-hover); }
.mesa-tabla tfoot .col-sueldo { background: var(--surface-sunken); z-index: 2; }

/* ----- A qué sueldo pega cada incidencia -----
   La respuesta a «cómo lo plasmamos sin tener celdas duplicadas»: una sola
   celda, y el ámbito escrito bajo el título. */

.col-ambito {
  display: block;
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: .02em;
  text-transform: uppercase;
}

.col-ambito--fiscal .col-ambito    { color: var(--state-success); }
.col-ambito--resguardo .col-ambito { color: var(--state-info); }

/* Una franja del color de su carril bajo el título: se ve el bloque de
   columnas que solo afectan a uno sin leer cada una. */
.col-ambito--fiscal    { border-bottom: 2px solid var(--state-success-soft); }
.col-ambito--resguardo { border-bottom: 2px solid var(--state-info-soft); }

@media (max-width: 991.98px) {
  .col-sueldo { position: static; box-shadow: none; }
}


/* La regla que no es obvia: la incapacidad descuenta del fiscal y el resguardo
   se sigue pagando. Va escrita bajo la tabla porque un título de columna no da
   para explicarla, y equivocarse ahí subpaga a alguien. */
.mesa-nota--regla {
  flex: 1 1 100%;
  padding: 9px 13px;
  border-radius: 8px;
  background: var(--surface-sunken);
  color: var(--text-secondary);
}


/* Infonavit y pensión en el padrón: son retenciones del sueldo FISCAL, que
   lleva CONTPAQ, y aquí la pregunta es **si la persona tiene**, no cuánto.

   Un importe obliga a leer quince cifras para contestar «¿quién tiene
   crédito?»; una marca se cuenta de un vistazo. El importe no se pierde: va en
   el título emergente. */
.col-marca {
  border-left: 1px solid var(--border-subtle, var(--border-default));
  text-align: center;
  white-space: nowrap;
}

/* Una palomita. Es la respuesta entera a «¿tiene crédito?», y se lee sin
   detenerse: una columna de importes obliga a comparar quince cifras para
   contestar lo mismo. */
.marca-si {
  color: var(--state-success);
  font-size: var(--text-md);
  line-height: 1;
}

.marca-si--pension { color: var(--state-warning-content); }

.padron-marca { cursor: pointer; }

.padron-marca:hover,
.padron-marca:focus-visible {
  background: var(--bg-hover);
  outline: none;
  box-shadow: inset 0 -2px 0 var(--accent-border);
}

.marca-no { color: var(--text-tertiary); }

/* ============================================================================
   BANDEJA DE EXCEPCIONES — el razonamiento (4-sep-2026)

   La pantalla dejó de ser una tabla de siete columnas porque el razonamiento
   no cabía en la celda del detalle. Cada excepción es una tarjeta que contesta
   cuatro cosas: qué se decide, qué está pasando hoy, cuánto vale y quién
   contesta. Ver el comentario de `templates/excepciones/index.html`.

   Todo con tokens: la escala tipográfica y la paleta ya existían, y el
   problema nunca fue que faltara sistema sino no seguirlo.
   ========================================================================= */

/* ── Quién tiene la palabra ─────────────────────────────────────────────── */

.espera {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-5) var(--space-6);
  margin-bottom: var(--space-6);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
}

.espera-titulo { color: var(--content-tertiary); }

.espera-lista {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
  flex: 1 1 auto;
}

.espera-dueno {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
}

.espera-num {
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
  color: var(--content-primary);
  line-height: 1;
}

.espera-quien {
  font-size: var(--text-sm);
  color: var(--content-secondary);
}

/* «Nadie» no es un pendiente: son avisos de una regla que ya no existe. Se
   apaga para que no compita con lo que sí espera a una persona. */
.espera-dueno.is-nadie .espera-num,
.espera-dueno.is-nadie .espera-quien { color: var(--content-tertiary); }

.espera-dinero {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding-left: var(--space-6);
  border-left: 1px solid var(--border-subtle);
}

.espera-dinero .amount {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
}

/* ── La tarjeta de razonamiento ─────────────────────────────────────────── */

.razones {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

.razon {
  padding: var(--space-6) var(--space-7);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  /* Misma convención que `.cal-period-card` y `.record-card`: el estado se
     lleva en el borde izquierdo —no en el fondo, que detrás de un párrafo
     largo le baja el contraste al texto— y **arranca neutro**.
     🔑 El color marca la excepción a la norma, no la norma. Pintar de rojo
     «abierta» dejaba las cuarenta tarjetas iguales en la vista por defecto,
     y un indicador que vale lo mismo en todas las filas no informa: grita. */
  border-left: 3px solid var(--border-default);
}

/* Esto sí es la excepción, y es lo que hay que priorizar: la misma excepción
   abierta en dos quincenas no es un caso raro, es un movimiento real que
   nadie aplicó. */
.razon.is-repetida { border-left-color: var(--state-danger); }

.razon.is-resuelta {
  border-left-color: var(--state-success);
  background: var(--surface-sunken);
}

/* Un aviso muerto frena el cierre, pero no hay nada que investigar en él. */
.razon.is-muerta {
  border-left-color: var(--border-strong);
  opacity: .8;
}

.razon-cabeza {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-6);
  flex-wrap: wrap;
}

.razon-titular { flex: 1 1 320px; min-width: 0; }

.razon-pregunta {
  margin: 0;
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  line-height: 1.35;
  color: var(--content-primary);
}

.razon-quien {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-3);
}

.razon-nombre {
  font-size: var(--text-sm);
  color: var(--content-secondary);
}

.razon-dueno {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  text-align: right;
  padding: var(--space-3) var(--space-5);
  background: var(--state-info-soft);
  border: 1px solid var(--state-info-border);
  border-radius: var(--radius-md);
  color: var(--state-info-content);
}

.razon-dueno .t-overline { opacity: .8; }
.razon-dueno strong { font-size: var(--text-sm); }

.razon-dueno.is-nadie {
  background: var(--surface-sunken);
  border-color: var(--border-subtle);
  color: var(--content-tertiary);
}

/* ── Lo medido ──────────────────────────────────────────────────────────── */

.razon-hechos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--space-5);
  margin: var(--space-6) 0 0;
  padding: var(--space-5) 0;
  border-top: 1px solid var(--border-subtle);
  border-bottom: 1px solid var(--border-subtle);
}

.razon-hechos dt {
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--content-tertiary);
  margin-bottom: var(--space-2);
}

.razon-hechos dd {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--content-primary);
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-3);
}

/* ── Qué está pasando ahora mismo ───────────────────────────────────────── */

.razon-hoy { margin-top: var(--space-6); }
.razon-hoy .t-overline { color: var(--content-tertiary); }

.razon-hoy p {
  margin: var(--space-2) 0 0;
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--content-primary);
  max-width: 78ch;
}

.razon-nota {
  margin: var(--space-5) 0 0;
  padding-left: var(--space-5);
  border-left: 2px solid var(--border-default);
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--content-secondary);
  max-width: 78ch;
}

/* ── La evidencia, plegada ──────────────────────────────────────────────── */

.razon-evidencia { margin-top: var(--space-5); }

.razon-evidencia summary {
  cursor: pointer;
  font-size: var(--text-xs);
  color: var(--content-tertiary);
  width: max-content;
}

.razon-evidencia summary:hover { color: var(--content-secondary); }

.razon-detalle {
  margin: var(--space-4) 0 var(--space-3);
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--content-secondary);
  max-width: 78ch;
}

.razon-origen { margin: 0; }

/* ── Las opciones ───────────────────────────────────────────────────────── */

.razon-form {
  margin-top: var(--space-6);
  padding-top: var(--space-6);
  border-top: 1px solid var(--border-subtle);
}

.razon-opciones {
  border: 0;
  margin: 0 0 var(--space-6);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.razon-opciones legend {
  float: none;
  width: auto;
  margin-bottom: var(--space-4);
  padding: 0;
  color: var(--content-tertiary);
}

.opcion {
  display: flex;
  align-items: flex-start;
  gap: var(--space-5);
  padding: var(--space-5);
  background: var(--surface-base);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: border-color .12s ease, background .12s ease;
}

.opcion:hover { border-color: var(--border-default); background: var(--surface-hover); }

.opcion:focus-within {
  border-color: var(--accent-border);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.opcion input[type="radio"] { margin-top: 3px; flex: 0 0 auto; }

.opcion-cuerpo { display: flex; flex-direction: column; gap: var(--space-2); }

.opcion-dice {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--content-primary);
}

/* La consecuencia es la mitad que faltaba: sin ella se elige la opción que
   suena menos grave, que no es lo mismo que la correcta. */
.opcion-consecuencia {
  font-size: var(--text-xs);
  line-height: 1.55;
  color: var(--content-secondary);
  max-width: 74ch;
}

.razon-expediente,
.razon-justificacion { margin-bottom: var(--space-5); max-width: 640px; }

.razon-expediente label,
.razon-justificacion label {
  display: block;
  margin-bottom: var(--space-2);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--content-primary);
}

.razon-acciones {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-6);
  flex-wrap: wrap;
  padding-top: var(--space-4);
}

/* Por qué le toca a ese dueño. Es la explicación del dato más accionable de la
   tarjeta, así que se lee: en `tertiary` quedaba por debajo del umbral de
   contraste sobre la superficie elevada, sobre todo en tema oscuro. */
.razon-acciones span {
  max-width: 62ch;
  color: var(--content-secondary);
  line-height: 1.5;
}

/* ── Cómo se resolvió ───────────────────────────────────────────────────── */

.razon-cerrada {
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border-subtle);
}

.razon-cerrada-quien {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.razon-cerrada-motivo {
  margin: var(--space-4) 0 0;
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--content-secondary);
  max-width: 78ch;
}

@media (max-width: 640px) {
  .razon { padding: var(--space-5); }
  .razon-dueno { text-align: left; }
  .espera-dinero { padding-left: 0; border-left: 0; }
}

/* ==========================================================================
   EXPEDIENTES Y ENTREGABLES — fases 4 y 5
   ==========================================================================

   Las dos pantallas abren con una cifra sola y grande: en Expedientes es
   «cuánto se debe todavía» y en Entregables «cuánto se va a dispersar». Es el
   mismo patrón del resumen de la mesa, y por eso comparten reglas: dos cajas
   que se ven distinto para decir lo mismo se leen como dos sistemas.

   Todo el color sale de tokens semánticos. Nada de hex aquí: un color escrito
   a mano es el que el tema oscuro no alcanza. */

.expediente-resumen,
.entregable-resumen {
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  margin-bottom: var(--space-8);
}

.expediente-resumen-ante,
.entregable-resumen-ante {
  margin: 0;
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--content-tertiary);
}

.expediente-resumen-cifra,
.entregable-resumen-cifra {
  margin: var(--space-3) 0 var(--space-2);
  font-size: var(--text-3xl);
  font-weight: var(--weight-bold);
  line-height: var(--leading-tight);
  color: var(--content-primary);
  /* Cifras tabulares: sin esto los importes bailan al cambiar de pantalla. */
  font-variant-numeric: tabular-nums;
}

.expediente-resumen-pie,
.entregable-resumen-pie {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--content-secondary);
}

/* Las partes que explican la cifra de arriba. Van más pequeñas a propósito:
   son el desglose, no el titular. */
.expediente-resumen-partes {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-9);
  margin: var(--space-7) 0 0;
  padding-top: var(--space-6);
  border-top: 1px solid var(--border-subtle);
}

.expediente-resumen-partes dt {
  margin: 0 0 var(--space-2);
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--content-tertiary);
}

.expediente-resumen-partes dd {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--content-primary);
  font-variant-numeric: tabular-nums;
}

/* La nota que aclara qué NO hace la pantalla. Informativa, no una alarma. */
.expediente-nota,
.entregable-nota {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  margin: 0 0 var(--space-7);
  padding: var(--space-5) var(--space-6);
  background: var(--state-info-soft);
  border: 1px solid var(--state-info-border);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  color: var(--state-info-content);
}

.expediente-filtros {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.expediente-filtro {
  padding: var(--space-3) var(--space-6);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  background: var(--surface-raised);
  color: var(--content-secondary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  text-decoration: none;
  transition: background var(--duration-fast) var(--ease),
              border-color var(--duration-fast) var(--ease);
}

.expediente-filtro:hover {
  background: var(--surface-hover);
  color: var(--content-primary);
}

/* El filtro activo se distingue por fondo Y por borde, no solo por color:
   quien no distingue tonos tiene que poder ver cuál está puesto. */
.expediente-filtro.is-activo {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-content);
  font-weight: var(--weight-semibold);
}

.expediente-debe {
  color: var(--state-danger-content);
  font-variant-numeric: tabular-nums;
}

/* «Liquidado» lleva palomita además del color: el color solo no puede ser el
   portador del significado. */
.expediente-saldado {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  color: var(--state-success-content);
}

.entregable-acciones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-top: var(--space-7);
  padding-top: var(--space-6);
  border-top: 1px solid var(--border-subtle);
}

/* Una cuenta bancaria se lee dígito a dígito y se compara contra otra: va en
   monoespaciada o los grupos no se alinean. */
.entregable-cuenta {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  letter-spacing: 0.01em;
  color: var(--content-primary);
}

.entregable-pendientes {
  margin-top: var(--space-10);
}

.entregable-pendientes-titulo {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin: 0 0 var(--space-5);
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  color: var(--content-secondary);
}

.btn-secundario--sm {
  padding: var(--space-2) var(--space-5);
  font-size: var(--text-xs);
}

@media (max-width: 768px) {
  .expediente-resumen,
  .entregable-resumen { padding: var(--space-6); }

  .expediente-resumen-cifra,
  .entregable-resumen-cifra { font-size: var(--text-2xl); }

  .expediente-resumen-partes { gap: var(--space-7); }
}

/* ==========================================================================
   PAGOS POR FUERA DE LA NÓMINA — en la mesa de cálculo
   ==========================================================================

   Gente que cobra en la dispersión y no está en el padrón. Va en la mesa
   porque contesta la pregunta de esa pantalla —cuánto se paga esta quincena—
   y porque es ahí donde se aprueba el período. */

/* El global vive debajo de la cifra de nómina y más pequeño: es la suma, no
   el protagonista. Aparece solo cuando hay algo por fuera. */
.resumen-mesa-global {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  margin: var(--space-3) 0 0;
  font-size: var(--text-md);
  color: var(--content-secondary);
}

.resumen-mesa-global-etiqueta {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--content-tertiary);
}

.resumen-mesa-global strong {
  color: var(--content-primary);
  font-variant-numeric: tabular-nums;
}

.por-fuera {
  margin: var(--space-10) 0;
  padding: var(--space-8);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
}

.por-fuera-encabezado {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-6);
  margin-bottom: var(--space-7);
}

.por-fuera-titulo {
  margin: 0 0 var(--space-2);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--content-primary);
}

.por-fuera-ayuda {
  margin: 0;
  max-width: 62ch;          /* la medida legible; más ancho cansa */
  font-size: var(--text-sm);
  color: var(--content-secondary);
}

.por-fuera-suma {
  margin: 0;
  text-align: right;
}

.por-fuera-suma-etiqueta {
  display: block;
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--content-tertiary);
}

.por-fuera-suma strong {
  font-size: var(--text-xl);
  color: var(--content-primary);
  font-variant-numeric: tabular-nums;
}

.por-fuera-nadie {
  margin: 0;
  padding: var(--space-7);
  text-align: center;
  font-size: var(--text-sm);
  color: var(--content-tertiary);
  background: var(--surface-sunken);
  border-radius: var(--radius-md);
}

/* El alta va plegada: la mayoría de las veces se entra a esta pantalla a ver,
   no a capturar. Se despliega cuando hace falta. */
.por-fuera-alta {
  margin-top: var(--space-7);
  border-top: 1px solid var(--border-subtle);
  padding-top: var(--space-6);
}

.por-fuera-alta > summary {
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--accent-content);
}

.por-fuera-alta > summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius-xs);
}

.por-fuera-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-6);
  margin-top: var(--space-6);
}

.por-fuera-form .campo--ancho { grid-column: 1 / -1; }

.por-fuera-acciones {
  grid-column: 1 / -1;
  display: flex;
  gap: var(--space-4);
}

.por-fuera-copiar {
  margin-top: var(--space-6);
}

@media (max-width: 768px) {
  .por-fuera { padding: var(--space-6); }
  .por-fuera-suma { text-align: left; }
  .por-fuera-form { grid-template-columns: 1fr; }
}


/* El adeudo de hologramas que se arrastra de quincenas anteriores.
   Va bajo el nombre y no en la columna del importe: esa celda es editable y
   lo que se enseña aquí NO se captura — sale del expediente. */
.mesa-adeudo {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--text-2xs);
  line-height: var(--leading-snug);
  color: var(--state-warning-content);
  font-variant-numeric: tabular-nums;
}

.mesa-adeudo i {
  opacity: 0.7;
}


/* ═══════════════════════════════════════════════════════════════════════════
   PRIMAS VACACIONALES — la cola de aprobación de un período
   ═══════════════════════════════════════════════════════════════════════════

   Todo con prefijo `primas-`. Una clase genérica aquí colisionaría en silencio
   con otra pantalla: ya pasó con `.detalle` y con `.opcion`, y el síntoma es
   que se rompe la pantalla ajena, no esta.

   Ni un color literal: los tokens de estado ya resuelven claro y oscuro, y un
   `#hex` escrito aquí es exactamente el color que el tema no alcanza. */

.primas-seccion {
  margin: var(--space-9) 0 var(--space-5);
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  color: var(--content-secondary);
}

/* ── La tarjeta ───────────────────────────────────────────────────────────── */

.primas-tarjeta {
  padding: var(--space-7);
  margin-bottom: var(--space-6);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  /* Misma convención que `.record-card` y la tarjeta de excepciones: el estado
     va en el borde izquierdo y **arranca neutro**.
     🔑 Aquí nació en ámbar, y estaba mal por la razón que esa convención ya
     tenía escrita: en esta sección **todas** las tarjetas son propuestas, así
     que un borde ámbar en todas no distingue ninguna. El color se reserva para
     la excepción de verdad —la que se apartó de lo calculado—. */
  border-left: 3px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

/* Esto sí es la excepción: alguien movió el importe a mano. Es la tarjeta que
   hay que revisar con más cuidado, y ahora se localiza sin leerlas todas. */
.primas-tarjeta--ajustada {
  border-left-color: var(--state-info);
}

.primas-tarjeta-cabeza {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  align-items: flex-start;
  justify-content: space-between;
}

.primas-nombre {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-snug);
  color: var(--content-primary);
}

.primas-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  margin: var(--space-3) 0 0;
  font-size: var(--text-xs);
  color: var(--content-tertiary);
}

/* El importe manda en la tarjeta: es lo que se aprueba. */
.primas-total {
  margin: 0;
  text-align: right;
  font-size: var(--text-2xl);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--content-primary);
  font-variant-numeric: tabular-nums;
}

.primas-total-pie {
  display: block;
  font-size: var(--text-2xs);
  font-weight: var(--weight-normal);
  color: var(--content-tertiary);
}

/* ── De dónde sale el número ──────────────────────────────────────────────── */

.primas-desglose {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-5);
  margin: var(--space-7) 0 0;
  padding: var(--space-6);
  background: var(--surface-sunken);
  border-radius: var(--radius-md);
}

.primas-desglose dt {
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--content-tertiary);
}

.primas-desglose dd {
  margin: var(--space-2) 0 0;
  font-size: var(--text-base);
  color: var(--content-primary);
  font-variant-numeric: tabular-nums;
}

/* ── Calculado contra lo que se paga ──────────────────────────────────────── */

.primas-importes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-6);
  margin-top: var(--space-6);
}

.primas-importes-col {
  padding: var(--space-6);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

/* Cuando alguien movió el importe, la columna de la derecha deja de ser una
   copia y hay que poder verlo sin comparar cifra por cifra. */
.primas-importes--ajustada .primas-importes-col:last-child {
  border-color: var(--state-info-border);
  background: var(--state-info-soft);
}

.primas-importes-col .t-overline { color: var(--content-tertiary); }

.primas-importes-linea {
  display: flex;
  justify-content: space-between;
  gap: var(--space-5);
  margin: var(--space-4) 0 0;
  font-size: var(--text-sm);
  color: var(--content-secondary);
}

.primas-importes-linea .num { color: var(--content-primary); }

.primas-importes-suma {
  margin: var(--space-5) 0 0;
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-subtle);
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  color: var(--content-primary);
  font-variant-numeric: tabular-nums;
}

.primas-importes-suma .t-2xs {
  margin-left: var(--space-3);
  font-weight: var(--weight-normal);
}

.primas-motivo {
  margin: var(--space-5) 0 0;
  padding-left: var(--space-5);
  border-left: 2px solid var(--state-info-border);
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--content-secondary);
  max-width: 78ch;
}

.primas-motivo .t-overline {
  display: block;
  color: var(--content-tertiary);
}

/* ── Qué pasa si nadie hace nada ──────────────────────────────────────────── */

.primas-hoy { margin-top: var(--space-7); }
.primas-hoy .t-overline { color: var(--content-tertiary); }

.primas-hoy p {
  margin: var(--space-2) 0 0;
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--content-primary);
  max-width: 78ch;
}

/* ── El ajuste, plegado ───────────────────────────────────────────────────── */

.primas-ajuste { margin-top: var(--space-7); }

.primas-ajuste summary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-5);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  color: var(--content-secondary);
  cursor: pointer;
}

.primas-ajuste summary:hover {
  background: var(--surface-hover);
  color: var(--content-primary);
}

.primas-ajuste summary:focus-visible {
  outline: none;
  box-shadow: var(--ring-focus);
}

.primas-ajuste form {
  margin-top: var(--space-6);
  padding: var(--space-6);
  background: var(--surface-sunken);
  border-radius: var(--radius-md);
}

.primas-ajuste-campos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--space-5);
}

.primas-ajuste-campos label,
.primas-ajuste-motivo label {
  display: block;
  margin-bottom: var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--content-secondary);
}

.primas-ajuste-motivo { margin-top: var(--space-6); }

.primas-ajuste-acciones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  align-items: center;
  margin-top: var(--space-6);
}

/* ── Las dos decisiones ───────────────────────────────────────────────────── */

.primas-decisiones {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--space-6);
  margin-top: var(--space-7);
  padding-top: var(--space-7);
  border-top: 1px solid var(--border-subtle);
}

.primas-decision {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  align-items: flex-start;
}

/* La consecuencia va ANTES del botón, no en un tooltip: sin ella se elige la
   opción que suena menos grave, que no es la misma que la correcta. */
.primas-decision-consecuencia {
  margin: 0;
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--content-secondary);
}

.primas-decision-nota { margin: 0; }

.primas-decision input[type="text"] { width: 100%; }

/* ── Los avisos: marcadas y sin poder calcular ─────────────────────────────── */

.primas-avisos {
  margin-bottom: var(--space-8);
  padding: var(--space-6);
  background: var(--state-danger-soft);
  border: 1px solid var(--state-danger-border);
  border-radius: var(--radius-md);
}

.primas-avisos-titulo {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: 0;
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--state-danger-content);
}

.primas-avisos-texto {
  margin: var(--space-3) 0 0;
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--content-secondary);
  max-width: 78ch;
}

.primas-avisos-lista,
.primas-rechazadas {
  margin: var(--space-6) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-5);
}

.primas-avisos-lista li,
.primas-rechazadas li {
  display: grid;
  gap: var(--space-2);
}

.primas-avisos-nombre {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--content-primary);
}

.primas-avisos-porque {
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--content-secondary);
  max-width: 78ch;
}

.primas-rechazadas {
  padding: var(--space-6);
  background: var(--surface-sunken);
  border-radius: var(--radius-md);
}

/* ── Las aprobadas ────────────────────────────────────────────────────────── */

.primas-tabla-marco {
  overflow-x: auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
}

.primas-tabla { margin: 0; }

.primas-tabla .col-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.primas-tabla .t-2xs { display: block; }

.primas-nota-recalculo {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin: var(--space-5) 0 0;
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--state-warning-content);
  max-width: 78ch;
}

/* ── El aviso que sale en la mesa de la empresa ────────────────────────────
   Vive aquí y no en el bloque `.mesa-*` porque es de primas: quien busque por
   qué la mesa enseña este renglón lo encuentra junto al resto del módulo. */

.primas-aviso-mesa {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-6);
  padding: var(--space-5) var(--space-6);
  background: var(--state-warning-soft);
  border: 1px solid var(--state-warning-border);
  border-radius: var(--radius-md);
}

.primas-aviso-mesa-texto {
  margin: 0;
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--content-primary);
}

.primas-aviso-mesa-texto i {
  margin-right: var(--space-3);
  color: var(--state-warning);
}
