/* ═══════════════════════════════════════════════════════════════
   SGI DESIGN SYSTEM — Paleta Azul Claro / Negro
   ═══════════════════════════════════════════════════════════════ */
/* ══════════════════════════════════════════════════════════════════
   TOKENS DEL SISTEMA
   ══════════════════════════════════════════════════════════════════
   Escalas de espaciado, radio, sombra y tipografía, más la paleta.

   Criterio de la paleta — REGLA DE ESCASEZ DEL COLOR:
   los neutrales son grises slate y el azul queda reservado para la
   acción (botón principal, foco, estado activo, selección). Antes los
   neutrales eran azules —fondo #eef4fb, borde #b8d0ea, franja de tabla
   #ddeaf8— así que el azul aparecía en todas partes y dejaba de
   significar nada. Un color que está en todo no comunica.

   Escalera tonal de superficies, de la más lejana a la más cercana:
     --bg-primary  #f1f5f9  fondo de la aplicación
     --bg-card     #ffffff  tarjetas y contenedores de trabajo
     --bg-table-alt#f8fafc  franja alterna, apenas perceptible
     --bg-hover    #f1f5f9  fila o zona bajo el cursor
   ══════════════════════════════════════════════════════════════════ */
:root {
  /* ── ESPACIADO ─────────────────────────────────────────────────── */
  --esp-xs:  4px;
  --esp-sm:  8px;
  --esp-md:  12px;
  --esp-lg:  16px;
  --esp-xl:  24px;
  --esp-2xl: 32px;

  /* ── RADIO ─────────────────────────────────────────────────────── */
  /* Tres pasos, no uno. Radios grandes (12px+) leen como aplicación de
     consumo; una herramienta de trabajo usa esquinas contenidas. */
  --radio-sm: 4px;   /* chips cuadrados, celdas, indicadores */
  --radio-md: 6px;   /* botones, campos de formulario, menús */
  --radio-lg: 8px;   /* tarjetas, contenedores, modales */

  /* ── SOMBRA: PLANO EN REPOSO, ELEVADO AL INTERACTUAR ───────────── */
  /* Una superficie se gana la sombra solo si flota sobre el contenido,
     es temporal o responde al cursor. La profundidad se construye con
     tonos y bordes, no con brillos. */
  --sombra-reposo:   none;
  --sombra-tarjeta:  0 1px 2px rgb(15 23 42 / 0.06);   /* tarjetas compactas */
  --sombra-flotante: 0 10px 24px rgb(15 23 42 / 0.16); /* menús, desplegables */
  --sombra-dialogo:  0 24px 60px rgb(15 23 42 / 0.22); /* modales */

  /* ── TIPOGRAFÍA ────────────────────────────────────────────────── */
  /* Cinco niveles con contraste real de tamaño y peso. Pantallas densas
     necesitan jerarquía: si toda etiqueta pesa igual, no hay jerarquía. */
  --fs-display:  1.5rem;    --fw-display:  600;
  --fs-headline: 1.25rem;   --fw-headline: 600;
  --fs-title:    1.125rem;  --fw-title:    600;
  --fs-body:     0.875rem;  --fw-body:     400;
  --fs-label:    0.75rem;   --fw-label:    600;
  --ls-display:  -0.01em;
  --ls-label:    0.04em;    /* las etiquetas van espaciadas, no apretadas */

  /* ── SUPERFICIES (neutrales slate, sin tinte azul) ─────────────── */
  --bg-primary:     #f1f5f9;
  --bg-secondary:   #ffffff;
  --bg-card:        #ffffff;
  --bg-panel:       #f1f5f9;
  --bg-table-alt:   #f8fafc;
  --bg-hover:       #f1f5f9;
  --border-color:   #e2e8f0;
  --border-strong:  #94a3b8;
  --text-primary:   #0f172a;
  --text-secondary: #64748b;   /* gris neutro, sin tono azul que confunda con enlaces */
  --text-header:    #ffffff;

  /* ── ACCIÓN (el único color saturado del sistema) ──────────────── */
  --accent-primary: #1a56db;
  --accent-hover:   #1647c0;
  --accent-light:   #eff6ff;   /* tinte suave: hover y fila seleccionada */
  --accent-glow:    rgba(26, 86, 219, 0.18);
  --anillo-foco:    0 0 0 3px rgba(26, 86, 219, 0.35);
  --th-bg:          #1a56db;
  --th-bg-alt:      #1647c0;

  /* ── SEMÁNTICOS ────────────────────────────────────────────────── */
  /* Siempre acompañados de texto o icono: el color nunca comunica solo. */
  --success:        #15803d;
  --success-soft:   #f0fdf4;
  --warning:        #b45309;
  --warning-soft:   #fffbeb;
  --danger:         #b91c1c;
  --danger-soft:    #fef2f2;
  --info:           #0369a1;
  --info-soft:      #f0f9ff;

  /* ── TABLAS: TOKENS ÚNICOS ────────────────────────────────────
     Antes cada tabla traía su propio color de encabezado escrito en un
     atributo style: 32 tonos distintos entre index.html y los módulos que
     generan tablas. Como el estilo en línea gana sobre la hoja de estilos,
     no había forma de unificarlo desde aquí.

     La referencia es "Alertas de Vencimiento" (#epp-venc-table): slate
     oscuro, compacto y legible. Estos tokens son la única fuente de ese
     color, así que cambiarlo aquí lo cambia en todo el sistema.

     El color de fondo pasa a ser estructural, nunca decorativo: dentro de
     las celdas sigue significando estado (vencido, crítico, alerta). */
  --tabla-thead-bg:      #1e293b;   /* fondo de toda celda de encabezado */
  --tabla-thead-bg-fija: #0f172a;   /* única variante: columnas congeladas */
  --tabla-thead-fg:      #ffffff;
  --tabla-thead-borde:   rgba(255,255,255,0.18);
  --tabla-fila-alt:      #f8fafc;   /* franja alterna del cuerpo */
  --tabla-fila-hover:    #eff6ff;   /* fila bajo el cursor: tinte de acción */
  --tabla-celda-pad-y:   8px;
  --tabla-celda-pad-x:   10px;
  --tabla-fuente:        0.82rem;

  /* Radio de tarjeta alineado a la escala. Antes 12px, que junto con la
     sombra azul daba aspecto de aplicación de consumo. */
  --card-radius:    var(--radio-lg);
  /* Sombra neutra y mínima en lugar del brillo azul permanente. */
  --card-shadow:    var(--sombra-tarjeta);
  --font-family:    'Inter', system-ui, -apple-system, sans-serif;
  --sidebar-width:  260px;
}

body.dark-theme {
  --bg-primary:     #0b1120;
  --bg-secondary:   #111e30;
  --bg-card:        #152035;
  --bg-table-alt:   #1a2d42;
  --border-color:   rgba(100,160,220,0.18);
  --text-primary:   #e8f0fb;
  --text-secondary: #8bafd4;
  --accent-primary: #3b82f6;
  --accent-hover:   #2563eb;
  --accent-light:   rgba(59,130,246,0.15);
  --accent-glow:    rgba(59,130,246,0.3);
  --th-bg:          #1e3a6e;
  --th-bg-alt:      #163060;
  --success:        #10b981;
  --warning:        #f59e0b;
  --danger:         #ef4444;

  /* En tema oscuro el encabezado ya es oscuro: lo que cambia es la franja
     alterna del cuerpo, que en claro es casi blanca y aquí debe ser un
     azul apagado para no deslumbrar. */
  --tabla-thead-bg:      #17233a;
  --tabla-thead-bg-fija: #0d1626;
  --tabla-fila-alt:      #16263a;
}

/* ── RESET ─────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

body {
  font-family: var(--font-family);
  background-color: var(--bg-primary);
  color: var(--text-primary);
  min-height: 100vh;
  line-height: 1.5;
  font-size: 0.92rem;
}

/* ── LAYOUT ─────────────────────────────────────────────────────── */
.app-layout { display: flex; min-height: 100vh; }

/* ── SIDEBAR ─────────────────────────────────────────────────────── */
.sidebar {
  width: var(--sidebar-width);
  background-color: var(--bg-secondary);
  border-right: 1px solid var(--border-color);
  padding: 1.25rem 0.75rem;
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0; bottom: 0; left: 0;
  z-index: 100;
  overflow-y: auto;
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 1.5rem;
  padding: 0 8px;
}

.brand-icon {
  width: 40px; height: 40px;
  border-radius: var(--radio-md);
  /* Color plano: el gradiente era decorativo y no explicaba ningún estado. */
  background: var(--accent-primary);
  display: flex; align-items: center; justify-content: center;
  color: white;
  flex-shrink: 0;
}
.brand-icon svg { width: 22px; height: 22px; }

.brand-text h2 {
  font-size: 1.1rem; font-weight: 800;
  color: var(--text-primary);
  letter-spacing: 0.5px;
}
.brand-text span {
  font-size: 0.65rem;
  color: var(--text-secondary);
  font-weight: 600;
  letter-spacing: 1px;
}

.sidebar-module-switch { padding: 0 4px 12px; border-bottom: 1px solid var(--border-color); margin-bottom: 10px; }

.nav-menu { display: flex; flex-direction: column; gap: 4px; }

.nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  color: var(--text-secondary);
  background: transparent; border: none;
  font-size: 0.85rem; font-weight: 600;
  cursor: pointer;
  transition: all 0.15s ease;
  width: 100%; text-align: left;
}
.nav-item:hover { background-color: var(--accent-light); color: var(--accent-primary); }
.nav-item.active {
  background: var(--accent-primary) !important;
  color: #ffffff !important;
  font-weight: 700;
  box-shadow: 0 2px 8px var(--accent-glow);
}
.nav-item svg { width: 17px; height: 17px; flex-shrink: 0; }

