/* ============================================================================
   styles.css  ·  Tema webHerreria (oscuro + rojo Klassen) para el front unificado.
   Base tomada de webHerreria/assets/css/app.css + login + overrides de Bootstrap
   para el shell (permisos): modal, botones, dropdown de usuario.
   ============================================================================ */
:root {
  --klassen-red: #d7263d;
  --klassen-red-strong: #b71f32;
  --klassen-red-soft: rgba(215, 38, 61, 0.14);

  --bg-0: #14161a;
  --bg-1: #1b1e24;
  --bg-2: #22262e;
  --bg-3: #2a2f38;
  --border: #2c313b;
  --border-soft: #262b33;
  /* Borde de los cuadros de acceso rapido de Inicio. Token aparte de --border
     porque esas tarjetas van sobre el panel de Inicio, no sobre el fondo de
     pagina: con --border (un gris casi del mismo tono que el panel) los cuadros
     no se distinguian. Aqui va casi blanco; en el tema claro voltea a un gris
     OSCURO, porque sobre el panel claro un borde blanco desaparece. */
  --border-home: #f0f2f5;

  /* Transparencia unificada (alpha 0-1) en 2 perillas globales: cambiar
     cualquiera de las dos ajusta TODA la transparencia relacionada sin tocar
     reglas individuales.
     --trans-home    = panel de accesos rapidos de Inicio (inicioScreen.js).
     --trans-content = todo lo demas: bg-1-t/2-t/3-t de abajo, que alimentan
                       card-surface, grids, filtros, dropdowns y modales. */
  --trans-home: 0.70;
  --trans-content: 0.85;

  /* Version semitransparente de bg-1/2/3, usada por las superficies que
     envuelven cada pantalla (card-surface, grids, modal) para que la imagen
     de fondo elegida en el topbar (ver fondoSelector.js) se note detras.
     Sin imagen de fondo elegida se ven practicamente iguales al solido de
     siempre, porque queda encima del body oscuro. */
  --bg-1-t: rgba(27, 30, 36, var(--trans-content));
  --bg-2-t: rgba(34, 38, 46, var(--trans-content));
  --bg-3-t: rgba(42, 47, 56, var(--trans-content));
  /* Igual que --bg-1-t pero con la perilla de Inicio. Existe como TOKEN (y no
     como literal dentro de .ini-panel) porque el tema claro tiene que poder
     voltearlo: hardcodeado ahi, el panel se quedaba oscuro en claro y las
     tarjetas de acceso -- que si usan --bg-1-t -- salian claras encima. */
  --bg-home-t: rgba(27, 30, 36, var(--trans-home));

  /* Imagen de fondo del area de contenido (fondoSelector.js la fija via JS).
     'none' por defecto: sin seleccion, el body se ve como antes. */
  --fondo-img: none;

  --text: #e6e8ec;
  /* Un punto mas brillante que el texto normal, para lo que TITULA: titulo de
     pantalla y encabezado de seccion de una ficha. Que resalten sobre el resto
     es lo que deja leer la jerarquia de un vistazo. */
  --text-strong: #f6f8fb;
  --text-muted: #9aa0ab;
  /* Gris mas tenue de la escala. Aclarado desde #6f7681 (2.9:1 sobre bg-1, por
     debajo de AA) a #8f959f, que da >=4.5:1 sobre bg-0/1/2 en texto normal. */
  --text-dim: #8f959f;

  --radius: 10px;
  --sidebar-w: 264px;

  /* ---------- Tipografia UNIFICADA ----------
     Una sola familia y una sola escala para TODO el front. Las pantallas que
     traian pila propia (Consumibles y Envios/Recibo importaban 'Public Sans' e
     'IBM Plex Mono' de Google Fonts) ahora consumen estos tokens, asi que ya no
     se ven de otra familia ni con otro tamano de titulo que el resto.
     Regla para pantallas nuevas: NO declarar font-family; para tamanos, usar
     estas variables o heredar.
     PENDIENTE: quedan ~75 font-size en px sueltos (celdas densas, badges, pies
     de tabla) sin migrar a la escala -- se analiza aparte porque mover esos
     valores cambia el alto de varias tablas. */
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  --fs-base: 14px;
  /* Secundario: subtitulos de pantalla y textos de ayuda. */
  --fs-sm: 12.5px;
  /* Minimo legible: badges y encabezados de seccion. */
  --fs-xs: 11.5px;
  /* Titulo de pantalla: .screen-head h1 y sus equivalentes por pantalla. */
  --fs-h1: 19px;
  --fs-h2: 15px;
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  background-color: var(--bg-0);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
}

/* Los controles de formulario NO heredan la fuente del documento: el navegador
   les impone la suya. Sin esto un <input>/<select>/<button> se dibuja con otra
   familia que el texto que lo rodea, que es parte de lo que se veia disparejo
   entre pantallas. */
input,
select,
textarea,
button,
optgroup {
  font-family: inherit;
}

/* El fondo vive en una CAPA FIJA propia, no en el background del body con
   background-attachment: fixed: en movil ese modo no se repinta parejo
   mientras el navegador contrae/expande su barra de direcciones, y la imagen
   se veia dando saltos al hacer scroll. Siendo un elemento fixed detras del
   contenido (z-index -1) la imagen se queda completamente quieta.
   Capa 1 (arriba): degradado oscuro->transparente SOLO en el primer tercio de
   la pantalla, para que el titulo/descripcion de CADA pantalla (screen-head,
   justo debajo del topbar) sea legible sin importar que tan clara/ocupada sea
   la imagen elegida. De ahi para abajo la imagen queda sin oscurecer (el ultimo
   stop en 0 evita el efecto de versiones anteriores, donde el degradado se
   quedaba plano en vez de seguir aclarando).
   Capa 2 (abajo): la imagen (--fondo-img, que fondoSelector.js fija en <html>). */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  /* Alto estable: con lvh la imagen no se re-encuadra cuando la barra del
     navegador movil aparece o desaparece (100vh si no conoce lvh). */
  height: 100vh;
  height: 100lvh;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(to bottom,
      rgba(10, 12, 15, .90) 0,
      rgba(10, 12, 15, .60) 160px,
      rgba(10, 12, 15, .28) 340px,
      rgba(10, 12, 15, 0) 560px,
      rgba(10, 12, 15, 0) 100%),
    var(--fondo-img);
  background-size: cover, cover;
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
}

/* ---------- Layout ---------- */
.app {
  display: flex;
  min-height: 100vh;
}

.content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

/* ---------- Sidebar ---------- */
.sidebar {
  width: var(--sidebar-w);
  background: var(--bg-1);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  z-index: 2;
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 61px;
  padding: 0 18px;
  /* misma altura que .topbar -> bordes alineados */
  border-bottom: 1px solid var(--border-soft);
}

.brand-mark {
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
  object-fit: contain;
}

.brand-title {
  font-weight: 600;
  line-height: 1.1;
}

.brand-sub {
  font-size: 11.5px;
  color: var(--text-dim);
}

.sidebar-nav {
  padding: 10px;
  overflow-y: auto;
  flex: 1;
}

.nav-group>.nav-group-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  cursor: pointer;
  color: var(--text-muted);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
  font-weight: 600;
  border-radius: 8px;
  user-select: none;
}

.nav-group>.nav-group-header:hover {
  background: var(--bg-2);
  color: var(--text);
}

.nav-group-header .chev {
  margin-left: auto;
  transition: transform .15s ease;
  font-size: 13px;
}

.nav-group.collapsed .chev {
  transform: rotate(-90deg);
}

.nav-group.collapsed .nav-children {
  display: none;
}

.nav-children {
  margin: 2px 0 6px;
  padding-left: 10px;
  /* indentacion por nivel (sin guia lateral) */
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  /* mismo left que .nav-group-header: modulos y pantallas del mismo nivel se alinean */
  border-radius: 8px;
  cursor: pointer;
  color: var(--text);
  border-left: 2px solid transparent;
  margin: 1px 0;
  /* Dejar presionada una pantalla abre su menu ("Agregar a Inicio", ver
     components/filaAccionesMenu.js): sin el callout nativo ni la seleccion de
     texto que lo interrumpirian. */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

.nav-item:hover {
  background: var(--bg-2);
}

.nav-item.active {
  background: var(--klassen-red-soft);
  border-left-color: var(--klassen-red);
  color: #fff;
}

.nav-item .bi {
  color: var(--text-dim);
  font-size: 15px;
}

.nav-item.active .bi {
  color: var(--klassen-red);
}

.sidebar-foot {
  padding: 10px 16px;
  border-top: 1px solid var(--border-soft);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.sidebar-foot-version {
  font-size: 11px;
  color: var(--text-dim);
  min-height: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
}

.sidebar-foot-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

/* Barra inferior del sidebar: version al centro, engranaje a la derecha. */
.sidebar-bar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  padding: 8px 12px;
  border-top: 1px solid var(--border-soft);
}

.sidebar-version {
  flex: 1;
  text-align: center;
  font-size: 11px;
  color: var(--text-dim);
  word-break: break-all;
}

.sidebar-bar-btn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
  width: 36px;
  height: 36px;
  border-radius: 8px;
  display: grid;
  place-items: center;
  cursor: pointer;
  font-size: 18px;
}

.sidebar-bar-btn:hover {
  background: var(--bg-2);
  color: var(--text);
}

.sidebar-backdrop {
  display: none;
}

/* ---------- Topbar ---------- */
.topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 61px;
  padding: 0 22px;
  background: var(--bg-1);
  /* misma altura que .sidebar-brand */
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  /* position+z-index aqui crea un stacking context propio para TODO el topbar
     (incluidos sus dropdowns, ej. el menu de usuario): con z-index bajo (era
     5) ese stacking context completo queda por debajo de paneles con z-index
     mayor en el contenido (ej. .filtros-bar/.filtros-panel en z-index:10),
     tapando el dropdown aunque el dropdown-menu de Bootstrap tenga z-index
     propio de 1000 -- ese 1000 solo compite DENTRO del stacking context del
     topbar, no contra el de afuera. 15 alcanza para ganarle a esos paneles de
     contenido (10) sin tapar el drawer del sidebar en movil (30) ni su fondo
     oscuro (20, ver @media abajo). */
  z-index: 15;
}

.topbar-title {
  font-size: 16px;
  font-weight: 600;
  margin-right: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow: hidden;
}

/* Migaja de pan del topbar (solo visual, no clickeable): modulo(s) del menu
   hasta la pantalla actual. Los ancestros van atenuados; la pantalla actual
   con el mismo peso/color que tenia el titulo antes de volverse migaja. */
.topbar-title span {
  color: var(--text-muted);
  font-weight: 500;
  white-space: nowrap;
}

.topbar-title span.crumb-actual {
  color: var(--text);
  font-weight: 600;
}

.topbar-title .crumb-sep {
  color: var(--text-dim);
  font-size: 11px;
}

.btn-icon {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
  width: 34px;
  height: 34px;
  border-radius: 8px;
  display: none;
  place-items: center;
  cursor: pointer;
}

.btn-icon:hover {
  background: var(--bg-2);
}

/* Igual que .btn-icon pero SIEMPRE visible (.btn-icon solo aparece en movil,
   ver el media query de responsive mas abajo) -- para el boton de imagen
   de fondo del topbar. */
.btn-fondo {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
  width: 34px;
  height: 34px;
  border-radius: 8px;
  display: grid;
  place-items: center;
  cursor: pointer;
}

.btn-fondo:hover {
  background: var(--bg-2);
}

