/* Administración web de TagFlow. Sin estilos en línea: la política de seguridad (CSP) de admin.
   solo permite este archivo (style-src 'self') — cualquier style="" o elemento.style.x en JS queda
   bloqueado en silencio por el navegador, ver TAGFLOW.md.

   Rediseño visual (2026-09-25): paleta y tipografía nuevas a partir de un mockup en Figma que
   aprobó Andrés (misma estructura de página, mismos nombres de clase — solo cambian los valores).
   Tipografía: IBM Plex Sans, servida desde /admin/fonts (self-hosted, nada de Google Fonts — la CSP
   de admin. no permite fuentes de terceros, font-src 'self') y elegida a propósito para no caer en
   los defaults típicos de cualquier panel generado (Inter/Roboto/system-ui). */

@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 400; font-display: swap; src: url("/admin/fonts/ibm-plex-sans-400.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 500; font-display: swap; src: url("/admin/fonts/ibm-plex-sans-500.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 600; font-display: swap; src: url("/admin/fonts/ibm-plex-sans-600.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 700; font-display: swap; src: url("/admin/fonts/ibm-plex-sans-700.woff2") format("woff2"); }

:root {
  color-scheme: light;
  /* Navy: tres tonos (antes uno solo) — header más oscuro que el sidebar, y el ítem activo del
     sidebar más claro que el panel donde vive, calcado del mockup aprobado. */
  --navy: #0B192C; --navy-2: #112240; --navy-d: #1E3A5F; --on-navy: #FFFFFF; --on-navy-muted: #94A3B8;
  --line-dark: #1B355A;
  --mint: #2AAFA0; --mint-d: #0F6F68; --mint-bg: #E6F6F4;
  --ink: #1E293B; --muted: #64748B; --muted-d: #475569; --line: #E2E8F0;
  --bg: #F8FAFC; --card: #FFFFFF; --card2: #F8FAFC;
  --accent-bg: #E3EAF5; --accent: #0B192C;
  --ok: #047857; --ok-bg: #ECFDF5; --ok-line: #A7F3D0;
  --warn: #B45309; --warn-bg: #FFFBEB; --warn-line: #FDE68A;
  --bad: #B91C1C; --bad-bg: #FEF2F2; --bad-line: #FCA5A5;
  --radio: 8px; --radio-md: 12px; --radio-lg: 16px; --radio-full: 999px;
  --sombra-card: 0 4px 6px rgba(15, 23, 42, .06);
  --sombra-header: 0 2px 4px rgba(15, 23, 42, .08);
  --sombra-flotante: 0 8px 20px rgba(11, 25, 44, .14);
}
* { box-sizing: border-box; }
html, body { margin: 0; }
body { background: var(--bg); color: var(--ink); font: 15px/1.45 "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; }
[hidden] { display: none !important; }
a { color: var(--mint-d); }
:focus-visible { outline: 3px solid var(--mint); outline-offset: 2px; border-radius: 6px; }
input[type="checkbox"], input[type="radio"] { accent-color: var(--mint); }

/* ---- encabezado ---- */
.cabecera { background: var(--navy); color: var(--on-navy); position: sticky; top: 0; z-index: 30; box-shadow: var(--sombra-header); }
.cabecera .fila { display: flex; align-items: center; gap: 16px; min-height: 56px; padding: 0 16px; }
.hamburguesa { display: none; background: none; border: 0; color: var(--on-navy); font-size: 20px; line-height: 1; padding: 6px 8px; border-radius: var(--radio); cursor: pointer; }
.hamburguesa:hover { background: var(--navy-2); }
.marca { display: inline-flex; align-items: center; gap: 8px; color: var(--on-navy); font-weight: 800; font-size: 18px; text-decoration: none; }
.marca img { display: block; }
.marca span span { color: var(--mint); }
/* Nombre del tenant junto a la marca (2026-09-26, pedido de Andrés viendo un segundo mockup: "no
   tener tantas cosas a la vista que distraigan") — antes vivía pegado al nombre de la persona a la
   derecha ("Fulano · Santorini Bisutería · cliente 5572"), dos líneas de texto denso. Ahora una sola
   línea a cada lado: marca+tenant a la izquierda, avatar+nombre+Salir a la derecha. El número de
   cliente (dato interno, no operativo) se quitó del encabezado — sigue disponible en Empresa.*/
.marca-empresa { color: var(--on-navy-muted); font-size: 13px; padding-left: 12px; margin-left: 4px; border-left: 1px solid var(--line-dark); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.persona { display: flex; align-items: center; gap: 8px; color: var(--on-navy-muted); font-size: 13px; margin-left: auto; }
.persona strong { color: var(--on-navy); font-weight: 600; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.avatar { width: 28px; height: 28px; border-radius: var(--radio-full); background: var(--mint); color: var(--navy); font-size: 12px; font-weight: 700;
  display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.salir { background: var(--navy-2); border: 1px solid var(--line-dark); color: var(--on-navy-muted); border-radius: 6px; padding: 8px 12px; font: inherit; font-weight: 600; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px; }
.salir:hover { color: var(--on-navy); border-color: var(--mint); }
.salir .lateral-icono { width: 15px; height: 15px; }

/* ---- disposición: barra lateral fija (Sesión 20, F1) + contenido ---- */
/* Antes: max-width + margin:auto en .disposicion centraba TODO el bloque (barra + contenido) dejando
   un espacio en blanco antes de la barra -> no quedaba pegada al borde. Ahora .disposicion ocupa el
   ancho completo y el max-width/centrado se mueve solo a <main> (columna de contenido, ver abajo). */
.disposicion { display: grid; grid-template-columns: 252px 1fr; align-items: start; }
.lateral { background: var(--navy-2); position: sticky; top: 56px; height: calc(100vh - 56px); overflow-y: auto; padding: 10px 0 24px; z-index: 20;
  scrollbar-width: none; }
.lateral::-webkit-scrollbar { display: none; }
.lateral-item { display: flex; align-items: center; justify-content: space-between; gap: 8px; color: var(--on-navy-muted); text-decoration: none;
  font-weight: 500; font-size: 14px; padding: 10px 18px; margin: 0 12px; border-radius: var(--radio); border-left: 3px solid transparent; width: calc(100% - 24px); }
/* Hover distinto del ítem activo (2026-09-30, pedido de Andrés) -- antes usaban el mismo
   var(--navy-d), así que pasar el mouse por CUALQUIER ítem se veía igual que la página en la que
   ya estás, sin la barra menta de acento: confundía cuál era la seleccionada de verdad. */
a.lateral-item:hover { color: var(--on-navy); background: rgba(255, 255, 255, .08); }
.lateral-item[aria-current="page"] { color: var(--on-navy); font-weight: 600; background: var(--navy-d); border-left-color: var(--mint); }
.lateral-inicio { font-size: 15px; font-weight: 700; border-bottom: 1px solid var(--line-dark); margin-bottom: 6px; border-radius: 0; margin-left: 0; margin-right: 0; width: 100%; padding-left: 18px; gap: 10px; }
.lateral-item.pronto { cursor: default; opacity: .7; }
.lateral-etiqueta-pronto { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--on-navy-muted); border: 1px solid var(--line-dark); border-radius: var(--radio); padding: 2px 6px; white-space: nowrap; }
.lateral-seccion summary { display: flex; align-items: center; gap: 10px; cursor: pointer; list-style: none;
  color: var(--muted-d); font-weight: 700; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; padding: 10px 18px 6px; }
.lateral-seccion summary .lateral-titulo-texto { flex: 1; }
/* Íconos del sidebar (2026-09-26, pedido de Andrés viendo el mockup de Figma: "faltaron los iconos
   que mostraba figma"). Un SVG mínimo por sección top-level, self-hosted en /admin/icons — se aplican
   con mask (no <img>) para que hereden el color del texto (muted/blanco/mint) en sus tres estados. */
.lateral-icono { width: 18px; height: 18px; flex: 0 0 auto; background-color: currentColor;
  -webkit-mask-size: contain; mask-size: contain; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center; }
.icono-inicio { -webkit-mask-image: url(/admin/icons/inicio.svg); mask-image: url(/admin/icons/inicio.svg); }
.icono-inventario { -webkit-mask-image: url(/admin/icons/inventario.svg); mask-image: url(/admin/icons/inventario.svg); }
.icono-picking { -webkit-mask-image: url(/admin/icons/picking.svg); mask-image: url(/admin/icons/picking.svg); }
.icono-packing { -webkit-mask-image: url(/admin/icons/packing.svg); mask-image: url(/admin/icons/packing.svg); }
.icono-usuarios { -webkit-mask-image: url(/admin/icons/usuarios.svg); mask-image: url(/admin/icons/usuarios.svg); }
.icono-alertas { -webkit-mask-image: url(/admin/icons/alertas.svg); mask-image: url(/admin/icons/alertas.svg); }
.icono-ventas { -webkit-mask-image: url(/admin/icons/ventas.svg); mask-image: url(/admin/icons/ventas.svg); }
.icono-logistica { -webkit-mask-image: url(/admin/icons/logistica.svg); mask-image: url(/admin/icons/logistica.svg); }
.icono-reportes { -webkit-mask-image: url(/admin/icons/reportes.svg); mask-image: url(/admin/icons/reportes.svg); }
.icono-perfil-empresa { -webkit-mask-image: url(/admin/icons/empresa.svg); mask-image: url(/admin/icons/empresa.svg); }
.icono-integraciones { -webkit-mask-image: url(/admin/icons/integraciones.svg); mask-image: url(/admin/icons/integraciones.svg); }
.icono-config { -webkit-mask-image: url(/admin/icons/config.svg); mask-image: url(/admin/icons/config.svg); }
.icono-salir { -webkit-mask-image: url(/admin/icons/salir.svg); mask-image: url(/admin/icons/salir.svg); }
/* Etiqueta que separa, DENTRO de una sección del sidebar, un subgrupo de páginas del resto — primer
   uso: "Maestros del catálogo" (Categorías/Impuestos y tarifas/Sucursales y bodegas) aparte de las
   páginas operativas de Inventario (Ajustes de inventario, Conteos…). Pedido de Andrés viendo un
   mockup: que "Ajustes de inventario" (ajustar un saldo) y las tablas de configuración del catálogo
   no se lean como la misma cosa. No es un <details> propio — sigue dentro del mismo, solo divide. */
.lateral-separador { display: flex; align-items: center; gap: 8px; color: var(--on-navy-muted); font-weight: 700;
  font-size: 10px; text-transform: uppercase; letter-spacing: .04em; padding: 10px 18px 6px 34px; margin-top: 4px; border-top: 1px solid var(--line-dark); }
.lateral-separador .lateral-icono { width: 14px; height: 14px; }
.lateral-seccion summary::-webkit-details-marker { display: none; }
.lateral-seccion summary::after { content: '›'; font-size: 18px; line-height: 1; color: var(--on-navy-muted); transition: transform .15s ease; text-transform: none; }
.lateral-seccion[open] summary::after { transform: rotate(90deg); }
.lateral-seccion summary:hover { color: var(--on-navy); }
.lateral-paginas { display: flex; flex-direction: column; padding-bottom: 4px; gap: 2px; }
.lateral-paginas .lateral-item { padding-left: 34px; font-weight: 500; }
.lateral-fondo { display: none; }

/* Sesión 29 (pedido de Andrés): antes `max-width:1180px; margin:0 auto` centraba el contenido dejando un
   colchón vacío a los lados en pantallas anchas — sobre todo entre el sidebar y las fichas/tablas, que
   nunca quedaban pegadas a él. Ahora <main> ocupa TODO el ancho de su columna del grid; las grillas internas
   (.metricas, .formulario, .tarjetas…) ya usan repeat(auto-fit,…) así que aprovechan el espacio solas. */
main { padding: 24px 32px 48px; min-width: 0; width: 100%; }
h1 { font-size: 24px; font-weight: 700; margin: 0 0 4px; color: var(--ink); }
h2 { font-size: 16px; font-weight: 700; margin: 0 0 10px; color: var(--ink); }
.sub { color: var(--muted); margin: 0 0 16px; }

/* ---- controles ---- */
button, input, select { font: inherit; color: inherit; }
.boton { background: var(--mint); color: var(--navy); border: 0; border-radius: var(--radio); padding: 9px 16px; font-weight: 700; cursor: pointer; min-height: 40px; text-decoration: none; display: inline-flex; align-items: center; justify-content: center; }
.boton:hover { background: var(--mint-d); color: var(--on-navy); }
.boton:disabled { opacity: .55; cursor: default; }
.boton.claro { background: var(--card); color: var(--muted-d); border: 1px solid var(--line); }
.boton.claro:hover { background: var(--card2); border-color: var(--muted); }
/* Botones de acción con intención (2026-09-26, pedido de Andrés viendo el admin desplegado: "los
   botones de acción deberían tener colores" — antes Desactivar/Anular/Borrar/Rotar secreto se veían
   igual de neutros que Copiar/Cancelar). ".malo" = destruye o desactiva algo, ".aviso" = una acción
   delicada mejor pensarla dos veces (ej. rotar un secreto invalida el anterior). Mismo lenguaje visual
   que .chip (fondo suave + borde del color, se rellena sólido al hover). */
.boton.malo { background: var(--bad-bg); color: var(--bad); border: 1px solid var(--bad-line); }
.boton.malo:hover { background: var(--bad); color: #fff; border-color: var(--bad); }
.boton.aviso { background: var(--warn-bg); color: var(--warn); border: 1px solid var(--warn-line); }
.boton.aviso:hover { background: var(--warn); color: #fff; border-color: var(--warn); }
/* Regla estricta (2026-09-30, pedido de Andrés): "tienes buen espacio de pantalla, no seas corto con
   los input spaces" -- el CONTENEDOR (".campo", su columna del grid/flex) manda el ancho, nunca el
   tamaño intrínseco del navegador (~20 caracteres para un input de texto, que cortaba placeholders
   largos como el del buscador de artículos). "width: 100%" acá, no solo "max-width", para que crezca
   hasta llenar su columna en vez de quedarse angosto adentro de una columna más ancha. */
input[type="search"], input[type="text"], input[type="password"], input[type="number"], input[type="email"], input[type="date"], select, textarea {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radio); padding: 8px 10px; min-height: 40px; width: 100%; max-width: 100%;
}
input:focus-visible, select:focus-visible, textarea:focus-visible { border-color: var(--mint); }
/* Regla estricta (2026-09-30, pedido de Andrés): un <textarea> nunca debe quedarse con el ancho
   intrínseco del navegador (~20 caracteres, angosto) -- crece siempre al 100% de su contenedor, sea
   éste una fila completa o una sola columna de un formulario a dos columnas (el contenedor decide el
   ancho, no el textarea). Reemplaza la necesidad de overrides puntuales por pantalla. */
textarea { min-height: 80px; resize: vertical; font-family: inherit; width: 100%; }
label { font-size: 13px; font-weight: 600; color: var(--ink); display: block; margin-bottom: 4px; }

/* ---- formulario de datos (Sesión 25: ficha de usuario) — más ancho/alto que .filtros, sin fila única obligatoria ---- */
.formulario { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; margin-bottom: 14px; }
.formulario .campo.ancho { grid-column: 1 / -1; }
/* Sesión 39: "ancho" solo estiraba la CELDA del grid — el <input>/<textarea> de adentro se quedaba
   con su tamaño intrínseco del navegador (~20 caracteres), recortando cualquier texto largo (ej. el
   placeholder de recogidas.js, "Escanea el pedido que acaba de llegar"). Mismo criterio que ya usaba
   ".filtros .campo.ancho input". */
.formulario .campo.ancho input, .formulario .campo.ancho textarea { width: 100%; }
.formulario .acciones { grid-column: 1 / -1; display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.formulario .marca-check { display: flex; align-items: center; gap: 6px; min-height: 40px; }
.formulario .marca-check label { margin: 0; color: var(--ink); font-size: 14px; font-weight: 400; }

/* ---- fila de botones suelta (Sesión 26: Alertas de pedidos) — a diferencia de .formulario .acciones, esta no exige un <form> alrededor ---- */
/* Regla estricta (2026-09-30, pedido de Andrés): sin "align-items", flexbox por defecto ESTIRA los
   hijos a la altura del más alto ("stretch") -- un botón junto a un ".mensaje" de error (que trae su
   propio padding/margin y es más alto) se veía bien vacío, pero se estiraba feo en cuanto aparecía el
   mensaje. "center" mantiene la altura natural de cada uno (el botón siempre igual, con o sin error al
   lado). Usado en 16+ pantallas -- se arregla acá una sola vez para todas.*/
.fila-botones { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 10px; align-items: center; }

/* ---- zona de subida de archivo (Sesión 26: Picking · Cargar pedidos) ---- */
.zona-subida { border: 2px dashed var(--line); border-radius: var(--radio-md); padding: 26px 18px; text-align: center; cursor: pointer; color: var(--muted); }
.zona-subida:hover, .zona-subida.arrastrando { border-color: var(--mint); background: var(--mint-bg); }
.zona-subida.lleno { border-style: solid; border-color: var(--navy); color: var(--ink); background: var(--card); }
.zona-subida strong { display: block; color: var(--ink); margin-bottom: 4px; }
/* ---- lista de checkboxes (Sesión 33: Retenciones de Cotizaciones) — a diferencia de .opciones-prioridad
   (elegir UNA), aquí se pueden marcar varias; sin recuadro por fila, solo una lista vertical simple. ---- */
.lista-checks { display: flex; flex-direction: column; gap: 8px; margin: 6px 0 14px; }
.check-linea { display: flex; align-items: flex-start; gap: 8px; margin: 0; color: var(--ink); font-size: 14px; font-weight: 500; cursor: pointer; }
.check-linea input { margin-top: 3px; }
/* Sesión 40 (Roles editables, roles.js): ".formulario .campo.ancho input { width:100% }" de arriba
   está pensada para un único input de texto, pero también agarra cualquier checkbox anidado en un
   .campo.ancho (ej. la lista de áreas) y lo estira, empujando su etiqueta lejos a la derecha — bug
   real visto en vivo por Andrés. No se puede corregir con un style="" en línea: la CSP del sitio
   (style-src 'self') lo bloquea. Más específica que la regla de arriba (4 clases/attr vs 3), gana sin `!important`. */
.formulario .campo.ancho input[type="checkbox"] { width: auto; }

/* ---- Sesión 40: mismo hallazgo que arriba, pero en 9 pantallas más (bodegas.js, cotizacion.js,
   guia.js, guias.js, orden-venta.js, lectores.js, ordenes-venta.js, recogidas.js,
   pagos-pendientes.js) — todas armaban un style="" en línea desde JS para un ajuste puntual, y la
   CSP de admin. (style-src 'self', sin unsafe-inline) lo venía bloqueando en silencio desde que se
   activó (2026-09-21): el layout quedaba un poco roto sin que nada más fallara, así que nadie lo
   notó hasta ahora. Reemplazado por estas clases modificadoras reutilizables. ---- */
.formulario.bajo-cabecera { margin-top: 10px; }
.fila-botones.bajo-cabecera { margin-top: 14px; }
.marca-check.espaciado { margin-top: 6px; }
.filtros.chips { gap: 8px; }
.filtros.centrado { justify-content: center; }
.formulario.tres-columnas { grid-template-columns: 1fr 1fr auto; }
.campo-conexion { display: flex; gap: 8px; }
.select-modo-conexion { flex: 0 0 160px; }
.input-conexion { flex: 1 1 auto; min-width: 0; }
.fila-id { margin-top: 4px; }
.input-corto { width: 70px; }
.empuja-derecha { margin-left: auto; }

.opciones-prioridad { display: flex; gap: 10px; flex-wrap: wrap; margin: 14px 0; }
.opciones-prioridad label { display: flex; align-items: center; gap: 8px; border: 1px solid var(--line); border-radius: var(--radio); padding: 10px 14px; cursor: pointer; margin: 0; color: var(--ink); font-size: 14px; font-weight: 500; }
.opciones-prioridad label.elegida { border-color: var(--navy); background: var(--accent-bg); font-weight: 700; }
.opciones-prioridad label.elegida.urgente { border-color: var(--bad); background: var(--bad-bg); color: var(--bad); }

/* ---- zona de peligro (borrar usuario) ---- */
.zona-peligro { border-color: var(--bad); }
.zona-peligro h2 { color: var(--bad); }

/* ---- clave/PIN/secreto generado: se muestra UNA sola vez, nunca se guarda. Sesión 39: el secreto
   de un lector (32 bytes en base64, ~44 caracteres) es mucho más largo que una clave temporal de
   12 — sin min-width:0 y sin partir la palabra, el <code> empujaba la caja más ancha que su
   contenedor en vez de acomodarse. ---- */
.clave-generada { display: flex; align-items: center; gap: 10px; background: var(--card2); border: 1px solid var(--line); border-radius: var(--radio); padding: 10px 14px; margin: 10px 0; flex-wrap: wrap; }
.clave-generada code { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 16px; font-weight: 700; letter-spacing: .02em; word-break: break-all; overflow-wrap: anywhere; min-width: 0; flex: 1 1 220px; }

/* ---- tarjetas del inicio ---- */
.bloque-inicio { margin-bottom: 26px; }
.bloque-inicio:last-child { margin-bottom: 0; }
.tarjetas { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 14px; margin-top: 12px; }
.tarjeta { display: block; background: var(--card); border: 1px solid var(--line); border-radius: var(--radio-md); padding: 16px 18px; text-decoration: none; color: var(--ink); box-shadow: var(--sombra-card); }
.tarjeta strong { display: block; color: var(--ink); font-size: 17px; font-weight: 700; margin-bottom: 4px; }
.tarjeta span { color: var(--muted); font-size: 14px; }
a.tarjeta:hover { border-color: var(--mint); }
.tarjeta.pronto { background: var(--card2); border-style: dashed; box-shadow: none; }
.tarjeta.pronto strong { color: var(--muted); }
.etiqueta-pronto { display: inline-block; margin-top: 8px; font-size: 12px; font-weight: 600; background: var(--warn-bg); color: var(--warn); padding: 2px 8px; border-radius: var(--radio-full); }

/* ---- pestañas (Sesión 20, F2: Packing) — cambian un filtro en la URL, nunca recargan la página ---- */
.pestanas { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: 16px; flex-wrap: wrap; }
.pestana { background: none; border: 0; border-bottom: 3px solid transparent; color: var(--muted); font-weight: 600; font-size: 14px; padding: 10px 14px; cursor: pointer; }
.pestana:hover { color: var(--ink); }
.pestana[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--mint); }

/* ---- filtros y tabla ---- */
.filtros { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; background: var(--card); border: 1px solid var(--line); border-radius: var(--radio-md); padding: 14px; margin-bottom: 14px; }
/* El botón que agrega un registro (maestros-comun.js: Impuestos, Tarifas, Categorías…) quedaba pegado
   justo después del último campo en vez de ir al otro extremo de la fila — pedido de Andrés viendo
   "Impuestos y tarifas" desplegado. Solo empuja ESTE botón, nunca "Buscar"/"Filtrar" del mismo .filtros. */
.filtros .boton-agregar { margin-left: auto; }
.filtros .campo { min-width: 150px; }
.filtros .campo.ancho { flex: 1; min-width: 220px; position: relative; }
.filtros .campo.ancho input { width: 100%; }
/* Regla estricta (2026-09-30, pedido de Andrés): ".filtros" alinea los campos por ABAJO a propósito
   (un botón sin label queda a la altura de los inputs) -- un campo con una línea de más debajo del
   control (ej. el estado de un buscador, "Todos los artículos.") rompía eso, empujando SU control más
   arriba que los demás. Esa línea de más se saca del flujo (no cuenta para la altura que ve el flex)
   y queda posicionada donde siempre se vio, debajo del control. Aplicar ".nota-bajo-campo" a esa nota
   y ".con-nota-bajo-campo" al ".filtros" que la contiene (reserva el espacio para que no se solape
   con lo que venga después) en cualquier pantalla con este mismo patrón.*/
.nota-bajo-campo { position: absolute; left: 0; right: 0; top: 100%; margin-top: 4px; }
.filtros.con-nota-bajo-campo { padding-bottom: 34px; }
/* Mismo bug de Sesión 40 (línea 180, .formulario), esta vez en .filtros: descuentos.js mete una
   .lista-checks de canales dentro de un .campo.ancho y la regla de arriba estira cada checkbox. */
.filtros .campo.ancho input[type="checkbox"] { width: auto; }
.filtros .marca-check { display: flex; align-items: center; gap: 6px; min-height: 40px; }
.filtros .marca-check label { margin: 0; color: var(--ink); font-size: 14px; font-weight: 400; }
.tabla-envoltorio { background: var(--card); border: 1px solid var(--line); border-radius: var(--radio-md); box-shadow: var(--sombra-card); overflow-x: auto; }
table.tabla { width: 100%; border-collapse: collapse; font-size: 14px; }
.tabla th { text-align: left; font-weight: 700; font-size: 12px; color: var(--muted); padding: 12px; border-bottom: 1px solid var(--line); white-space: nowrap; background: var(--card2); }
.tabla td { padding: 11px 12px; border-top: 1px solid var(--line); vertical-align: top; }
.tabla tbody tr:first-child td { border-top: 0; }
.tabla tr.fila-link:hover { background: var(--card2); }
/* Fila elegida en un drill-down (Zona → Pasillo → Mueble → Ubicación de bodega-estructura.js). */
.tabla tr.fila-elegida { background: var(--mint-bg); }
.tabla td.num, .tabla th.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
/* Celda con varios botones de acción (Editar/Anular…) — sin esto, en una tabla dentro de una columna
   angosta (ej. ".dos-columnas") los botones se apilaban en 2 líneas aun en escritorio ancho, pedido
   de Andrés viendo Categorías. Fuerza una sola fila; si de verdad no cabe, la tabla ya scrollea
   horizontal (".tabla-envoltorio" tiene overflow-x: auto). */
.tabla td.acciones, .mini-tabla td.acciones { white-space: nowrap; }
/* Regla estricta (2026-09-30, pedido de Andrés): "los botones deben ir a la derecha siempre". La
   columna de acciones (normalmente la última, sin encabezado) quedaba con un hueco raro antes de los
   botones cuando esa celda terminaba más ancha que su contenido (auto-layout de la tabla, texto
   alineado a la izquierda por defecto). ":has(button)" cubre además las tablas que NO usan la clase
   ".acciones" explícita (bodegas.js, bodega-estructura.js, categorias-marcas.js…) sin tener que tocar
   cada pantalla una por una.*/
.tabla td.acciones, .tabla td:last-child:has(button) { text-align: right; }
.tabla td a.nombre { color: var(--ink); font-weight: 600; text-decoration: none; }
.tabla td a.nombre:hover { color: var(--mint-d); text-decoration: underline; }
/* Sesión 39: ".aparte" solo tenía esta regla dentro de ".tabla" — fuera de una tabla (ej. cliente.js,
   el dígito de verificación al lado del número de identificación) quedaba como <span> en línea, pegado
   al texto anterior sin separación. Regla general para que se comporte igual en cualquier contexto. */
.aparte { display: block; color: var(--muted); font-size: 12px; }
.paginador { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 12px; flex-wrap: wrap; }
.paginador .info { color: var(--muted); font-size: 13px; }
.vacio { padding: 28px 16px; text-align: center; color: var(--muted); }

/* ---- etiquetas ---- */
.chip { display: inline-flex; align-items: center; font-size: 12px; font-weight: 600; padding: 4px 10px; border-radius: var(--radio-full); background: var(--card2); border: 1px solid var(--line); color: var(--muted-d); white-space: nowrap; }
.chip.raiz { background: var(--ok-bg); border-color: var(--ok-line); color: var(--ok); }
.chip.aviso { background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn); }
.chip.malo { background: var(--bad-bg); border-color: var(--bad-line); color: var(--bad); }

/* ---- ficha de artículo (mockup aprobado 2026-09-18; rediseño visual 2026-09-25) ---- */
.miga { font-size: 13px; margin-bottom: 10px; color: var(--muted); }
.ficha { background: var(--card); border: 1px solid var(--line); border-radius: var(--radio-lg); padding: 20px 24px; margin-bottom: 16px; box-shadow: var(--sombra-card); }
.ficha-cabecera { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; margin-bottom: 14px; flex-wrap: wrap; }
/* Regla general (2026-09-30, pedido de Andrés): el botón de acción principal de una sección (ej. "+
   Nuevo rol", "Abrir conteo") va SIEMPRE arriba a la derecha, nunca con un título aparte al lado --
   el botón ya dice qué hace, un título es redundante. Concordancia de estética = uso fluido: el
   usuario ya sabe dónde mirar en cualquier módulo, no lo redescubre pantalla por pantalla. Si más
   adelante esa misma fila lleva filtros, van a la izquierda (agregar el elemento ahí y cambiar esta
   clase por ".ficha-cabecera" es un cambio de una línea, no reescribir la pantalla).*/
.ficha-accion-superior { display: flex; justify-content: flex-end; margin-bottom: 14px; }
.ficha-cabecera .titulo { font-size: 20px; font-weight: 700; color: var(--ink); }
.ficha-cabecera .datos { font-size: 13px; color: var(--muted); }
/* Foto real del producto (crítica para picking/packing — la separadora la usa para identificar la
   pieza físicamente; NUNCA quitar esto aunque un mockup de referencia no la incluya). */
.ficha-foto { width: 96px; height: 96px; object-fit: cover; border-radius: var(--radio-md); background: var(--card2); border: 1px solid var(--line); flex: none; }
/* Vista previa del logo en Perfil de empresa (Sesión 37): sin esto un logo de alta resolución se ve a tamaño real. */
.logo-vista-previa { display: block; width: auto !important; height: auto !important; max-width: 220px; max-height: 90px; object-fit: contain; margin-bottom: 10px; border: 1px solid var(--line); border-radius: 8px; padding: 8px; background: #fff; }
.ficha-arriba { display: flex; gap: 16px; align-items: flex-start; }
.ficha-arriba > div { flex: 1; min-width: 0; }
.metricas { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 16px; }
.metrica { background: var(--card); border: 1px solid var(--line); border-radius: var(--radio-md); padding: 14px 16px; box-shadow: var(--sombra-card); }
.metrica .etq { font-size: 13px; font-weight: 600; color: var(--muted); }
.metrica .valor { font-size: 22px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.metrica .detalle { font-size: 12px; color: var(--muted); }
.metrica.warn { background: var(--warn-bg); border-color: var(--warn-line); }
.metrica.warn .etq, .metrica.warn .valor { color: var(--warn); }
.subtitulo-precio { font-size: 13px; color: var(--muted); margin-bottom: 6px; }
.presentaciones { width: 100%; border-collapse: collapse; font-size: 13px; }
.presentaciones th { text-align: left; font-weight: 600; color: var(--muted); padding: 6px 6px; }
.presentaciones td { padding: 8px 6px; border-top: 1px solid var(--line); vertical-align: top; }
.presentaciones tr.elegible { cursor: pointer; }
.presentaciones tr.elegible:hover { background: var(--card2); }
.presentaciones tr.elegida { background: var(--mint-bg); }
.presentaciones tr.elegida .nombre-pres { font-weight: 700; }
.presentaciones .num { text-align: right; font-variant-numeric: tabular-nums; }
.nota-tabla { font-size: 12px; color: var(--muted); margin: 6px 0 14px; }
.calculo { border-top: 1px solid var(--line); padding-top: 14px; }
.calculo .fila-cant { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; color: var(--muted); font-size: 13px; }
.calculo input[type="number"] { width: 90px; }
.bloques { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; }
.bloque { background: var(--card2); border: 1px solid var(--line); border-radius: var(--radio-md); padding: 12px 14px; }
.bloque .etq { font-size: 12px; font-weight: 600; color: var(--muted); }
.bloque .texto { font-size: 13px; margin-top: 2px; }
.bloque.picking { background: var(--ok-bg); border-color: var(--ok-line); }
.bloque.picking .etq, .bloque.picking .texto { color: var(--ok); }
.bloque.picking .grande { font-size: 16px; font-weight: 700; color: var(--ok); margin-top: 2px; }
.dos-columnas { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 16px; }
.mini-tabla { width: 100%; border-collapse: collapse; font-size: 13px; }
.mini-tabla th { text-align: left; font-weight: 600; color: var(--muted); padding: 5px 6px; }
.mini-tabla td { padding: 6px; border-top: 1px solid var(--line); }
.mini-tabla .num { text-align: right; font-variant-numeric: tabular-nums; }
/* 2026-10-02, pedido de Andrés ("ampliar el input de stock en existencias de bodega"): el input de
   cantidad en una celda de mini-tabla (ej. "Existencias por bodega" de articulo.js) se quedaba angosto
   -- la tabla con layout automático lo encoge a su mínimo intrínseco, igual que ya pasaba con los
   <input>/<textarea> de .formulario/.filtros (ver comentario de la línea ~146). Mismo criterio. */
.mini-tabla input[type="number"] { min-width: 140px; }
.entra { color: var(--ok); font-weight: 700; }
.sale { color: var(--bad); font-weight: 700; }

/* ---- Buscador con sugerencias (Sesión 30: elegir artículo/cliente en Cotizaciones) ---- */
.buscador-con-sugerencias { position: relative; }
.sugerencias { position: absolute; z-index: 10; top: 100%; left: 0; right: 0; margin-top: 4px; max-height: 260px; overflow-y: auto;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radio); box-shadow: var(--sombra-flotante); }
.sugerencias button { display: block; width: 100%; text-align: left; background: none; border: 0; border-bottom: 1px solid var(--line);
  padding: 8px 12px; cursor: pointer; font: inherit; color: inherit; }
.sugerencias button:last-child { border-bottom: 0; }
.sugerencias button:hover, .sugerencias button:focus-visible { background: var(--card2); }

/* ---- Tabla de líneas editable (Sesión 30: Cotizaciones) — inputs/selects dentro de una celda, sin desbordar ---- */
table.lineas td input, table.lineas td select { width: 100%; min-width: 68px; min-height: 34px; padding: 4px 6px; }
table.lineas td.num-celda { text-align: right; }
.tabla tfoot td { font-weight: 700; background: var(--card2); border-top: 2px solid var(--line); }
.tabla tfoot td.num { font-variant-numeric: tabular-nums; }

/* ---- Tablero de bodega (Sesión 20/22, F3): tarjetas de carro físico — libre / con dueña / en pausa ---- */
.carros-tablero { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 12px; }
.carro-tablero { background: var(--card); border: 1.5px solid var(--line); border-radius: var(--radio-md); padding: 14px 16px; box-shadow: var(--sombra-card); }
.carro-tablero.libre { border-style: dashed; color: var(--muted); box-shadow: none; }
.carro-tablero.pausa { border-color: var(--warn); }
.carro-tablero-num { font-size: 12px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .03em; }
.carro-tablero-due { font-size: 16px; font-weight: 700; margin-top: 2px; }
.carro-tablero-det { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.carro-tablero-accion { margin-top: 10px; }

/* ---- avisos ---- */
.mensaje { padding: 12px 14px; border-radius: var(--radio); background: var(--bad-bg); border: 1px solid var(--bad-line); color: var(--bad); margin: 12px 0; font-weight: 500; }
.mensaje.info { background: var(--accent-bg); border-color: var(--line); color: var(--accent); }
.mensaje.ok { background: var(--ok-bg); border-color: var(--ok-line); color: var(--ok); }
.cargando { color: var(--muted); padding: 24px 0; }

/* ---- pantalla de clave pendiente ---- */
.panel-clave { max-width: 420px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radio-lg); padding: 20px 24px; box-shadow: var(--sombra-card); }
.panel-clave .campo { margin-bottom: 12px; }
.panel-clave input { width: 100%; }

/* ---- Modal (Sesión 39: crear cliente sin salir del POS — pedido explícito de Andrés porque las
   cajeras usan celular, donde una pestaña nueva es incómoda). Primer y único uso hoy: mantenerlo
   simple hasta que haga falta un segundo caso. ---- */
.modal-fondo { position: fixed; inset: 0; background: rgba(11, 25, 44, .55); z-index: 42; display: flex; align-items: center; justify-content: center; padding: 16px; }
.modal { background: var(--card); border-radius: var(--radio-lg); padding: 20px 22px; max-width: 440px; width: 100%; max-height: 90vh; overflow-y: auto; box-shadow: var(--sombra-flotante); }
.modal h2 { margin-top: 0; }
.modal .campo { margin-bottom: 12px; }
.modal input, .modal select { width: 100%; }

/* ---- Modal GRANDE (2026-10-02, pedido del CEO vía Andrés): "pantallas de creación" que ocupan casi
   toda la pantalla, para que un click accidental en el sidebar no tire el trabajo en curso. A
   propósito un z-index MÁS BAJO que .modal-fondo (41 vs 42, ambos por ENCIMA de la cabecera, que es 30 -- antes el grande era 29 y la cabecera le tapaba el botón Cerrar): un modal chico (ej. "Crear cliente") que
   se abre DESDE adentro de uno grande (ej. Venta POS) debe quedar encima, no debajo — con divs (no
   <dialog>.showModal(), que siempre va al top layer del navegador por encima de cualquier z-index)
   el apilamiento es simple y predecible. NO cierra con click en el fondo (ESE es justo el accidente
   que se quiere evitar) — solo por el botón Cerrar o Escape, y con confirmación si hay trabajo sin
   guardar (ver ADM.abrirModalGrande). ---- */
.modal-grande-fondo { position: fixed; inset: 0; background: var(--bg); z-index: 41; display: flex; align-items: stretch; justify-content: stretch; padding: 0; }
.modal-grande { background: var(--bg); width: 100vw; height: 100vh; display: flex; flex-direction: column; box-shadow: var(--sombra-flotante); overflow: hidden; }
.modal-grande-cabecera { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 20px; border-bottom: 1px solid var(--line); background: var(--card); flex: none; }
.modal-grande-cabecera h1 { margin: 0; font-size: 18px; }
.modal-grande-cuerpo { flex: 1; overflow-y: auto; padding: 20px; }

/* ---- barra lateral en móvil (Sesión 20, F1): pasa de columna fija a cajón (drawer) que se abre con el ☰ del encabezado ---- */
@media (max-width: 900px) {
  .hamburguesa { display: inline-flex; align-items: center; justify-content: center; }
  .disposicion { display: block; }
  .lateral {
    position: fixed; top: 56px; left: 0; bottom: 0; width: 264px; max-width: 82vw; height: auto;
    transform: translateX(-100%); transition: transform .18s ease; box-shadow: 2px 0 14px rgba(0, 0, 0, .3);
  }
  body.lateral-abierta .lateral { transform: translateX(0); }
  .lateral-fondo { display: none; }
  body.lateral-abierta .lateral-fondo { display: block; position: fixed; inset: 56px 0 0 0; background: rgba(11, 25, 44, .55); z-index: 15; }
  main { padding: 16px 14px 40px; }
}

@media (max-width: 640px) {
  .cabecera .fila { padding: 8px 12px; gap: 8px; }
  /* Antes decía ".marca span:first-child" — no coincidía con nada real (el span de "TagFlow" es el
     SEGUNDO hijo de .marca, después del <img>; nunca se ocultaba nada y el encabezado se veía cortado
     en pantallas angostas). Pedido de Andrés: en móvil solo el ícono, nunca el texto a medias. */
  .marca span { display: none; }
  .marca-empresa { display: none; }
  .persona { font-size: 11px; }
  .persona strong { max-width: 28vw; }
  .ficha { padding: 14px; }
}
.presentaciones .sub-fila { font-size: 12px; color: var(--muted); }

/* Grilla de ubicaciones de un mueble (2026-09-29, bulk edit por rango) — filas=Nivel, columnas=Posición. */
.tabla-grilla-mueble { border-collapse: collapse; }
/* Regla estricta (2026-09-30): SOLO las celdas de datos (números de columna) van centradas -- todo lo
   demás sigue la misma convención del resto de la app ("primera columna" / encabezados a la
   izquierda, ver ".tabla th"). Selector compuesto a propósito para que gane SIEMPRE por especificidad,
   sin depender del orden en que quede este bloque dentro del archivo. */
.tabla-grilla-mueble th, .tabla-grilla-mueble td { border: 1px solid var(--line); text-align: center; padding: 0; }
.tabla-grilla-mueble .celda-etiqueta-fila { text-align: left; padding: 4px 8px; }
.celda-etiqueta-fila, .celda-etiqueta-col { background: var(--card2); color: var(--muted-d); font-size: 11px; font-weight: 700; white-space: nowrap; }
.celda-mueble { width: 30px; height: 28px; min-width: 30px; font-size: 12px; color: var(--ink); cursor: pointer; background: var(--card); }
.celda-mueble:hover { background: var(--mint-bg); }
.celda-vacia { color: var(--muted); background: var(--card2); border-style: dashed; }
.celda-anulada { background: var(--bad-bg); color: var(--bad); text-decoration: line-through; }
.celda-dividida { font-weight: 700; }
.celda-con-articulos { box-shadow: inset 0 -3px 0 var(--mint-d); }
.celda-elegida { outline: 3px solid var(--navy); outline-offset: -3px; }
/* Multiubicación (2026-09-28): bloque de casillas contiguas con inventario compartido -- se pinta
   como "un cajón grande" quitando el borde interno entre celdas vecinas del MISMO bloque (los
   *-sin-borde-* los calcula bodega-grilla-mueble.js mirando el bloqueId del vecino). */
.celda-bloque { box-shadow: inset 0 0 0 2px var(--muted-d); }
.celda-bloque-cabecera { box-shadow: inset 0 0 0 2px var(--navy); font-weight: 700; }
.bloque-sin-borde-arriba { border-top-color: transparent; }
.bloque-sin-borde-abajo { border-bottom-color: transparent; }
.bloque-sin-borde-izq { border-left-color: transparent; }
.bloque-sin-borde-der { border-right-color: transparent; }
.cat-0 { background: #E0F2FE; } .cat-1 { background: #FCE7F3; } .cat-2 { background: #FEF3C7; } .cat-3 { background: #DCFCE7; }
.cat-4 { background: #EDE9FE; } .cat-5 { background: #FFE4E6; } .cat-6 { background: #E2E8F0; } .cat-7 { background: #FFEDD5; }
.cat-0.celda-anulada, .cat-1.celda-anulada, .cat-2.celda-anulada, .cat-3.celda-anulada,
.cat-4.celda-anulada, .cat-5.celda-anulada, .cat-6.celda-anulada, .cat-7.celda-anulada { background: var(--bad-bg); }

/* ---- Franja compacta de Venta POS (2026-10-02, Andrés: la caja y el cliente ocupaban demasiado) ---- */
.pos-franja { display: flex; flex-wrap: wrap; gap: 12px 24px; align-items: flex-start; margin-bottom: 14px; }
.pos-cliente { flex: 1 1 280px; max-width: 460px; }
.pos-caja { flex: 1 1 280px; }
.pos-caja-linea { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.pos-caja-opciones { margin-top: 6px; font-size: 13px; color: var(--muted); }
.pos-caja-opciones summary { cursor: pointer; }
.pos-caja-opciones .formulario { margin-top: 8px; }
.boton.chico { padding: 4px 10px; min-height: 30px; font-size: 13px; }

/* Modal grande a PANTALLA COMPLETA (2026-10-02, Andrés: "los modal sean pantalla completa") */
.modal-grande-cuerpo { padding: 16px 24px 28px; }
.pos-fila { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 16px; margin-top: 14px; align-items: start; }
@media (max-width: 820px) { .pos-fila { grid-template-columns: minmax(0, 1fr); } }
.pos-cobrar { display: flex; flex-direction: column; gap: 8px; }
.pos-cobrar .boton { width: 100%; min-height: 48px; font-size: 16px; }

/* ---- Pantalla Ubicaciones (2026-10-02) ---- */
.ubi-mapa { display: flex; flex-wrap: wrap; gap: 10px; }
.ubi-mueble { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; min-width: 130px; padding: 10px 14px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radio-md); cursor: pointer; text-align: left; font: inherit; color: var(--ink); }
.ubi-mueble:hover { border-color: var(--mint); }
.ubi-mueble strong { font-size: 18px; }
.ubi-fila { display: flex; gap: 10px; align-items: flex-start; margin-bottom: 10px; }
.ubi-fila-celdas { display: flex; flex-wrap: wrap; gap: 8px; flex: 1; }
.ubi-celda { width: 190px; min-height: 96px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radio); padding: 6px 8px; display: flex; flex-direction: column; gap: 6px; }
.ubi-celda.elegida { border-color: var(--mint); background: var(--mint-bg); }
.ubi-celda.miembro { opacity: .55; }
.ubi-celda-cab { display: flex; align-items: center; justify-content: space-between; gap: 6px; font-size: 12px; font-weight: 600; }
.ubi-celda-marca { display: flex; align-items: center; gap: 4px; margin: 0; cursor: pointer; }
.ubi-celda-arts { display: flex; flex-direction: column; gap: 4px; }
.ubi-art { display: flex; align-items: center; gap: 6px; font-size: 12px; }
.ubi-art.grande { padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 14px; }
.ubi-art-nombre { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ubi-foto { width: 28px; height: 28px; object-fit: cover; border-radius: 4px; flex: none; background: var(--card2); }
.ubi-foto.grande { width: 56px; height: 56px; }
.ubi-foto.sin-foto { display: inline-flex; align-items: center; justify-content: center; color: var(--muted); border: 1px dashed var(--line); }
.ubi-quitar { border: 0; background: transparent; color: var(--bad); cursor: pointer; font-size: 16px; line-height: 1; padding: 0 4px; }
.ubi-resultados { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.ubi-resultado { display: flex; gap: 10px; align-items: center; text-align: left; padding: 6px 8px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radio); cursor: pointer; font: inherit; color: var(--ink); }
.ubi-resultado:hover { border-color: var(--mint); }
.ubi-resultado span { display: flex; flex-direction: column; }
.ubi-lista { display: flex; flex-direction: column; }
.ubi-reinicio { margin-top: 24px; }

/* ---- Contador de efectivo por denominación (turno de caja, 2026-10-02): un recuadro por billete/moneda colombiana. Cada tarjeta lleva la foto real
   (PNG en /admin/denominaciones), el valor, el input de cantidad y el subtotal. ---- */
.modal.modal-caja { max-width: 760px; }
.contador-efectivo h3 { margin: 14px 0 8px; }
.den-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; }
.den { border-radius: var(--radio); padding: 10px 10px 8px; border: 1px solid var(--line); background: var(--card2); display: flex; flex-direction: column; gap: 6px; text-align: center; }
.den-foto { height: 76px; display: flex; align-items: center; justify-content: center; }
.den-img { max-width: 100%; max-height: 100%; object-fit: contain; filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .35)); user-select: none; }
.den-valor { font-weight: 700; font-size: 15px; }
.den input { width: 100%; text-align: center; font-size: 18px; font-weight: 600; }
.den-subtotal { font-size: 12px; min-height: 16px; text-align: center; }
.den-total { margin-top: 12px; padding: 10px 14px; background: var(--card2); border-radius: var(--radio); font-size: 16px; }
.cuadre-texto { white-space: pre-wrap; background: var(--card2); border: 1px solid var(--line); border-radius: var(--radio); padding: 12px 14px; font-size: 13px; max-height: 50vh; overflow: auto; }

/* Aviso de entorno de PRUEBAS (2026-10-02): lo pone api.js / ingresar.js según el hostname. Cartel fijo abajo a la izquierda: no tapa cabeceras. */
.banner-entorno { position: fixed; left: 8px; bottom: 8px; z-index: 9999; background: #c62828; color: #fff; font: 600 12px/1 system-ui, sans-serif; padding: 6px 12px; border-radius: 999px; box-shadow: 0 2px 8px rgba(0, 0, 0, .3); pointer-events: none; }