.badge-accent,
.badge-info,
.badge-warning {
  font-size: 0.65rem; font-weight: 700;
  padding: 2px 6px; border-radius: 5px;
  margin-left: auto; white-space: nowrap;
}
.badge-accent  { background: rgba(26,86,219,0.12); color: var(--accent-primary); }
.badge-info    { background: rgba(3,105,161,0.12); color: #0369a1; }
.badge-warning { background: rgba(180,83,9,0.12); color: #b45309; }

/* ═══════════════════════════════════════════════════════════════
   INSIGNIAS DEL MENÚ LATERAL — ESTILO NEUTRAL ÚNICO
   ═══════════════════════════════════════════════════════════════
   Las 29 insignias del menú traían 12 colores de fondo distintos en
   estilo inline, sin sistema que los explicara: la misma palabra
   "Métricas" salía azul en Tareas y ámbar en Herramientas, y
   descriptores equivalentes (Editable, Costos, Diaria, Quincenal,
   Masivo, DIAN) tenían cada uno su color. Eso competía por atención
   con el elemento activo del menú, que es la única señal de estado
   que de verdad importa ahí.

   Ahora todas comparten un gris neutro. Se conserva el texto, que es
   lo informativo, y el `!important` es necesario porque los colores
   venían en el atributo style de cada botón.

   NOTA: los colores de los encabezados de tabla NO se tocaron. Esos sí
   siguen un sistema (en Nómina Maestra el verde marca devengados, el
   rojo deducciones, el azul horas extra), así que aplanarlos habría
   quitado información útil en tablas de 39 y 47 columnas. */
.sidebar .nav-item .badge-accent,
.sidebar .nav-item .badge-info,
.sidebar .nav-item .badge-warning {
  background: var(--bg-primary) !important;
  color: var(--text-secondary) !important;
  border: 1px solid var(--border-color) !important;
  font-weight: 700 !important;
  letter-spacing: 0.1px;
}

/* Sobre el elemento activo la insignia se aclara para leerse sobre el
   fondo azul. Esta regla va después para ganar en el orden de cascada. */
.sidebar .nav-item.active .badge-accent,
.sidebar .nav-item.active .badge-info,
.sidebar .nav-item.active .badge-warning {
  background: rgba(255,255,255,0.22) !important;
  color: #ffffff !important;
  border-color: rgba(255,255,255,0.32) !important;
}
.nav-item.active svg { stroke: #ffffff !important; }

/* ═══════════════════════════════════════════════════════════════
   INSIGNIAS DEL MENÚ — LA PÍLDORA SE LEE COMPLETA O BAJA DE RENGLÓN
   ═══════════════════════════════════════════════════════════════
   El botón es una fila flex con tres piezas: icono, nombre de la sección
   e insignia. Una etiqueta a medias no informa, así que la insignia es
   la pieza rígida del reparto y el nombre es el que cede espacio:

   · La insignia no se encoge nunca (`flex: 0 0 auto`), de modo que
     conserva el ancho de su texto en cualquier resolución.
   · El nombre absorbe el espacio restante (`flex: 1 1 auto` con
     `min-width: 0`) y parte en dos renglones si hace falta.
   · El botón admite salto de línea, así que cuando el nombre necesita
     la fila entera la insignia pasa sola al renglón siguiente, alineada
     a la derecha igual que en el caso de una sola línea.

   Es una regla única para las 41 insignias del menú: ningún botón
   necesita ajuste propio y el ancho del panel puede cambiar (260 px en
   escritorio, 220 px en portátil) sin recortar ningún texto. */
.sidebar .nav-item {
  flex-wrap: wrap;
  row-gap: 3px;
}
.sidebar .nav-item > span:not(.badge-accent):not(.badge-info):not(.badge-warning) {
  flex: 1 1 auto;
  min-width: 0;
}
.sidebar .nav-item .badge-accent,
.sidebar .nav-item .badge-info,
.sidebar .nav-item .badge-warning {
  flex: 0 0 auto;
  max-width: 100%;
}

/* ── LAYOUT TIPO ERP — APROVECHAMIENTO PLENO DE LA VENTANA ──────
   Antes: .app-layout tenía overflow-y:auto (scroll de página) y las
   tablas tenían max-height:70vh, resultando en tablas cortadas con
   grandes espacios vacíos debajo cuando el contenido era corto y
   scroll doble cuando era largo.

   Ahora: el layout ocupa exactamente 100vh sin scroll de página. El
   header queda fijo arriba y la vista activa recibe todo el espacio
   restante. Las tablas, dashboards y actas usan ese espacio disponible
   sin dejar zonas muertas. */
.app-layout { 
  max-width: 100vw; 
  width: 100vw;
  height: 100vh;
  overflow: hidden;         /* nada se sale ni de lado ni por abajo */
  display: flex;
}

.main-content {
  flex: 1 1 auto;
  margin-left: var(--sidebar-width);
  padding: 1rem 1.5rem;
  max-width: calc(100vw - var(--sidebar-width));
  min-width: 0;
  /* Columna vertical: header arriba, vista abajo llenando el resto.
     Se eliminó height:100vh porque .app-layout ya fija el alto del viewport
     y .main-content como hijo flex:1 lo hereda; el valor explícito causaba
     que al entrar en pantalla completa el contenedor excediera el viewport
     y el contenido quedara cortado sin scroll. */
  display: flex;
  flex-direction: column;
  min-height: 0;            /* permite que los hijos flex se encojan */
  overflow: hidden;         /* el scroll vive dentro de la vista, no aquí */
}

/* El header ocupa solo lo que necesita y no se comprime */
.top-header { flex-shrink: 0; }

/* El contenedor de vistas ocupa todo el alto restante y hace scroll
   INTERNO cuando el contenido de la vista es más largo que la ventana */
.view-container {
  flex: 1 1 auto;
  min-height: 0;
  min-width: 0;
  overflow-y: auto;
  overflow-x: hidden;
  /* Scroll suave y visible */
  scrollbar-width: thin;
  scrollbar-color: #94a3b8 transparent;
}
.view-container::-webkit-scrollbar { width: 10px; }
.view-container::-webkit-scrollbar-track { background: transparent; }
.view-container::-webkit-scrollbar-thumb {
  background: #94a3b8; border-radius: 5px;
}
.view-container::-webkit-scrollbar-thumb:hover { background: var(--accent-primary); }

/* Cada vista ocupa el alto disponible y organiza sus hijos en columna
   para que una tabla pueda estirarse hasta el borde inferior */
.app-view { display: none; }
.app-view.active {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  min-width: 0;
  gap: 0;
}

/* ── VISTA DE TABLA ÚNICA: se ajusta exactamente a la ventana ────
   `min-height: 100%` deja que la vista CREZCA con su contenido. Para un
   panel con varias secciones eso es lo correcto: el .view-container se
   encarga del desplazamiento.

   Pero en una vista cuyo contenido principal es una sola tabla, ese
   crecimiento anula el ajuste: la vista se estiraba a la altura natural
   de la tabla (5152px con 193 filas) y el `flex: 1` del card-box se
   limitaba a rellenar ese alto ya crecido, así que la tabla nunca se
   constreñía y el desplazamiento terminaba en la página en lugar de
   dentro de la tabla.

   Con .view-fills la vista queda fija al alto del contenedor, de modo
   que el card-box marcado tiene que encogerse y el desplazamiento
   ocurre dentro de la tabla, con su encabezado fijo a la vista.
   La clase la aplica switchView() junto con .grow. */
.app-view.active.view-fills {
  height: 100%;
  min-height: 0;
  overflow: hidden;
}

/* .card-box, page-header, filtros y demás bloques mantienen su tamaño
   natural. Solo el card-box de la tabla marcada crece para llenar
   el resto del espacio disponible (ver .card-box.grow más abajo). */
.card-box { 
  min-width: 0;
}
.page-header { flex-shrink: 0; }

/* ── HEADER ──────────────────────────────────────────────────── */
/* Compacto pero con espacio suficiente para no envolver. El problema del
   corte venía de flex sin wrap + gap muy pequeño + elementos sin min-width.
   Ahora con wrap controlado y mejor distribución de espacio. */
.top-header {
  display: flex; 
  justify-content: space-between; 
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 1rem; 
  gap: 10px;
  background: var(--accent-primary);
  padding: 10px 16px;
  border-radius: 10px;
  box-shadow: 0 2px 8px var(--accent-glow);
  min-height: 56px;
}

.search-box {
  display: flex; align-items: center; gap: 8px;
  background-color: rgba(255,255,255,0.15);
  border: 1px solid rgba(255,255,255,0.3);
  border-radius: 8px;
  padding: 7px 12px;
  flex: 1 1 280px;
  max-width: 400px;
  min-width: 200px;
}
.search-box svg { width: 16px; height: 16px; color: rgba(255,255,255,0.8); flex-shrink: 0; }
.search-box input {
  background: transparent; border: none; outline: none;
  color: #ffffff; font-size: 0.88rem; 
  width: 100%;
  min-width: 0;
}
.search-box input::placeholder { color: rgba(255,255,255,0.6); }

/* ═══════════════════════════════════════════════════════════════
   BUSCADORES — COMPONENTE UNIFICADO
   ═══════════════════════════════════════════════════════════════
   Ver modules/shared/sgi-search.js

   PROBLEMA CORREGIDO: .search-box se diseñó para el header azul
   (fondo translúcido claro + texto blanco). Pero 9 de los 10 filtros
   del sistema viven dentro de .card-box, sobre fondo blanco, donde
   solo se les cambiaba el borde por estilo inline. El texto seguía
   siendo blanco: al escribir no se veía nada.

   Ahora toda .search-box que esté dentro de una tarjeta, un modal o
   un encabezado de página adopta automáticamente la variante clara,
   con texto oscuro legible. El buscador del header conserva su
   aspecto sobre azul. */
.card-box .search-box,
.page-header .search-box,
.modal-body .search-box,
.filters-bar .search-box,
.search-box.search-box--light {
  background-color: var(--bg-primary);
  border: 1px solid var(--border-color);
}
.card-box .search-box svg,
.page-header .search-box svg,
.modal-body .search-box svg,
.filters-bar .search-box svg,
.search-box.search-box--light svg { color: var(--text-secondary); }

.card-box .search-box input,
.page-header .search-box input,
.modal-body .search-box input,
.filters-bar .search-box input,
.search-box.search-box--light input { color: var(--text-primary); }

.card-box .search-box input::placeholder,
.page-header .search-box input::placeholder,
.modal-body .search-box input::placeholder,
.filters-bar .search-box input::placeholder,
.search-box.search-box--light input::placeholder { color: #94a3b8; }

/* Foco visible y consistente en cualquier superficie */
.search-box:focus-within {
  border-color: var(--accent-primary);
  box-shadow: 0 0 0 3px var(--accent-glow);
}

/* ── Botón de limpiar (aparece solo cuando hay texto) ─────────── */
.sgi-search { position: relative; }
.sgi-search__clear {
  display: none;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  padding: 0;
  margin-left: 2px;
  border: none;
  border-radius: 50%;
  background: rgba(15, 23, 42, 0.12);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.sgi-search--filled .sgi-search__clear { display: flex; }
.sgi-search__clear svg { width: 11px; height: 11px; }
.sgi-search__clear:hover {
  background: #dc2626;
  color: #ffffff;
}
/* Sobre el header azul el botón necesita más contraste */
.top-header .sgi-search__clear {
  background: rgba(255, 255, 255, 0.28);
  color: #ffffff;
}
.top-header .sgi-search__clear:hover { background: #dc2626; }

/* ═══════════════════════════════════════════════════════════════
   COMBOBOX — selector de registro con autocompletado
   ═══════════════════════════════════════════════════════════════
   Sustituye a los <select> gigantes siempre desplegados y a los
   <datalist> nativos, que no permitían resaltar coincidencias ni
   mostrar el dato secundario. */
.sgi-combo {
  position: relative;
  display: flex;
  align-items: center;
  gap: 7px;
  background: var(--bg-card);
  border: 1.5px solid var(--border-color);
  border-radius: 9px;
  padding: 0 10px;
  min-width: 260px;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.sgi-combo:hover { border-color: #94a3b8; }
.sgi-combo:focus-within {
  border-color: var(--accent-primary);
  box-shadow: 0 0 0 3px var(--accent-glow);
}
/* Confirmación visual discreta de que hay un registro elegido */
.sgi-combo--selected { border-color: #059669; }
.sgi-combo--selected:focus-within {
  border-color: var(--accent-primary);
}

.sgi-combo__icon {
  display: flex;
  flex-shrink: 0;
  color: var(--text-secondary);
}
.sgi-combo__icon svg { width: 15px; height: 15px; }
.sgi-combo--selected .sgi-combo__icon { color: #059669; }

/* El input hereda el aspecto del contenedor: sin borde propio, para
   que el conjunto se lea como un solo control. Se usa !important
   porque varios campos traen borde y relleno en estilo inline. */
.sgi-combo__input {
  flex: 1 1 auto;
  min-width: 0;
  border: none !important;
  outline: none !important;
  background: transparent !important;
  box-shadow: none !important;
  padding: 9px 0 !important;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text-primary);
}
.sgi-combo__input::placeholder {
  color: #94a3b8;
  font-weight: 500;
}

.sgi-combo__clear {
  display: none;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(15, 23, 42, 0.12);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.sgi-combo--filled .sgi-combo__clear { display: flex; }
.sgi-combo__clear svg { width: 11px; height: 11px; }
.sgi-combo__clear:hover { background: #dc2626; color: #ffffff; }

/* ── Panel de resultados ─────────────────────────────────────────
   Altura acotada: muestra ~6 resultados y desplaza el resto. Antes
   el <select> desplegaba 70 filas de golpe y tapaba la pantalla. */
.sgi-combo__panel {
  position: absolute;
  top: calc(100% + 5px);
  left: 0;
  right: 0;
  z-index: 9800;
  max-height: 288px;
  overflow-y: auto;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: 10px;
  box-shadow: 0 10px 28px rgba(15, 23, 42, 0.16);
  padding: 5px;
  scrollbar-width: thin;
  scrollbar-color: #cbd5e1 transparent;
  overscroll-behavior: contain;
}
.sgi-combo__panel::-webkit-scrollbar { width: 9px; }
.sgi-combo__panel::-webkit-scrollbar-track { background: transparent; }
.sgi-combo__panel::-webkit-scrollbar-thumb {
  background: #cbd5e1; border-radius: 5px; border: 2px solid var(--bg-card);
}
.sgi-combo__panel::-webkit-scrollbar-thumb:hover { background: #94a3b8; }

/* ── Cada resultado: jerarquía en dos niveles ─────────────────── */
.sgi-combo__option {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 8px 10px;
  border-radius: 7px;
  cursor: pointer;
  transition: background 0.1s;
}
.sgi-combo__option--active { background: var(--accent-light); }
.sgi-combo__primary {
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.3;
}
.sgi-combo__secondary {
  font-size: 0.75rem;
  font-weight: 500;
  color: #64748b;
  line-height: 1.3;
}
.sgi-combo__option--active .sgi-combo__primary { color: var(--accent-primary); }

/* Resaltado de la coincidencia */
.sgi-combo__panel mark {
  background: #fef08a;
  color: inherit;
  padding: 0 1px;
  border-radius: 2px;
  font-weight: 800;
}
.sgi-combo__option--active mark { background: #fde047; }

/* ── Mensajes del panel ──────────────────────────────────────── */
.sgi-combo__empty {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 12px;
  color: var(--text-secondary);
  font-size: 0.83rem;
  font-weight: 600;
  justify-content: center;
}
.sgi-combo__empty svg { width: 15px; height: 15px; opacity: 0.6; flex-shrink: 0; }

.sgi-combo__hint {
  padding: 7px 10px;
  margin-top: 3px;
  border-top: 1px solid var(--border-color);
  color: #64748b;
  font-size: 0.73rem;
  font-weight: 600;
  text-align: center;
}

/* Tema oscuro */
body.dark-theme .sgi-combo__panel mark { background: #a16207; color: #fff; }
body.dark-theme .sgi-combo__option--active mark { background: #ca8a04; }
body.dark-theme .sgi-search__clear,
body.dark-theme .sgi-combo__clear { background: rgba(255,255,255,0.14); color: #cbd5e1; }

/* Responsive: en pantallas estrechas el combobox ocupa el ancho
   disponible y el panel se acorta para no tapar la vista */
@media (max-width: 768px) {
  .sgi-combo { min-width: 0; width: 100%; }
  .sgi-combo__panel { max-height: 232px; }
  /* Objetivos táctiles más cómodos */
  .sgi-combo__option { padding: 10px 11px; }
  .sgi-search__clear,
  .sgi-combo__clear { width: 24px; height: 24px; }
}

.header-actions { 
  display: flex; 
  align-items: center; 
  gap: 8px; 
  flex-wrap: nowrap; 
  flex-shrink: 0;
  min-width: 0; 
}

/* ── LA BARRA SUPERIOR NUNCA SALTA DE LÍNEA EN ESCRITORIO ────────
   Con `flex-wrap: wrap`, bastaba que el contenido excediera el ancho en
   5px para que el grupo de la derecha bajara de renglón; y una vez
   abajo, el bloque izquierdo se estiraba a todo el ancho, de modo que
   un desbordamiento mínimo se convertía en una barra del doble de alto
   con un gran hueco azul.

   En escritorio se prohíbe el salto y se deja que los bloques se
   compriman: el nombre del usuario se recorta con puntos suspensivos,
   que es una degradación mucho más discreta. En tableta y móvil se
   mantiene el salto, que ahí sí es el comportamiento deseable. */
@media (min-width: 1025px) {
  .top-header { flex-wrap: nowrap; }
  .header-actions { flex-shrink: 1; }
  #sgi-user-badge { min-width: 0; }
}

/* ── UBICACIÓN ACTUAL EN LA BARRA SUPERIOR ───────────────────────
   La zona izquierda de la barra quedaba con 501px y ningún elemento
   visible en Herramientas, Tareas, Nómina y Portal, porque el único
   ocupante era el selector de almacén, propio de EPP. Este rastro de
   ubicación aprovecha ese espacio y además orienta: dice en qué módulo
   y en qué vista está el usuario. */
.header-breadcrumb {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  flex-shrink: 1;
  padding: 4px 2px;
  color: #ffffff;
}
.header-breadcrumb .hb-icon {
  font-size: 1rem;
  line-height: 1;
  flex-shrink: 0;
}
.header-breadcrumb .hb-module {
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  opacity: 0.75;
  white-space: nowrap;
  /* Puede encogerse y recortarse: es lo que impide que la barra salte a
     dos líneas cuando el módulo trae además el selector de almacén. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.header-breadcrumb .hb-sep {
  font-size: 0.9rem;
  opacity: 0.5;
  flex-shrink: 0;
}
.header-breadcrumb .hb-view {
  font-size: 0.92rem;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* En el módulo que trae el selector de almacén (EPP) el nombre del módulo
   cede su sitio: entre etiqueta, lista y dos botones ese selector ocupa unos
   420px, y con el nombre delante la barra no cabía en una línea. El icono
   sigue identificando el módulo. */
body.modulo-con-selector .header-breadcrumb .hb-module,
body.modulo-con-selector .header-breadcrumb .hb-sep { display: none; }

/* Por debajo de 1300px se oculta en todos los módulos */
@media (max-width: 1300px) {
  .header-breadcrumb .hb-module,
  .header-breadcrumb .hb-sep { display: none; }
}

/* En el header, los botones son más bajos para no engordar la barra */
.top-header .btn-secondary,
.top-header .btn-primary {
  padding: 6px 11px;
  font-size: 0.82rem;
  min-height: 34px;
}

/* El selector de proyecto es específico de EPP: se compacta y el propio
   app.js lo muestra u oculta según el módulo activo. */
.top-header .project-selector-wrapper { padding: 4px 8px !important; gap: 6px !important; }

.theme-toggle {
  background: rgba(255,255,255,0.15);
  border: 1px solid rgba(255,255,255,0.3);
  color: #ffffff;
  width: 34px; height: 34px;
  border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; transition: all 0.2s;
  flex-shrink: 0;
}
.theme-toggle:hover { background: rgba(255,255,255,0.25); }
.theme-toggle svg { width: 18px; height: 18px; }

/* ── BOTONES ─────────────────────────────────────────────────── */
.btn-primary {
  background-color: var(--accent-primary); color: white;
  border: none; border-radius: 8px;
  padding: 9px 16px; font-weight: 700; font-size: 0.88rem;
  cursor: pointer; transition: all 0.2s;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  box-shadow: 0 2px 6px var(--accent-glow);
}
.btn-primary:hover { background-color: var(--accent-hover); transform: translateY(-1px); }

.btn-secondary {
  background-color: var(--bg-secondary); color: var(--text-primary);
  border: 1.5px solid var(--border-color);
  border-radius: 8px; padding: 9px 14px;
  font-weight: 600; font-size: 0.88rem;
  cursor: pointer; transition: all 0.2s;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
}
.btn-secondary:hover { border-color: var(--accent-primary); color: var(--accent-primary); background-color: var(--accent-light); }

.btn-sm { padding: 4px 10px !important; font-size: 0.78rem !important; border-radius: 6px !important; }

/* ── VISTAS ──────────────────────────────────────────────────── */
.app-view { display: none; }
/* Modo "selector de módulos": oculta sidebar y header. En este modo el
   layout ERP-fijo no aplica: el .main-content debe permitir scroll y
   ocupar todo el ancho de la pantalla. */
body.in-selector-view .sidebar,
body.in-selector-view .top-header { display: none !important; }
body.in-selector-view .app-layout { overflow: auto; height: auto; min-height: 100vh; }
body.in-selector-view .main-content { 
  margin-left: 0 !important; 
  max-width: 100% !important; 
  padding: 0 !important;
  height: auto;
  overflow: visible;
}
body.in-selector-view .view-container { overflow: visible; }

#view-module-selector.active {
  display: flex !important; flex-direction: column;
  align-items: center;
  padding: 48px 24px 48px;
  min-height: 100vh;
}

/* ── ENCABEZADO DE PÁGINA ────────────────────────────────────────
   Tarjeta consistente para todas las vistas. Los page-header traían
   estilos inline dispares (unos con fondo blanco, otros sin nada), lo
   que daba una jerarquía visual irregular entre módulos. Esta base los
   iguala; el layout flex de cada uno sigue viniendo del inline. */
.page-header {
  margin-bottom: 1rem;
  padding: 10px 16px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}
.page-title { font-size: 1.3rem; font-weight: 800; letter-spacing: -0.4px; margin-bottom: 1px; color: var(--text-primary); line-height: 1.25; }
/* FIX: --text-secondary en el tema claro es #2c4a6e (azul oscuro) y se confundía
   con un hipervínculo. Se usa un gris neutro para que sea claramente texto secundario. */
.page-description { color: #64748b; font-size: 0.84rem; }

/* Ya no hay encabezados con degradado oscuro: los dos que quedaban
   (Dashboard de Herramientas e Informe de Gestión de Tareas) se pasaron al
   estilo claro para que todos los encabezados del sistema coincidan. */

/* ── KPIS ────────────────────────────────────────────────────── */
.kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 0.7rem; }

/* Tarjetas de indicadores delgadas: median 100-145px de alto para mostrar
   un rótulo y una cifra. Con el relleno y la interlínea ajustados bajan a
   unos 60px, y esos 40-85px por vista van a las filas de la tabla. La
   cifra conserva un cuerpo grande, que es lo que se lee de un vistazo. */
.kpi-card {
  background-color: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--card-radius);
  padding: 0.5rem 0.85rem;
  display: flex; justify-content: space-between; align-items: center;
  box-shadow: var(--card-shadow);
}
.kpi-title {
  font-size: 0.68rem; color: var(--text-secondary); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.4px; line-height: 1.2;
}
.kpi-value { font-size: 1.35rem; font-weight: 800; margin: 0; color: var(--text-primary); line-height: 1.2; }
.kpi-subtitle { font-size: 0.68rem; color: var(--text-secondary); line-height: 1.2; }
.kpi-icon {
  width: 36px; height: 36px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.kpi-icon.blue  { background: var(--accent-light); color: var(--accent-primary); }
.kpi-icon.green { background: #dcfce7; color: #15803d; }
.kpi-icon.warning { background: #fef3c7; color: #b45309; }
.kpi-icon.danger { background: #fee2e2; color: #b91c1c; }
.kpi-icon svg { width: 22px; height: 22px; }

/* ── CARD-BOX ────────────────────────────────────────────────── */
.card-box {
  background-color: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--card-radius);
  padding: 1.25rem;
  box-shadow: var(--card-shadow);
}
.card-subtitle { font-size: 1rem; font-weight: 700; color: var(--text-primary); }

/* ── TABLAS — SISTEMA UNIFICADO ──────────────────────────────── */

/*
 * CONTENEDOR CON DOBLE BARRA DE SCROLL (arriba y abajo).
 * La barra superior la crea JS (ver app.js: initTableScroll).
 */
.table-wrap {
  position: relative;
  width: 100%;
  border: 1px solid var(--border-color);
  border-radius: var(--card-radius);
  overflow: hidden;
  background: var(--bg-card);
  box-shadow: var(--card-shadow);
}

/* Barra de scroll SUPERIOR (espejo) */
.table-scroll-top {
  width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  height: 12px;
  border-bottom: 1px solid var(--border-color);
}
.table-scroll-top-inner { height: 1px; }

/* Contenedor de scroll REAL (inferior) */
.table-scroll-body {
  width: 100%;
  overflow-x: auto;
  overflow-y: auto;
  max-height: var(--table-max-height, 600px);
}

/* Clase helper para cambiar alto desde HTML */
.table-h-sm  { --table-max-height: 400px; }
.table-h-md  { --table-max-height: 600px; }
.table-h-lg  { --table-max-height: 800px; }
.table-h-full{ --table-max-height: calc(100vh - 280px); }

/* ── TABLA PRINCIPAL ─────────────────────────────────────────── */
.s-table {
  width: max-content;
  min-width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 0.83rem;
  white-space: nowrap;
}

.s-table th {
  background: var(--th-bg);
  color: var(--text-header);
  font-weight: 700;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  padding: 0;          /* el padding va dentro del th-inner */
  position: sticky;
  top: 0;
  z-index: 10;
  border-right: 1px solid rgba(255,255,255,0.15);
  border-bottom: 2px solid rgba(255,255,255,0.3);
  background-clip: padding-box;
}

/* Encabezado con botones sort/filter */
.th-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 4px;
  padding: 8px 10px;
  min-height: 38px;
}

.th-label { flex: 1; min-width: 0; }

/* Botón de ordenamiento */
.sort-btn {
  background: transparent; border: none;
  color: rgba(255,255,255,0.6);
  cursor: pointer; padding: 1px 3px;
  border-radius: 3px; font-size: 0.7rem;
  transition: color 0.15s, background 0.15s;
  line-height: 1;
  display: flex; flex-direction: column; gap: 1px;
  flex-shrink: 0;
}
.sort-btn:hover { color: #ffffff; background: rgba(255,255,255,0.15); }
.sort-btn.asc .s-up   { color: #ffffff; }
.sort-btn.desc .s-down { color: #ffffff; }
.s-up, .s-down { display: block; line-height: 0.9; }

/* Popover de filtro por columna */
.col-filter-btn {
  background: transparent; border: none;
  color: rgba(255,255,255,0.5);
  cursor: pointer; padding: 2px 3px;
  border-radius: 3px; font-size: 0.7rem;
  transition: color 0.15s, background 0.15s;
  flex-shrink: 0;
}
.col-filter-btn:hover, .col-filter-btn.active {
  color: #ffffff; background: rgba(255,255,255,0.2);
}

.col-filter-pop {
  display: none;
  position: absolute;
  top: 100%; left: 0;
  z-index: 9999;
  background: #ffffff;
  border: 1.5px solid var(--border-color);
  border-radius: 8px;
  box-shadow: 0 6px 20px rgba(0,0,0,0.15);
  padding: 10px;
  min-width: 180px;
  color: var(--text-primary);
  white-space: normal;
}
.col-filter-pop.open { display: block; }
.col-filter-pop input, .col-filter-pop select {
  width: 100%; padding: 6px 8px;
  border: 1px solid var(--border-color);
  border-radius: 6px; font-size: 0.82rem;
  color: var(--text-primary); background: var(--bg-secondary);
  outline: none;
}
.col-filter-pop input:focus, .col-filter-pop select:focus {
  border-color: var(--accent-primary);
  box-shadow: 0 0 0 2px var(--accent-glow);
}
.col-filter-actions {
  display: flex; gap: 6px; margin-top: 8px;
}
.col-filter-actions button {
  flex: 1; padding: 5px 8px;
  border-radius: 5px; font-size: 0.78rem; font-weight: 700;
  cursor: pointer; border: none;
}
.cf-apply  { background: var(--accent-primary); color: #fff; }
.cf-clear  { background: #f1f5f9; color: var(--text-secondary); border: 1px solid var(--border-color) !important; }

/* Header en vertical (para tablas EPP con muchas columnas) */
.th-v {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  text-align: center !important;
  vertical-align: bottom !important;
  height: 140px; max-height: 140px;
  padding: 6px 4px !important;
  white-space: nowrap;
  font-size: 0.7rem;
}

/* Grupos de columnas: ligera variación de tono */
.th-g2 { background: var(--th-bg-alt) !important; }   /* tono más oscuro */
.th-g3 { background: #1a5276 !important; }            /* tono azul oscuro */

/* Celdas de datos */
.s-table td {
  padding: 6px 10px;
  border-bottom: 1px solid var(--border-color);
  border-right: 1px solid var(--border-color);
  color: var(--text-primary);
  vertical-align: middle;
  background: var(--bg-card);
}
.s-table tbody tr:nth-child(even) td { background-color: var(--bg-table-alt); }
.s-table tbody tr:hover td { background-color: var(--accent-light) !important; }
.s-table tbody tr:last-child td { border-bottom: none; }

/* Fila de totales */
.s-table tfoot tr td {
  background: var(--th-bg) !important;
  color: #ffffff !important;
  font-weight: 800;
  border-color: rgba(255,255,255,0.2);
}

/* Celda consumida (EPP) */
.cell-consumed {
  background-color: #dcfce7 !important;
  color: #15803d !important;
  font-weight: 700 !important;
  text-align: center;
}
.cell-alert-high {
  background: #fee2e2 !important;
  color: #991b1b !important;
  font-weight: 800 !important;
  border: 1.5px solid #f87171 !important;
  animation: pulse-alert 2s infinite ease-in-out;
}
body.dark-theme .cell-consumed { background-color: rgba(16,185,129,0.2) !important; color: #34d399 !important; }

/* Celda editable (input dentro de tabla) */
.s-table .excel-cell-input {
  width: 100%;
  background: #ffffff;
  color: #0a0f1e;
  border: 1px solid #c7d9ed;
  border-radius: 4px;
  padding: 4px 6px;
  font-weight: 600;
  font-size: 0.82rem;
  transition: border-color 0.15s;
}
body.dark-theme .s-table .excel-cell-input { background: #1a2d42; color: #e8f0fb; border-color: #2d4a6e; }
.s-table .excel-cell-input:focus {
  border-color: var(--accent-primary) !important;
  background: #f0f7ff !important;
  outline: none;
  box-shadow: 0 0 0 2px var(--accent-glow);
}

/* ═══════════════════════════════════════════════════════════════
   CONTENEDOR DE SCROLL — ÚNICO PARA TODAS LAS TABLAS
   ═══════════════════════════════════════════════════════════════
   El desplazamiento vive AQUÍ, nunca en la página completa. Antes
   convivían tres envoltorios distintos (.table-responsive, un div con
   overflow inline, y .sgi-table-scroll), así que unas tablas tenían
   encabezado fijo y otras no.

   `position: relative` es obligatorio: sin él el encabezado sticky se
   ancla al scroll de la página en vez del contenedor. */
.table-responsive {
  width: 100%;
  max-width: 100%;
  overflow: auto;
  position: relative;
  /* Reserva el carril de las barras de desplazamiento para que no se
     dibujen encima de la última fila ni de la última columna. Antes la
     barra horizontal tapaba parte de los datos. */
  scrollbar-gutter: stable;
  /* Ya NO usa 70vh fijo. En su lugar, si su card-box padre tiene la
     clase .grow, la tabla llenará el espacio disponible; si no, se
     ajusta al contenido con un tope generoso para tablas largas. */
  max-height: var(--table-max-height, calc(100vh - 220px));
  /* El rebote del scroll no se propaga al contenedor de vistas */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

/* Barra de desplazamiento visible y cómoda: en tablas de 39 y 47
   columnas la barra fina por defecto es difícil de agarrar. */
.table-responsive::-webkit-scrollbar { height: 12px; width: 12px; }
.table-responsive::-webkit-scrollbar-track { background: var(--bg-primary); border-radius: 6px; }
.table-responsive::-webkit-scrollbar-thumb {
  background: #94a3b8; border-radius: 6px; border: 2px solid var(--bg-primary);
}
.table-responsive::-webkit-scrollbar-thumb:hover { background: var(--accent-primary); }
.table-responsive { scrollbar-width: thin; scrollbar-color: #94a3b8 var(--bg-primary); }

/* Tablas cortas (pocas filas) no deben reservar 70vh en vano */
.table-responsive.table-auto { max-height: none; }

/* ═══════════════════════════════════════════════════════════════
   CARD-BOX QUE LLENA EL ALTO DISPONIBLE
   ═══════════════════════════════════════════════════════════════
   Las vistas cuya tabla principal debe aprovechar todo el alto llevan
   la clase .grow en su card-box (asignada automáticamente por
   switchView() cuando detecta el patrón page-header + tabla única).
   Sin ella el card-box mantiene su tamaño natural — así los
   dashboards con varias secciones no se ven afectados y siguen
   usando el scroll del .view-container. */
.app-view.active > .card-box.grow {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.app-view.active > .card-box.grow > .table-responsive,
.app-view.active > .card-box.grow > .sgi-table-scroll {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
}

/* ── DOCUMENTOS RENDERIZADOS (acta, desprendible, certificado) ──
   Estas vistas no tienen un card-box con tabla sino un contenedor
   donde se pinta el documento completo. Debe crecer para llenar el
   espacio y ser scrolleable dentro de sí mismo si el documento es
   largo, sin dejar espacio muerto debajo. */
#foe-acta-render-area,
#payslip-document-container,
#portal-employee-content {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
}

/* Dentro de un modal el espacio es menor: 70vh dejaría los botones de
   guardar fuera de la vista. */
.modal-body .table-responsive { max-height: 46vh; }

/* ── REQUISITO TÉCNICO DEL ENCABEZADO FIJO ──────────────────────
   Con `border-collapse: collapse` los bordes pertenecen a la tabla y no a
   la celda, así que al fijar el encabezado con position:sticky los bordes
   se quedan atrás y las filas se ven por debajo del encabezado.

   Varias tablas traían `border-collapse:collapse` en el estilo en línea
   (que gana sobre la hoja de estilos), de ahí el !important: es la única
   forma de corregirlo sin editar decenas de atributos inline. El borde se
   restituye por celda más abajo, así que el aspecto de cuadrícula se
   mantiene igual. */
.table-responsive table[data-sgi-enhanced],
.table-responsive .custom-table,
.table-responsive .excel-grid-table {
  border-collapse: separate !important;
  border-spacing: 0 !important;
}

/* Al pasar a `separate`, cada celda dibuja su propio borde */
.table-responsive .custom-table th,
.table-responsive .custom-table td {
  border-right: 1px solid var(--border-color);
}
.table-responsive .custom-table th {
  border-right-color: rgba(255,255,255,0.18);
  border-bottom: 2px solid rgba(255,255,255,0.28);
  background-clip: padding-box;
  white-space: nowrap;
}

/* .custom-table — tablas simples no-spreadsheet */

/* `width: 100%` obligaba a la tabla a caber en el contenedor, así que el
   navegador estrechaba las columnas y los encabezados quedaban apretados.
   Con `width: max-content` y `min-width: 100%` la tabla ocupa lo que su
   contenido necesita —desplazándose en horizontal cuando hace falta— y
   sigue llenando el ancho disponible si le sobra sitio. */
.custom-table {
  width: max-content;
  min-width: 100%;
  border-collapse: collapse;
  text-align: left;
  font-size: 0.88rem;
}
.custom-table th {
  padding: 10px 14px;
  background: var(--th-bg);
  color: #ffffff;
  font-weight: 700;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  border-right: 1px solid rgba(255,255,255,0.15);
  /* Sitio para los controles de orden y filtro sin pegarse al texto */
  padding-right: 18px;
}
.custom-table td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--border-color);
  color: var(--text-primary);
  vertical-align: middle;
}

/* ── TOPE DE ALTURA EN CELDAS DE TEXTO LARGO ─────────────────────
   Se midieron filas de 118px en Gestión de Tareas: las columnas de
   descripción y comentarios envolvían el texto en cuatro o cinco líneas,
   así que en pantalla cabía UNA sola fila. Con un tope de tres líneas la
   fila baja a unos 70px y se ve el triple de registros.

   El recorte se aplica a un <span> interior, no al <td>: `display:
   -webkit-box` sobre una celda rompería el cálculo de anchos de la tabla.
   El texto completo queda en el atributo title de la celda, y la columna
   se puede ensanchar arrastrando el borde del encabezado, así que no se
   pierde nada. Lo marca la función marcarCeldasLargas() de app.js. */
.celda-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Señal de que hay más texto del que se ve. Va sobre la celda cuando el
   recorte lo marca app.js, y sobre el propio span cuando el módulo que
   pinta la fila ya entrega el texto recortado. */
.custom-table td[title],
.celda-clamp[title] { cursor: help; }
.custom-table tbody tr:nth-child(even) { background: var(--bg-table-alt); }
.custom-table tbody tr:hover { background: var(--accent-light) !important; }
.custom-table tfoot tr {
  background: var(--th-bg) !important;
  color: #ffffff !important;
  font-weight: 800;
}

/* ── FORMULARIOS ─────────────────────────────────────────────── */
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 1rem; }
.form-group { display: flex; flex-direction: column; gap: 5px; }
.form-group label {
  font-size: 0.8rem; font-weight: 700;
  color: var(--text-primary);
}
.form-group input,
.form-group select,
.form-group textarea,
.select-input,
.form-control {
  background-color: var(--bg-secondary);
  border: 1.5px solid var(--border-color);
  border-radius: 7px;
  padding: 9px 11px;
  color: var(--text-primary);
  font-family: inherit; font-size: 0.88rem;
  outline: none; width: 100%;
  transition: border-color 0.15s, box-shadow 0.15s;
}
/* ═══════════════════════════════════════════════════════════════
   OPCIONES DE LOS DESPLEGABLES — LEGIBILIDAD GARANTIZADA
   ═══════════════════════════════════════════════════════════════
   BUG CORREGIDO: las <option> nativas heredan el color de texto y el
   fondo de su <select>. El selector de almacén de la barra superior
   lleva `color: #ffffff` y un fondo translúcido claro para leerse sobre
   el azul del encabezado, así que al desplegarlo las opciones salían en
   blanco sobre el fondo blanco del menú del sistema: se veían vacías o
   cortadas. No existía ninguna regla `option` en la hoja de estilos.

   Se fija color y fondo explícitos para toda opción del sistema, así
   ningún <select> —presente o futuro— puede heredar un color que la
   vuelva ilegible. El `!important` es necesario porque varios selects
   traen su color en el atributo style. */
select option,
select optgroup {
  color: #0f172a !important;
  background-color: #ffffff !important;
  font-weight: 600;
  /* Sitio suficiente para que la opción no se vea recortada */
  padding: 6px 8px;
}
select option:disabled {
  color: #94a3b8 !important;
}
/* Opción seleccionada y opción bajo el cursor */
select option:checked {
  background-color: var(--accent-light) !important;
  color: var(--accent-primary) !important;
}

body.dark-theme select option,
body.dark-theme select optgroup {
  color: #e8f0fb !important;
  background-color: #16293d !important;
}
body.dark-theme select option:checked {
  background-color: #24405c !important;
  color: #ffffff !important;
}

/* El propio selector de la barra superior: se le da un fondo algo más
   opaco para que el texto blanco tenga contraste suficiente cerrado. */
.top-header select {
  background-color: rgba(255, 255, 255, 0.22) !important;
}

/* ═══════════════════════════════════════════════════════════════
   BARRA DE FILTROS COMPACTA — buscador visible, resto colapsado
   ═══════════════════════════════════════════════════════════════
   Ver modules/shared/sgi-filters.js */

/* El bloque de filtros pasa a una sola línea */
.sgi-barra-filtros {
  display: flex !important;
  flex-wrap: wrap;
  align-items: center;
  gap: 9px !important;
  padding: 9px 13px !important;
}

/* Botón que abre y cierra los filtros avanzados */
.sgi-filtros-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  border: 1.5px solid var(--border-color);
  border-radius: 8px;
  background: var(--bg-card);
  color: var(--text-secondary);
  font-size: 0.82rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.sgi-filtros-toggle:hover {
  border-color: var(--accent-primary);
  color: var(--accent-primary);
}
.sgi-filtros-toggle svg { width: 14px; height: 14px; flex-shrink: 0; }
.sgi-filtros-toggle .sf-flecha {
  font-size: 0.7rem;
  transition: transform 0.18s ease;
}
.sgi-filtros-abierto .sgi-filtros-toggle .sf-flecha { transform: rotate(180deg); }

/* Contador de filtros aplicados: evita que un filtro quede activo sin
   que se note, ahora que el panel puede estar cerrado. */
.sgi-filtros-toggle .sf-cuenta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 17px; height: 17px;
  padding: 0 4px;
  border-radius: 9px;
  background: var(--accent-primary);
  color: #ffffff;
  font-size: 0.68rem;
  font-weight: 800;
}
/* Con filtros aplicados el botón se resalta */
.sgi-filtros-activos .sgi-filtros-toggle {
  border-color: var(--accent-primary);
  color: var(--accent-primary);
  background: var(--accent-light);
}

/* Panel con los desplegables. Ocupa toda la fila siguiente para que los
   filtros se alineen en una cuadrícula regular. */
.sgi-filtros-panel {
  flex: 1 0 100%;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 9px 12px;
  margin-top: 3px;
  padding-top: 10px;
  border-top: 1px dashed var(--border-color);
}
/* El atributo `hidden` del navegador vale `display: none`, pero lo aplica
   una regla de agente de usuario con menos peso que un selector de clase:
   sin esto, `display: grid` ganaba y el panel NUNCA se ocultaba. Medido:
   los bloques de filtros crecieron de 94px a 275px en lugar de encogerse. */
.sgi-filtros-panel[hidden] { display: none !important; }
.sgi-filtro-item {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.sgi-filtro-item label {
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Dentro del panel el filtro sí ocupa el ancho de su celda */
.sgi-filtros-panel .select-input {
  width: 100%;
  min-width: 0;
}

@media (max-width: 768px) {
  .sgi-filtros-panel { grid-template-columns: 1fr; }
}

/* ── BUSCADOR MÁS ESTRECHO EN LAS BARRAS DE FILTRO ───────────────
   Se midieron buscadores de 400px dentro de las barras de filtro. Con
   la lista de filtros ya recogida, el buscador no necesita estirarse:
   se le fija un ancho contenido y el resto de la fila queda libre. */
.card-box .search-box,
.page-header .search-box,
.sgi-barra-filtros .search-box {
  flex: 0 1 260px;
  min-width: 190px;
  max-width: 280px;
}

/* ── FILTROS: ANCHO SEGÚN CONTENIDO, NO AL 100% ──────────────────
   .select-input es la clase de los filtros sueltos (nunca se usa dentro
   de un .form-group; los formularios usan .form-control). Heredaba
   `width: 100%` de la regla anterior, así que dentro de una fila flexible
   cada filtro reclamaba el ancho completo y se apilaba uno por renglón:
   se midieron 20 filtros ocupando entre el 57% y el 89% del ancho, y
   bloques de filtros de cuatro renglones donde cabían en uno.

   Con ancho automático y un mínimo legible, los cuatro filtros de una
   vista comparten un solo renglón y el espacio recuperado va a los datos. */
.select-input {
  width: auto;
  min-width: 168px;
  max-width: 100%;
}

.form-group input:focus,
.form-group select:focus,
.select-input:focus,
.form-control:focus {
  border-color: var(--accent-primary);
  box-shadow: 0 0 0 3px var(--accent-glow);
}

.flex-1 { flex: 1; min-width: 160px; }
.flex-2 { flex: 2; min-width: 240px; }
.flex-3 { flex: 3; min-width: 300px; }

.modal-form-row { display: flex; gap: 14px; margin-bottom: 12px; flex-wrap: wrap; }

/* ── MODALES ─────────────────────────────────────────────────── */
.modal-overlay {
  position: fixed; top: 0; left: 0; right: 0; bottom: 0;
  width: 100vw; height: 100vh;
  /* Velo opaco sin desenfoque. El backdrop-filter: blur(5px) obligaba al
     navegador a recomponer todo el viewport en cada fotograma, y con una tabla
     densa detrás el modal tardaba en abrir. Con el velo al 72% el desenfoque
     era además casi imperceptible: costaba rendimiento sin aportar foco. */
  background: rgba(10,15,30,0.72);
  z-index: 9000;
  display: flex; align-items: center; justify-content: center;
  padding: 20px; box-sizing: border-box;
}
.modal-overlay.active { display: flex; }

.modal-container {
  background: var(--bg-secondary);
  color: var(--text-primary);
  width: 100%; max-width: 900px;
  max-height: 90vh;
  border-radius: 12px;
  border: 1.5px solid var(--border-color);
  box-shadow: 0 20px 50px rgba(0,0,0,0.25);
  display: flex; flex-direction: column; overflow: hidden;
  animation: modalIn 0.22s cubic-bezier(0.16,1,0.3,1);
}
@keyframes modalIn {
  from { opacity: 0; transform: scale(0.96) translateY(10px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}

.modal-header {
  background: var(--accent-primary) !important;
  color: #ffffff !important;
  padding: 16px 22px;
  display: flex; align-items: center; justify-content: space-between;
  border-bottom: 2px solid var(--accent-hover);
  flex-shrink: 0;
}
.modal-title   { margin: 0; font-size: 1.1rem; font-weight: 800; color: #ffffff !important; }
.modal-subtitle{ margin: 3px 0 0; font-size: 0.8rem; color: rgba(255,255,255,0.8) !important; }

.modal-close {
  background: rgba(255,255,255,0.15); color: #ffffff !important;
  border: 1px solid rgba(255,255,255,0.4);
  padding: 5px 12px; border-radius: 6px;
  font-size: 0.82rem; font-weight: 700; cursor: pointer;
  transition: background 0.15s;
}
.modal-close:hover { background: #dc2626 !important; border-color: #dc2626 !important; }

/* Alias usado en modales existentes */
.btn-modal-close-header { @extend .modal-close; }

.modal-body {
  background: var(--bg-primary) !important;
  padding: 22px; overflow-y: auto; flex: 1;
}
.modal-section-title {
  font-size: 0.82rem; font-weight: 800;
  color: var(--accent-primary);
  border-bottom: 2px solid var(--border-color);
  padding-bottom: 5px; margin-bottom: 12px;
  text-transform: uppercase; letter-spacing: 0.5px;
}
.modal-footer {
  background: var(--bg-secondary) !important;
  border-top: 1.5px solid var(--border-color) !important;
  padding: 14px 22px !important;
  display: flex !important; justify-content: flex-end !important;
  align-items: center !important; gap: 10px !important;
  flex-shrink: 0;
}
.btn-modal-cancel {
  background: #f1f5f9; color: var(--danger);
  border: 1.5px solid #fca5a5;
  padding: 9px 18px; border-radius: 7px;
  font-size: 0.88rem; font-weight: 700; cursor: pointer;
  transition: background 0.15s;
}
.btn-modal-cancel:hover { background: #fee2e2; }
.btn-modal-save {
  background: var(--accent-primary); color: #ffffff;
  border: none; padding: 9px 22px; border-radius: 7px;
  font-size: 0.88rem; font-weight: 800; cursor: pointer;
  box-shadow: 0 2px 6px var(--accent-glow);
  transition: background 0.15s;
}
.btn-modal-save:hover { background: var(--accent-hover); }

/* ── MODAL HEADER LEGACY (mantener compatibilidad) ─────────── */
.modal-content {
  background-color: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--card-radius);
  width: 90%; max-width: 600px;
  max-height: 90vh; overflow-y: auto; padding: 1.5rem;
}
.close-btn { background: transparent; border: none; color: var(--text-secondary); font-size: 1.4rem; cursor: pointer; }

/* ── EPP INPUTS ──────────────────────────────────────────────── */
.epp-input-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(175px, 1fr)); gap: 10px; }
.epp-input-card {
  background: var(--bg-secondary);
  border: 1.5px solid var(--border-color);
  border-radius: 8px; padding: 9px 11px;
  display: flex; flex-direction: column; gap: 5px;
}
.epp-input-card label { font-size: 0.78rem; font-weight: 700; color: var(--text-secondary); }
.num-input { text-align: center !important; font-weight: 800 !important; color: var(--accent-primary) !important; }

.worker-badge-info {
  background: var(--accent-light);
  border: 1.5px solid #93c5fd;
  border-radius: 7px; padding: 9px 13px;
  font-size: 0.84rem; color: var(--accent-primary);
}

/* ── TOASTS ──────────────────────────────────────────────────── */
.toast-container {
  position: fixed; bottom: 20px; right: 20px;
  display: flex; flex-direction: column; gap: 8px; z-index: 9999;
}
.toast {
  background: var(--bg-secondary); color: var(--text-primary);
  border: 1px solid var(--border-color);
  padding: 11px 16px; border-radius: 9px;
  box-shadow: 0 6px 20px rgba(0,0,0,0.15);
  font-size: 0.88rem;
  display: flex; align-items: center; gap: 9px;
  animation: slideIn 0.25s forwards;
}
/* Severidad del aviso.
   showToast() recibe un tipo desde siempre ('info', 'success', 'error') y lo
   pega como clase, pero ninguna variante tenía estilo: un "otra persona pisó su
   cambio" se veía idéntico a un "guardado". Con el control de concurrencia
   activo hay avisos que la persona NO puede pasar por alto, así que la
   severidad se distingue aquí, en un solo sitio, en vez de que cada vista
   invente su color. El borde izquierdo grueso es lo que se ve de reojo. */
.toast-success { border-left: 4px solid #15803d; }
.toast-info    { border-left: 4px solid #1d4ed8; }
.toast-warning { border-left: 4px solid #b45309; background: #fffbeb; color: #78350f; }
.toast-error   { border-left: 4px solid #b91c1c; background: #fef2f2; color: #7f1d1d; font-weight: 600; }
/* Un conflicto de guardado se lee en varias líneas: el ancho fijo evita que el
   texto salga en una tira de una sola línea contra el borde de la pantalla. */
.toast-error, .toast-warning { max-width: 420px; line-height: 1.4; align-items: flex-start; }
@keyframes slideIn {
  from { transform: translateX(100%); opacity: 0; }
  to   { transform: translateX(0); opacity: 1; }
}

/* ── BADGES ──────────────────────────────────────────────────── */
.badge { display: inline-flex; align-items: center; padding: 3px 9px; border-radius: 16px; font-size: 0.73rem; font-weight: 700; }
.badge-success { background: #dcfce7; color: #15803d; }
.badge-warning { background: #fef3c7; color: #92400e; }
.badge-danger  { background: #fee2e2; color: #991b1b; }

.priority-badge { padding: 3px 9px; border-radius: 10px; font-weight: 700; font-size: 0.75rem; display: inline-block; text-align: center; text-transform: uppercase; }
.priority-alta  { background: #fee2e2; color: #991b1b; border: 1px solid #fca5a5; }
.priority-media { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; }
.priority-baja  { background: #dcfce7; color: #166534; border: 1px solid #86efac; }

.task-status-badge { padding: 3px 9px; border-radius: 10px; font-weight: 700; font-size: 0.75rem; display: inline-block; text-align: center; text-transform: uppercase; }
.status-cumplida    { background: #dcfce7; color: #15803d; border: 1px solid #bbf7d0; }
.status-en-proceso  { background: #ffedd5; color: #c2410c; border: 1px solid #fed7aa; }
.status-atrasada    { background: #fee2e2; color: #b91c1c; border: 1px solid #fca5a5; }
.status-sin-iniciar { background: #f1f5f9; color: #475569; border: 1px solid #cbd5e1; }

.badge-alert-count {
  background: #fee2e2; color: #991b1b;
  border: 1px solid #fca5a5;
  padding: 3px 9px; border-radius: 16px;
  font-size: 0.78rem; font-weight: 800;
  display: inline-flex; align-items: center; gap: 4px;
}

/* ── MÓDULO SELECTOR ─────────────────────────────────────────── */
/* ── SELECTOR DE MÓDULOS — pantalla de bienvenida ───────────────
   FIX: con minmax(240px,1fr) y 5 tarjetas a 1366px solo caben 4 y la
   quinta aparece cortada en segunda fila. Con 190px las 5 caben desde
   ~1050px. El selector ya no usa min-height:100vh sino min-height:100%
   para no depender del tamaño real de la ventana del navegador. */
.modules-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 18px;
  max-width: 1080px;
  margin: 0 auto;
  width: 100%;
}

.module-card {
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: 16px;
  padding: 26px 22px 22px;
  text-align: left; cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
  box-shadow: var(--card-shadow);
  display: flex; flex-direction: column;
  position: relative; overflow: hidden;
  width: auto;               /* la rejilla define el ancho */
  min-height: 190px;
}
/* Franja de color a la izquierda, siempre visible (identidad del módulo) */
/* Aquí había una franja de acento de 5px a la izquierda de cada tarjeta.
   Se retira: el icono con fondo teñido ya distingue el módulo, y la franja
   duplicaba esa señal insinuando además una jerarquía entre módulos que no
   existe —todos valen igual—. El color del módulo sigue vivo en el icono y
   en el borde al pasar el cursor. */
.module-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 14px 30px rgba(15,23,42,0.14);
  border-color: var(--m-color, var(--accent-primary));
}
/* Flecha de "entrar" que aparece al pasar el cursor */
.module-card::after {
  content: '→';
  position: absolute; right: 20px; bottom: 18px;
  font-size: 1.2rem; font-weight: 800;
  color: var(--m-color, var(--accent-primary));
  opacity: 0; transform: translateX(-6px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.module-card:hover::after { opacity: 1; transform: translateX(0); }

/* Color por módulo, en una sola variable que alimenta franja, flecha e icono */
.module-card.m-epp     { --m-color: #1a56db; }
.module-card.m-tools   { --m-color: #0369a1; }
.module-card.m-tasks   { --m-color: #15803d; }
.module-card.m-payroll { --m-color: #6d28d9; }
.module-card.m-portal  { --m-color: #047857; }

.module-icon-wrapper {
  width: 56px; height: 56px; border-radius: 14px;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 16px; font-size: 1.8rem;
  background: color-mix(in srgb, var(--m-color, var(--accent-primary)) 14%, transparent);
}
/* Respaldo para navegadores sin color-mix */
.m-epp    .module-icon-wrapper { background: var(--accent-light); }
.m-tools  .module-icon-wrapper { background: #e0f2fe; }
.m-tasks  .module-icon-wrapper { background: #dcfce7; }
.m-payroll .module-icon-wrapper { background: #ede9fe; }
.m-portal  .module-icon-wrapper { background: #d1fae5; }

.module-card h3 { margin: 0 0 8px; font-size: 1.06rem; font-weight: 800; color: var(--text-primary); }
.module-card p  { margin: 0; font-size: 0.84rem; color: #64748b; line-height: 1.5; }

/* Encabezado de la pantalla de bienvenida */
.selector-hero {
  text-align: center;
  margin-bottom: 34px;
}
.selector-hero .hero-badge {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--accent-light); color: var(--accent-primary);
  font-weight: 800; font-size: 0.72rem; letter-spacing: 1px;
  text-transform: uppercase;
  padding: 6px 14px; border-radius: 20px;
  margin-bottom: 16px;
}
.selector-hero h1 {
  font-size: 2rem; font-weight: 800; color: var(--text-primary);
  letter-spacing: -0.5px; margin-bottom: 8px;
}
.selector-hero p { color: var(--text-secondary); font-size: 1rem; }

/* ── SELECTOR DE MÓDULOS (dentro de sidebar) ─────────────────── */
.module-selector { display: flex; background: var(--bg-primary); padding: 3px; border-radius: 8px; border: 1px solid var(--border-color); gap: 3px; }
.module-tab { flex: 1; padding: 7px 8px; border: none; background: transparent; color: var(--text-secondary); font-size: 0.78rem; font-weight: 700; border-radius: 6px; cursor: pointer; transition: all 0.15s; }
.module-tab:hover { color: var(--text-primary); }
.module-tab.active { background: var(--accent-primary); color: #ffffff; }

/* ── KANBAN ──────────────────────────────────────────────────── */
.kanban-board { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: 14px; align-items: flex-start; }
.kanban-column { background: var(--bg-table-alt); border-radius: 10px; border: 1px solid var(--border-color); display: flex; flex-direction: column; max-height: 80vh; }
.kanban-col-header { padding: 12px 14px; display: flex; align-items: center; justify-content: space-between; border-bottom: 2px solid var(--border-color); font-weight: 800; font-size: 0.88rem; }
.kanban-col-cards { padding: 10px; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; flex: 1; min-height: 100px; }
.kanban-card {
  background: var(--bg-card); border-radius: 9px;
  border: 1px solid var(--border-color); padding: 12px;
  box-shadow: var(--card-shadow);
  transition: transform 0.15s, box-shadow 0.15s; cursor: grab;
}
.kanban-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(26,86,219,0.12); border-color: var(--accent-primary); }
.kanban-card-title { font-size: 0.88rem; font-weight: 700; color: var(--text-primary); margin-bottom: 7px; line-height: 1.35; }
.kanban-card-meta  { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 8px; }
.kanban-badge { font-size: 0.7rem; font-weight: 800; padding: 2px 7px; border-radius: 5px; text-transform: uppercase; }
.kanban-card-footer { display: flex; align-items: center; justify-content: space-between; border-top: 1px solid var(--border-color); padding-top: 8px; margin-top: 6px; font-size: 0.78rem; color: var(--text-secondary); }

/* ── TIMELINE HERRAMIENTAS ───────────────────────────────────── */
.tool-timeline { position: relative; padding-left: 26px; border-left: 2px solid var(--border-color); margin: 12px 0; }
.timeline-item  { position: relative; margin-bottom: 18px; }
.timeline-dot   { position: absolute; left: -33px; top: 2px; width: 13px; height: 13px; border-radius: 50%; background: var(--accent-primary); border: 3px solid var(--bg-secondary); box-shadow: 0 0 0 2px var(--accent-primary); }
.timeline-dot.return { background: var(--success); box-shadow: 0 0 0 2px var(--success); }
.timeline-box   { background: var(--bg-table-alt); padding: 10px 14px; border-radius: 7px; border: 1px solid var(--border-color); }

/* ── STOCK BADGES ────────────────────────────────────────────── */
.stock-badge-critical { background: #fee2e2; color: #991b1b; border: 1px solid #fca5a5; font-weight: 800; padding: 3px 7px; border-radius: 5px; font-size: 0.75rem; display: inline-flex; align-items: center; gap: 3px; }
.stock-badge-reorder  { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; font-weight: 800; padding: 3px 7px; border-radius: 5px; font-size: 0.75rem; display: inline-flex; align-items: center; gap: 3px; }
.stock-badge-optimal  { background: #dcfce7; color: #166534; border: 1px solid #86efac; font-weight: 800; padding: 3px 7px; border-radius: 5px; font-size: 0.75rem; display: inline-flex; align-items: center; gap: 3px; }

/* ── DASHBOARD CHARTS ────────────────────────────────────────── */
.dashboard-charts-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(430px, 1fr)); gap: 18px; margin-bottom: 20px; }
.chart-card { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 11px; padding: 18px; box-shadow: var(--card-shadow); }
.chart-card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; padding-bottom: 9px; border-bottom: 1px solid var(--border-color); }
.chart-card-title  { font-size: 0.95rem; font-weight: 800; color: var(--accent-primary); display: flex; align-items: center; gap: 7px; }
.chart-bar-list  { display: flex; flex-direction: column; gap: 10px; }
.chart-bar-item  { display: flex; flex-direction: column; gap: 3px; }
.chart-bar-info  { display: flex; justify-content: space-between; font-size: 0.83rem; font-weight: 700; }
.chart-bar-track { height: 11px; background: var(--bg-table-alt); border-radius: 5px; overflow: hidden; }
.chart-bar-fill  { height: 100%; border-radius: 5px; transition: width 0.7s cubic-bezier(0.4,0,0.2,1); }
/* Barras de progreso en color plano. El gradiente hacía que el mismo valor
   se leyera distinto según el ancho de la barra, porque el tono cambiaba a
   lo largo del recorrido. Un color plano es comparable entre filas. */
.fill-blue   { background: var(--accent-primary); }
.fill-green  { background: var(--success); }
.fill-amber  { background: var(--warning); }
.fill-red    { background: var(--danger); }
.fill-purple { background: #6d28d9; }
.chart-bar-row { display: flex; align-items: center; gap: 10px; padding: 5px 0; border-bottom: 1px solid var(--border-color); }
.chart-bar-label { width: 135px; font-size: 0.8rem; font-weight: 700; color: var(--text-secondary); text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chart-bar-val  { width: 44px; font-size: 0.8rem; font-weight: 800; color: var(--accent-primary); }

/* ── NÓMINA DESPRENDIBLE ─────────────────────────────────────── */
.payslip-doc { background: #ffffff; color: #0f172a; font-family: -apple-system, sans-serif; line-height: 1.35; border: 1px solid #cbd5e1; padding: 22px; border-radius: 8px; }
.payslip-doc-header { border-bottom: 2px solid #0f172a; padding-bottom: 10px; margin-bottom: 14px; text-align: center; }
.payslip-company-title { font-size: 1.05rem; font-weight: 900; color: #0f172a; text-transform: uppercase; }
.payslip-company-nit   { font-size: 0.85rem; font-weight: 800; color: #475569; margin-top: 3px; }
.payslip-period-banner { background: #f1f5f9; border: 1px solid #cbd5e1; border-radius: 5px; padding: 5px 10px; margin: 8px 0; font-size: 0.88rem; font-weight: 800; }
.payslip-doc-subtitle  { font-size: 0.95rem; font-weight: 900; color: #0f172a; letter-spacing: 0.05em; margin-top: 5px; }
.payslip-table { width: 100%; border-collapse: collapse; margin-bottom: 14px; font-size: 0.82rem; }
.payslip-table th, .payslip-table td { border: 1px solid #cbd5e1; padding: 5px 7px; }
.payslip-table th { background: #0f172a; color: #ffffff; font-weight: 800; text-align: center; font-size: 0.75rem; text-transform: uppercase; }
.payslip-table .payslip-subtotal td { background: #f1f5f9; font-weight: 800; }
/* Fila de datos del trabajador: dos o tres celdas con fondo tenue, sin encabezado. */
.payslip-data-row { margin-bottom: 12px; }
.payslip-data-row td { border: 1px solid #e2e8f0; background: #f8fafc; font-size: 0.84rem; }
/* Devengos y deducciones lado a lado. */
.payslip-two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: start; }
.payslip-net-box { display: flex; justify-content: space-between; align-items: center; background: #f8fafc; border: 2px solid #0f172a; border-radius: 7px; padding: 11px 16px; margin: 6px 0 18px; font-size: 1.05rem; font-weight: 900; color: #0f172a; }
.payslip-net-val { font-size: 1.35rem; font-weight: 900; color: #0070c0; }
.payslip-recibi { margin-top: 18px; }
.payslip-bank-note { font-size: 0.78rem; color: #475569; margin-top: 6px; }
.payslip-sign-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 36px; margin-top: 26px; padding-top: 16px; }
.payslip-sign-box { border-top: 1px solid #0f172a; text-align: center; padding-top: 5px; font-size: 0.82rem; font-weight: 700; }

/* ── ACTA FOE ────────────────────────────────────────────────── */
.foe-acta-container { background: #ffffff; color: #0f172a; border: 2px solid #0f172a; padding: 22px; font-family: 'Inter', sans-serif; border-radius: 7px; }
.foe-header-table { width: 100%; border-collapse: collapse; margin-bottom: 14px; }
.foe-header-table td { border: 1.5px solid #0f172a; padding: 7px 10px; vertical-align: middle; }
.foe-header-title  { text-align: center; font-weight: 800; font-size: 13px; color: #0f172a; text-transform: uppercase; }
.foe-info-section  { background: #f8fafc; border: 1px solid #cbd5e1; padding: 10px 14px; border-radius: 5px; margin-bottom: 14px; }
.foe-info-grid     { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; }
.foe-info-item     { font-size: 0.83rem; }
.foe-info-item strong { color: #0f172a; }
.foe-legal-text    { background: #f1f5f9; border: 1px solid #cbd5e1; padding: 10px 14px; border-radius: 5px; font-size: 0.76rem; line-height: 1.5; text-align: justify; margin-top: 16px; color: #334155; }
.foe-signatures-container { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; margin-top: 28px; text-align: center; }
.foe-signature-box { border-top: 1.5px solid #0f172a; padding-top: 7px; font-size: 0.83rem; font-weight: 700; }
.foe-sizes-table   { width: 100%; border-collapse: collapse; margin-bottom: 10px; font-size: 0.76rem; }
.foe-sizes-table th, .foe-sizes-table td { border: 1px solid #0f172a; padding: 3px 5px; text-align: center; }
.foe-sizes-table th { background: var(--accent-primary); color: #ffffff; font-weight: 700; }
.foe-sizes-table td.label-col { background: #f1f5f9; font-weight: 700; text-align: left; }
.foe-sizes-table td.selected-size { background: #fef08a; font-weight: 800; color: #854d0e; }

/* ── RESUMEN CORPORATIVO ─────────────────────────────────────── */
.summary-card-corporate { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 8px; padding: 9px 13px; text-align: center; box-shadow: var(--card-shadow); }
.summary-card-label { font-size: 0.72rem; font-weight: 700; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.5px; display: block; }
.summary-card-value { font-size: 1.2rem; font-weight: 800; color: var(--accent-primary); margin-top: 2px; }

/* ── ELIMINACIÓN ─────────────────────────────────────────────── */
.btn-delete-text {
  background: #fef2f2; border: 1px solid #fca5a5;
  border-radius: 5px; padding: 3px 9px; cursor: pointer;
  display: inline-flex; align-items: center; gap: 4px;
  transition: all 0.15s;
}
.btn-delete-text:hover { background: #fee2e2; border-color: #f87171; }

/* ── MÉTRICAS ────────────────────────────────────────────────── */
.metric-bar-cell { position: relative; display: flex; align-items: center; justify-content: flex-end; padding: 3px 7px; min-height: 26px; }
/* Tinte plano de acción: la barra mide magnitud con su ancho, no con el tono.
   Con gradiente, dos filas del mismo valor se veían de distinto color. */
.metric-bar-bg { position: absolute; left: 0; top: 3px; bottom: 3px; background: rgba(26,86,219,0.16); border-radius: var(--radio-sm); z-index: 1; }
.metric-bar-val { position: relative; z-index: 2; font-weight: 700; font-size: 0.85rem; color: var(--text-primary); }

/* ── UTILIDADES ──────────────────────────────────────────────── */
.mb-3 { margin-bottom: 1rem; }
.mb-4 { margin-bottom: 1.5rem; }

/* ── RITMO VERTICAL UNIFORME ENTRE BLOQUES DE UNA VISTA ──────────
   Se midieron separaciones de 16, 18, 24 y 30px mezcladas entre los
   bloques de una misma vista, según llevaran .mb-4, un margen inline o
   ninguno. Además de verse desigual, ese espacio se acumula: en Nómina
   Maestra los cuatro huecos sumaban 78px que la tabla no podía usar.

   Se fija una separación única de 14px para los hijos directos de una
   vista. No se toca el tamaño de ningún componente ni de la tipografía:
   solo el aire entre bloques, que es lo que estaba disparejo. */
.app-view.active > * { margin-bottom: 14px; }
.app-view.active > *:last-child { margin-bottom: 0; }
/* La utilidad .mb-4 dentro de una vista se alinea al mismo ritmo */
.app-view.active > .mb-4,
.app-view.active > .mb-3 { margin-bottom: 14px; }
.mt-3 { margin-top: 1rem; }
.text-warning { color: var(--warning); }
.text-danger  { color: var(--danger); }
.text-muted   { color: var(--text-secondary); }
.text-currency-stock  { color: var(--success) !important; font-weight: 800; }
.text-currency-spent  { color: var(--danger) !important; font-weight: 800; }
.number-center { text-align: center; }
.kits-bar { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; padding: 9px; background: var(--bg-secondary); border-radius: 9px; border: 1px solid var(--border-color); }
.kits-title { font-size: 0.83rem; font-weight: 700; color: var(--accent-primary); }
.btn-kit { background: var(--accent-light); color: var(--accent-primary); border: 1px solid var(--border-color); padding: 5px 11px; border-radius: 7px; font-size: 0.78rem; font-weight: 700; cursor: pointer; transition: all 0.15s; }
.btn-kit:hover { background: var(--accent-primary); color: white; }

/* ── ANIMACIONES ─────────────────────────────────────────────── */
@keyframes pulse-alert {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.82; }
}

/* ── SCROLL SINCRONIZADO (JS lo usa) ─────────────────────────── */
/* ═══════════════════════════════════════════════════════════════
   .excel-grid-table — CUADRÍCULAS ANCHAS (EPP y Nómina)
   ═══════════════════════════════════════════════════════════════
   Este bloque estaba vacío, así que el aspecto de las tablas de 47, 44,
   39 y 27 columnas dependía por completo de los estilos inline de cada
   <th>. Como 42 de las 47 columnas de Movimientos no declaraban ancho,
   el navegador las comprimía y los nombres se cortaban.

   Ahora la cuadrícula tiene reglas propias: ancho por contenido, ancho
   mínimo por columna y bordes de celda. */
.excel-grid-table {
  /* Crece con el contenido pero nunca deja huecos si sobra espacio */
  width: max-content;
  min-width: 100%;
  border-collapse: separate;   /* requisito del encabezado sticky */
  border-spacing: 0;
  font-size: 0.82rem;
}

.excel-grid-table th {
  /* El nombre de la columna se lee completo en una línea */
  white-space: nowrap;
  /* Ancho mínimo para que las columnas sin medida declarada no se
     compriman hasta cortar el texto */
  min-width: 92px;
  padding: 8px 10px;
  font-weight: 700;
  font-size: 0.76rem;
  letter-spacing: 0.3px;
  vertical-align: middle;
  text-align: center;
  border-right: 1px solid rgba(255,255,255,0.18);
  border-bottom: 2px solid rgba(255,255,255,0.28);
  /* Evita que el fondo del encabezado se pinte bajo el borde al hacer
     scroll con position: sticky */
  background-clip: padding-box;
}

.excel-grid-table td {
  padding: 5px 8px;
  border-bottom: 1px solid var(--border-color);
  border-right: 1px solid var(--border-color);
  color: var(--text-primary);
  background: var(--bg-card);
  vertical-align: middle;
  white-space: nowrap;
}

.excel-grid-table tbody tr:nth-child(even) td { background-color: var(--bg-table-alt); }
.excel-grid-table tbody tr:hover td { background-color: var(--accent-light) !important; }

.excel-grid-table tfoot td,
.excel-grid-table tfoot th {
  background: var(--th-bg) !important;
  color: #ffffff !important;
  font-weight: 800;
  border-color: rgba(255,255,255,0.2);
}

/* Las columnas numéricas de EPP no necesitan 92px: son de 1 o 2 dígitos.
   Se marcan con un ancho menor para no desperdiciar ancho útil. */
.excel-grid-table th.col-num { min-width: 62px; }

/* ── COLUMNAS DE IDENTIFICACIÓN ─────────────────────────────────
   Las clases col-sticky-1/2/3 (Movimientos y Consumos) solo traían reglas
   de posición, sin ancho, así que heredaban el mínimo genérico: el número
   de fila quedaba demasiado ancho y el nombre del trabajador demasiado
   angosto. Se les da la medida que corresponde a su contenido. */
.excel-grid-table th.col-sticky-1 { min-width: 46px;  width: 46px;  text-align: center; }
.excel-grid-table th.col-sticky-2 { min-width: 112px; text-align: left; }
.excel-grid-table th.col-sticky-3 { min-width: 210px; text-align: left; }

/* El nombre del trabajador es el dato de lectura de la fila, así que se
   alinea a la izquierda. Se limita a las dos cuadrículas que tienen el
   nombre en la tercera columna (Movimientos y Consumos); en Ingresos e
   Inventario esa posición es una cantidad y debe ir centrada. */
#view-movimientos .excel-grid-table tbody td:nth-child(3),
#view-consumos   .excel-grid-table tbody td:nth-child(3) { text-align: left; }

/* ── COLUMNAS DE IDENTIFICACIÓN EN LA CUADRÍCULA EPP ────────────
   FIX: los nombres se cortaban porque 210px es insuficiente para nombres
   colombianos compuestos de cuatro palabras. Con 240px
   cabe la mayoría sin cortar. Los nombres más largos siguen mostrando
   elipsis — eso es correcto: el usuario puede agrandar la columna. */
.excel-grid-table th.col-sticky-1 { min-width: 46px;  width: 46px;  text-align: center; }
.excel-grid-table th.col-sticky-2 { min-width: 110px; text-align: left; }
.excel-grid-table th.col-sticky-3 { min-width: 240px; text-align: left; }

/* Texto de la celda: una sola línea, truncado con elipsis si desborda.
   Es mejor que verlo partido en dos líneas dentro de la cuadrícula. */
.excel-grid-table tbody td.col-sticky-2,
.excel-grid-table tbody td.col-sticky-3 {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 240px;   /* activa el truncado solo cuando la columna se comprime */
}

/* Las celdas bajo un encabezado vertical son cantidades: centradas y
   angostas, para que la columna no se ensanche por el contenido. */
.excel-grid-table td.cell-qty { text-align: center; min-width: 40px; }

/* ── ENCABEZADOS VERTICALES ─────────────────────────────────────
   .th-vertical solo tenía estilos dentro de @media print, así que en
   pantalla los 40 encabezados de Consumos se dibujaban en horizontal y
   la tabla se volvía larguísima. Al girarlos, la misma tabla pasa de
   unos 4.000 px de ancho a caber casi entera. */
.excel-grid-table th.th-vertical,
th.th-vertical {
  height: 150px;
  min-width: 40px;
  max-width: 44px;
  padding: 8px 3px;
  vertical-align: bottom;
  text-align: center;
}

th.th-vertical > span {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  display: inline-block;
  white-space: nowrap;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.2px;
  line-height: 1;
}

/* El tirador de redimensionar no aplica a columnas verticales: su ancho
   lo define el texto girado. */
th.th-vertical .sgi-col-resizer { display: none; }

/* ── ENCABEZADO DE GRUPO DE TALLAS ──────────────────────────────
   Las diez columnas de talla pertenecen a dos prendas. El rótulo del grupo
   (CHAQUETA DE VAQUETA / PANTALÓN DE VAQUETA) va horizontal y centrado sobre
   sus cinco columnas; debajo va la talla corta. Se reutiliza el tono del
   encabezado de tabla para no introducir un color nuevo. */
th.th-grupo-talla {
  background: var(--tabla-thead-bg);
  color: var(--tabla-thead-fg);
  text-align: center;
  vertical-align: middle;
  white-space: nowrap;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  padding: 6px 4px;
  border-right: 1px solid var(--tabla-thead-borde);
  border-bottom: 1px solid var(--tabla-thead-borde);
}

/* Talla corta bajo cada prenda: caja angosta como la de las columnas
   verticales, pero con el texto horizontal para que S/M/L/XL/XXL se lea
   sin cortar. */
th.th-grupo-talla-sub {
  background: var(--tabla-thead-bg);
  color: var(--tabla-thead-fg);
  text-align: center;
  vertical-align: middle;
  min-width: 40px;
  max-width: 44px;
  padding: 6px 3px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.3px;
}

th.th-grupo-talla-sub .sgi-col-resizer { display: none; }

/* ── EXCEL CELL INPUTS (legacy class, mantenida para compatibilidad) ── */
.excel-cell-input {
  width: 100%;
  background: #ffffff;
  color: #0a0f1e;
  border: 1px solid #c7d9ed;
  border-radius: 4px;
  padding: 4px 6px;
  font-weight: 600;
  font-size: 0.82rem;
  transition: border-color 0.15s;
}
body.dark-theme .excel-cell-input { background: #1a2d42; color: #e8f0fb; border-color: #2d4a6e; }
.excel-cell-input:focus {
  border-color: var(--accent-primary) !important;
  background: #f0f7ff !important;
  outline: none;
  box-shadow: 0 0 0 2px var(--accent-glow);
}

/* ── FIRMA DIGITAL ───────────────────────────────────────────── */
.signature-container { display: flex; flex-direction: column; align-items: center; background: #ffffff; border-radius: 9px; padding: 10px; border: 2px dashed var(--border-color); }
#signature-canvas { touch-action: none; cursor: crosshair; background: #ffffff; border-radius: 5px; }
.signature-actions { display: flex; justify-content: space-between; align-items: center; width: 100%; margin-top: 8px; padding-top: 7px; border-top: 1px solid var(--border-color); }
.signature-status { font-size: 0.83rem; color: var(--text-secondary); font-weight: 600; }

/* ═══════════════════════════════════════════════════════════════
   TIPOGRAFÍA UNIFICADA DE ENCABEZADOS DE TABLA
   ═══════════════════════════════════════════════════════════════
   Se midieron 9 combinaciones distintas de tamaño, grosor, mayúsculas
   y espaciado entre los encabezados del sistema: desde 11,2px sin
   transformar hasta 13,12px, unos en mayúsculas y otros no. Eso hacía
   que dos tablas contiguas se vieran de familias distintas.

   Se unifica SOLO la tipografía. El color de fondo se deja intacto a
   propósito: en las tablas anchas agrupa columnas por significado
   (devengados, deducciones, tallas, alturas) y perder eso restaría
   legibilidad en lugar de sumarla.

   El !important es necesario porque 45 encabezados traían el tamaño o el
   grosor en el atributo style, que gana sobre la hoja de estilos. */
thead th,
.custom-table thead th,
.excel-grid-table thead th,
.s-table th {
  font-size: 0.76rem !important;
  font-weight: 700 !important;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  line-height: 1.25;
}

/* Los encabezados girados conservan su tamaño propio: el texto va en
   vertical y necesita algo menos de cuerpo para caber en 40px. */
thead th.th-vertical {
  font-size: 0.72rem !important;
  letter-spacing: 0.3px;
}

/* ═══════════════════════════════════════════════════════════════
   SISTEMA ÚNICO DE TABLAS
   ═══════════════════════════════════════════════════════════════
   PROBLEMA QUE RESUELVE
   Había 32 colores de fondo distintos en encabezados de tabla, escritos
   como style="background:..." en index.html y en los módulos que generan
   tablas. Cada vista parecía de un sistema diferente y, al ir en línea,
   ganaban sobre la hoja de estilos: era imposible unificarlo desde aquí.

   REFERENCIA
   La vista "Alertas de Vencimiento" (#epp-venc-table): encabezado slate
   oscuro sobre fila más oscura, celdas de 8px, cuerpo de 0.82rem, una
   sola línea por encabezado, columnas descriptivas a la izquierda y
   numéricas centradas.

   REGLA
   El fondo del encabezado es estructural y sale de --tabla-thead-bg.
   La única variante admitida es --tabla-thead-bg-fija, para el bloque de
   columnas congeladas, que necesita distinguirse cuando la tabla se
   desplaza en horizontal por debajo. El color con significado (vencido,
   crítico, alerta, estado) vive DENTRO de las celdas del cuerpo, nunca
   en las cabeceras. La comprobación "Unificación de color de encabezado"
   de audit/audit-ui.js exige como máximo 2 tonos distintos por tabla.

   DEUDA DE DISEÑO PENDIENTE (no se toca aquí)
   Los encabezados girados verticalmente (.th-vertical, 124 casos) siguen
   en pie. No son un descuido de color: Movimientos y Consumos tienen
   entre 39 y 47 columnas numéricas y, en horizontal, la tabla pasa de
   unos 4.000 px de ancho. Girarlos fue la única forma de que cupieran.
   Quitarlos exige rediseñar esas dos cuadrículas —agrupar elementos por
   categoría, paginar columnas o pasar a una vista por trabajador—, así
   que queda documentado como deuda pendiente de ese rediseño y fuera del
   alcance de la unificación de color. */

/* Alcance: las tres familias de tabla del sistema más las tablas que
   traen id propio. Se enumeran los id porque varias no llevan clase y su
   único estilo era el atributo inline que se retiró. */
.custom-table thead th,
.excel-grid-table thead th,
.s-table thead th,
.sgi-table thead th,
.payslip-table thead th,
#epp-venc-table thead th,
#epp-stock-table thead th,
#epp-cumpl-table thead th,
#sst-eventos-table thead th,
#sst-riesgos-table thead th,
#sst-plan-table thead th,
#bk-table thead th,
#nomina-maestro-table thead th,
#tasks-metrics-table thead th,
#payroll-rates-table thead th,
#reten-tabla-uvt thead th,
#liq-historial-table thead th,
#apr-solicitudes-table thead th,
#sol-mis-solicitudes-table thead th,
table[data-sgi-enhanced] thead th {
  background: var(--tabla-thead-bg);
  color: var(--tabla-thead-fg);
  border-right: 1px solid var(--tabla-thead-borde);
  border-bottom: 2px solid var(--tabla-thead-borde);
  /* Sin esto el fondo se pinta bajo el borde al desplazar con sticky y la
     fila de encabezado se ve partida. */
  background-clip: padding-box;
  white-space: nowrap;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

/* La fila del encabezado lleva el tono más oscuro: es lo que se ve por
   las juntas entre celdas y bajo el bloque de columnas congeladas. */
.custom-table thead tr,
.excel-grid-table thead tr,
.s-table thead tr,
.sgi-table thead tr,
#epp-venc-table thead tr,
#epp-stock-table thead tr,
#epp-cumpl-table thead tr,
#sst-eventos-table thead tr,
#sst-riesgos-table thead tr,
#sst-plan-table thead tr,
#bk-table thead tr,
#nomina-maestro-table thead tr,
#tasks-metrics-table thead tr,
#payroll-rates-table thead tr,
#reten-tabla-uvt thead tr,
#liq-historial-table thead tr,
table[data-sgi-enhanced] thead tr {
  background: var(--tabla-thead-bg-fija);
}

/* Medida de celda: la del patrón de referencia. Se excluyen los girados,
   que necesitan su propia caja de 40px de ancho, y .s-table, cuyo padding
   va dentro de .th-inner junto a los controles de orden y filtro. */
.custom-table thead th:not(.th-vertical),
.excel-grid-table thead th:not(.th-vertical),
#epp-venc-table thead th,
#epp-stock-table thead th,
#epp-cumpl-table thead th,
#sst-eventos-table thead th,
#sst-riesgos-table thead th,
#sst-plan-table thead th,
#bk-table thead th,
#nomina-maestro-table thead th,
#tasks-metrics-table thead th,
#payroll-rates-table thead th,
#reten-tabla-uvt thead th,
#liq-historial-table thead th,
#apr-solicitudes-table thead th,
#sol-mis-solicitudes-table thead th,
.sgi-table thead th {
  padding: var(--tabla-celda-pad-y) var(--tabla-celda-pad-x);
  font-size: var(--tabla-fuente);
}

/* Única variante de color admitida: el bloque congelado a la izquierda.
   Solo aplica mientras la columna esté realmente congelada; cuando
   table-enhancer.js la libera (.sgi-unfrozen) vuelve al tono base y la
   tabla queda con un solo color de encabezado. */
thead th.col-sticky-1:not(.sgi-unfrozen),
thead th.col-sticky-2:not(.sgi-unfrozen),
thead th.col-sticky-3:not(.sgi-unfrozen) {
  background: var(--tabla-thead-bg-fija);
}

/* Las variaciones de tono por grupo de columnas dejan de pintar: agrupar
   columnas se comunica con el texto del encabezado, no con el color.
   Las clases se conservan para no tener que editar el marcado. */
.th-g2,
.th-g3 {
  background: var(--tabla-thead-bg) !important;
}

/* Alineación: descriptivo a la izquierda, numérico centrado. Es lo que
   permite recorrer una columna de cifras de un vistazo. */
.custom-table thead th.col-num,
.excel-grid-table thead th.col-num,
thead th.cell-qty,
thead th.th-num { text-align: center; }
.custom-table thead th.col-txt,
.excel-grid-table thead th.col-txt,
thead th.col-sticky-2,
thead th.col-sticky-3 { text-align: left; }

/* Franja alterna y realce del cuerpo. Se declara aquí para que las tres
   familias de tabla compartan el mismo ritmo de lectura. */
.custom-table tbody tr:nth-child(even) > td,
#epp-venc-table tbody tr:nth-child(even) > td,
#epp-stock-table tbody tr:nth-child(even) > td,
#epp-cumpl-table tbody tr:nth-child(even) > td,
#sst-eventos-table tbody tr:nth-child(even) > td,
#sst-riesgos-table tbody tr:nth-child(even) > td,
#sst-plan-table tbody tr:nth-child(even) > td,
#bk-table tbody tr:nth-child(even) > td,
#nomina-maestro-table tbody tr:nth-child(even) > td,
#tasks-metrics-table tbody tr:nth-child(even) > td,
#payroll-rates-table tbody tr:nth-child(even) > td,
#reten-tabla-uvt tbody tr:nth-child(even) > td,
#liq-historial-table tbody tr:nth-child(even) > td {
  background-color: var(--tabla-fila-alt);
}

/* Pies de tabla (totales): mismo tono que el encabezado, para que se lean
   como cierre de la cuadrícula y no como un dato más. */
.custom-table tfoot tr,
.custom-table tfoot th,
.custom-table tfoot td,
.excel-grid-table tfoot th,
.excel-grid-table tfoot td,
.s-table tfoot td {
  background: var(--tabla-thead-bg) !important;
  color: var(--tabla-thead-fg) !important;
  font-weight: 800;
}

/* Banda de agrupación dentro del cuerpo (Nómina Maestra separa
   trabajadores por horas y fijos). Antes cada grupo traía su propio color
   en línea; ahora es un único tono y el grupo se distingue por su texto,
   que es la forma accesible de comunicarlo. */
.tabla-banda-grupo > td,
.tabla-banda-grupo > th {
  background: var(--tabla-thead-bg-fija) !important;
  color: var(--tabla-thead-fg) !important;
}

/* ── INDICADOR DE ORIENTACIÓN EN LOS BOTONES DE IMPRIMIR ─────────
   Cada botón declara si la hoja saldrá horizontal o vertical, para que
   el usuario sepa qué esperar antes de abrir el diálogo del navegador. */
.print-orient {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.22);
  border: 1px solid rgba(255, 255, 255, 0.3);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.2px;
  text-transform: none;
  white-space: nowrap;
}
/* Sobre botones claros el distintivo necesita otro contraste */
.btn-secondary .print-orient {
  background: rgba(15, 23, 42, 0.08);
  border-color: rgba(15, 23, 42, 0.14);
  color: var(--text-secondary);
}
@media (max-width: 768px) {
  /* En móvil el texto del botón manda: el distintivo se reduce al icono */
  .print-orient { font-size: 0; gap: 0; padding: 1px 4px; }
  .print-orient::first-letter { font-size: 0.72rem; }
}

/* ── IMPRESIÓN ───────────────────────────────────────────────────
   Los documentos del sistema (acta, desprendible, etiqueta, matriz y
   reportes) se imprimen desde una ventana aislada con su propio @page
   — ver modules/shared/sgi-print.js. Este bloque solo cubre la
   impresión directa del navegador (Ctrl+P) sobre la vista en curso.

   BUG CORREGIDO: aquí había `body * { visibility: hidden }` seguido de
   mostrar únicamente #payslip-document-container. La regla no estaba
   acotada, así que se aplicaba a toda impresión: al imprimir el acta,
   la matriz o cualquier tabla salía una hoja en blanco. Se retiró; el
   aislamiento del desprendible ahora lo hace la ventana aparte.

   ORIENTACIÓN: por omisión horizontal, porque las vistas del sistema
   son cuadrículas anchas (Movimientos tiene 43 columnas). Un documento
   vertical puede pedirlo con la clase .print-vertical en el body. */
@media print {
  @page { size: A4 landscape; margin: 6mm; }

  body {
    background: #ffffff !important; color: #000000 !important;
    font-family: Arial, sans-serif !important; margin: 0 !important; padding: 0 !important;
    -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important;
  }

  /* Cromo de la aplicación fuera del papel */
  .sidebar, .top-header, .sgi-menu-toggle, .sgi-menu-backdrop,
  .page-header, .btn-print-acta, .theme-toggle, .btn-primary, .btn-secondary,
  .modal-overlay, #toast-container, .sgi-th-tools, .sgi-col-resizer,
  .sgi-combo__panel, .search-box, .no-print { display: none !important; }

  /* El layout de pantalla completa no aplica en papel */
  .app-layout { height: auto !important; overflow: visible !important; display: block !important; }
  .main-content {
    margin-left: 0 !important; max-width: 100% !important;
    height: auto !important; overflow: visible !important; display: block !important;
    padding: 0 !important;
  }
  .view-container { overflow: visible !important; height: auto !important; }
  .app-view.active { display: block !important; min-height: 0 !important; }
  .card-box.grow { display: block !important; }

  /* Las tablas se muestran completas, sin recorte ni desplazamiento */
  .sgi-table-scroll,
  .table-responsive {
    max-height: none !important;
    overflow: visible !important;
    border: none !important;
  }
  thead.sgi-sticky-head th,
  thead th { position: static !important; }
  /* El encabezado se repite en cada hoja de una tabla larga */
  thead { display: table-header-group; }
  tfoot { display: table-footer-group; }
  tr { page-break-inside: avoid; }

  /* En papel los encabezados girados se leen mejor en horizontal */
  .th-vertical { writing-mode: horizontal-tb !important; height: auto !important; }
  .th-vertical span { writing-mode: horizontal-tb !important; transform: none !important; }

  /* Documentos que sí son verticales lo declaran en el body */
  body.print-vertical { }
}

/* Cuando el body lleva .print-vertical la hoja pasa a vertical */
@media print {
  body.print-vertical { page: vertical; }
}
@page vertical { size: A4 portrait; margin: 10mm; }

/* ── TRANSFORMACIÓN MAYÚSCULAS ───────────────────────────────── */
/* REGLA ELIMINADA: input[type="text"] causaba mayúsculas forzadas en login */
/* Solo mantener para elementos específicos que lo necesiten */
.custom-table td,
.custom-table th,
.kpi-title,
.badge-accent,
.payslip-doc,
.payslip-table td,
.payslip-table th,
.chart-bar-label { text-transform: uppercase; }

/* ═══════════════════════════════════════════════════════════════
   MÓDULO DE AUTENTICACIÓN — Login page
   ═══════════════════════════════════════════════════════════════ */
.login-page {
  min-height: 100vh;
  /* Fondo plano: el degradado azul-a-negro era el único de la aplicación y
     hacía que la entrada pareciera de otro producto. */
  background: #0f172a;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.login-card {
  background: #ffffff; border-radius: 16px;
  padding: 40px 36px; width: 100%; max-width: 420px;
  box-shadow: 0 25px 50px rgba(0,0,0,0.35);
}
.login-logo {
  text-align: center; margin-bottom: 28px;
}
.login-logo-icon {
  width: 56px; height: 56px; border-radius: var(--radio-lg);
  background: var(--accent-primary);
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto var(--esp-md);
}
.login-logo-icon svg { width: 30px; height: 30px; color: white; }
.login-logo h1 { font-size: 1.6rem; font-weight: 900; color: #0a0f1e; margin: 0; }
.login-logo span { font-size: 0.78rem; color: #64748b; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; }
.login-title { font-size: 1.1rem; font-weight: 800; color: #0a0f1e; margin-bottom: 20px; text-align: center; }
.login-group { margin-bottom: 16px; }
.login-group label { display: block; font-size: 0.82rem; font-weight: 700; color: #334155; margin-bottom: 5px; }
.login-input {
  width: 100%; padding: 11px 14px;
  border: 1.5px solid #cbd5e1; border-radius: 8px;
  font-size: 0.92rem; color: #0a0f1e;
  background: #f8fafc; outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.login-input:focus { border-color: #1a56db; box-shadow: 0 0 0 3px rgba(26,86,219,0.18); background: #fff; }
.login-btn {
  width: 100%; padding: 12px;
  background: #1a56db; color: white;
  border: none; border-radius: 9px;
  font-size: 0.95rem; font-weight: 800;
  cursor: pointer; margin-top: 8px;
  transition: background 0.2s, transform 0.15s;
  box-shadow: 0 4px 14px rgba(26,86,219,0.3);
}
.login-btn:hover { background: #1647c0; transform: translateY(-1px); }
.login-btn:disabled { background: #94a3b8; cursor: not-allowed; transform: none; }
.login-error {
  background: #fee2e2; border: 1px solid #fca5a5;
  color: #991b1b; border-radius: 7px;
  padding: 10px 14px; font-size: 0.84rem; font-weight: 700;
  margin-bottom: 14px; display: none;
}
.login-error.show { display: block; }
.login-footer { text-align: center; margin-top: 20px; font-size: 0.75rem; color: #94a3b8; }

/* ── PANEL ADMIN DE USUARIOS ─────────────────────────────────── */
.user-role-badge {
  padding: 3px 9px; border-radius: 10px;
  font-size: 0.72rem; font-weight: 800; text-transform: uppercase;
}
.role-admin      { background: #1a56db; color: #fff; }
.role-sst        { background: #dcfce7; color: #15803d; border: 1px solid #86efac; }
.role-almacen    { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; }
.role-nomina     { background: #ede9fe; color: #6d28d9; border: 1px solid #c4b5fd; }
.role-supervisor { background: #e0f2fe; color: #0369a1; border: 1px solid #bae6fd; }

/* Borde completo en lugar de franja lateral de acento. La franja sugiere una
   jerarquía o un estado que aquí no existe: todas las entradas del historial
   valen igual. Un borde completo las delimita sin insinuar prioridad. */
.audit-log-entry {
  padding: var(--esp-sm) var(--esp-md);
  border-radius: var(--radio-md);
  border: 1px solid var(--border-color);
  background: var(--bg-table-alt);
  margin-bottom: var(--esp-xs);
  font-size: var(--fs-body);
}
.audit-log-entry.action-delete { border-left-color: var(--danger); }
.audit-log-entry.action-create { border-left-color: var(--success); }
.audit-log-entry.action-edit   { border-left-color: var(--warning); }
.audit-time  { font-size: 0.72rem; color: var(--text-secondary); margin-top: 2px; }

/* ── USER INFO en header ─────────────────────────────────────── */
.user-chip {
  display: flex; align-items: center; gap: 8px;
  background: rgba(255,255,255,0.15);
  border: 1px solid rgba(255,255,255,0.3);
  border-radius: 20px; padding: 5px 12px 5px 6px;
  cursor: default;
}
.user-chip-avatar {
  width: 28px; height: 28px; border-radius: 50%;
  background: rgba(255,255,255,0.25);
  display: flex; align-items: center; justify-content: center;
  font-size: 0.78rem; font-weight: 800; color: #fff;
}
.user-chip-name { font-size: 0.82rem; font-weight: 700; color: #fff; }
.user-chip-role { font-size: 0.7rem; color: rgba(255,255,255,0.7); text-transform: uppercase; }

.btn-logout {
  background: rgba(220,38,38,0.2);
  border: 1px solid rgba(220,38,38,0.4);
  color: #fca5a5; border-radius: 8px;
  padding: 6px 12px; font-size: 0.82rem; font-weight: 700;
  cursor: pointer; transition: all 0.15s;
  display: flex; align-items: center; gap: 5px;
}
.btn-logout:hover { background: #dc2626; color: #fff; border-color: #dc2626; }

/* ═══════════════════════════════════════════════════════════════
   COMPORTAMIENTO ESTÁNDAR DE TABLAS (SGI)
   Aplica a TODAS las tablas del sistema, sin importar su clase.
   Complementa a modules/shared/table-enhancer.js

   1. Ninguna columna congelada (ni la de totales)
   2. Primera fila (encabezado) fija al hacer scroll vertical
   3. Columnas redimensionables arrastrando el borde del encabezado
   ═══════════════════════════════════════════════════════════════ */

/* ── 1. SIN COLUMNAS CONGELADAS ─────────────────────────────────
   Se anulan las columnas fijas heredadas para que todas se desplacen
   con el scroll horizontal.

   IMPORTANTE: esta regla se limita a las celdas del CUERPO de la tabla.
   Antes alcanzaba también a los <th>, y como lleva !important vencía al
   `position: sticky` del encabezado fijo. El resultado: las tres primeras
   celdas del encabezado (#, Cédula, Nombre) se quedaban estáticas y se
   iban con el scroll, mientras el resto seguía anclado arriba. La fila de
   encabezado se partía en dos y el bloque "CARGO / PUESTO" aparecía
   flotando sobre los datos, tapando celdas. */
tbody .col-sticky-1,
tbody .col-sticky-2,
tbody .col-sticky-3,
tbody [class*="col-sticky"],
tbody .sgi-unfrozen {
  position: static !important;
  left: auto !important;
}

/* ── 2. ENCABEZADO FIJO ─────────────────────────────────────────
   La primera fila permanece visible. Se aplica a las celdas del thead
   porque con border-collapse el sticky sobre <thead> no es fiable.

   Solo se fija `top`, nunca `left`: así el encabezado se ancla en
   vertical pero acompaña a la tabla al desplazarse en horizontal, que es
   justo lo que se busca al no tener columnas congeladas. El !important y
   el `left: auto` son necesarios para ganar a cualquier regla heredada
   de columna fija. */
thead.sgi-sticky-head th,
thead.sgi-sticky-head th[class*="col-sticky"],
thead.sgi-sticky-head th.sgi-unfrozen {
  position: sticky !important;
  top: 0 !important;
  left: auto !important;
  z-index: 20 !important;   /* si no, las celdas de datos pasan por encima */
  background-clip: padding-box;
}

/* Encabezados de varias filas: la segunda fila se ancla bajo la primera */
thead.sgi-sticky-head tr:nth-child(2) th {
  z-index: 19;
}

/* Contenedor con scroll: requisito para que el sticky funcione.
   Igual que .table-responsive, aprovecha todo el espacio disponible
   cuando su card-box padre lo permite. */
.sgi-table-scroll {
  overflow: auto;
  max-height: var(--table-max-height, calc(100vh - 220px));
  position: relative;
}
/* Solo la caja marcada con .grow libera el tope de altura.
   Aquí había además un selector `.card-box:last-child`, resto de una
   versión anterior de esta lógica. Al no depender de .grow, seguía
   aplicando `max-height: none` a la última tarjeta de CUALQUIER vista,
   incluso cuando el ajuste había decidido no fijar la altura: la tabla
   de Inventario de Herramientas llegaba a 28.000px de alto y había que
   recorrer toda la página para ver la última fila. */
.app-view.active > .card-box.grow > .sgi-table-scroll {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
}

/* La fila de totales se desplaza con el contenido (no queda fija) */
tfoot td,
tfoot th {
  position: static !important;
}

/* ── 3. COLUMNAS REDIMENSIONABLES ───────────────────────────────
   Tirador invisible en el borde derecho de cada encabezado. */
.sgi-col-resizer {
  position: absolute;
  top: 0;
  right: 0;
  width: 6px;
  height: 100%;
  cursor: col-resize;
  user-select: none;
  touch-action: none;
  background: transparent;
  transition: background 0.12s ease;
  z-index: 25;
}

.sgi-col-resizer:hover,
.sgi-col-resizer:active {
  background: rgba(56, 189, 248, 0.85);
}

/* Indicador sutil de que la columna es ajustable */
thead.sgi-sticky-head th:hover .sgi-col-resizer {
  background: rgba(255, 255, 255, 0.35);
}

/* Mientras se arrastra, evitar selección de texto en toda la página */
body.sgi-resizing,
body.sgi-resizing * {
  user-select: none !important;
  cursor: col-resize !important;
}

/* ── LEGIBILIDAD DE ENCABEZADOS ─────────────────────────────────
   Los nombres de columna ya no se recortan: se permite el ajuste de
   ancho y el texto se muestra completo (caso EPP Movimientos). */
thead.sgi-sticky-head th {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  /* Espacio para el tirador, evita que el texto quede debajo */
  padding-right: 12px;
}

/* Las celdas del cuerpo respetan el ancho elegido por el usuario */
table[data-sgi-enhanced] td {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── ORDENAR Y FILTRAR POR COLUMNA ──────────────────────────────
   Controles que aparecen en cada encabezado de tabla.
   Los gestiona modules/shared/table-enhancer.js */

.sgi-th-tools {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  margin-left: 5px;
  vertical-align: middle;
}

.sgi-sort-btn,
.sgi-filter-btn {
  background: transparent;
  border: none;
  color: rgba(255, 255, 255, 0.55);
  cursor: pointer;
  padding: 1px 3px;
  border-radius: 3px;
  font-size: 0.72rem;
  line-height: 1;
  transition: color 0.15s, background 0.15s;
}

.sgi-sort-btn:hover,
.sgi-filter-btn:hover {
  color: #ffffff;
  background: rgba(255, 255, 255, 0.18);
}

.sgi-sort-btn.is-asc,
.sgi-sort-btn.is-desc {
  color: #7dd3fc;
  background: rgba(125, 211, 252, 0.18);
}

.sgi-filter-btn.is-active {
  color: #fde68a;
  background: rgba(253, 230, 138, 0.2);
}

/* Panel de filtro por columna */
.sgi-filter-panel {
  position: fixed;
  z-index: 9500;
  width: 240px;
  background: #ffffff;
  border: 1px solid #cbd5e1;
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.22);
  font-size: 0.82rem;
  color: #0f172a;
  overflow: hidden;
}

.sgi-filter-head {
  padding: 8px;
  border-bottom: 1px solid #e2e8f0;
}

.sgi-filter-search {
  width: 100%;
  padding: 6px 8px;
  border: 1px solid #cbd5e1;
  border-radius: 6px;
  font-size: 0.82rem;
  color: #0f172a;
  box-sizing: border-box;
}

.sgi-filter-actions {
  display: flex;
  gap: 6px;
  padding: 6px 8px;
  border-bottom: 1px solid #e2e8f0;
  background: #f8fafc;
}

.sgi-filter-actions button {
  flex: 1;
  padding: 4px 6px;
  font-size: 0.75rem;
  font-weight: 700;
  border: 1px solid #cbd5e1;
  background: #ffffff;
  color: #334155;
  border-radius: 5px;
  cursor: pointer;
}

.sgi-filter-actions button:hover {
  background: #e2e8f0;
}

.sgi-filter-list {
  max-height: 220px;
  overflow-y: auto;
  padding: 4px;
}

.sgi-filter-item {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 4px 6px;
  border-radius: 5px;
  cursor: pointer;
}

.sgi-filter-item:hover {
  background: #f1f5f9;
}

.sgi-filter-item span {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sgi-filter-item em {
  font-style: normal;
  font-size: 0.72rem;
  color: #64748b;
  background: #e2e8f0;
  padding: 0 5px;
  border-radius: 8px;
}

.sgi-filter-foot {
  display: flex;
  gap: 6px;
  padding: 8px;
  border-top: 1px solid #e2e8f0;
  background: #f8fafc;
}

.sgi-filter-foot button {
  flex: 1;
  padding: 6px 8px;
  font-size: 0.78rem;
  font-weight: 700;
  border: 1px solid #cbd5e1;
  background: #ffffff;
  color: #334155;
  border-radius: 6px;
  cursor: pointer;
}

.sgi-filter-foot button.primary {
  background: #0070c0;
  color: #ffffff;
  border-color: #0070c0;
}

.sgi-filter-foot button:hover {
  filter: brightness(0.95);
}

/* El encabezado necesita espacio para los controles */
thead.sgi-sticky-head th {
  padding-right: 16px;
}

/* ═══════════════════════════════════════════════════════════════
   ADAPTACIÓN A MÓVIL Y TABLETA (mejora P3)

   El sistema se usa en oficina, en bodega y en campo. Estas reglas
   adaptan la misma aplicación web a pantallas pequeñas, sin necesidad
   de una aplicación nativa aparte.

   Puntos de quiebre:
     ≤ 1024px  Tableta: menú lateral colapsable
     ≤  768px  Móvil: menú superpuesto, tarjetas apiladas, controles grandes
     ≤  480px  Móvil pequeño: ajustes finos de tipografía y espaciado
   ═══════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════
   SIDEBAR COLAPSABLE EN ESCRITORIO
   ═══════════════════════════════════════════════════════════════
   Estado expandido (por defecto): icono + texto, 260px.
   Estado colapsado: solo icono, 68px, con el texto en un tooltip al pasar
   el cursor. El contenido principal recupera el ancho automáticamente
   porque tanto el ancho del sidebar como el margen del contenido se
   derivan de la misma variable --sidebar-width.

   La preferencia se guarda: el body arranca con la clase que corresponda
   (ver app.js), por eso las transiciones no deben dispararse en la carga. */

/* Transición suave solo del ancho y el margen */
.sidebar { transition: width 0.22s ease, transform 0.25s ease; }
.main-content { transition: margin-left 0.22s ease, max-width 0.22s ease; }

/* --- Botón de colapso, dentro del sidebar --- */
.sidebar-collapse-btn {
  display: flex; align-items: center; justify-content: center;
  gap: 8px;
  width: 100%;
  margin-top: 4px;
  padding: 8px;
  border: 1px solid var(--border-color);
  border-radius: 8px;
  background: var(--bg-primary);
  color: var(--text-secondary);
  font-size: 0.78rem; font-weight: 700;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.sidebar-collapse-btn:hover { background: var(--accent-light); color: var(--accent-primary); }
.sidebar-collapse-btn svg { width: 16px; height: 16px; flex-shrink: 0; transition: transform 0.22s ease; }

/* ─── ESTADO COLAPSADO (escritorio) ─── */
body.sidebar-collapsed {
  --sidebar-width: 68px;
}

/* Ocultar todo lo que sea texto, dejando solo el icono centrado */
body.sidebar-collapsed .brand-text,
body.sidebar-collapsed .nav-item > span:not(.badge-accent):not(.badge-info):not(.badge-warning),
body.sidebar-collapsed .nav-item .badge-accent,
body.sidebar-collapsed .nav-item .badge-info,
body.sidebar-collapsed .nav-item .badge-warning,
body.sidebar-collapsed .sidebar-module-switch button span,
body.sidebar-collapsed .sidebar-collapse-btn span {
  display: none;
}

body.sidebar-collapsed .brand { justify-content: center; padding: 0; }
body.sidebar-collapsed .nav-item { justify-content: center; padding: 11px 0; }
body.sidebar-collapsed .nav-item svg { width: 20px; height: 20px; }

/* El botón "Cambiar Módulo" se vuelve un icono compacto */
body.sidebar-collapsed .sidebar-module-switch { padding: 0 4px 10px; }
body.sidebar-collapsed .sidebar-module-switch button {
  padding: 10px 0 !important;
  font-size: 1.1rem !important;
}
/* Rotar la flecha del botón de colapso al estar colapsado */
body.sidebar-collapsed .sidebar-collapse-btn svg { transform: rotate(180deg); }

/* --- TOOLTIP en estado colapsado --- */
/* El nombre de cada sección aparece al pasar el cursor, tomado del atributo
   data-label que pone app.js. Así no se pierde la navegación al colapsar. */
body.sidebar-collapsed .nav-item { position: relative; }
body.sidebar-collapsed .nav-item::after {
  content: attr(data-label);
  position: absolute;
  left: calc(100% + 10px);
  top: 50%;
  transform: translateY(-50%);
  background: #0f172a;
  color: #ffffff;
  padding: 6px 11px;
  border-radius: 7px;
  font-size: 0.8rem;
  font-weight: 700;
  white-space: nowrap;
  box-shadow: 0 4px 14px rgba(15, 23, 42, 0.28);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.14s ease;
  z-index: 9700;
}
body.sidebar-collapsed .nav-item:hover::after { opacity: 1; }
/* Flechita del tooltip */
body.sidebar-collapsed .nav-item::before {
  content: "";
  position: absolute;
  left: calc(100% + 4px);
  top: 50%;
  transform: translateY(-50%);
  border: 6px solid transparent;
  border-right-color: #0f172a;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.14s ease;
  z-index: 9700;
}
body.sidebar-collapsed .nav-item:hover::before { opacity: 1; }

/* ── PORTÁTIL 1366×768 y similares ──────────────────────────────
   Entre 1025px y 1440px el sidebar de 260px come demasiado ancho útil
   para las tablas anchas. Se reduce a 220px (el texto sigue cabiendo) y
   el contenido respira. El usuario puede colapsarlo del todo si quiere. */
@media (min-width: 1025px) and (max-width: 1440px) {
  :root { --sidebar-width: 220px; }
  .main-content { padding: 1rem 1.25rem; }
  .nav-item { font-size: 0.82rem; padding: 9px 10px; }
}

/* En pantallas pequeñas el colapso de escritorio no aplica: ahí manda el
   panel deslizable, así que se ignora el estado colapsado. */
@media (max-width: 1024px) {
  body.sidebar-collapsed { --sidebar-width: 260px; }
  .sidebar-collapse-btn { display: none; }
}

/* Botón para abrir el menú en pantallas pequeñas (oculto en escritorio) */
.sgi-menu-toggle {
  display: none;
  position: fixed;
  top: 10px;
  left: 10px;
  z-index: 9600;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: 10px;
  background: #0070c0;
  color: #ffffff;
  font-size: 1.3rem;
  cursor: pointer;
  box-shadow: 0 3px 10px rgba(15, 23, 42, 0.25);
  align-items: center;
  justify-content: center;
}

/* Capa oscura detrás del menú abierto */
.sgi-menu-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 9400;
  background: rgba(15, 23, 42, 0.5);
}
.sgi-menu-backdrop.visible { display: block; }

/* ── TABLETA: hasta 1024px ─────────────────────────────────────── */
@media (max-width: 1024px) {
  /* En tablet/móvil el layout ERP-fijo es incómodo (poca altura útil).
     Volvemos al scroll de página completa para dar más aire vertical. */
  .app-layout { 
    height: auto; 
    min-height: 100vh; 
    overflow: auto;
    display: block;
  }
  .main-content { 
    height: auto; 
    overflow: visible;
  }
  .view-container { overflow: visible; }
  .app-view.active { display: block; min-height: auto; }
  /* En tablet las tablas retoman su tope de altura fijo */
  .app-view.active > .card-box.grow {
    flex: none;
    display: block;
  }
  .app-view.active > .card-box.grow > .table-responsive,
  .app-view.active > .card-box.grow > .sgi-table-scroll {
    flex: none;
    max-height: 65vh;
  }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    height: 100vh;
    width: 260px;
    z-index: 9500;
    transform: translateX(-100%);
    transition: transform 0.25s ease;
    overflow-y: auto;
  }
  .sidebar.sgi-open { transform: translateX(0); }

  .main-content {
    margin-left: 0 !important;
    width: 100%;
  }

  .sgi-menu-toggle { display: flex; }

  /* Espacio para que el botón del menú no tape el buscador */
  .top-header {
    padding-left: 62px;
    flex-wrap: wrap;
    gap: 10px;
  }

  /* Las tarjetas de indicadores se acomodan de dos en dos */
  .kpi-grid {
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)) !important;
  }
}

/* ── MÓVIL: hasta 768px ────────────────────────────────────────── */
@media (max-width: 768px) {
  /* Encabezado de página apilado */
  .page-header {
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 12px !important;
  }
  .page-title { font-size: 1.25rem !important; }
  .page-description { font-size: 0.85rem !important; }

  /* Los botones de acción ocupan el ancho y son cómodos de pulsar */
  .page-header > div:last-child {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
  }
  .page-header button,
  .btn-primary,
  .btn-secondary {
    flex: 1 1 auto;
    min-height: 42px;
    font-size: 0.86rem;
  }

  /* Indicadores en una sola columna para que el número sea legible */
  .kpi-grid {
    grid-template-columns: 1fr 1fr !important;
    gap: 10px !important;
  }
  .kpi-value { font-size: 1.3rem !important; }
  .kpi-title { font-size: 0.7rem !important; }

  /* Barras de filtros: cada control en su línea */
  .card-box[style*="flex-wrap"] {
    flex-direction: column !important;
    align-items: stretch !important;
  }
  .card-box select,
  .card-box input[type="text"],
  .card-box input[type="date"],
  .card-box input[type="number"] {
    width: 100% !important;
    min-height: 42px;
    font-size: 0.9rem;
  }
  .search-box { width: 100%; }
  .search-box input { width: 100%; }

  /* Tablas: desplazamiento táctil suave y altura acotada */
  .table-responsive,
  .sgi-table-scroll {
    -webkit-overflow-scrolling: touch;
    max-height: 65vh;
  }
  .excel-grid-table,
  table[data-sgi-enhanced] {
    font-size: 0.76rem;
  }
  thead.sgi-sticky-head th { font-size: 0.68rem; padding: 6px 8px; }

  /* Los tiradores de columna se agrandan para el dedo */
  .sgi-col-resizer { width: 14px; }

  /* Modales a pantalla casi completa */
  .modal-container {
    max-width: 96vw !important;
    width: 96vw;
    max-height: 92vh;
    margin: 4vh auto;
  }
  .modal-form-row {
    flex-direction: column !important;
    gap: 10px !important;
  }
  .modal-form-row .form-group {
    flex: 1 1 auto !important;
    width: 100%;
  }
  .form-control { min-height: 42px; font-size: 0.9rem; }

  /* Tarjetas del selector de módulos: una sola columna en móvil */
  .modules-grid { grid-template-columns: 1fr; }
  .selector-hero h1 { font-size: 1.5rem; }

  /* Panel de filtro de columna adaptado al ancho de la pantalla */
  .sgi-filter-panel {
    width: calc(100vw - 24px) !important;
    left: 12px !important;
  }

  /* Insignia de usuario compacta */
  #sgi-user-badge {
    flex-wrap: wrap;
    font-size: 0.78rem;
  }
}

/* ── MÓVIL PEQUEÑO: hasta 480px ────────────────────────────────── */
@media (max-width: 480px) {
  .kpi-grid { grid-template-columns: 1fr !important; }
  .page-title { font-size: 1.1rem !important; }

  .top-header { padding-left: 58px; }
  #global-search-input { font-size: 0.85rem; }

  /* Ocultar el selector de proyecto del encabezado: está en el menú */
  #header-epp-project-wrapper { width: 100%; justify-content: space-between; }

  .modal-header { padding: 12px 14px; }
  .modal-body { padding: 14px; }
  .modal-footer { flex-direction: column; gap: 8px; }
  .modal-footer button { width: 100%; }

  /* Firma digital: lienzo más alto para firmar con el dedo */
  #epp-firma-canvas { height: 200px !important; }
}

/* ── IMPRESIÓN ─────────────────────────────────────────────────── */
@media print {
  .sidebar,
  .top-header,
  .sgi-menu-toggle,
  .sgi-menu-backdrop,
  .page-header button,
  .sgi-th-tools,
  .sgi-col-resizer {
    display: none !important;
  }
  .main-content { margin-left: 0 !important; }
  .sgi-table-scroll,
  .table-responsive {
    max-height: none !important;
    overflow: visible !important;
  }
  thead.sgi-sticky-head th { position: static !important; }
  body { background: #ffffff !important; }
}

/* ══════════════════════════════════════════════════════════════════
   SISTEMA DE DISEÑO — CAPA SISTEMÁTICA
   ══════════════════════════════════════════════════════════════════
   Va al final a propósito: con la misma especificidad, lo último gana,
   así que estas reglas normalizan lo que quedó disperso por el archivo
   sin tener que reescribir cada bloque anterior.

   Cinco criterios:
     1. Jerarquía tipográfica con contraste real de tamaño y peso.
     2. Plano en reposo; la sombra se reserva para lo que flota.
     3. El foco de teclado siempre visible.
     4. El estado nunca se comunica solo con color.
     5. Esqueletos para carga de contenido, no ruedas girando.
   ══════════════════════════════════════════════════════════════════ */

/* ── 1. JERARQUÍA TIPOGRÁFICA ─────────────────────────────────────
   Cinco niveles. El problema previo no era el tamaño de cada texto por
   separado, sino que títulos, secciones y etiquetas pesaban casi igual:
   sin diferencia de peso no hay jerarquía, y en pantallas densas el ojo
   no encuentra dónde empezar. */

.page-title {
  font-size: var(--fs-display);
  font-weight: var(--fw-display);
  letter-spacing: var(--ls-display);
  line-height: 1.25;
  color: var(--text-primary);
  margin-bottom: 2px;
}
.page-description {
  font-size: var(--fs-body);
  font-weight: var(--fw-body);
  line-height: 1.5;
  color: var(--text-secondary);
  /* Texto para leer: se limita el ancho de línea. Una descripción que
     cruza toda la pantalla obliga a barrer la cabeza y se pierde el
     renglón al volver. */
  max-width: 75ch;
}

/* Título de sección dentro de una vista o modal */
.modal-section-title,
.section-title {
  font-size: var(--fs-label);
  font-weight: var(--fw-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--text-secondary);
  padding-bottom: var(--esp-xs);
  border-bottom: 1px solid var(--border-color);
  margin: var(--esp-lg) 0 var(--esp-md);
}
.modal-title { font-size: var(--fs-title); font-weight: var(--fw-title); }

/* Etiquetas de formulario: pequeñas, con peso, sin competir con el dato */
.form-group > label,
label.form-label {
  font-size: var(--fs-label);
  font-weight: var(--fw-label);
  color: #334155;
  letter-spacing: 0.01em;
  display: block;
  margin-bottom: var(--esp-xs);
}

/* Encabezados de tabla como etiquetas espaciadas, no como texto normal */
.custom-table th {
  font-size: var(--fs-label);
  font-weight: var(--fw-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}

/* Título y valor de KPI: el valor manda, el título orienta */
.kpi-title {
  font-size: var(--fs-label);
  font-weight: var(--fw-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--text-secondary);
  line-height: 1.33;
}
.kpi-value {
  font-size: 1.35rem;
  font-weight: 700;
  line-height: 1.15;
  /* Cifras de ancho fijo: en una columna de KPIs los números quedan
     alineados y se comparan de un vistazo. */
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* Todo número en tabla o KPI se alinea por columna */
.custom-table td,
.kpi-value,
.metric-bar-val { font-variant-numeric: tabular-nums; }


/* ── 2. PLANO EN REPOSO, ELEVADO AL INTERACTUAR ───────────────────
   Antes toda tarjeta llevaba un brillo azul permanente. Una sombra
   constante no aporta información: si todo flota, nada destaca. */

.card-box,
.kpi-card,
.chart-card,
.summary-card-corporate {
  box-shadow: var(--sombra-tarjeta);
  border-radius: var(--card-radius);
  border: 1px solid var(--border-color);
  transition: box-shadow 0.15s ease, border-color 0.15s ease;
}

/* Solo lo que realmente flota lleva sombra fuerte */
.modal-container { box-shadow: var(--sombra-dialogo); border-radius: var(--radio-lg); }
.dropdown-menu,
.autocomplete-list,
.context-menu { box-shadow: var(--sombra-flotante); border-radius: var(--radio-md); }


/* ── 3. FOCO DE TECLADO SIEMPRE VISIBLE ──────────────────────────
   Quien navega con teclado necesita ver dónde está. Se usa
   :focus-visible para que el anillo no aparezca al hacer clic con el
   ratón, solo al tabular. */

:focus-visible {
  outline: 2px solid var(--accent-primary);
  outline-offset: 2px;
  border-radius: var(--radio-sm);
}
.form-control:focus,
select:focus,
textarea:focus,
input:focus {
  border-color: var(--accent-primary);
  box-shadow: var(--anillo-foco);
  outline: none;
}
/* Nunca anular el foco sin reemplazarlo */
*:focus-visible { outline-color: var(--accent-primary); }


/* ── 4. EL ESTADO NUNCA SE COMUNICA SOLO CON COLOR ───────────────
   Alrededor del 8% de los hombres no distingue rojo de verde. Un saldo
   en rojo y otro en verde son indistinguibles para esa persona si el
   color es la única diferencia. Cada chip lleva un punto de forma
   distinta más el texto del estado. */

.estado-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 10px;
  border-radius: 9999px;
  font-size: var(--fs-label);
  font-weight: var(--fw-label);
  letter-spacing: var(--ls-label);
  border: 1px solid transparent;
  white-space: nowrap;
}
/* El punto delantero cambia de forma, no solo de color */
.estado-chip::before {
  content: '';
  width: 7px; height: 7px;
  background: currentColor;
  flex-shrink: 0;
}
.estado-chip--ok      { background: var(--success-soft); color: var(--success); border-color: #86efac; }
.estado-chip--ok::before      { border-radius: 50%; }                    /* círculo */
.estado-chip--aviso   { background: var(--warning-soft); color: var(--warning); border-color: #fcd34d; }
.estado-chip--aviso::before   { clip-path: polygon(50% 0, 100% 100%, 0 100%); }  /* triángulo */
.estado-chip--error   { background: var(--danger-soft); color: var(--danger); border-color: #fca5a5; }
.estado-chip--error::before   { clip-path: polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%); } /* hexágono */
.estado-chip--info    { background: var(--info-soft); color: var(--info); border-color: #7dd3fc; }
.estado-chip--info::before    { border-radius: 50%; }
.estado-chip--neutro  { background: var(--bg-panel); color: var(--text-secondary); border-color: var(--border-color); }
.estado-chip--neutro::before  { border-radius: 1px; }                    /* cuadrado */

/* Importes con signo: el símbolo acompaña al color para que el sentido
   se lea sin depender de distinguir rojo de verde. */
.importe-negativo { color: var(--danger); font-weight: 700; }
.importe-negativo::before { content: '\2212\00a0'; }   /* menos real, no guion */
.importe-positivo { color: var(--success); font-weight: 700; }
.importe-nulo     { color: #cbd5e1; }


/* ── 5. TABLAS: FILA ACTIVA Y CELDAS VACÍAS ──────────────────────── */

/* Fila bajo el cursor: tinte de acción, para saber en qué renglón se está
   al recorrer una tabla ancha. */
.custom-table tbody tr:hover > td { background-color: var(--tabla-fila-hover); }
/* La celda fija hereda el mismo tinte: si no, al pasar el cursor queda
   una isla blanca en medio de la fila resaltada. */
.custom-table tbody tr:hover > td[style*="sticky"] { background-color: var(--tabla-fila-hover) !important; }

/* Fila seleccionable: se indica que es pulsable de forma consistente */
.custom-table tbody tr.fila-pulsable { cursor: pointer; }

/* Celda sin dato: hueco tenue, nunca relleno de ceros ni guiones que
   compitan con las cifras reales. */
.celda-vacia { color: #cbd5e1; }
.celda-vacia::after { content: '\00b7'; }


/* ── 6. ESQUELETOS DE CARGA ──────────────────────────────────────
   Un bloque con la forma del contenido que va a llegar informa mejor que
   una rueda girando: se ve cuánto viene y no hay salto de layout al
   pintar. */

.esqueleto {
  background: linear-gradient(90deg, #f1f5f9 25%, #e2e8f0 37%, #f1f5f9 63%);
  background-size: 400% 100%;
  animation: esqueletoBrillo 1.4s ease-in-out infinite;
  border-radius: var(--radio-sm);
  color: transparent !important;
  user-select: none;
}
.esqueleto-texto  { height: 0.9em; margin: 4px 0; }
.esqueleto-linea  { height: 38px; margin-bottom: var(--esp-sm); }
.esqueleto-tarjeta{ height: 72px; }
@keyframes esqueletoBrillo {
  0%   { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}


/* ── 7. ESTADO VACÍO ────────────────────────────────────────────
   Un mensaje concreto que diga qué falta y cuál es el siguiente paso,
   en lugar de una tabla en blanco que parece un error. */

.estado-vacio {
  padding: var(--esp-2xl) var(--esp-xl);
  text-align: center;
  background: var(--bg-table-alt);
  border: 1px dashed var(--border-color);
  border-radius: var(--radio-lg);
  color: var(--text-secondary);
}
.estado-vacio h4 {
  font-size: var(--fs-title);
  font-weight: var(--fw-title);
  color: var(--text-primary);
  margin: 0 0 var(--esp-xs);
}
.estado-vacio p { font-size: var(--fs-body); margin: 0 auto; max-width: 52ch; }
.estado-vacio .estado-vacio-accion { margin-top: var(--esp-lg); }


/* ── 8. BOTONES Y CAMPOS: GEOMETRÍA ÚNICA ────────────────────────
   Misma altura y mismo radio para que en una barra de acciones todo
   quede alineado, sin escalones. */

.btn-primary,
.btn-secondary,
.btn-danger {
  border-radius: var(--radio-md);
  font-size: var(--fs-body);
  font-weight: 600;
  min-height: 38px;
  padding: var(--esp-sm) var(--esp-lg);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.form-control,
select.form-control,
.select-input {
  border-radius: var(--radio-md);
  border: 1px solid var(--border-color);
  /* Fondo blanco y borde sutil: un campo editable debe parecer campo, no
     botón. Si parece botón, el usuario no sabe que puede escribir. */
  background-color: var(--bg-secondary);
  font-size: var(--fs-body);
  min-height: 38px;
}
.form-control::placeholder { color: #94a3b8; }
.form-control:disabled,
.select-input:disabled {
  /* Deshabilitado baja opacidad y conserva el espacio: si el control
     desapareciera, el formulario saltaría. */
  opacity: 0.55;
  cursor: not-allowed;
  background-color: var(--bg-panel);
}


/* ── 9. NAVEGACIÓN: ESTADO ACTIVO CLARO ──────────────────────────── */

.nav-item {
  border-radius: var(--radio-md);
  font-size: var(--fs-body);
}
.nav-item.active,
.nav-item[aria-current="page"] {
  /* Tinte de acción más peso: el activo se distingue por dos señales, no
     solo por el color de fondo. */
  background: var(--accent-light);
  color: var(--accent-primary);
  font-weight: 700;
}
.nav-item:hover:not(.active) { background: var(--bg-hover); }


/* ── 10. MOVIMIENTO REDUCIDO ─────────────────────────────────────
   Quien configura el sistema para reducir animaciones suele hacerlo por
   mareo o sensibilidad vestibular. Se respeta. */

@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;
  }
  .esqueleto { animation: none; background: #e2e8f0; }
}


/* ── 11. IMPRESIÓN ───────────────────────────────────────────────
   Las actas y desprendibles se imprimen: fuera navegación, botones y
   fondos que gastan tinta. */

@media print {
  .sidebar, .top-header, .nav-item,
  .btn-primary, .btn-secondary, .btn-danger,
  .modal-overlay, #sgi-user-badge { display: none !important; }
  .main-content { margin-left: 0 !important; max-width: 100% !important; }
  .card-box, .kpi-card { box-shadow: none !important; border: 1px solid #cbd5e1 !important; }
  .custom-table th {
    background: #f1f5f9 !important;
    color: #0f172a !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  a[href]::after { content: ''; }   /* sin URLs impresas entre paréntesis */
}

/* ── 12. CABECERAS DE MODAL Y BOTÓN DE GUARDAR ────────────────────
   Los trece modales del sistema traían cada uno su propio color de cabecera
   escrito en un atributo style: cian, slate, verde, azul marino, teal… Trece
   tratamientos para el mismo elemento. Además todos eran degradados, y el
   degradado quedaba tapado por la regla de esta hoja, así que era código
   muerto que solo confundía al mantener el archivo.
   Ahora la cabecera es una sola: azul de acción plano. */

.modal-header {
  border-radius: var(--radio-lg) var(--radio-lg) 0 0;
}

/* Botón de guardar de los modales: mismo azul de acción que el resto del
   sistema, sin degradado ni sombra de color. */
.btn-modal-save {
  background: var(--accent-primary);
  color: #ffffff;
  border: none;
  border-radius: var(--radio-md);
  padding: var(--esp-sm) var(--esp-lg);
  min-height: 38px;
  font-size: var(--fs-body);
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.btn-modal-save:hover { background: var(--accent-hover); }
.btn-modal-save:disabled { opacity: 0.55; cursor: not-allowed; }

/* ── 13. VARIANTES SEMÁNTICAS DE TARJETA KPI ──────────────────────
   Diecisiete tarjetas KPI llevaban una franja de acento de 4px escrita en un
   atributo style, con nueve colores distintos para cuatro significados: tres
   tonos de rojo, tres de ámbar, cuatro de verde y cuatro de azul. Nueve
   decisiones de color para decir cuatro cosas.

   Ahora son cuatro variantes con nombre. Cada una usa BORDE COMPLETO más
   fondo teñido en lugar de franja lateral: la franja insinúa una jerarquía
   entre tarjetas que no existe, mientras que el borde delimita sin sugerirla.

   El significado no depende solo del color: el título de la tarjeta lo dice
   con palabras ("Pendientes", "Vencidos"), que es la señal principal. */

.kpi-card.kpi--ok,
.kpi-card.kpi--warning,
.kpi-card.kpi--danger,
.kpi-card.kpi--info,
.kpi-card.kpi--neutro { border-width: 1px; border-style: solid; }

.kpi-card.kpi--ok      { border-color: #86efac; background-color: var(--success-soft); }
.kpi-card.kpi--warning { border-color: #fcd34d; background-color: var(--warning-soft); }
.kpi-card.kpi--danger  { border-color: #fca5a5; background-color: var(--danger-soft); }
.kpi-card.kpi--info    { border-color: #7dd3fc; background-color: var(--info-soft); }
.kpi-card.kpi--neutro  { border-color: var(--border-color); background-color: var(--bg-panel); }

/* El valor toma el color de la variante para que la cifra, que es lo que se
   mira, quede clara sin necesidad de leer el borde. */
.kpi-card.kpi--ok      .kpi-value { color: var(--success); }
.kpi-card.kpi--warning .kpi-value { color: var(--warning); }
.kpi-card.kpi--danger  .kpi-value { color: var(--danger); }
.kpi-card.kpi--info    .kpi-value { color: var(--info); }


/* ── 14. TARJETAS DE MÓDULO: GEOMETRÍA A ESCALA ───────────────────
   Radios de 16px y 14px quedaban fuera de la escala del sistema y hacían que
   la pantalla de entrada se viera de otro producto que el resto. */

.module-card { border-radius: var(--radio-lg); }
.module-icon-wrapper { border-radius: var(--radio-md); }
/* Elevación al pasar el cursor con el valor del vocabulario de sombra: la
   tarjeta sí se acerca al usuario, así que se gana la sombra. */
.module-card:hover { box-shadow: var(--sombra-flotante); }

/* ── 15. PANTALLA DE ENTRADA: RECUPERAR ALTURA ────────────────────
   La cabecera de bienvenida gastaba unos 170px antes de la primera tarjeta:
   una etiqueta "SISTEMA DE GESTIÓN INTEGRAL", un título de 2rem y un
   subtítulo, los tres centrados y separados. En una pantalla de portátil eso
   empujaba la segunda fila de módulos fuera de la vista, así que había que
   desplazarse para ver la mitad de las opciones.

   Se compacta a lo que informa: el título y una línea de instrucción. La
   etiqueta superior repetía el nombre del producto que ya está en la barra
   lateral, así que se retira. */

.selector-hero {
  margin-bottom: var(--esp-lg);
}
.selector-hero .hero-badge { display: none; }
.selector-hero h1 {
  font-size: var(--fs-display);
  font-weight: var(--fw-display);
  letter-spacing: var(--ls-display);
  margin-bottom: 2px;
}
.selector-hero p { font-size: var(--fs-body); }

/* Las tarjetas se ajustan a su contenido. El min-height de 190px dejaba un
   hueco muerto bajo las descripciones cortas, y el hueco no comunica nada:
   la rejilla ya iguala la altura de las tarjetas de una misma fila. */
.module-card {
  min-height: 0;
  padding: var(--esp-lg) var(--esp-lg) var(--esp-md);
}
.module-icon-wrapper { width: 44px; height: 44px; }

/* ═══════════════════════════════════════════════════════════════
   LISTA DE TRABAJADORES — maestro compacto y ficha 360°
   ═══════════════════════════════════════════════════════════════ */
.tw-page-header { display:flex; justify-content:space-between; align-items:flex-start; gap:12px; flex-wrap:wrap; margin-bottom:10px; }
.tw-header-actions { display:flex; gap:6px; flex-wrap:wrap; }
.tw-kpi-strip { 
  display:grid; 
  grid-template-columns:repeat(5,minmax(110px,1fr)); 
  gap:1px; 
  background:var(--border-color); 
  border:1px solid var(--border-color); 
  border-radius:var(--radio-lg); 
  overflow:visible; /* CORREGIDO: era hidden, cortaba indicadores */
  margin-bottom:8px; 
}
.tw-kpi-strip > div { 
  display:flex; 
  align-items:baseline; 
  justify-content:space-between; 
  gap:8px; 
  padding:8px 12px; 
  background:var(--bg-secondary); 
  min-height:44px; /* Asegurar altura mínima para legibilidad */
}
.tw-kpi-strip span { color:var(--text-secondary); font-size:.72rem; font-weight:700; text-transform:uppercase; letter-spacing:.03em; }
.tw-kpi-strip strong { color:var(--text-primary); font-size:1.05rem; }
.tw-toolbar { display:flex; align-items:center; gap:8px; flex-wrap:wrap; padding:8px 10px; margin-bottom:8px; }
.tw-search { flex:1; min-width:260px; margin:0; }
.tw-result-count { color:var(--text-secondary); font-size:.78rem; font-weight:700; white-space:nowrap; }
.tw-advanced-filters { flex-basis:100%; display:grid; grid-template-columns:repeat(4,minmax(150px,1fr)) auto; gap:7px; padding-top:8px; border-top:1px solid var(--border-color); }
.tw-advanced-filters[hidden] { display:none; }
.tw-table-card { padding:0; overflow:hidden; flex:1; min-height:0; }
.tw-table { width:100%; font-size:.79rem; }
.tw-table th { white-space:nowrap; position:sticky; top:0; z-index:4; }
.tw-table td { vertical-align:middle; }
.tw-table .tw-col-id { position:sticky; left:0; z-index:3; min-width:105px; background:var(--bg-secondary); font-weight:700; }
.tw-table .tw-col-name { position:sticky; left:105px; z-index:3; min-width:210px; background:var(--bg-secondary); }
.tw-table th.tw-col-id, .tw-table th.tw-col-name { z-index:6; background:var(--accent-primary); }
.tw-row--inactive { opacity:.72; }
.tw-row--inactive .tw-col-id, .tw-row--inactive .tw-col-name { background:#f8fafc; }
.tw-col-name small, .tw-table td > small { display:block; color:var(--text-secondary); font-size:.69rem; margin-top:2px; }
.tw-person-link { border:0; padding:0; background:none; color:var(--accent-primary); font:inherit; font-weight:800; cursor:pointer; text-align:left; }
.tw-person-link:hover { text-decoration:underline; }
.tw-money { text-align:right; white-space:nowrap; font-weight:700; }
.tw-status { display:inline-flex; align-items:center; white-space:nowrap; border:1px solid; border-radius:4px; padding:2px 6px; font-size:.69rem; font-weight:800; }
.tw-status--success { color:#166534; background:#f0fdf4; border-color:#86efac; }
.tw-status--warning { color:#92400e; background:#fffbeb; border-color:#fcd34d; }
.tw-status--danger { color:#991b1b; background:#fff1f2; border-color:#fca5a5; }
.tw-status--muted { color:#475569; background:#f8fafc; border-color:#cbd5e1; }
.tw-pending { color:#b45309; font-weight:700; }
.tw-progress { width:62px; height:5px; overflow:hidden; background:#e2e8f0; border-radius:3px; }
.tw-progress span { display:block; height:100%; background:var(--accent-primary); }
.tw-actions { display:flex; gap:4px; white-space:nowrap; }
.tw-icon-action { border:1px solid #cbd5e1; border-radius:4px; padding:3px 6px; background:#fff; color:#334155; font-size:.7rem; font-weight:700; cursor:pointer; }
.tw-icon-action:hover { border-color:var(--accent-primary); color:var(--accent-primary); }
.tw-icon-action--danger { color:#991b1b; border-color:#fecaca; }
.tw-icon-action--success { color:#166534; border-color:#86efac; }
.tw-empty { text-align:center; color:var(--text-secondary); padding:34px !important; }
.tw-empty strong, .tw-empty span { display:block; }
.tw-empty span { margin-top:4px; font-size:.78rem; }
.tw-check-field { justify-content:center; padding:8px 10px; border:1px solid var(--border-color); border-radius:var(--radio-md); background:#f8fafc; }
.tw-check-field label { display:flex; align-items:center; gap:7px; font-weight:700; }
.tw-check-field input { width:17px; height:17px; }
.tw-check-field span { color:var(--text-secondary); font-size:.7rem; }
.tw-detail-modal { width:min(1040px,96vw); max-width:1040px; }
.tw-detail-hero { display:flex; align-items:center; justify-content:space-between; gap:12px; padding-bottom:12px; border-bottom:1px solid var(--border-color); }
.tw-detail-hero strong, .tw-detail-hero span { display:block; }
.tw-detail-hero strong { font-size:1.05rem; }
.tw-detail-hero span { color:var(--text-secondary); margin-top:2px; }
.tw-detail-kpis { display:grid; grid-template-columns:repeat(4,1fr); gap:8px; margin:12px 0; }
.tw-detail-kpis > div { border:1px solid var(--border-color); border-radius:var(--radio-md); padding:9px 11px; background:#fff; }
.tw-detail-kpis span, .tw-detail-kpis small { display:block; color:var(--text-secondary); font-size:.7rem; }
.tw-detail-kpis strong { display:block; margin:2px 0; font-size:1rem; }
.tw-detail-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:9px; }
.tw-detail-grid section { border:1px solid var(--border-color); border-radius:var(--radio-md); padding:10px 12px; background:#fff; }
.tw-detail-grid h4 { margin:0 0 7px; font-size:.8rem; color:var(--accent-primary); text-transform:uppercase; letter-spacing:.03em; }
.tw-detail-item { display:flex; justify-content:space-between; gap:12px; padding:4px 0; border-bottom:1px solid #f1f5f9; font-size:.77rem; }
.tw-detail-item:last-child { border:0; }
.tw-detail-item span { color:var(--text-secondary); }
.tw-detail-item strong { text-align:right; }
.tw-detail-actions, .tw-context-actions { display:flex; gap:6px; flex-wrap:wrap; margin-top:9px; }
.tw-context-actions { border-top:1px solid var(--border-color); padding-top:11px; }
.tw-context-actions button { border:1px solid #cbd5e1; background:#fff; color:#334155; border-radius:4px; padding:5px 9px; font-size:.75rem; font-weight:700; cursor:pointer; }
.tw-context-actions button:hover { color:var(--accent-primary); border-color:var(--accent-primary); }
@media (max-width:900px) {
  .tw-kpi-strip { grid-template-columns:repeat(2,1fr); }
  .tw-advanced-filters { grid-template-columns:1fr 1fr; }
  .tw-detail-kpis, .tw-detail-grid { grid-template-columns:1fr 1fr; }
}
@media (max-width:600px) {
  .tw-kpi-strip, .tw-detail-kpis, .tw-detail-grid, .tw-advanced-filters { grid-template-columns:1fr; }
  .tw-table .tw-col-name { position:static; }
}

/* ══════════════════════════════════════════════════════════════════
   PORTAL · MIS TAREAS
   ══════════════════════════════════════════════════════════════════
   Pantalla de un trabajador consultando lo que tiene asignado. Las
   decisiones de estilo siguen el criterio del resto del sistema:
   · la fila atrasada se marca con una BANDA a la izquierda, no solo con
     color de texto: el color por sí solo no se ve en pantallas de obra
     con reflejo, y no sirve para quien no distingue rojo y verde;
   · el encabezado y la columna de la actividad quedan fijos al
     desplazar, porque la actividad es lo que identifica la fila;
   · nada de relleno en las celdas vacías: si no hay avance registrado,
     la celda se queda en blanco.
   ══════════════════════════════════════════════════════════════════ */

/* Tira de indicadores: son BOTONES de filtro, así que se ven pulsables */
.pt-kpis {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.pt-kpi {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  min-width: 104px;
  padding: 8px 14px;
  border: 1px solid #e2e8f0;
  border-radius: 10px;
  background: #ffffff;
  cursor: pointer;
  text-align: left;
  transition: border-color .15s, box-shadow .15s, transform .15s;
}
.pt-kpi:hover { border-color: #94a3b8; transform: translateY(-1px); }
.pt-kpi:focus-visible { outline: 2px solid #6366f1; outline-offset: 2px; }
.pt-kpi-valor { font-size: 1.32rem; font-weight: 800; line-height: 1.1; color: #0f172a; }
.pt-kpi-eti   { font-size: 0.74rem; font-weight: 700; color: #64748b; text-transform: uppercase; letter-spacing: .02em; }

/* El seleccionado se distingue por borde y fondo, no por un color distinto
   en cada tarjeta: así la tira no parece un semáforo de cuatro luces. */
.pt-kpi--activo { border-color: #6366f1; box-shadow: 0 0 0 2px rgba(99,102,241,.16); background: #f5f3ff; }
.pt-kpi--rojo  .pt-kpi-valor { color: #b91c1c; }
.pt-kpi--verde .pt-kpi-valor { color: #15803d; }
.pt-kpi--azul  .pt-kpi-valor { color: #1d4ed8; }
.pt-kpi--gris  .pt-kpi-valor { color: #475569; }

/* La caja se estira para que la tabla se quede el alto disponible.
   OJO con los hijos: al poner la caja en columna hay que decir QUÉ crece. Sin
   estas dos reglas, .search-box (que no trae flex propio) se estiraba hasta
   ~260px y dejaba un bloque gris vacío por encima de la tabla, justo lo que no
   debe pasar: un contenedor inerte comiéndose el espacio de los datos. */
.pt-caja { display: flex; flex-direction: column; min-height: 0; padding: 14px 16px; }
.pt-caja > .search-box { flex: 0 0 auto; align-self: flex-start; }
.pt-caja > #pt-contenido { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.pt-scroll { flex: 1 1 auto; overflow: auto; max-height: 58vh; border: 1px solid #e2e8f0; border-radius: 10px; }

.pt-tabla { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 0.85rem; }
.pt-tabla thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--tabla-thead-bg, #f8fafc);
  border-bottom: 1px solid #e2e8f0;
  padding: 9px 12px;
  font-size: 0.74rem;
  font-weight: 800;
  color: #334155;
  text-transform: uppercase;
  letter-spacing: .02em;
  white-space: nowrap;
}
.pt-tabla td { padding: 9px 12px; border-bottom: 1px solid #f1f5f9; color: #1e293b; vertical-align: middle; }

/* Actividad: es el identificador de la fila, se queda fija a la izquierda.
   Se recorta con ellipsis para que una descripción larga no estire la fila;
   el texto completo va en el title. */
.pt-th-fijo, .pt-td-fijo {
  position: sticky;
  left: 0;
  z-index: 1;
  background: #ffffff;
  max-width: 340px;
  min-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}
.pt-th-fijo { z-index: 3; background: var(--tabla-thead-bg, #f8fafc); }

.pt-td-num   { text-align: right; font-variant-numeric: tabular-nums; }
.pt-td-plazo { white-space: nowrap; }
.pt-fecha    { font-variant-numeric: tabular-nums; }
.pt-fecha--tarde { color: #b91c1c; font-weight: 700; }
.pt-atraso   { display: block; font-size: 0.72rem; color: #b91c1c; }

/* Banda izquierda para la fila atrasada */
.pt-fila--tarde .pt-td-fijo { box-shadow: inset 3px 0 0 0 #dc2626; }
.pt-fila--tarde td { background: #fef2f2; }
.pt-fila--tarde .pt-td-fijo { background: #fef2f2; }

/* Lo cumplido pasa a segundo plano: sigue consultable, deja de competir */
.pt-fila--cerrada td { color: #64748b; }
.pt-fila--cerrada .pt-td-fijo { font-weight: 500; }

.pt-chip {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 10px;
  font-size: 0.72rem;
  font-weight: 700;
  white-space: nowrap;
  border: 1px solid transparent;
}
.pt-chip--verde { background: #dcfce7; color: #166534; border-color: #86efac; }
.pt-chip--rojo  { background: #fee2e2; color: #991b1b; border-color: #fca5a5; }
.pt-chip--azul  { background: #dbeafe; color: #1e40af; border-color: #93c5fd; }
.pt-chip--gris  { background: #f1f5f9; color: #475569; border-color: #cbd5e1; }

.pt-pie   { margin: 10px 0 0; font-size: 0.76rem; color: #64748b; }
.pt-vacio { padding: 34px 16px; text-align: center; color: #64748b; font-size: 0.88rem; }
.pt-aviso {
  padding: 14px 16px;
  border-radius: 10px;
  background: #fffbeb;
  border: 1px solid #fde68a;
  color: #92400e;
  font-size: 0.85rem;
  line-height: 1.45;
}

@media (max-width: 720px) {
  .pt-kpi { flex: 1 1 44%; min-width: 0; }
  .pt-th-fijo, .pt-td-fijo { position: static; max-width: none; min-width: 0; white-space: normal; }
  .pt-scroll { max-height: none; }
}

/* ═══════════════════════════════════════════════════════════════
   PLANILLA DE ASISTENCIA: SELECCIÓN MÚLTIPLE
   ═══════════════════════════════════════════════════════════════
   La barra de acciones aparece únicamente cuando hay turnos marcados
   (atributo hidden). Así no ocupa alto en el uso normal, que es mirar la
   planilla, y cuando aparece deja claro cuántos turnos se van a afectar
   antes de pulsar nada. */
.asis-lote {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 14px;
  margin-bottom: 12px;
  background: var(--accent-light, #eff6ff);
  border: 1px solid var(--accent-primary, #2563eb);
  border-radius: 8px;
}
.asis-lote[hidden] { display: none; }

.asis-lote-cuenta { font-size: 0.85rem; color: #1e293b; }
.asis-lote-cuenta b { font-size: 1rem; color: var(--accent-primary, #2563eb); }

.asis-lote-acciones { display: flex; flex-wrap: wrap; gap: 6px; }
.asis-lote-acciones button {
  padding: 6px 12px;
  border-radius: 6px;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
}

/* El borrado se distingue del resto: es la única acción que no se deshace */
.asis-lote-borrar {
  background: #fff;
  border: 1px solid #fca5a5;
  color: #b91c1c;
}
.asis-lote-borrar:hover { background: #fee2e2; }

/* Columna de casillas: ancha lo justo, centrada y sin que el clic en la
   celda arrastre la selección de texto. */
.tabla-asistencia th.asis-col-check,
.tabla-asistencia td.asis-col-check {
  width: 38px;
  min-width: 38px;
  text-align: center;
  user-select: none;
}
.tabla-asistencia input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--accent-primary, #2563eb);
  cursor: pointer;
  vertical-align: middle;
}

/* Fila marcada: se tiñe para que no haya duda de qué se va a modificar.
   Gana al rayado par/impar y al hover, que si no la ocultaban. */
.tabla-asistencia tbody tr.asis-fila-sel,
.tabla-asistencia tbody tr.asis-fila-sel:nth-child(even),
.tabla-asistencia tbody tr.asis-fila-sel:hover {
  background: #dbeafe !important;
}

@media (max-width: 720px) {
  .asis-lote { flex-direction: column; align-items: stretch; }
  .asis-lote-acciones button { flex: 1 1 auto; }
}

/* Texto disponible para lectores de pantalla y ausente en pantalla. Se usa
   en encabezados de columna que solo llevan un control, para que la tabla
   no tenga una cabecera sin nombre. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ═══════════════════════════════════════════════════════════════
   SELECCIÓN DE FILAS CON CASILLAS  (modules/shared/sgi-select.js)
   ═══════════════════════════════════════════════════════════════
   Generaliza lo que antes era exclusivo de la planilla de asistencia
   (.asis-lote y .asis-col-check, que siguen más arriba porque esa vista
   conserva sus ids y su prueba de navegador los usa).

   LA COLUMNA ES LO MÁS ESTRECHA QUE PUEDE SER
   Sin filas, el ancho de la tabla lo fija solo el encabezado, y cada celda
   pide su rótulo más el cromo que no depende del rótulo. La columna de
   casillas no lleva rótulo visible ni los controles de ordenar y filtrar
   (el realzador los omite al ver data-sgi-no-tools), así que su suelo es la
   casilla más el relleno: 14 + 3 + 3 = 20px, 22px con el borde.

   Son 22px que hay que justificar: la tabla más justa del sistema
   (Herramientas · Catálogo) tiene un suelo de 964px contra 964px útiles a
   1280x720 con el menú desplegado. Cada píxel de esta columna sale de ahí,
   y por eso no se le pone ni un padding de adorno. La medición está en
   audit/medir-suelo-tablas.js. */

/* El relleno va con !important y con el selector de tabla por delante porque
   compite con reglas más específicas que ya existen: `table[data-sgi-enhanced]
   thead th` fija 10px 12px, y por especificidad le ganaba a `th.sgi-sel-celda`.
   Con ese relleno heredado la columna medía 35px en lugar de 22px, y esos 13px
   de más sacaban de su contenedor a la bandeja de solicitudes. */
th.sgi-sel-celda,
td.sgi-sel-celda,
table thead th.sgi-sel-celda,
table tbody td.sgi-sel-celda,
table[data-sgi-enhanced] thead th.sgi-sel-celda {
  width: 22px !important;
  min-width: 22px !important;
  max-width: 22px;
  padding: 0 3px !important;
  text-align: center;
  /* El clic en la celda no arrastra selección de texto: se marca muy seguido */
  user-select: none;
}

/* La casilla ocupa toda la celda para que el blanco de alrededor también
   valga como zona de clic. La fila mide unos 32px de alto, así que el área
   real es 22x32 y no los 14x14 del dibujo. */
.sgi-sel-celda input[type="checkbox"] {
  width: 14px;
  height: 14px;
  margin: 0;
  accent-color: var(--accent-primary, #2563eb);
  cursor: pointer;
  vertical-align: middle;
}

/* La columna de casillas NO se congela: no lleva ninguna clase col-sticky-*,
   así que unfreezeColumns() del realzador sigue liberando la tabla entera.
   Esta regla solo la deja explícita para que nadie la fije por descuido. */
th.sgi-sel-celda,
td.sgi-sel-celda { position: static !important; left: auto !important; }

/* El encabezado de la columna conserva la fijación VERTICAL que pone
   stickHeader, igual que el resto de la fila: si se quedara suelta, la
   casilla maestra desaparecería al bajar por la tabla. */
table[data-sgi-enhanced] thead th.sgi-sel-celda { position: sticky !important; }

/* Fila marcada: se tiñe para que no haya duda de qué se va a modificar.
   Gana al rayado par/impar y al hover, que si no la tapaban. */
tbody tr.sgi-sel-fila,
tbody tr.sgi-sel-fila:nth-child(even),
tbody tr.sgi-sel-fila:hover {
  background: #dbeafe !important;
}

/* ── Barra de acciones ──────────────────────────────────────────
   Solo aparece cuando hay algo marcado (atributo hidden). En el uso normal,
   que es mirar la tabla, no ocupa ni una fila de alto. */
.sgi-sel-barra {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  padding: 9px 14px;
  margin-bottom: 10px;
  background: var(--accent-light, #eff6ff);
  border: 1px solid var(--accent-primary, #2563eb);
  border-radius: 8px;
}
.sgi-sel-barra[hidden] { display: none; }

.sgi-sel-cuenta {
  font-size: 0.85rem;
  color: #1e293b;
  display: flex;
  align-items: baseline;
  gap: 6px;
  flex-wrap: wrap;
}
.sgi-sel-cuenta b {
  font-size: 1rem;
  color: var(--accent-primary, #2563eb);
}

/* De dónde sale la selección: de esta página o de todo el filtro. Sin este
   dato "seleccionar todo" es ambiguo y el usuario no sabe qué va a tocar. */
.sgi-sel-alcance {
  font-size: 0.74rem;
  font-weight: 700;
  color: #1d4ed8;
  background: #dbeafe;
  border: 1px solid #93c5fd;
  border-radius: 10px;
  padding: 1px 8px;
  white-space: nowrap;
}

/* La oferta de ampliar al filtro completo va separada de las acciones: es
   una selección, no una ejecución, y confundirlas es el riesgo que pide
   evitar el requisito de las acciones peligrosas. */
.sgi-sel-ampliar { margin-right: auto; }

.sgi-sel-btn-ampliar {
  padding: 5px 11px;
  border-radius: 6px;
  font-size: 0.77rem;
  font-weight: 700;
  cursor: pointer;
  background: #ffffff;
  border: 1px dashed var(--accent-primary, #2563eb);
  color: #1d4ed8;
  white-space: nowrap;
}
.sgi-sel-btn-ampliar:hover { background: #eff6ff; }

.sgi-sel-acciones { display: flex; flex-wrap: wrap; gap: 6px; }

/* Un solo estilo de botón para todas las acciones en lote de todos los
   módulos: la barra se ve igual en asistencia, en herramientas y en
   viáticos, así que se reconoce sin leerla. */
.sgi-sel-btn {
  padding: 6px 12px;
  border-radius: 6px;
  font-size: 0.78rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  background: #ffffff;
  border: 1px solid #cbd5e1;
  color: #334155;
}
.sgi-sel-btn:hover { background: #f1f5f9; }

/* Lo irreversible se distingue del resto ANTES de pulsarlo. */
.sgi-sel-btn-peligro {
  border-color: #fca5a5;
  color: #b91c1c;
}
.sgi-sel-btn-peligro:hover { background: #fee2e2; }

.sgi-sel-btn-quitar { border-style: dashed; color: #475569; }

@media (max-width: 720px) {
  .sgi-sel-barra { flex-direction: column; align-items: stretch; }
  .sgi-sel-ampliar { margin-right: 0; }
  .sgi-sel-acciones button { flex: 1 1 auto; }
}