/* Campana de notificaciones (topbar): .btn-fondo necesita position:relative
   para anclar el badge en su esquina superior derecha. */
#btnNotificaciones {
  position: relative;
}

.notif-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--klassen-red);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}

.notif-item {
  padding: 10px 12px;
  border-bottom: 1px solid var(--border-soft);
  cursor: pointer;
}

.notif-item:last-child {
  border-bottom: none;
}

/* Un poco menor que el texto base: en el popup caben mas sin que se sienta apretado. */
.notif-msg {
  font-size: var(--fs-sm);
}

.notif-item:hover {
  background: var(--bg-3);
}

/* Sin ver (aún no le has dado clic): resaltadas en ROJO. Al dar clic pasan a
   "vista" y se ven en GRIS (estilo normal), para distinguir leídas de no leídas. */
.notif-item.no-vista {
  background: rgba(207, 43, 43, 0.10);
  border-left: 3px solid var(--klassen-red);
}

.notif-item.no-vista .notif-msg {
  color: var(--klassen-red);
  font-weight: 600;
}

.notif-item.no-vista:hover {
  background: rgba(207, 43, 43, 0.16);
}

.notif-fecha {
  font-size: 11px;
  margin-top: 2px;
}

.dropdown-item-danger {
  color: var(--klassen-red);
}

.dropdown-item-danger:hover {
  background: var(--bg-3);
  color: var(--klassen-red);
}

/* ---------- Screen / Grid ---------- */
.screen {
  padding: 22px;
}

.screen-head {
  display: flex;
  align-items: flex-end;
  gap: 14px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.screen-head .titles {
  margin-right: auto;
}

.screen-head h1 {
  font-size: var(--fs-h1);
  margin: 0 0 2px;
  font-weight: 600;
  color: var(--text-strong);
}

.screen-head .sub {
  /* Mismo color que el titulo (no --text-muted): sobre el degradado del
     fondo (ver body en la seccion de arriba) necesita el mismo contraste
     que el h1 para leerse bien encima de cualquier imagen. */
  color: var(--text);
  font-size: var(--fs-sm);
}

/* Titulos de SECCION sueltos (ej. "Pendientes de aprobacion" / "Todas las
   solicitudes" en Seguimiento): igual que .screen-head, se dibujan DIRECTO
   sobre el degradado/imagen del fondo, no sobre una superficie. Por eso llevan
   el color fuerte y no el de texto normal.
   Se enganchan por ser hijos DIRECTOS de #contenido, que es justo lo que
   distingue un titulo "sobre el fondo" de uno dentro de una .card-surface, un
   modal o un formulario -- esos quedan fuera de la regla a proposito, porque
   ahi el fondo es la superficie y el color normal es el correcto. Cualquier
   pantalla nueva que suelte un titulo al mismo nivel lo hereda sin tocar nada. */
#contenido > h1,
#contenido > h2,
#contenido > h3,
#contenido > h4,
#contenido > h5,
#contenido > h6 {
  color: var(--text-strong);
}

/* El contador que va dentro del titulo ("(1)") es .field-help, que apunta a
   --text-dim: sobre una superficie se lee, sobre el fondo no. */
#contenido > h1 .field-help,
#contenido > h2 .field-help,
#contenido > h3 .field-help,
#contenido > h4 .field-help,
#contenido > h5 .field-help,
#contenido > h6 .field-help {
  color: var(--text);
}

.card-surface {
  background: var(--bg-1-t);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

/* ---------- Secciones de pantalla (filtros / acciones / grid) ----------
   Patron unico: cada zona de una pantalla es una .screen-section con la misma
   separacion vertical, un encabezado opcional (.section-head) y, cuando el
   bloque necesita fondo propio, ademas .card-surface. */
.screen-section {
  margin-bottom: 16px;
}

.screen-section:last-child {
  margin-bottom: 0;
}

.section-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 10px;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-muted);
  font-weight: 600;
}

.section-head .bi {
  font-size: 13px;
}

/* Acciones alineadas a la derecha del encabezado de seccion. */
.section-head-acciones {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Barra de filtros / acciones de lote. El layout vive aqui (antes venia como
   estilo inline desde listView.js). Con .card-surface se vuelve un bloque con
   fondo propio; overflow visible para que los paneles de filtro (absolutos)
   no queden recortados por el overflow:hidden de card-surface. */
.filtros-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 16px;
  /* La barra se apila por encima del grid que la sigue: con .card-surface el
     backdrop-filter la vuelve contexto de apilamiento y, sin esto, el panel de
     filtros (absoluto, z-index 60) quedaria pintado DEBAJO de la superficie
     del grid. */
  position: relative;
  z-index: 10;
}

.filtros-bar.card-surface {
  padding: 12px 14px;
  overflow: visible;
}

/* Variante con CAMPOS ETIQUETADOS (label arriba, control abajo), que es como
   filtran Transacciones, Consumibles y el Dashboard almacenista. La barra base
   centra verticalmente, que sirve cuando solo hay botones; con etiquetas hay
   que alinear por la BASE o los controles quedan escalonados segun cuantas
   lineas ocupe cada label. */
.filtros-bar.filtros-campos {
  align-items: flex-end;
  gap: 12px;
}

.filtros-bar.filtros-campos>.filtro-campo {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 150px;
}

/* El campo de busqueda se queda con el espacio sobrante del renglon. */
.filtros-bar.filtros-campos>.filtro-campo.crece {
  flex: 1;
  min-width: 180px;
}

/* Filtro resuelto con un campo de lupa (AlmacenajePicker) en vez de un
   <select>: adentro conviven el texto de lo elegido, la "x" y la lupa, asi que
   con los 150px de un campo normal el nombre quedaba en dos letras. */
.filtros-bar.filtros-campos>.filtro-campo-lookup {
  min-width: 240px;
}

.filtros-bar.filtros-campos .form-label {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--fs-sm);
}

/* Panel unico que agrupa varias barras (filtros arriba, seleccion de lote
   abajo): un solo fondo con un renglon por barra, separados por una linea. */
.filtros-panel {
  margin-bottom: 16px;
  /* Mismo motivo que .filtros-bar: el backdrop-filter de .card-surface vuelve
     al panel contexto de apilamiento, y sin esto los paneles de filtro
     (absolutos) quedarian pintados debajo de la superficie del grid. */
  position: relative;
  z-index: 10;
  overflow: visible;
}

.filtros-panel>.filtros-bar {
  margin-bottom: 0;
  padding: 12px 14px;
}

.filtros-panel>.filtros-bar+.filtros-bar {
  border-top: 1px solid var(--border-soft);
  /* Los paneles de filtro son absolutos con z-index 60, pero quedan ATRAPADOS
     en el stacking context de su .filtros-bar (z-index 10): ese 60 solo ordena
     DENTRO de la barra. Una barra hermana con el MISMO z-index que va despues
     en el DOM -- la de lote, "Categorizar seleccionados" -- gana por orden de
     pintado y se monta encima del desplegable: su contenido se ve ENCIMA del
     panel (que parece transparente aunque su fondo sea solido) y se traga los
     clics de las casillas y de Todos/Ninguno, que quedan muertos.
     Esta barra no tiene desplegables propios, asi que no necesita nivel: sin
     z-index se pinta por debajo de la capa de la barra de filtros. */
  z-index: auto;
}

/* Empuja lo que sigue al extremo derecho de la barra. */
.filtros-bar-fin {
  margin-left: auto;
}

/* Tarjeta que CONTIENE un desplegable propio (.combo-list, panel de filtro).
   Dos cosas la rompen y las dos se arreglan aqui:
     1. .card-surface trae overflow:hidden -> recortaba la lista desplegada.
     2. su backdrop-filter la vuelve contexto de apilamiento, asi que el
        z-index de la lista NO compite contra las tarjetas hermanas: la
        siguiente .card-surface del DOM se pintaba ENCIMA del desplegable
        (asi quedaba tapado el combo de recetas en Produccion).
   Subir la tarjeta entera por encima de lo que le sigue resuelve ambas. */
.card-surface.panel-flotante {
  overflow: visible;
  position: relative;
  /* TECHO: por debajo del topbar (15). Esta tarjeta es un stacking context a
     nivel de documento, asi que su z-index compite contra el del topbar; con un
     valor mayor tapaba sus desplegables -- el panel de notificaciones quedaba
     detras del panel de filtros. Con 12 le sigue ganando a la .card-surface
     hermana que la sigue (z-index auto), que es lo unico que necesita.
     Regla general: NINGUN panel de contenido pasa de 14. Ver la escala en
     .topbar (15 topbar · 20 fondo del drawer movil · 30 drawer). */
  z-index: 12;
}

/* Tarjeta del GRID, que contiene el desplegable de "Mostrar N" del paginador.
   Mismo problema 1 que arriba -- overflow:hidden lo recortaba -- pero NO el 2:
   aqui el z-index tiene que quedarse abajo. Esta tarjeta va DESPUES de
   .filtros-panel (z-index 10) en el DOM; subirla a 12 como .panel-flotante
   taparia los paneles de filtro que bajan de la barra. Sin z-index propio, el
   desplegable del paginador cae hacia abajo, donde no compite con nada.

   Por que no basta con que Popper lo voltee: con pocas filas la tarjeta mide
   ~200px y el menu ~178px, asi que no cabe ni abajo ni arriba del boton, y
   Popper se queda en 'bottom-start' cortado a la mitad (se veia en
   Departamentos con 2 registros).

   El scroll horizontal del grid no se ve afectado: lo recorta #tabla, que
   tiene overflow-x propio. */
.card-surface.grid-flotante {
  overflow: visible;
}

/* Contrapartida del overflow:visible de arriba. La tarjeta dibuja sus esquinas
   redondeadas, pero al renunciar a recortar ya no obliga a sus hijos a
   respetarlas: el fondo del thead (primer hijo) y el de la barra de paginacion
   (ultimo hijo) pintan por encima de las cuatro esquinas y el grid se ve con
   los extremos cuadrados sobresaliendo de la tarjeta. Se disimulaba mientras
   esos fondos eran casi del color de la tarjeta; con el encabezado gris
   pizarra del tema claro quedo a la vista.
   El recorte se devuelve hijo por hijo: #tabla ya es contenedor de scroll
   (overflow-x:auto en la regla .card-surface>#tabla), asi que con darle el
   radio recorta su propia tabla -- NO ponerle overflow:hidden aqui, eso mataria
   el scroll horizontal de los grids anchos. */
.card-surface.grid-flotante>#tabla {
  border-top-left-radius: var(--radius);
  border-top-right-radius: var(--radius);
}

/* Sin barra de paginacion (ListView con paginacion:false) el grid es el ultimo
   hijo y le tocan tambien las dos esquinas de abajo. */
.card-surface.grid-flotante>#tabla:last-child {
  border-bottom-left-radius: var(--radius);
  border-bottom-right-radius: var(--radius);
}

/* La barra de paginacion cierra la tarjeta en todas las pantallas que la
   arman (ListView, TreeView, Existencias, Transacciones, pantallasAcciones),
   vaya o no dentro de una .grid-flotante. */
.paginacion-controles:last-child {
  border-bottom-left-radius: var(--radius);
  border-bottom-right-radius: var(--radius);
}

/* Toolbar de las pantallas de permisos (por rol y por usuario):
     · grupo "Copiar de:" -> caja con borde propio, se lee como una accion
     · buscador           -> al extremo DERECHO (.filtros-bar-fin), igual que la
                             busqueda incremental del resto de las pantallas
   "Regresar" ya no vive aqui: subio al screen-head (ver la norma en
   rolPermisosScreen.js). */
.perm-toolbar {
  gap: 10px;
}

.perm-toolbar-grupo {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-2-t);
}

.perm-toolbar-grupo .form-label {
  color: var(--text-muted);
  font-size: var(--fs-sm);
  white-space: nowrap;
}

.perm-toolbar-grupo .form-select {
  width: auto;
  min-width: 220px;
}

@media (max-width: 820px) {

  .perm-toolbar .search,
  .perm-toolbar-grupo {
    width: 100%;
  }

  .perm-toolbar-grupo .form-select {
    flex: 1;
    min-width: 0;
  }
}

/* ---------- Lookup de almacenajes (almacenajePicker.js) ----------
   Rejilla de filtros del modal: el buscador ocupa el renglon completo y los
   cuatro acotadores (empresa / sucursal / almacen / enlace) se reparten abajo,
   colapsando a uno por renglon en pantallas angostas. */
.ap-filtros {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr)) auto;
  gap: 8px;
  margin-bottom: 12px;
}

.ap-filtros .ap-f-texto {
  grid-column: 1 / -1;
}

@media (max-width: 720px) {
  .ap-filtros {
    grid-template-columns: 1fr;
  }
}

/* ---------- Campo "con lupa": muestra lo elegido y abre un lookup ----------
   El valor NO se escribe, se elige en el modal (AlmacenajePicker/ItemPicker),
   asi que el campo va de solo lectura y el boton es el que manda. Se usa donde
   antes habia un <select> plano con el catalogo completo. */
.campo-lookup {
  display: flex;
  gap: 6px;
  align-items: stretch;
}

.campo-lookup .campo-lookup-valor {
  flex: 1;
  min-width: 0;
  cursor: pointer;
}

/* El campo es readonly porque el valor se ELIGE, no se teclea -- pero muestra
   un dato real, asi que no debe verse apagado como un campo deshabilitado
   (.form-control[readonly] lo atenua por defecto). */
.campo-lookup .campo-lookup-valor[readonly] {
  background: var(--bg-2);
  color: var(--text);
}

.campo-lookup .campo-lookup-valor[readonly]:hover {
  border-color: var(--klassen-red);
}

/* Boton "x" (opcional, campoHtml con limpiable:true): vuelve el campo a SIN
   almacenaje. Es la pieza que hace que el lookup pueda usarse de FILTRO -- sin
   ella, elegir un almacenaje seria un viaje de ida. Solo se muestra cuando hay
   algo que quitar, y va mas angosto que la lupa para que el acento siga estando
   en la accion principal. */
.campo-lookup .campo-lookup-limpiar {
  flex: 0 0 auto;
  padding-left: 9px;
  padding-right: 9px;
  color: var(--text-muted);
}

.campo-lookup .campo-lookup-limpiar:hover {
  color: var(--text);
}

/* Segunda linea bajo el campo: la ubicacion completa del almacenaje elegido
   (empresa > sucursal > almacen > celda), que no cabe en el propio campo. La
   variante compacta (barras de filtros) no la pinta y deja la ubicacion en el
   title del campo. */
.campo-lookup-ubicacion {
  margin-top: 4px;
  min-height: 16px;
}

/* Encabezado de seccion dentro de una ficha/modal (campo.seccion en formModal).
   Deliberadamente NO reusa .section-head: ese es gris tenue y en mayusculas,
   pensado para rotular una zona de la pantalla, y dentro del formulario quedaba
   mas apagado que las propias etiquetas de los campos. Aqui va con el blanco
   intenso de los titulos de pantalla, para que se lea como un corte real. */
.form-seccion {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
  color: var(--text-strong);
  font-size: var(--fs-h2);
  font-weight: 600;
}

/* Las secciones que siguen a la primera necesitan aire arriba: cierran el
   bloque anterior y abren el suyo. */
.form-seccion.form-seccion-siguiente {
  margin-top: 10px;
}

/* Boton de filtro + su panel desplegable. */
.filtro-wrap {
  position: relative;
}

.filtro-panel {
  display: none;
  position: absolute;
  left: 0;
  top: calc(100% + 6px);
  z-index: 60;
  min-width: 260px;
  max-height: 60vh;
  overflow: auto;
  padding: 10px;
}

/* El panel de filtro se pinta con .card-surface, que es translucida. Como este
   FLOTA, se le devuelve el fondo solido (mismo criterio que .combo-list). */
.filtro-panel.card-surface {
  background: var(--bg-2);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .5);
}

table.grid {
  width: 100%;
  border-collapse: collapse;
}

table.grid thead th {
  background: var(--bg-2-t);
  color: var(--text-muted);
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: .03em;
  text-align: left;
  padding: 11px 14px;
  border-bottom: 1px solid var(--border);
  font-weight: 600;
}

table.grid tbody td {
  padding: 11px 14px;
  border-bottom: 1px solid var(--border-soft);
}

table.grid tbody tr:last-child td {
  border-bottom: none;
}

table.grid tbody tr:hover {
  background: var(--bg-2);
}

.col-acciones {
  text-align: right;
  white-space: nowrap;
  width: 1%;
}

/* Contenedor con scroll horizontal para grids anchos. #tabla es el contenedor
   que arman ListView/TreeView; .grid-scroll es para pantallas custom. Hace
   falta que el scroll viva AQUI (y no en la tabla) para que la columna de
   acciones pueda quedarse pegada a la derecha (position: sticky). */
.card-surface>#tabla,
.grid-scroll {
  overflow-x: auto;
}

/* La columna de acciones es una columna NORMAL del grid. Antes se quedaba
   pegada a la derecha (position: sticky) al desplazar en horizontal, pero al
   sobreponerse sobre las demas celdas necesitaba fondo propio, y ese fondo
   -- encima del que ya pone .card-surface -- apilaba dos capas translucidas y
   se veia mas opaca que el resto del grid. Si el grid no cabe, scrollea el
   contenedor (.card-surface>#tabla / .grid-scroll, y table.grid en movil); en
   pantallas chicas la columna se oculta y sus acciones se llegan por el menu
   contextual (components/filaAccionesMenu.js). */

.row-btn {
  background: transparent;
  border: 1px solid var(--border);
  color: #ffffff;
  width: 30px;
  height: 30px;
  border-radius: 7px;
  /* editar/ver: blanco intenso */
  cursor: pointer;
  margin-left: 4px;
}

.row-btn:hover {
  background: var(--bg-3);
  color: #ffffff;
}

.row-btn.danger {
  color: var(--klassen-red);
  border-color: var(--klassen-red);
}

/* eliminar: rojo de la paleta */
.row-btn.danger:hover {
  color: #fff;
  background: var(--klassen-red-strong);
  border-color: var(--klassen-red-strong);
}

/* Menu de acciones de una fila (components/filaAccionesMenu.js): click derecho
   o long-press sobre la fila. Flota sobre el contenido, asi que va SOLIDO
   (como .dropdown-menu) y no translucido: tiene que leerse sin importar lo que
   quede atras. */
.fila-menu {
  position: fixed;
  z-index: 1100;
  min-width: 190px;
  padding: 6px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .5);
}

.fila-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 12px;
  background: transparent;
  border: 0;
  border-radius: 8px;
  color: var(--text);
  text-align: left;
  font-size: 13.5px;
  cursor: pointer;
}

.fila-menu-item:hover {
  background: var(--bg-3);
}

.fila-menu-item.danger {
  color: var(--klassen-red);
}

.fila-menu-item.danger:hover {
  background: var(--klassen-red-strong);
  color: #fff;
}

/* Elemento sobre el que esta abierto el menu: se resalta para no perder de
   vista a cual corresponden las acciones. */
table.grid tbody tr.fila-menu-activa>td,
.nav-item.fila-menu-activa {
  background: var(--klassen-red-soft);
}

.empty {
  padding: 44px 20px;
  text-align: center;
  color: var(--text-dim);
}

.empty .bi {
  font-size: 30px;
  display: block;
  margin-bottom: 8px;
}

/* Grid tipo arbol */
.tree-cell {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.tree-toggle {
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0;
  width: 18px;
  height: 18px;
  display: inline-grid;
  place-items: center;
  font-size: 13px;
}

.tree-toggle:hover {
  color: var(--text);
}

.tree-spacer {
  display: inline-block;
  width: 18px;
}

table.grid.tree tbody td:first-child {
  white-space: nowrap;
}

/* ---------- Reordenar hermanos arrastrando (TreeView reordenable) ----------
   La fila que se arrastra se atenua; la fila sobre la que se suelta marca con
   una linea EN QUE BORDE va a quedar (arriba o abajo), que es lo unico que
   distingue "antes de" de "despues de" al soltar. */
table.grid tbody tr[draggable="true"] {
  cursor: grab;
}

table.grid tbody tr.fila-drag>td {
  opacity: .45;
}

table.grid tbody tr.drop-antes>td {
  box-shadow: inset 0 2px 0 0 var(--klassen-red);
}

table.grid tbody tr.drop-despues>td {
  box-shadow: inset 0 -2px 0 0 var(--klassen-red);
}

/* ---------- Buscador (input .search estilizado del tema) ----------
   Mismo fondo y radio que .form-control/.form-select para que no se vea como
   un input de otra familia; se usa background-color (no el atajo background)
   porque debajo va la lupa como background-image. */
.search {
  background-color: var(--bg-2);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius);
  padding: 8px 12px 8px 32px;
  width: 240px;
  max-width: 46vw;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%239aa0ab' viewBox='0 0 16 16'%3E%3Cpath d='M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 10px center;
}

.no-search {
  background: var(--bg-1-t);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 8px;
  padding: 8px 12px 8px 32px;
  width: 240px;
  max-width: 46vw;
  background-repeat: no-repeat;
  background-position: 10px center;
}

.search:focus {
  outline: none;
  border-color: var(--klassen-red);
}

/* ---------- Combobox con busqueda incremental ---------- */
.combo {
  position: relative;
}

.combo-list {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 4px);
  /* SOLIDO a proposito: flota sobre el grid y tiene que leerse sin que se
     transparente lo que quede atras (ver .dropdown-menu / .fila-menu). */
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  max-height: 260px;
  overflow-y: auto;
  z-index: 30;
  display: none;
  box-shadow: 0 8px 26px rgba(0, 0, 0, .4);
}

/* Desplegable hacia ARRIBA: lo pone combo.js cuando abajo no queda hueco
   utilizable dentro del modal (ver ajustarAlto). El max-height inline que
   calcula ese mismo codigo manda sobre el de arriba. */
.combo-list.es-arriba {
  top: auto;
  bottom: calc(100% + 4px);
}

.combo-item {
  padding: 9px 12px;
  cursor: pointer;
}

.combo-item:hover {
  background: var(--bg-3);
}

.combo-empty {
  padding: 10px 12px;
  color: var(--text-dim);
}

.combo-wrap {
  position: relative;
}

/* ---------- Arbol de receta (BOM lazy) ---------- */
.rrow {
  display: grid;
  /* La ultima columna paso de 90px a 126px: ademas de editar/eliminar, cada
     fila lleva ahora el atajo "Consultar item". */
  grid-template-columns: 1fr 100px 100px 130px 126px;
  align-items: center;
  padding: 9px 14px;
  border-bottom: 1px solid var(--border-soft);
}

.rrow.rhead {
  background: var(--bg-2);
  color: var(--text-muted);
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: .03em;
  font-weight: 600;
}

.rnode>.rrow:not(.rhead):hover {
  background: var(--bg-2);
}

/* La celda "Componente" lleva la etiqueta larga "#id · codigo · nombre  (tipo)",
   asi que tiene que poder envolver. El min-width:0 va en los TRES niveles
   (celda del grid, flex container y flex item) porque el default es
   min-width:auto en cada uno: basta que uno lo conserve para que la columna 1fr
   se desborde sobre Cantidad en vez de partir la etiqueta en dos renglones.
   El chevron no debe encogerse en el camino. */
.rrow>div:first-child,
.rrow .tree-cell,
.rrow .tree-cell>span {
  min-width: 0;
}

.rrow .tree-cell>span {
  overflow-wrap: break-word;
}

.rrow .tree-toggle,
.rrow .tree-spacer {
  flex: 0 0 auto;
}

/* ---------- Panel de filtro por categoria (Items) ---------- */
.filtro-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  cursor: pointer;
  user-select: none;
}

.filtro-head:hover {
  background: var(--bg-2);
}

.filtro-head .chev {
  margin-left: auto;
}

.filtro-badge {
  font-size: 12px;
  color: var(--klassen-red);
  font-weight: 600;
}

.filtro-body {
  padding: 0 16px 16px;
  border-top: 1px solid var(--border-soft);
}

.filtro-body .cat-picker {
  margin-top: 12px;
}

.filtro-acc {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 12px;
  flex-wrap: wrap;
}

/* ---------- Seccion de categorias en la ficha del item ---------- */
.sep {
  border: none;
  border-top: 1px solid var(--border-soft);
  margin: 18px 0 14px;
}

.cat-seccion-title {
  font-weight: 600;
  margin-bottom: 12px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.cat-sub {
  margin-bottom: 14px;
}

.cat-sub-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--text-muted);
  font-weight: 600;
}

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

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px 4px 10px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 13px;
}

.chip-ro {
  padding: 4px 10px;
}

.chip-x {
  background: none;
  border: none;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  padding: 0 2px;
}

.chip-x:hover {
  color: var(--klassen-red);
}

.chip-tag {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--klassen-red);
  border: 1px solid var(--klassen-red);
  border-radius: 4px;
  padding: 0 4px;
}

/* ---------- Ayudas de formulario / modo ---------- */
.field-help {
  font-size: 11.5px;
  color: var(--text-dim);
  margin-top: 4px;
}

.req::after {
  content: " *";
  color: var(--klassen-red);
}

.modal-mode {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--klassen-red);
  font-weight: 700;
  margin-bottom: 2px;
}

/* Selector de categorias (buscar) */
.cat-picker {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 340px;
  overflow-y: auto;
}

.cat-chk {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 6px;
  border-radius: 6px;
  cursor: pointer;
}

.cat-chk:hover {
  background: var(--bg-2);
}

.cat-chk input {
  accent-color: var(--klassen-red);
}

/* Orden por columna */
th.sortable {
  cursor: pointer;
  user-select: none;
}

th.sortable:hover {
  color: var(--text);
}

.sort-ind {
  color: var(--klassen-red);
  font-size: 11px;
}

/* Badges composicion/proceso */
/* Rosa claro para texto sobre --klassen-red-soft (fondo casi negro rojizo).
   Antes #f2a6b0 / #e88b97; se aclara a #ffb3bd para dejar holgura de AA en
   textos chicos (badges y chips de 10-12px). */
.badge-comp {
  background: var(--klassen-red-soft);
  color: #ffb3bd;
  border: 1px solid var(--klassen-red);
}

.badge-proc {
  background: var(--bg-3);
  color: var(--text-muted);
  border: 1px solid var(--border);
}

.badge-soft {
  padding: 3px 9px;
  border-radius: 20px;
  font-size: 11.5px;
  font-weight: 600;
}

/* ---------- Botones ---------- */
.btn-red {
  background: var(--klassen-red);
  border-color: var(--klassen-red);
  color: #fff;
}

.btn-red:hover {
  background: var(--klassen-red-strong);
  border-color: var(--klassen-red-strong);
  color: #fff;
}

/* ---------- Formularios / Modal ---------- */
.form-label {
  font-size: 14.5px;
  color: var(--text-muted);
  margin-bottom: 5px;
}

.form-control,
.form-select {
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius);
}

/* El popup nativo del <select> (la lista que despliega el navegador) no se
   puede redondear via CSS -- lo dibuja el SO, no hay pseudo-elemento
   estandar para eso. Lo que SI se puede tematizar es el color de sus
   <option> (Chrome/Edge lo respetan) para que no rompa contra el tema
   oscuro con un fondo blanco y resaltado azul por defecto. */
.form-select option {
  background: var(--bg-2);
  color: var(--text);
}

.form-select option:checked,
.form-select option:hover {
  background: var(--klassen-red-soft);
  color: var(--text);
}

.form-control:focus,
.form-select:focus {
  background: var(--bg-2);
  color: var(--text);
  border-color: var(--klassen-red);
  box-shadow: 0 0 0 .18rem var(--klassen-red-soft);
}

.form-control:disabled,
.form-select:disabled {
  opacity: .7;
}

.form-control[readonly] {
  background: var(--bg-1);
  color: var(--text-muted);
}

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

/* ---------- Campos de fecha/hora ----------
   El calendario que despliega un input type=date lo dibuja el NAVEGADOR: desde
   CSS solo se alcanza a elegir si sale claro u oscuro (color-scheme), no su
   forma ni su tipografia, y por eso se veia como una pieza ajena al lado de los
   demas desplegables. La solucion esta partida en dos:
     1. aqui se OCULTA el icono nativo -- que es lo unico que abre ese popup --
        y se estiliza el boton propio que pone components/datePicker.js;
     2. el calendario tematizado lo pinta ese componente (.dp-pop, abajo).
   El input sigue siendo type=date: se puede teclear la fecha y el navegador
   sigue validando el formato. */
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"],
input[type="week"] {
  color-scheme: dark;
  font-family: inherit;
  font-size: inherit;
}

input[type="date"].form-control,
input[type="time"].form-control,
input[type="datetime-local"].form-control,
input[type="month"].form-control,
input[type="week"].form-control {
  min-height: 38px;
  /* El input de fecha nativo no se encoge por debajo de su contenido: sin esto
     un Desde/Hasta dentro de un flex angosto desbordaba la barra de filtros. */
  min-width: 0;
}

/* Los campos ya mejorados esconden el icono nativo: su calendario lo abre el
   boton .dp-btn. Los que todavia no pasaron por datePicker.js conservan el
   suyo, para no quedarse sin forma de abrir nada. */
input[type="date"][data-dp]::-webkit-calendar-picker-indicator,
input[type="datetime-local"][data-dp]::-webkit-calendar-picker-indicator {
  display: none;
}

input[type="time"]::-webkit-calendar-picker-indicator,
input[type="month"]::-webkit-calendar-picker-indicator,
input[type="week"]::-webkit-calendar-picker-indicator {
  opacity: .65;
  cursor: pointer;
}

input[type="time"]::-webkit-calendar-picker-indicator:hover,
input[type="month"]::-webkit-calendar-picker-indicator:hover,
input[type="week"]::-webkit-calendar-picker-indicator:hover {
  opacity: 1;
}

/* ---------- Calendario propio (components/datePicker.js) ---------- */
/* El wrapper hereda el sitio que ocupaba el input (puede venir dentro de una
   columna o de un flex) y el input se estira dentro de el. */
.dp-wrap {
  position: relative;
  display: block;
}

.dp-wrap>input {
  width: 100%;
  /* Espacio a la derecha para el boton, que va encima del campo. */
  padding-right: 34px;
}

.dp-btn {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}

.dp-btn:hover {
  background: var(--bg-3);
  color: var(--text);
}

/* Vive en body con position:fixed para no quedar recortado por el overflow de
   una tarjeta o de un modal. SOLIDO, como todo lo que flota. */
.dp-pop {
  position: fixed;
  z-index: 2100;
  width: 268px;
  padding: 10px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 14px 38px rgba(0, 0, 0, .55);
  color: var(--text);
  font-size: var(--fs-sm);
}

.dp-head {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
}

.dp-titulo {
  flex: 1;
  text-align: center;
  font-weight: 600;
  color: var(--text-strong);
  font-size: var(--fs-base);
}

.dp-nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-1);
  color: var(--text-muted);
  cursor: pointer;
}

.dp-nav:hover {
  background: var(--bg-3);
  color: var(--text);
}

.dp-semana,
.dp-dias {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}

.dp-semana span {
  text-align: center;
  padding: 4px 0;
  color: var(--text-dim);
  font-size: var(--fs-xs);
  font-weight: 600;
}

.dp-dia {
  height: 30px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--text);
  cursor: pointer;
  font-size: var(--fs-sm);
}

.dp-dia:hover:not(.off) {
  background: var(--bg-3);
}

/* Relleno de la semana que pertenece al mes anterior o al siguiente: se deja
   visible y clickeable, pero atenuado, para no confundirlo con el mes en curso. */
.dp-dia.otro-mes {
  color: var(--text-dim);
}

.dp-dia.hoy {
  border-color: var(--border);
  font-weight: 600;
}

.dp-dia.sel {
  background: var(--klassen-red);
  border-color: var(--klassen-red);
  color: #fff;
  font-weight: 600;
}

.dp-dia.sel:hover {
  background: var(--klassen-red-strong);
}

/* Fuera del min/max que declare el campo. */
.dp-dia.off {
  opacity: .3;
  cursor: default;
}

.dp-pie {
  display: flex;
  justify-content: space-between;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}

.dp-link {
  border: 0;
  background: none;
  padding: 2px 4px;
  color: var(--text-muted);
  cursor: pointer;
  font-size: var(--fs-sm);
}

.dp-link:hover {
  color: var(--klassen-red);
}

/* ---------- Quill (editor de texto enriquecido, tema oscuro) ---------- */
.quill-oscuro .ql-toolbar.ql-snow {
  background: var(--bg-2);
  border: 1px solid var(--border) !important;
  border-bottom: none !important;
  border-radius: var(--radius) var(--radius) 0 0;
}

.quill-oscuro .ql-container.ql-snow {
  background: var(--bg-2);
  border: 1px solid var(--border) !important;
  border-radius: 0 0 var(--radius) var(--radius);
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
}

.quill-oscuro .ql-editor {
  min-height: 100px;
  outline: none;
}

.quill-oscuro .ql-editor.ql-blank::before {
  color: var(--text-dim);
  font-style: normal;
}

.quill-oscuro .ql-snow .ql-stroke {
  stroke: var(--text-muted);
}

.quill-oscuro .ql-snow .ql-fill {
  fill: var(--text-muted);
}

.quill-oscuro .ql-snow .ql-picker {
  color: var(--text-muted);
}

.quill-oscuro .ql-toolbar.ql-snow button:hover .ql-stroke,
.quill-oscuro .ql-toolbar.ql-snow button.ql-active .ql-stroke {
  stroke: var(--klassen-red);
}

.quill-oscuro .ql-toolbar.ql-snow button:hover .ql-fill,
.quill-oscuro .ql-toolbar.ql-snow button.ql-active .ql-fill {
  fill: var(--klassen-red);
}

/* Solo lectura: mismo look que .form-control[readonly] (fondo mas oscuro,
   texto atenuado). Sin toolbar, asi que el container lleva el radio completo. */
.quill-oscuro.quill-solo-lectura .ql-container.ql-snow {
  background: var(--bg-1);
  border-radius: var(--radius);
}

.quill-oscuro.quill-solo-lectura .ql-editor {
  color: var(--text-muted);
}

/* Bootstrap deja 1.75rem de margen arriba y abajo, asi que el modal nunca
   pasaba de 100% - 3.5rem. Bajando el margen a .75rem gana ~2rem de alto: mas
   aire vertical, y menos veces el desplegable de un select tiene que recortarse
   contra el borde inferior (ver .combo-list.es-arriba y combo.js). */
.modal {
  --bs-modal-margin: .75rem;
}

.modal-content {
  background: var(--bg-1-t);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  /* Tope de alto para TODOS los modales, no solo los .modal-dialog-scrollable:
     los que se arman al vuelo (Fabricar en Recetas, historial, confirmar
     borrado) no llevan esa clase y crecian sin limite, haciendo scrollear la
     ventana entera. Con esto el unico que scrollea es el cuerpo. */
  max-height: 90vh;
  overflow: hidden;
}

/* El mismo tope para los .modal-dialog-scrollable: el selector propio de
   Bootstrap (max-height:100% del dialogo, que ya mide casi toda la ventana) le
   gana en especificidad al de arriba y los dejaba pegados al borde. */
.modal-dialog-scrollable .modal-content {
  max-height: 90vh;
}

/* Un solo estilo de cabecera/pie para TODOS los modales, incluidos los que se
   crean al vuelo fuera de #modalRegistro (confirmarBorrado, categorizar en
   lote, historial): mismos paddings, mismo separador y botones del pie con
   separacion uniforme (Bootstrap los espacia con margenes por hijo). */
.modal-header,
.modal-footer {
  border-color: var(--border-soft);
  padding: 14px 18px;
}

/* Un poco mas de aire arriba y abajo que a los lados; y es el unico bloque del
   modal que scrollea (arriba .modal-content va con overflow:hidden). */
.modal-body {
  padding: 22px 18px;
  overflow-y: auto;
}

.modal-footer {
  gap: 8px;
}

.modal-footer>* {
  margin: 0;
}

.modal-title {
  font-size: 16px;
  font-weight: 600;
}

/* El modal de confirmar borrado (confirmarBorrado.js) hereda .modal-content,
   pero su cuerpo es solo un alert + un input: se le quita el margen final para
   que el bloque no quede descuadrado respecto al resto de modales. */
#modalConfirmBorrado .modal-body>.alert:last-child,
#modalConfirmBorrado .modal-body>.form-control:last-child {
  margin-bottom: 0;
}

/* ---------- Toasts (Bootstrap, tematizados) ---------- */
.toast {
  background: var(--bg-2);
  border: 1px solid var(--border);
}

/* ---------- Login (permisos) ---------- */
.login-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: var(--bg-0);
}

.login-card {
  width: 100%;
  max-width: 380px;
  background: var(--bg-1) !important;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
}

.login-card h4 {
  color: var(--text);
}

/* ============================================================================
   Overrides de Bootstrap (el shell de permisos usa clases .btn-*, dropdown, etc.)
   ============================================================================ */
.btn-primary {
  --bs-btn-bg: var(--klassen-red);
  --bs-btn-border-color: var(--klassen-red);
  --bs-btn-hover-bg: var(--klassen-red-strong);
  --bs-btn-hover-border-color: var(--klassen-red-strong);
  --bs-btn-active-bg: var(--klassen-red-strong);
  --bs-btn-active-border-color: var(--klassen-red-strong);
  --bs-btn-disabled-bg: var(--klassen-red);
  --bs-btn-disabled-border-color: var(--klassen-red);
}

.btn-secondary {
  --bs-btn-bg: var(--bg-3);
  --bs-btn-border-color: var(--border);
  --bs-btn-hover-bg: var(--bg-2);
  --bs-btn-hover-border-color: var(--border);
  --bs-btn-color: var(--text);
  --bs-btn-hover-color: var(--text);
}

.btn-outline-secondary {
  --bs-btn-color: var(--text-muted);
  --bs-btn-border-color: var(--border);
  --bs-btn-hover-bg: var(--bg-3);
  --bs-btn-hover-color: var(--text);
  --bs-btn-hover-border-color: var(--border);
}

.btn-outline-danger,
.btn-danger {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--klassen-red);
  --bs-btn-border-color: var(--klassen-red);
  --bs-btn-hover-bg: var(--klassen-red-strong);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-border-color: var(--klassen-red-strong);
}

.btn-warning {
  --bs-btn-bg: transparent;
  --bs-btn-color: var(--text);
  --bs-btn-border-color: var(--border);
  --bs-btn-hover-bg: var(--bg-3);
  --bs-btn-hover-color: var(--text);
  --bs-btn-hover-border-color: var(--border);
}

.btn-close {
  filter: invert(1) grayscale(1) brightness(1.4);
}

/* Tabs (Bootstrap .nav-tabs) con estilo de boton pill — aplica a TODAS las
   pantallas que usen nav-tabs/nav-link (formModal, solicitudes, sync, existencias, etc.). */
.nav-tabs {
  border-bottom: none;
  gap: 8px;
  flex-wrap: wrap;
}

.nav-tabs .nav-link {
  margin-bottom: 0;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg-3);
  color: var(--text-muted);
  padding: 6px 18px;
  font-size: .9em;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}

.nav-tabs .nav-link:hover,
.nav-tabs .nav-link:focus {
  isolation: auto;
  border-color: var(--border);
  background: var(--bg-2);
  color: var(--text);
}

.nav-tabs .nav-link.active,
.nav-tabs .nav-item.show .nav-link {
  background: var(--klassen-red);
  border-color: var(--klassen-red);
  color: #fff;
}

.nav-tabs .nav-link.active:hover {
  background: var(--klassen-red-strong);
  border-color: var(--klassen-red-strong);
}

/* Divisor arrastrable entre 2 paneles flex (components/panelResizer.js) —
   usado en Locaciones y Existencias para redimensionar ambos a la vez.
   El contenedor (.stk-panels/.loc-panels) ya tiene gap:16px entre hijos; al
   insertar este divisor como tercer hijo se sumarian DOS gaps (16+16) mas su
   ancho. El margen negativo descuenta ese gap extra para que la separacion
   total entre paneles quede igual que antes (sin el divisor). */
.panel-resizer {
  flex: 0 0 6px;
  margin: 0 -11px;
  align-self: stretch;
  cursor: col-resize;
  display: flex;
  align-items: center;
  justify-content: center;
}

.panel-resizer::before {
  content: '';
  width: 2px;
  height: 32px;
  border-radius: 999px;
  background: var(--border);
  transition: background .15s ease, width .15s ease;
}

.panel-resizer:hover::before,
.panel-resizer.is-dragging::before {
  background: var(--klassen-red);
  width: 3px;
}

.dropdown-menu {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.dropdown-item {
  color: var(--text-muted);
}

.dropdown-item:hover {
  background: var(--bg-3);
  color: var(--text);
}

.topbar .dropdown-toggle {
  color: var(--text) !important;
  text-decoration: none;
}

.alert-danger {
  background: var(--klassen-red-soft);
  border: 1px solid var(--klassen-red);
  color: #ffb3bd;
}

/* Bootstrap la pinta amarillo sobre blanco: se retematiza para el modo oscuro
   (la usa, entre otros, el modal de confirmar borrado). */
.alert-warning {
  background: rgba(255, 193, 7, .10);
  border: 1px solid rgba(255, 193, 7, .45);
  color: #ffd98a;
}

.text-muted {
  color: var(--text-muted) !important;
}

/* Scrollbar */
::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-track {
  background: var(--bg-0);
}

::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 6px;
}

::-webkit-scrollbar-thumb:hover {
  background: #33333a;
}

/* ---------- Responsive ---------- */
@media (max-width: 860px) {
  .sidebar {
    position: fixed;
    z-index: 30;
    left: 0;
    top: 0;
    transform: translateX(-100%);
    transition: transform .2s ease;
  }

  .app.nav-open .sidebar {
    transform: none;
  }

  .app.nav-open .sidebar-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .5);
    z-index: 20;
  }

  .btn-icon {
    display: grid;
  }

  /* Grids anchos en movil: cuando exceden el ancho de pantalla, el scroll
     horizontal lo pone el CONTENEDOR del grid, no la tabla (thead y tbody se
     desplazan juntos, las columnas quedan alineadas). Cubre todos los grids
     del sistema.

     Antes el scroll iba en la propia <table> (display:block + overflow-x).
     Eso la sacaba del layout de tabla: el bloque media el 100% del panel pero
     la tabla anonima de adentro quedaba shrink-to-fit, asi que los grids MAS
     ANGOSTOS que su panel se pintaban "cortados" a media tarjeta (la cabecera
     y el fondo de las filas terminaban donde acababa el texto). Se notaba en
     Existencias/Locaciones al achicar la ventana -- o girar a vertical --
     despues de haber redimensionado los paneles con el divisor. */
  :is(div, td, section):has(> table.grid) {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* Dejar presionada una fila abre su menu de acciones: sin el callout nativo
     ni la seleccion de texto que lo interrumpirian. */
  table.grid tbody tr {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
  }

  /* Paneles con divisor (components/panelResizer.js): en movil se apilan
     100% cada uno (como si nunca hubiera control) y el control desaparece. */
  .panel-resizer {
    display: none !important;
  }

  .panel-resizer-host {
    flex-wrap: wrap !important;
  }

  .panel-resizer-host>* {
    flex: 1 1 100% !important;
    min-width: 0 !important;
  }
}

/* ---------- Responsive · solo telefono ---------- */
/* Corte mas bajo que el de arriba a proposito: aca solo va lo que estorba en un
   telefono de verdad, no en una ventana angosta de escritorio ni en una tablet. */
@media (max-width: 600px) {

  /* La columna de acciones se oculta y sus botones se llegan con el menu de
     fila: click derecho o dejar presionada la fila (components/filaAccionesMenu.js).
     Es el ultimo recurso, no la regla general -- el grid ya scrollea en
     horizontal dentro de su contenedor cuando no cabe, asi que esconder la
     columna solo vale la pena cuando llegar a ella exigiria recorrer media
     tabla. De 600 a 860 px (tablet, ventana angosta) la columna se queda
     visible: ahi sobra ancho y el menu de fila no se descubre solo.

     Alcance acotado para no esconder nada que quede sin via alterna: solo
     dentro de #contenido (los grids de un modal, como el de Historial,
     conservan su columna) y solo si las acciones son los botones estandar de
     fila (.row-btn) -- las columnas con controles propios (los switches de
     permisos, el "Seleccionar" de los pickers) se quedan visibles. */
  #contenido table.grid:has(td.col-acciones .row-btn) th.col-acciones,
  #contenido table.grid:has(td.col-acciones .row-btn) td.col-acciones {
    display: none;
  }
}

/* ============================================================================
   Pantalla de permisos por rol · grid tipo arbol (modulo -> pantalla -> accion)
   ============================================================================ */
/* Nombre de cada fila del arbol segun su nivel. */
.perm-nombre-mod {
  font-weight: 600;
  color: var(--text);
}

.perm-nombre-pant {
  font-weight: 500;
  color: var(--text);
}

.perm-nombre-acc {
  color: var(--text-muted);
}

/* Etiqueta TIPO (chip). */
.perm-tipo {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: .04em;
  font-weight: 600;
  padding: 2px 9px;
  border-radius: 999px;
  white-space: nowrap;
}

.perm-tipo-mod {
  background: var(--klassen-red-soft);
  color: #ffb3bd;
}

.perm-tipo-pant {
  background: var(--bg-3);
  color: var(--text-muted);
}

.perm-tipo-acc {
  border: 1px solid var(--border-soft);
  color: var(--text-dim);
}

/* Contador de acciones otorgadas en la fila de pantalla. Sobre bg-3 (el gris
   mas claro) --text-dim se queda corto: usa --text-muted. */
.perm-badge {
  font-size: 11.5px;
  color: var(--text-muted);
  background: var(--bg-3);
  border-radius: 999px;
  padding: 1px 8px;
  margin-left: 8px;
}

/* Checkbox custom, acorde a la paleta (rojo Klassen). */
.perm-check {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  margin: 0;
  vertical-align: middle;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--bg-1);
  cursor: pointer;
  position: relative;
  transition: background .12s, border-color .12s;
}

.perm-check:hover {
  border-color: var(--klassen-red);
}

.perm-check:checked,
.perm-check:indeterminate {
  background: var(--klassen-red);
  border-color: var(--klassen-red);
}

.perm-check:checked::after {
  content: '';
  position: absolute;
  left: 5px;
  top: 2px;
  width: 5px;
  height: 9px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.perm-check:indeterminate::after {
  content: '';
  position: absolute;
  left: 3px;
  top: 7px;
  width: 10px;
  height: 2px;
  background: #fff;
}

.perm-check:disabled {
  opacity: .45;
  cursor: default;
}

.perm-check-master {
  width: 19px;
  height: 19px;
}


/* Todo el contenido de paginacion va cargado al extremo IZQUIERDO y en el mismo
   orden en todas las pantallas: "Mostrar N", navegacion y conteo. Ninguna zona
   se estira, asi el selector queda siempre en el mismo lugar aunque no haya
   botones de navegacion (una sola pagina). */
.paginacion-div {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 12px 18px;
  flex-wrap: wrap;
  width: 100%;
}

/* Barra al pie del grid. Es flex para que el bloque de acciones (boton de
   Historial de cambios) y el paginador no compartan celda ni se encimen:
   el boton conserva su ancho y el paginador se queda con el resto; si no
   caben, el paginador baja entero a la linea siguiente.
   SIN background propio a proposito: siempre vive como ultimo hijo dentro de
   un .card-surface (ver listView.js/treeView.js/stockScreen.js/etc.), que ya
   aplica su propia capa translucida+blur; agregar aqui otra capa con
   --trans-content apilaria dos translucideces y se veria mas opaco que el
   resto del grid. */
.paginacion-controles {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px 18px;
  flex-wrap: wrap;
  padding: 16px 18px;
  border-top: 1px solid var(--border-soft);
}

/* Acciones de la barra (boton de Historial de cambios): SIEMPRE pegadas al
   extremo derecho, en todas las pantallas que arman esta barra (ListView,
   TreeView, pantallasAcciones). */
.paginacion-acciones {
  flex: 0 0 auto;
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}

.paginacion-controles>.grid-paginacion {
  flex: 1 1 340px;
  min-width: 0;
}

.paginacion-tamano {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
}

.paginacion-tamano label {
  margin: 0;
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 500;
}

/* Dropdown propio del tamaño de página (ver listView.js): reemplaza al
   <select> nativo -- ese popup lo dibuja el SO y no se puede restylear
   (esquinas, color de la fila seleccionada). Con esto sí hay control total. */
.tamano-pagina-btn {
  height: 34px;
  min-width: 68px;
  padding: 0 12px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius);
}

.tamano-pagina-btn:hover,
.tamano-pagina-btn:focus {
  background: var(--bg-3);
  color: var(--text);
}

.dropdown-menu-tamano {
  min-width: 68px;
}

.dropdown-menu-tamano .dropdown-item {
  text-align: center;
}

.dropdown-menu-tamano .dropdown-item.active {
  background: var(--klassen-red);
  color: #fff;
}

.paginacion-botones {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  min-height: 34px;
}

/* Con una sola pagina no hay botones: se saca del flujo para que no deje el
   hueco de sus dos gaps entre el selector y el conteo. */
.paginacion-botones:empty {
  display: none;
}

.paginacion-botones .btn {
  min-width: 38px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--bg-3);
  color: var(--text);
  opacity: 1;
}

.paginacion-botones .btn-secondary,
.paginacion-botones .btn-secondary:disabled {
  background: var(--bg-3);
  border-color: var(--border);
  color: var(--text);
  opacity: 1;
}

.paginacion-botones .btn-secondary:hover:not(:disabled) {
  background: var(--bg-2);
  border-color: var(--klassen-red);
}

.paginacion-botones .btn-red,
.paginacion-botones .btn-red:disabled {
  background: var(--klassen-red);
  border-color: var(--klassen-red);
  color: #fff;
  opacity: 1;
}

.paginacion-botones .btn:disabled {
  opacity: 1;
  cursor: default;
  pointer-events: none;
}

/* Salto de rango entre bloques de paginas (…): .paginacion-puntos lo emite
   ListView, .pag-ellipsis el paginador compartido de gridUtils.js. */
.paginacion-puntos,
.pag-ellipsis {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  height: 34px;
  color: var(--text-muted);
  font-size: 16px;
  font-weight: 600;
}

.paginacion-info {
  flex: 0 0 auto;
  color: var(--text-muted);
  white-space: nowrap;
}

#catFiltroPanel {
  width: 420px;
  max-width: calc(100vw - 30px);
  padding: 10px !important;
  overflow: hidden !important;
}

.cat-tree-toolbar {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
}

.cat-tree-scroll {
  max-height: 360px;
  overflow-y: auto;
  overflow-x: hidden;
}

/* Evita que la tabla tome demasiado ancho dentro del dropdown */
#catPicker table.grid.tree {
  width: 100%;
  table-layout: fixed;
}

/* Checkbox y texto dentro de la misma celda 
  .cat-tree-check {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      min-width: 0;
      margin: 0;
      cursor: pointer;
  }*/

.cat-tree-check {
  display: flex;
  align-items: center;
  width: 100%;
}

.cat-tree-text {
  margin-right: 20px;
  flex: 1;
}

.cat-tree-check input {
  width: 15px;
  height: 15px;
  margin: 0;
  flex: 0 0 15px;
}

.cat-tree-check span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Anterior */
.js-pagina-anterior {
  margin-right: 10px;
}

/* Siguiente */
.js-pagina-siguiente {
  margin-left: 10px;
}

/* Botones numéricos */
.js-pagina {
  margin-left: 2px;
  margin-right: 2px;
}

/* ---------- Select personalizado (SelectBonito) ---------- */
.selbon {
  position: relative;
}

.selbon-btn {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 38px;
  padding: 8px 12px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius);
  text-align: left;
  cursor: pointer;
}

.selbon-btn:hover {
  background: var(--bg-3);
}

.selbon-btn:focus {
  outline: none;
  border-color: var(--klassen-red);
  box-shadow: 0 0 0 .18rem var(--klassen-red-soft);
}

.selbon-label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.selbon-chev {
  color: var(--text-muted);
}

.selbon.is-disabled .selbon-btn {
  opacity: .7;
  cursor: not-allowed;
}

/* .card-surface ya aporta fondo + blur + borde; aqui solo el comportamiento
   de "popup". El panel es una COLUMNA flex: el buscador queda fijo arriba y el
   scroll se lo lleva la lista (.selbon-items), no el panel entero -- si
   scrolleara el panel, el campo de busqueda se iria hacia arriba justo cuando
   se esta usando. De ahi el overflow:hidden aqui (que ademas respeta el
   border-radius) y el auto alla abajo. */
.selbon-panel {
  position: fixed;
  z-index: 2000;
  /* por encima de los modales de Bootstrap (~1055) */
  /* SOLIDO: flota sobre el contenido y tiene que leerse sin transparentar lo
     que quede atras (mismo criterio que .combo-list y .filtro-panel). */
  background: var(--bg-2);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  max-height: 280px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 6px;
  border-radius: 8px;
  box-shadow: 0 8px 26px rgba(0, 0, 0, .4);
}

/* Buscador incremental del desplegable. No se repinta nunca (solo la lista de
   abajo), asi que el cursor y el texto tecleado no se pierden. */
.selbon-buscador {
  position: relative;
  flex: 0 0 auto;
  margin-bottom: 6px;
}

.selbon-buscador-ico {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  pointer-events: none;
  font-size: .9rem;
}

.selbon-q {
  width: 100%;
  padding: 7px 10px 7px 30px;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  font-size: .92rem;
}

.selbon-q::placeholder {
  color: var(--text-dim);
}

.selbon-q:focus {
  outline: none;
  border-color: var(--klassen-red);
  box-shadow: 0 0 0 .18rem var(--klassen-red-soft);
}

/* min-height:0 es lo que permite que un hijo flex se encoja por debajo de su
   contenido y scrollee; sin eso el panel crece y el max-height no sirve. */
.selbon-items {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

.selbon-item {
  padding: 9px 12px;
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
}

.selbon-item:hover {
  background: var(--bg-3);
}

.selbon-item.is-sel {
  background: var(--klassen-red-soft);
  color: var(--text);
}

/* Fila donde estan paradas las flechas del teclado. Va con borde y no con
   fondo de color para no confundirse con .is-sel (lo que YA esta elegido):
   son dos cosas distintas y pueden verse al mismo tiempo. */
.selbon-item.is-act {
  box-shadow: inset 0 0 0 1px var(--klassen-red);
}

.selbon-empty {
  padding: 10px 12px;
  color: var(--text-dim);
}

/* ---------- Productos (grid de tarjetas) ---------- */
.prod-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 14px;
}

.prod-card {
  background: var(--bg-1-t);
  backdrop-filter: blur(10px);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.prod-card:hover {
  border-color: var(--klassen-red);
}

.prod-card .prod-icono {
  font-size: 2rem;
  color: var(--text-muted);
}

.prod-card .prod-nombre {
  font-weight: 600;
}

.prod-card .prod-codigo {
  font-size: 12px;
  color: var(--text-dim);
}

.prod-card .prod-precio {
  color: var(--klassen-red);
  font-weight: 700;
  margin-top: auto;
}


/* --- Codigo OTP: una casilla por digito (login 2FA y alta de 2FA) --------- */
.otp-inputs {
  display: flex;
  gap: 8px;
  justify-content: space-between;
}

.otp-box {
  text-align: center;
  font-size: 22px;
  font-weight: 600;
  padding: 8px 0;
  letter-spacing: 0;
}
/* Baja logica: filas de registros dados de baja, visibles cuando el selector de
   estado esta en "Inactivos" o "Todos". Se atenuan para que no se confundan con
   los vigentes -- sobre todo en "Todos", donde conviven los dos. Las acciones de
   la fila siguen activas, que es como se reactivan. */
.grid tbody tr.fila-inactiva td {
  color: var(--text-dim);
  font-style: italic;
  opacity: .75;
}

/* Selectores sueltos de la barra de filtros (Estado, y el combo generico
   .sel-filtro-wrap de listView.filtroSelect): la etiqueta va pegada al select,
   en linea con los botones de filtro (mas altos que un select suelto). */
.filtros-bar .estado-filtro-wrap,
.filtros-bar .sel-filtro-wrap {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 4px;
  white-space: nowrap;
}

.filtros-bar .estado-filtro-wrap .form-label,
.filtros-bar .sel-filtro-wrap .form-label {
  margin: 0;
  color: var(--text-muted);
}

.filtros-bar .estado-filtro-wrap .form-select,
.filtros-bar .sel-filtro-wrap .form-select {
  width: auto;
  min-width: 120px;
}

/* ============================================================================
   Tema claro (preferencia por usuario). El JS pone data-tema="claro" +
   data-bs-theme="light" en <html>. Redefine TODOS los tokens (el resto del CSS
   usa var(--...)) y mantiene la misma transparencia que el tema oscuro en las
   superficies.

   Criterio de color (alineado al sitio klassenpumps.com): la franja superior es
   ROJO Klassen de extremo a extremo, el sidebar es un gris frio que se despega
   de las tarjetas, y los encabezados de grid son gris pizarra oscuro. El rojo
   queda reservado para el header, la accion primaria y el estado activo; los
   encabezados de grid NO lo usan para no volverlo ruido.

   Antes los cuatro escalones de gris (--bg-0..3) vivian en 9 puntos de
   luminosidad: sidebar, tarjeta, encabezado de grid, boton secundario y pestana
   inactiva se veian practicamente del mismo color. Esta escala los separa.
   ============================================================================ */
html[data-tema="claro"] {
  /* Escala de grises AMPLIADA (antes #e8eaee..#dfe2e8, ~9 puntos de rango).
     Ahora el fondo de pagina es notablemente mas oscuro que las tarjetas, asi
     que una .card-surface se lee como una superficie elevada y no como una
     mancha del mismo tono. */
  --bg-0: #dde1e9;   /* fondo de pagina (detras de las tarjetas) */
  --bg-1: #f9fafc;   /* superficies elevadas: tarjetas, modales, dropdowns */
  --bg-2: #e7eaf1;   /* filas hover, zonas hundidas */
  --bg-3: #d6dce6;   /* controles y realces */
  --border: #bfc6d2;
  --border-soft: #d2d8e2;
  /* Contraparte de --border-home: gris OSCURO, no blanco. El panel de Inicio
     aqui es claro, asi que el blanco del tema oscuro se perderia; este tono
     baja lo suficiente para que los cuadros se sigan leyendo como cuadros. */
  --border-home: #8c95a5;

  /* Gris pizarra del encabezado de grid (table.grid thead, y los dos "head"
     propios de Consumibles). Valor afinado a mano por Pablo.
     Opaco (no el alpha .93 de una superficie de contenido): el head de grid es
     chrome solido igual que topbar/sidebar, no una tarjeta translucida sobre
     la imagen de fondo.
     NOTA AA: #7f848d sobre #eef1f6 da ~3.3:1 -- por debajo del 4.5:1 de texto
     normal (aunque arriba del 3:1 de texto grande). Elegido a proposito por
     encima de esa recomendacion; si en algun momento se ve muy lavado, la
     salida es oscurecer --grid-head-text, no este valor. */
  --grid-head-bg: #7f848d;
  --grid-head-text: #eef1f6;
  /* Gris claro para el texto secundario DENTRO de un encabezado de grid (la
     fila "Consumible @ almacenaje" de Consumibles): --text-muted es casi negro
     y sobre la pizarra no se lee. */
  --grid-head-text-dim: #c6ccd7;

  /* Sidebar: gris propio, independiente del pizarra de arriba -- mas oscuro
     que las tarjetas (--bg-1) para que la columna de navegacion se distinga
     del contenido, pero SIGUE SIENDO CLARO (con texto oscuro, no invertido).
     El bloque del logo no usa esta variable: .sidebar-brand se queda rojo,
     ver mas abajo. */
  --sidebar-bg: #d6dde8;
  --sidebar-border: #bac2d0;

  /* Misma transparencia que el modo oscuro: la imagen de fondo se ve a traves de
     las superficies (cards, grids, filtros, dropdowns, modales). */
  --trans-content: 0.85;
  --trans-home: 0.70;
  --bg-1-t: rgba(249, 250, 252, var(--trans-content));
  --bg-2-t: rgba(231, 234, 241, var(--trans-content));
  --bg-3-t: rgba(214, 220, 230, var(--trans-content));
  /* Panel de accesos rapidos de Inicio: el mismo blanco de --bg-1-t. Antes
     .ini-panel tenia el literal oscuro y era la unica superficie del front que
     no volteaba con el tema. */
  --bg-home-t: rgba(249, 250, 252, var(--trans-home));

  /* Texto oscuro con jerarquia. Los dos grises secundarios se oscurecieron
     (--text-muted #515863 -> #3f4653, --text-dim #6b7280 -> #545c6b) porque son
     los que pintan los iconos y las etiquetas del sidebar, que era justo lo que
     se perdia sobre fondo claro. */
  --text: #151922;
  --text-strong: #080b10;
  --text-muted: #3f4653;
  --text-dim: #545c6b;

  /* El rojo Klassen funciona en claro; el tinte suave queda como rosa muy tenue. */
  --klassen-red-soft: rgba(215, 38, 61, 0.12);
}

/* ---------------------------------------------------------------------------
   Banda superior EN DOS COLORES: el bloque del logo se queda ROJO Klassen
   (como el header del sitio); el resto del topbar (migajas, notificaciones,
   usuario) pasa a #1b1e24 -- el MISMO literal que usa .topbar en el tema
   OSCURO, a proposito: es identico al topbar de oscuro, solo que aqui convive
   con un sidebar y un contenido claros.
   Topbar y sidebar-brand son dos elementos distintos con la misma altura
   (61px) pegados uno al lado del otro, cada uno con su propio color -- por
   eso dos reglas separadas en vez de una compartida. */
html[data-tema="claro"] .sidebar-brand {
  background: var(--klassen-red);
  border-bottom: 1px solid var(--klassen-red-strong);
}

html[data-tema="claro"] .topbar {
  background: #1b1e24;
  border-bottom: 1px solid #2c313b;
}

/* Todo lo que viaja DENTRO de cualquiera de los dos bloques se invierte a
   blanco: hasta aqui estos elementos heredaban --text (casi negro), que sobre
   rojo u oscuro no se lee. */
html[data-tema="claro"] .sidebar-brand .brand-title {
  color: #fff;
}

html[data-tema="claro"] .sidebar-brand .brand-sub {
  color: rgba(255, 255, 255, .80);
}

/* Base del titulo: cubre las pantallas que ponen el texto SUELTO en
   #topbarTitle (Configuraciones, Roles, Usuarios permisos, "Inicio" -- ver
   app.js $('#topbarTitle').text(...)), que sin esto heredaban --text (casi
   negro) por no pasar por ninguna de las reglas de .span de abajo. Las
   pantallas con migaja de verdad (span.crumb-actual + span de ancestros)
   siguen mandando por ser mas especificas. */
html[data-tema="claro"] .topbar .topbar-title {
  color: #fff;
}

html[data-tema="claro"] .topbar .topbar-title span {
  color: rgba(255, 255, 255, .78);
}

html[data-tema="claro"] .topbar .topbar-title span.crumb-actual {
  color: #fff;
}

html[data-tema="claro"] .topbar .topbar-title .crumb-sep {
  color: rgba(255, 255, 255, .55);
}

/* Botones de icono del topbar (menu movil, notificaciones) y el menu de
   usuario. Se excluye el engranaje del pie del sidebar, que tambien es
   .btn-fondo pero vive sobre el gris del sidebar, no sobre el rojo. */
html[data-tema="claro"] .topbar .btn-icon,
html[data-tema="claro"] .topbar .btn-fondo,
html[data-tema="claro"] .topbar .dropdown-toggle {
  color: #fff !important;
  border-color: rgba(255, 255, 255, .45);
}

html[data-tema="claro"] .topbar .btn-icon:hover,
html[data-tema="claro"] .topbar .btn-fondo:hover {
  background: rgba(255, 255, 255, .18);
  border-color: rgba(255, 255, 255, .70);
}

/* El badge de notificaciones ya NO necesita invertirse: con la franja oscura
   (no roja) el rojo solido de base (.notif-badge, global) se lee bien tal
   cual -- rojo sobre oscuro, sin ningun override aqui. */

/* ---------------------------------------------------------------------------
   Sidebar: gris propio (ya no el casi-blanco de las tarjetas) y letras/iconos
   con mas cuerpo. Se queda CLARO -- solo el logo y el topbar de arriba son
   chrome oscuro/rojo; nav y pie del sidebar usan la misma paleta de texto
   oscuro que el resto del tema.
   --------------------------------------------------------------------------- */
html[data-tema="claro"] .sidebar {
  background: var(--sidebar-bg);
  border-right: 1px solid var(--sidebar-border);
}

html[data-tema="claro"] .sidebar-foot {
  border-top: 1px solid var(--sidebar-border);
}

/* El hover de una pantalla o de un modulo tira hacia el BLANCO de las tarjetas:
   sobre el gris del sidebar aclara, que es la direccion que se espera del
   hover (con --bg-2, mas oscuro que el fondo, el efecto se sentia invertido). */
html[data-tema="claro"] .nav-item:hover,
html[data-tema="claro"] .nav-group>.nav-group-header:hover {
  background: #f4f6fa;
}

/* Iconos de pantalla: --text-dim los dejaba muy lavados sobre el gris. */
html[data-tema="claro"] .nav-item .bi {
  color: var(--text-muted);
}

/* Pantalla activa: el tinte rosa por si solo apenas se distinguia del gris del
   sidebar, asi que el estado activo lo carga la LETRA (rojo fuerte + semibold)
   ademas del filete rojo de la izquierda. El fondo (klassen-red-soft) y el
   filete ya vienen de la regla base, sin tocar. */
html[data-tema="claro"] .nav-item.active {
  color: var(--klassen-red-strong);
  font-weight: 600;
}

/* ---------------------------------------------------------------------------
   Encabezados de grid: gris pizarra oscuro con letra clara.
   --------------------------------------------------------------------------- */
html[data-tema="claro"] table.grid thead th {
  background: var(--grid-head-bg);
  color: var(--grid-head-text);
  border-bottom-color: rgba(0, 0, 0, .25);
}

/* Las dos piezas que viven DENTRO del encabezado y estaban pensadas para un
   head claro: el hover de una columna ordenable aclaraba hacia --text (que en
   claro es casi negro, ilegible sobre la pizarra) y el indicador de orden usaba
   el rojo Klassen, que sobre ese gris oscuro pierde contraste. */
html[data-tema="claro"] table.grid thead th.sortable:hover {
  color: #fff;
}

html[data-tema="claro"] table.grid thead .sort-ind {
  color: #ff9aa8;
}

/* Encabezados de grid HECHOS A MANO: no son un <thead>, asi que la regla de
   arriba no los alcanza y se quedaban con el fondo claro de --bg-2 mientras
   todos los demas grids de la pantalla iban en pizarra.
   Hoy es uno solo: el arbol del BOM en Recetas (.rrow.rhead). Del resto del
   formato ya era un clon de table.grid thead th (11.5px, mayusculas, .03em,
   600) -- solo le faltaba el color que depende del tema.
   NOTA: la pantalla Envios/Recibo (.enr-root) tiene el mismo problema en su
   .enr-th, pero ahi NO se arregla con una regla de encabezado: esa pantalla
   redefine una paleta oscura completa en variables locales y no tiene bloque
   de tema claro (Consumibles si lo tiene, ver .cns-root mas abajo). Ponerle
   la pizarra al head la dejaria peor: un encabezado claro sobre una pantalla
   entera en oscuro. */
html[data-tema="claro"] .rrow.rhead {
  background: var(--grid-head-bg);
  color: var(--grid-head-text);
  border-bottom-color: rgba(0, 0, 0, .25);
}

/* El pie del sidebar (version + engranaje) NO necesita override: con el
   sidebar claro, .sidebar-foot-version hereda --text-dim (oscuro) y el
   engranaje (.btn-fondo) hereda --text/--border (oscuro/claro) de la base --
   los dos ya se ven bien sin tocar nada aqui.
   NOTA: la barra de paginacion al pie de un GRID (.paginacion-controles) se
   probo en pizarra y tampoco convencio -- se quedo en claro, sin override,
   heredando el look normal de --text-muted sobre la tarjeta. */

/* ---------------------------------------------------------------------------
   Controles que antes compartian tono con el panel que los contiene: pestanas
   inactivas y botones secundarios. Se resuelven como pildora/boton BLANCO con
   borde marcado, que contra el gris de la barra de filtros si se despega.
   --------------------------------------------------------------------------- */
/* El :not(.active) NO es decorativo: sin el, estos selectores (0,3,1) le ganan
   por especificidad a la regla base de la pestana activa (.nav-tabs
   .nav-link.active, 0,3,0) y la pestana seleccionada perdia el rojo Klassen. */
html[data-tema="claro"] .nav-tabs .nav-link:not(.active) {
  background: #fff;
  border-color: var(--border);
  color: var(--text-muted);
}

html[data-tema="claro"] .nav-tabs .nav-link:not(.active):hover,
html[data-tema="claro"] .nav-tabs .nav-link:not(.active):focus {
  background: var(--bg-2);
  border-color: #a9b2c0;
  color: var(--text);
}

html[data-tema="claro"] .btn-secondary {
  --bs-btn-bg: #fff;
  --bs-btn-border-color: var(--border);
  --bs-btn-hover-bg: var(--bg-2);
  --bs-btn-hover-border-color: #a9b2c0;
}

html[data-tema="claro"] .btn-outline-secondary,
html[data-tema="claro"] .btn-warning {
  --bs-btn-bg: #fff;
  --bs-btn-color: var(--text-muted);
  --bs-btn-border-color: var(--border);
  --bs-btn-hover-bg: var(--bg-2);
  --bs-btn-hover-color: var(--text);
  --bs-btn-hover-border-color: #a9b2c0;
}

/* Colores fijos pensados para oscuro: retematizar en claro. */
html[data-tema="claro"] .badge-comp,
html[data-tema="claro"] .alert-danger,
html[data-tema="claro"] .perm-tipo-mod {
  color: var(--klassen-red-strong);   /* rosa claro -> rojo fuerte, legible sobre el tinte */
}
html[data-tema="claro"] .alert-warning {
  background: rgba(255, 193, 7, 0.16);
  border-color: rgba(170, 120, 0, 0.40);
  color: #7a5c00;                     /* ambar oscuro en vez de #ffd98a */
}
html[data-tema="claro"] ::-webkit-scrollbar-thumb:hover { background: #a9b2c0; }

/* La X de cerrar de Bootstrap se invierte a blanco para el tema oscuro; en
   claro debe volver a su negro original para verse sobre el modal claro. */
html[data-tema="claro"] .btn-close { filter: none; }

/* El titulo y subtitulo de pantalla van SOBRE la banda del degradado (oscura en
   ambos temas), asi que en claro deben seguir siendo claros para leerse. */
html[data-tema="claro"] .screen-head h1  { color: #f6f8fb; }
html[data-tema="claro"] .screen-head .sub { color: #e9ebef; }

/* Misma razon para los titulos de seccion sueltos (ver #contenido > h1..h6 en
   la seccion de layout): en claro heredaban --text, que ahi es OSCURO, y se
   perdian contra la banda oscura del degradado. */
html[data-tema="claro"] #contenido > h1,
html[data-tema="claro"] #contenido > h2,
html[data-tema="claro"] #contenido > h3,
html[data-tema="claro"] #contenido > h4,
html[data-tema="claro"] #contenido > h5,
html[data-tema="claro"] #contenido > h6 { color: #f6f8fb; }

html[data-tema="claro"] #contenido > h1 .field-help,
html[data-tema="claro"] #contenido > h2 .field-help,
html[data-tema="claro"] #contenido > h3 .field-help,
html[data-tema="claro"] #contenido > h4 .field-help,
html[data-tema="claro"] #contenido > h5 .field-help,
html[data-tema="claro"] #contenido > h6 .field-help { color: #e9ebef; }

/* Avatar por defecto de "Mi perfil" (el bi-person-circle de #perfilFoto): va
   arriba de la pantalla, asi que cae en la banda oscura del degradado y se
   dibuja DIRECTO sobre el fondo, no sobre una superficie. En claro heredaba
   --text, que ahi es casi negro, y el icono se perdia contra esa banda. Mismo
   trato que screen-head y los titulos sueltos de arriba.
   Solo alcanza al ICONO: con foto cargada, #perfilFoto contiene un <img> y no
   hay color que corregir. */
html[data-tema="claro"] #perfilFoto>.bi {
  color: #f6f8fb;
}

/* Botones de accion del grid: en oscuro son blancos (#fff fijo); en claro deben
   ser oscuros para verse sobre la fila clara. */
html[data-tema="claro"] .row-btn,
html[data-tema="claro"] .row-btn:hover { color: var(--text); }
html[data-tema="claro"] .row-btn:hover { background: var(--bg-2); }
/* (los .row-btn.danger ya usan el rojo Klassen, se ven bien en ambos) */

/* ============================================================================
   Consumibles (js/components/consumiblesScreen.js) trae su PROPIO mini sistema
   de diseno: inyecta un <style> con variables --headrow/--tsec/--acc/etc.
   propias, fijas a valores de tema oscuro, sin relacion con los --bg-N / --text-N
   de arriba. Por eso "Entradas"/"Salidas" se quedaban oscuros con el tema claro
   activo -- no es que la regla no aplique, es que esas variables son de OTRO
   sistema, nunca redefinido para claro. Ademas hay colores fijos (no var())
   para los estados hover/nesting, que tambien hay que pisar aparte.
   Se resuelve REDEFINIENDO las variables locales dentro de .cns-root (misma
   tecnica que el resto de este bloque: solo se toca el valor, no la regla que
   lo consume), y dejando las superficies de firma (el area blanca donde se
   dibuja) intactas -- una hoja de firma es blanca en cualquier tema.
   ============================================================================ */
html[data-tema="claro"] .cns-root {
  --bg: var(--bg-0);
  --table: var(--bg-1);
  /* Fondo de boton/pildora/control: BLANCO (no --bg-1, que es el mismo tono
     que la tarjeta) para que se despegue del fondo, igual que .btn-secondary y
     .nav-tabs .nav-link en el resto de la app. .cns-th y .cns-rrow.h (los DOS
     encabezados tipo grid de esta pantalla) se sacan de esto mas abajo: ellos
     van en el mismo gris pizarra que table.grid thead, no en blanco. */
  --headrow: #fff;
  --field: #fff;
  /* Literal, NO var(--border): esta variable local se llama IGUAL que el
     token global --border, y reescribirla como var(--border) DENTRO de la
     misma regla que la declara es una autorreferencia -- la propiedad queda
     invalida (IACVT) en vez de heredar el valor de afuera. Incidente igual al
     que ya paso una vez en este archivo; se anota para no repetirlo. */
  --border: #bfc6d2;
  --ctl: var(--border);
  --rowsep: var(--border-soft);
  --tpri: var(--text-strong);
  --tbody: var(--text);
  --tsec: var(--text-muted);
  --tmut: var(--text-dim);
  --tdis: var(--text-dim);
  --acc: var(--klassen-red);
  --acch: var(--klassen-red-strong);
  /* Antes rosa claro (#f26372, pensado para leerse sobre --table casi negro):
     ilegible sobre cualquier fondo claro. Usa el mismo rojo fuerte que ya
     resuelve este mismo problema en badge-comp/alert-danger. */
  --acct: var(--klassen-red-strong);
  --accbg: rgba(215, 38, 61, 0.10);
  /* Un poco mas de cuerpo que el resto de los tintes --klassen-red-soft de este
     archivo: --accbg2 es el fondo de la pestana ACTIVA (Existencias/Entradas/
     Salidas) y del boton "Firmar" -- justo lo que se veia con poco contraste. */
  --accbg2: rgba(215, 38, 61, 0.16);
}

/* Los DOS encabezados tipo grid de esta pantalla (el head de la tabla de
   movimientos y el head de la lista compacta de items agregados en el modal
   de Nueva entrada/salida): mismo gris pizarra que table.grid thead, no el
   blanco que le toca al resto de --headrow. */
html[data-tema="claro"] .cns-root .cns-th,
html[data-tema="claro"] .cns-root .cns-rrow.h {
  background: var(--grid-head-bg);
}

html[data-tema="claro"] .cns-root .cns-th>div,
html[data-tema="claro"] .cns-root .cns-rrow.h {
  color: var(--grid-head-text-dim);
}

/* Pestana activa (Existencias/Entradas/Salidas) y el boton "Firmar": mismo
   texto rojo fuerte que --acct, sobre el tinte --accbg2 -- el rosa claro fijo
   que traian no se leia sobre el tinte, que es justo el contraste que hacia
   falta. */
html[data-tema="claro"] .cns-root .cns-tab.on,
html[data-tema="claro"] .cns-root .cns-firmar {
  color: var(--klassen-red-strong);
}

/* Estados hover/anidado con color fijo (no var()) pensado para un fondo casi
   negro: se piso aparte porque redefinir las variables de arriba no les llega. */
html[data-tema="claro"] .cns-root .cns-btn-sec:hover,
html[data-tema="claro"] .cns-root .cns-ab:hover,
html[data-tema="claro"] .cns-root .cns-addbtn:hover,
html[data-tema="claro"] .cns-root .cns-sig-b:hover,
html[data-tema="claro"] .cns-root .cns-padre:hover>div,
html[data-tema="claro"] .cns-root .cns-tr:hover>div {
  background: var(--bg-2);
}

/* Fila hija del arbol de existencias (un tono distinto a la fila padre, para
   marcar el nivel de anidacion) y su punto separador. */
html[data-tema="claro"] .cns-root .cns-hijo>div {
  background: var(--bg-2);
}

html[data-tema="claro"] .cns-root .cns-dot {
  background: var(--border);
}

/* Modales propios de la pantalla (editar/eliminar consumible, firmar salida):
   mismo casi-negro fijo que el resto -- se reemplaza por la superficie clara
   de tarjeta. La barra de acciones del modal de firma va un punto mas oscura,
   como cualquier pie que cierra un panel. */
html[data-tema="claro"] .cns-root .cns-modal,
html[data-tema="claro"] .cns-root .cns-sig {
  background: var(--bg-1);
}

html[data-tema="claro"] .cns-root .cns-sig-bar {
  background: var(--bg-2);
}

/* La superficie de firma (donde se dibuja) se queda BLANCA a proposito en los
   dos temas -- es una hoja, no un panel del tema. Nada que tocar aqui: no hay
   overrides para .cns-sig-wrap/.cns-sig-canvas/.cns-firma-img. */

/* --- Grupos: modal de asignación de usuarios (grid) --- */
.grp-grid { margin: 0; width: 100%; }
.grp-grid .grp-col-chk { width: 44px; text-align: center; }
.grp-grid tbody tr { cursor: pointer; }
.grp-grid tbody tr:hover { background: rgba(127,127,127,.10); }
