/* Identidad visual del ERP (CLAUDE.md seccion 20).
   Tokens en 3 capas -- nunca un color hardcodeado en un componente:
   1) base:      paleta cruda, uso interno de este archivo solamente
   2) semantico: significado (fondo, texto, borde, foco, estado)
   3) componente: superficie especifica (sidebar, card, input, badge)

   --- Rediseño 2026-08-07: de dark mode a LIGHT ---
   Antes esto era dark mode con glassmorphism (fondo #0a0e14). El usuario
   probo el ERP en local contra el sistema anterior (FM-Portal-Clientes, el
   portal de ShipAirGlobal que ya estaba en produccion) y el veredicto fue
   directo: la visual del anterior es "mucho mejor", esta "se ve muy raro".

   Tenia razon, y la razon es funcional, no de gusto: esto es una
   herramienta de mostrador que dos personas miran ocho horas por dia en un
   deposito iluminado. Un fondo casi negro con texto claro es el peor caso
   para eso -- fatiga visual, y ademas cualquier dato impreso o cotejado
   contra papel (etiquetas, facturas, manifiestos) vive en blanco.

   La paleta ahora sale del logo real (app/static/img/logo.png):
   SHIP en navy, AIR en azul, GLOBAL en gris plata, sobre blanco.
   Misma identidad que el sistema anterior, para que el staff no sienta que
   cambio de producto: contenido claro, y el sidebar como unica superficie
   oscura (ancla la navegacion y le da peso a la marca).
*/

:root {
  /* --- 1) base --- */
  /* Rampa neutra fria (slate) -- pareja con el gris plata del logo */
  --base-slate-50: #f8fafc;
  --base-slate-100: #f1f5f9;
  --base-slate-200: #e2e8f0;
  --base-slate-300: #cbd5e1;
  --base-slate-400: #94a3b8;
  --base-slate-500: #64748b;
  --base-slate-600: #475569;
  --base-slate-700: #334155;
  --base-slate-800: #1e293b;
  --base-white: #ffffff;

  /* Marca -- tomados del logo */
  --base-navy: #1e3a5f;
  --base-navy-deep: #0a1628;
  --base-blue: #0066cc;
  --base-blue-strong: #0052a6;
  --base-yellow: #ffd700;

  /* Fondo de la app: gris muy claro, nunca blanco puro -- asi las tarjetas
     blancas se despegan del fondo sin necesidad de bordes fuertes. */
  --base-canvas: #f5f7fa;

  --base-amber-500: #d97706;
  --base-emerald-500: #059669;
  --base-purple-500: #7c3aed;
  --base-pink-500: #db2777;
  --base-red-500: #dc2626;
  --base-red-700: #b91c1c;

  /* Tintes claros de estado. Estaban escritos a mano en banners, toasts y
     avisos de campo -- los MISMOS seis valores, repetidos en cinco lugares.
     Se suben a la capa base sin cambiarles un digito: es donde vive el color
     crudo, y ahora un ajuste se hace una vez. */
  --base-emerald-50: #ecfdf5;
  --base-emerald-200: #a7f3d0;
  --base-emerald-700: #047857;
  --base-red-50: #fef2f2;
  --base-red-200: #fecaca;
  --base-amber-50: #fffbeb;
  --base-amber-200: #fde68a;
  --base-amber-700: #b45309;
  --base-amber-800: #92400e;

  /* --- 2) semantico --- */
  --color-bg: var(--base-canvas);
  --color-bg-elevated: var(--base-white);
  --color-surface: var(--base-white);
  --color-surface-strong: var(--base-white);
  --color-surface-sunken: var(--base-slate-50);
  --color-border: var(--base-slate-200);
  --color-border-strong: var(--base-slate-300);
  --color-text: var(--base-slate-800);
  /* CONTRASTE DEL TEXTO SECUNDARIO (22/09/2026) -- "hay demasiada informacion
     secundaria con poco contraste" (el dueño, sobre capturas reales).
     Tenia razon y se puede medir: el gris de antes (slate-500, #64748b) da
     4,76:1 sobre blanco, que alcanza para texto normal... pero en este ERP casi
     todo lo que lo usa es CHICO -- encabezados de tabla a 10,9 px, titulos de
     tarjeta a 11,5 px, detalles de metrica a 12,5 px. A ese tamaño 4,76 se lee
     apagado en un deposito iluminado, que es donde se usa esto ocho horas.
     Ahora slate-600 (7,4:1): sigue siendo gris -- no compite con el dato -- pero
     se LEE. El "faint" subio de slate-400 (2,6:1, abajo de cualquier umbral, y
     lo usaban los placeholders) al gris que antes era el secundario. */
  --color-text-dim: var(--base-slate-600);
  --color-text-faint: var(--base-slate-500);
  --color-heading: var(--base-navy);
  --color-focus: var(--base-blue);
  --color-accent: var(--base-blue);
  --color-accent-hover: var(--base-blue-strong);
  --color-success: var(--base-emerald-500);
  --color-warning: var(--base-amber-500);
  --color-danger: var(--base-red-500);
  --color-danger-hover: var(--base-red-700);
  --color-info: var(--base-slate-500);

  /* SALIDA: el color de "esto se va del sistema" -- ver la jerarquia de
     botones mas abajo. Es el navy de la marca, no un azul mas: tiene que
     leerse de un vistazo como algo distinto de la accion celeste de todos los
     dias y del rojo de destruir. */
  --color-salida: var(--base-navy);
  --color-salida-hover: var(--base-navy-deep);

  /* Superficie oscura -- SOLO el sidebar. Tiene su propia escala de texto
     porque ahi la relacion figura/fondo se invierte respecto al resto. */
  --color-dark-surface: var(--base-navy-deep);
  --color-dark-text: rgba(255, 255, 255, 0.92);
  --color-dark-text-dim: rgba(255, 255, 255, 0.68);
  /* Los titulos de grupo del menu ("OPERACION", "ADMINISTRACION") usaban 0,38:
     sobre el navy del sidebar eso es ~3,3:1 en letra de 9,9 px. Son las
     etiquetas que le dicen a alguien que recien empieza DONDE esta parado en el
     menu -- no pueden ser lo menos legible de la pantalla. 0,55 ~= 6:1. */
  --color-dark-text-faint: rgba(255, 255, 255, 0.55);
  --color-dark-border: rgba(255, 255, 255, 0.1);
  --color-dark-hover: rgba(255, 255, 255, 0.08);

  /* Colores de estado -- FIJOS en toda la app, nunca reusar el de
     "entregado" para agrupado/retirado (son excepcionales, no el flujo
     feliz). Mismo mapeo para EstadoPaqueteEnum/EstadoGuiaEnum/
     EstadoAgrupacionEnum/EstadoPickupEnum. Tonos elegidos para contrastar
     >=4.5:1 sobre fondo claro, no los mismos que servian sobre negro. */
  --state-recibido: var(--base-slate-500);
  --state-en-transito: var(--base-amber-500);
  --state-entregado: var(--base-emerald-500);
  --state-agrupado: var(--base-purple-500);
  --state-retirado: var(--base-pink-500);
  --state-anulada: var(--base-red-500);
  --state-completa: var(--base-emerald-500);
  --state-en-progreso: var(--base-amber-500);
  --state-programado: var(--base-slate-500);
  --state-asignado: var(--base-blue);
  --state-recolectado: var(--base-amber-500);
  --state-ingresado: var(--base-emerald-500);

  /* --- 3) componente --- */
  --card-bg: var(--color-surface);
  --card-border: var(--color-border);
  --card-radius: 12px;

  /* ESCALA TIPOGRAFICA -- siete pasos, razon ~1,125 (21/09/2026).
     ===========================================================
     NO se invento: se RECUPERO. Una auditoria encontro 33 tamaños distintos en
     222 lugares, y al medirlos resulto que ya formaban una progresion de razon
     1,125 -- la que las referencias recomiendan para interfaces de datos
     densos -- solo que derivada, con ruido alrededor de cada paso.

     Los pasos son los CENTROS de los grupos reales, asi que casi nada cambia de
     aspecto: la base es 13,6 px porque es el tamaño mas usado del proyecto (45
     veces), y los demas son los otros grupos (26, 25, 23, 19 usos...).

     Se usan por el token, nunca tipeando el numero. El dia que haya que mover
     la escala, se mueve aca y no en 222 lugares.

     QUE FALTA (22/09/2026). En este archivo quedan ~15 tamaños tipeados a mano
     que NO caen sobre ningun paso: 0,7 · 0,72 · 0,74 · 0,82 · 0,88 · 0,9 ·
     0,92 · 1 · 1,15 rem. Los que caian exacto (0,65 · 0,75 · 0,8 · 0,85 ·
     0,95) ya pasaron al token, y los que estaban DEBAJO del paso mas chico
     subieron a --texto-micro, que era el problema de legibilidad que marco el
     dueño. Los que quedan hay que redondearlos EN UNA DIRECCION U OTRA, y
     elegir de memoria para veinticinco pantallas -- sin poder mirarlas -- es
     como se rompe un renglon que hoy entra justo. Van cuando alguien tenga la
     pantalla delante. No agregar pasos nuevos a la escala para que entren. */
  --texto-micro: 0.65rem; /* 10,4 px -- marquitas, insignias */
  --texto-chico: 0.75rem; /* 12 px   -- ayudas, pies de tabla */
  --texto-denso: 0.8rem; /*  12,8 px -- tablas densas */
  --texto-base: 0.85rem; /*  13,6 px -- el texto normal */
  --texto-grande: 0.95rem; /* 15,2 px -- lo destacado, h3 */
  --texto-titulo: 1.1rem; /*  17,6 px -- titulo de seccion, h2 */
  --texto-pantalla: 1.5rem; /* 24 px  -- titulo de pantalla, h1 */


  /* Sombras de light mode: mucho mas sutiles que en dark, y tintadas de
     navy en vez de negro puro (un gris neutro sobre fondo frio se ve sucio). */
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);
  --shadow-md: 0 1px 3px rgba(15, 23, 42, 0.07), 0 8px 20px -8px rgba(15, 23, 42, 0.1);
  --shadow-lg: 0 2px 6px rgba(15, 23, 42, 0.08), 0 24px 48px -16px rgba(15, 23, 42, 0.18);

  --input-bg: var(--base-white);
  --input-border: var(--base-slate-300);
  --sidebar-bg: var(--color-dark-surface);
  --topbar-bg: rgba(255, 255, 255, 0.86);

  --font-sans: "Plus Jakarta Sans", system-ui, -apple-system, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", monospace;
}

/* --- Transición entre pantallas ----------------------------------------- */

/* El ERP son páginas separadas, no una SPA: cada click en el menú es una
   navegación real del navegador. Y se notaba -- la pantalla se vaciaba, el
   sidebar (que es idéntico en todas) desaparecía y volvía a dibujarse, y
   recién después aparecía el contenido. Tres saltos para pasar entre dos
   pantallas que comparten casi todo lo que se ve.

   Con view transitions entre documentos el navegador retiene la pantalla
   anterior hasta que la nueva está lista, y solo cruza lo que cambió: la
   navegación se lee como cambiar de panel, no como recargar. Los nombres
   del sidebar y la topbar (para que queden quietos) están en shell.css;
   la activación va acá porque theme.css lo cargan TODAS las pantallas,
   incluidas Cargas y el simulador, que no usan el layout con sidebar --
   la transición requiere que las dos páginas del salto estén adheridas.

   Es progresivo por diseño: donde no está soportado (hoy Firefox y Safari)
   la navegación queda exactamente como estaba, sin nada roto ni degradado. */
@view-transition {
  navigation: auto;
}

/* Corta a propósito: tiene que hacer que el cambio se sienta continuo, no
   agregarle demora a un flujo de mostrador donde se cuentan los segundos. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 130ms;
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none;
  }
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

[data-mono="true"],
.mono,
.tracking,
.dato-exacto {
  font-family: var(--font-mono);
}

h1,
h2,
h3 {
  margin: 0 0 12px;
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--color-heading);
}

/* CADA UNO CON SU TAMAÑO, y en orden. Antes los tres compartian la regla de
   arriba, que les da margen, peso y color pero NINGUN tamaño: cada pantalla lo
   tipeaba a mano y ninguna coincidia. En los paneles del Inventario el h3 de
   adentro salia a 18,7 px sobre un h2 de 13,6: el titulo de adentro tapaba al
   de afuera. Una pantalla puede pisar esto cuando tenga un motivo, pero el
   default deja de ser "lo que decida el navegador". */
h1 {
  font-size: var(--texto-pantalla);
}

h2 {
  font-size: var(--texto-titulo);
}

h3 {
  font-size: var(--texto-grande);
}

a {
  color: var(--color-accent);
}

/* Foco visible -- no negociable por el flujo 100% teclado (seccion 20).
   Nunca quitar sin reemplazar por algo igual de visible. */
:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}

.glass-panel {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: var(--card-radius);
  box-shadow: var(--shadow-md);
}

/* --- Botones: CUATRO niveles, y el nivel se ve ---------------------------- */
/* ========================================================================= */
/* Hasta el 22/09/2026 habia tres variantes y una sola de ellas (.peligro) se
   usaba UNA vez en toda la app. El resultado, medido sobre las pantallas
   reales: "Export DBF" (manda un archivo a la aduana), "Sincronizar" (escribe
   en el sistema DOS), "Renumerar" y "Finalizar" estaban puestos como
   `.secundario`, o sea BLANCOS -- se veian MENOS importantes que un "Guardar"
   cualquiera. Y todo `<button>` sin clase sale azul, asi que en una fila de
   seis botones los seis gritaban igual.

   Para el hermano del dueño, que empieza solo en diez dias con la caja en la
   mano, eso es lo peor posible: el aspecto del boton no le dice nada sobre lo
   que va a pasar cuando lo apriete.

   La jerarquia es de CUATRO niveles y se elige por lo que HACE la accion, no
   por donde esta puesta en la pantalla:

     1. .principal  -- la accion segura de la pantalla. UNA SOLA por pantalla.
                       Azul lleno. (Un <button> sin clase ya sale asi: no hace
                       falta escribirla, existe para poder decirlo.)
     2. .secundario -- todo lo demas que es seguro y reversible. Blanco.
     3. .salida     -- MANDA DATOS FUERA: a la aduana, al sistema DOS, al
                       portal del cliente, un archivo que se despacha. Navy
                       lleno + flecha que sale. Ver abajo por que asi.
     4. .peligro    -- destructivo o irreversible: anular, borrar, renumerar,
                       cerrar una guia madre, finalizar. Rojo lleno.

   Regla para las seis pantallas: si una accion cae en 3 o en 4, NO puede
   quedar como .secundario "porque no es la principal". El nivel lo decide la
   consecuencia. */

button,
.btn {
  font-family: var(--font-sans);
  /* Era 0,875rem (14 px) tipeado a mano, a menos de medio pixel del paso base
     de la escala. Un boton es lo que mas se repite en la pantalla: si hay UN
     lugar donde el tamaño tiene que salir del token, es este. */
  font-size: var(--texto-base);
  font-weight: 600;
  border-radius: 8px;
  padding: 9px 16px;
  border: 1px solid transparent;
  cursor: pointer;
  background: var(--color-accent);
  color: var(--base-white);
  box-shadow: var(--shadow-sm);
  transition: background 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease;
}

/* 1) PRINCIPAL -- identica al default a proposito: los 200 botones que ya hay
   escritos sin clase no cambian de aspecto, y la clase existe para que una
   pantalla pueda DECIR cual es la principal en vez de que se deduzca. */
button.principal,
.btn.principal {
  background: var(--color-accent);
  color: var(--base-white);
  border-color: transparent;
}

/* `:not(:disabled)` en TODOS los hover: sin eso, un boton apagado seguia
   cambiando de color al pasarle el mouse, y prometia que se podia apretar. */
button:hover:not(:disabled),
.btn:hover:not(:disabled) {
  background: var(--color-accent-hover);
  box-shadow: var(--shadow-md);
}

/* Antes esto forzaba `background: var(--color-accent)`, o sea que un boton
   .peligro deshabilitado se ponia AZUL -- el unico rojo de la app desaparecia
   justo cuando estaba bloqueado. Ahora el deshabilitado solo apaga; cada
   variante conserva su color. */
button:disabled,
.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  box-shadow: none;
}

/* 2) SECUNDARIO */
button.secundario,
.btn.secundario {
  background: var(--base-white);
  border-color: var(--color-border-strong);
  color: var(--base-navy);
  box-shadow: var(--shadow-sm);
}

button.secundario:hover:not(:disabled),
.btn.secundario:hover:not(:disabled) {
  background: var(--base-slate-50);
  border-color: var(--base-slate-400);
  box-shadow: var(--shadow-sm);
}

/* 3) SALIDA -- "esto se va de acá"
   Dos señales, no una, porque el color solo no alcanza (ni para alguien
   apurado ni para alguien que no distingue bien el azul del navy):
     a) el navy de la marca, lleno -- mas oscuro y mas pesado que la accion
        celeste de todos los dias, y sin parecerse al rojo;
     b) una FLECHA QUE SALE, puesta por CSS, no por la pantalla: aparece sola
        en los seis lugares donde se use, nadie se la puede olvidar.
   El peso visual es deliberado: un export a la aduana no se deshace pidiendo
   perdon, pero tampoco es destruir algo, asi que no puede ser rojo. */
button.salida,
.btn.salida {
  background: var(--color-salida);
  color: var(--base-white);
  border-color: transparent;
}

button.salida:hover:not(:disabled),
.btn.salida:hover:not(:disabled) {
  background: var(--color-salida-hover);
  box-shadow: var(--shadow-md);
}

button.salida::after,
.btn.salida::after {
  content: "\2197"; /* ↗ */
  margin-left: 7px;
  font-weight: 700;
  opacity: 0.8;
}

/* 4) PELIGRO -- destructivo o irreversible */
button.peligro,
.btn.peligro {
  background: var(--color-danger);
  color: var(--base-white);
  border-color: transparent;
}
button.peligro:hover:not(:disabled),
.btn.peligro:hover:not(:disabled) {
  background: var(--color-danger-hover);
  box-shadow: var(--shadow-md);
}

/* El foco sobre los botones llenos: el outline azul general se pierde contra
   el propio relleno del boton. Se le agrega un halo blanco por dentro para que
   el anillo se despegue igual sobre navy y sobre rojo -- el flujo por teclado
   tiene que ver DONDE esta parado tambien en los botones peligrosos. */
button.salida:focus-visible,
.btn.salida:focus-visible,
button.peligro:focus-visible,
.btn.peligro:focus-visible {
  box-shadow: 0 0 0 2px var(--base-white) inset, var(--shadow-md);
}

/* Fila de botones. `.acciones` ya se usa en ocho lugares de Facturas y no
   estaba definida en ningun CSS compartido: la escribia cada pantalla en un
   <style> propio. Vive aca para que el proximo no la reinvente.
   `.acciones.a-la-derecha` empuja el grupo al final (pie de un formulario). */
.acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
}
.acciones.a-la-derecha {
  justify-content: flex-end;
}
/* Opcional, para cuando en la misma fila conviven un Guardar y un Anular:
   despega la accion peligrosa del resto para que no se apriete de mas por
   estar pegada al boton seguro. Es opt-in porque una fila que SOLO tiene la
   accion peligrosa no tiene que empujarla a ningun lado. */
.acciones.aparta-el-peligro .peligro {
  margin-left: auto;
}

/* Cuando lo irreversible son VARIOS botones, van juntos en un grupo que se
   aparta al final de la fila. Es la unica forma de separar lo peligroso: antes
   habia dos (esta, y una escrita a mano en Facturas con otro nombre), y la
   misma idea se veia distinta segun la pantalla. */
.acciones > .grupo-peligro {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

/* --- Campos ------------------------------------------------------------- */

input,
select,
textarea {
  font-family: var(--font-sans);
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  color: var(--color-text);
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 0.9rem;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

input::placeholder,
textarea::placeholder {
  color: var(--color-text-faint);
}

input:hover:not(:disabled),
select:hover:not(:disabled),
textarea:hover:not(:disabled) {
  border-color: var(--base-slate-400);
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  border-color: var(--color-focus);
  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.16);
}

/* Un campo deshabilitado tiene que LEERSE deshabilitado -- no alcanza con
   que el navegador lo ignore (ej. Tracking original cuando se tilda
   "No tiene", CLAUDE.md seccion 5.1). */
input:disabled,
select:disabled,
textarea:disabled {
  background: var(--base-slate-100);
  color: var(--color-text-faint);
  border-color: var(--color-border);
  cursor: not-allowed;
}

/* Desplegable con flecha propia -- el control nativo en Windows dibuja una
   flecha gris de sistema que no combina con nada. Mismo criterio que ya
   usaba el portal anterior. */
select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2364748b' stroke-width='2.5'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M19 9l-7 7-7-7'/%3E%3C/svg%3E");
  background-position: right 0.7rem center;
  background-repeat: no-repeat;
  background-size: 1rem 1rem;
  padding-right: 2.4rem;
}

/* Etiquetas de campo como "captions": mayusculas, tracking, peso 700 --
   patron estandar en formularios densos de producto, y el mismo que usaba
   el portal anterior (text-xs font-bold uppercase tracking-wider). */
label {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--base-navy);
  display: block;
  margin-bottom: 6px;
}

/* .chk-linea envuelve una oracion entera junto a un checkbox (ej. "Silenciar
   en este puesto", "Nuevo paquete") en varias pantallas -- es texto de
   lectura normal, no una caption de campo, asi que se excluye del
   tratamiento de arriba. */
.chk-linea {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: var(--texto-base);
  font-weight: 500;
  text-transform: none;
  letter-spacing: normal;
  color: var(--color-text);
  cursor: pointer;
}

input[type="checkbox"],
input[type="radio"] {
  width: 16px;
  height: 16px;
  padding: 0;
  accent-color: var(--color-accent);
  cursor: pointer;
}

.campo {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 16px;
}

/* Input con boton dentro (ej. "ver contraseña") -- un solo componente
   reusable en vez de reinventar el posicionamiento en cada pantalla. */
.input-con-icono {
  position: relative;
}
.input-con-icono input {
  width: 100%;
  padding-right: 40px;
}
.input-con-icono .btn-icono {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  background: transparent;
  border: none;
  box-shadow: none;
  color: var(--color-text-dim);
  width: 32px;
  height: 32px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.input-con-icono .btn-icono:hover {
  background: transparent;
  box-shadow: none;
  color: var(--color-text);
}

/* --- Badges de estado --------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: var(--texto-chico);
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid transparent;
}

.badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.badge[data-estado="recibido"],
.badge[data-estado="programado"] {
  color: var(--state-recibido);
  background: color-mix(in srgb, var(--state-recibido) 12%, white);
  border-color: color-mix(in srgb, var(--state-recibido) 26%, white);
}
.badge[data-estado="en_transito"],
.badge[data-estado="en_progreso"],
.badge[data-estado="recolectado"] {
  color: var(--state-en-transito);
  background: color-mix(in srgb, var(--state-en-transito) 12%, white);
  border-color: color-mix(in srgb, var(--state-en-transito) 26%, white);
}
.badge[data-estado="entregado"],
.badge[data-estado="completa"],
.badge[data-estado="ingresado"] {
  color: var(--state-entregado);
  background: color-mix(in srgb, var(--state-entregado) 12%, white);
  border-color: color-mix(in srgb, var(--state-entregado) 26%, white);
}
.badge[data-estado="agrupado"] {
  color: var(--state-agrupado);
  background: color-mix(in srgb, var(--state-agrupado) 12%, white);
  border-color: color-mix(in srgb, var(--state-agrupado) 26%, white);
}
.badge[data-estado="retirado"] {
  color: var(--state-retirado);
  background: color-mix(in srgb, var(--state-retirado) 12%, white);
  border-color: color-mix(in srgb, var(--state-retirado) 26%, white);
}
.badge[data-estado="anulada"] {
  color: var(--state-anulada);
  background: color-mix(in srgb, var(--state-anulada) 12%, white);
  border-color: color-mix(in srgb, var(--state-anulada) 26%, white);
}
.badge[data-estado="asignado"] {
  color: var(--state-asignado);
  background: color-mix(in srgb, var(--state-asignado) 12%, white);
  border-color: color-mix(in srgb, var(--state-asignado) 26%, white);
}

/* Estado incompleto -- NUNCA un error visual (seccion 20): indicacion
   neutral, no rojo, no icono de advertencia agresivo. */
.badge[data-estado="incompleto"] {
  color: var(--color-text-dim);
  background: var(--base-slate-100);
  border: 1px dashed var(--color-border-strong);
}

/* Rol Admin: no es un estado del negocio, es un nivel de privilegio -- ve
   datos personales completos, anula guias, edita tarifas (seccion 16). Se
   lee distinto de los badges de estado a proposito. */
.badge[data-estado="admin"] {
  color: var(--base-navy);
  background: color-mix(in srgb, var(--base-yellow) 30%, white);
  border-color: color-mix(in srgb, var(--base-yellow) 60%, white);
}

/* --- La fila propia en un listado de cuentas ---------------------------- */

.fila-propia > td {
  background: color-mix(in srgb, var(--color-accent) 5%, transparent);
}
.fila-propia > td:first-child {
  box-shadow: inset 3px 0 0 var(--color-accent);
}

.chip-vos {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--color-accent) 14%, transparent);
  color: var(--color-accent);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  vertical-align: 1px;
}

/* --- Banners ------------------------------------------------------------ */

.banner {
  padding: 11px 14px;
  border-radius: 8px;
  font-size: var(--texto-base);
  font-weight: 500;
  display: none;
  border: 1px solid transparent;
}
.banner.visible {
  display: block;
}
.banner.ok {
  background: var(--base-emerald-50);
  border-color: var(--base-emerald-200);
  color: var(--base-emerald-700);
}
.banner.error {
  background: var(--base-red-50);
  border-color: var(--base-red-200);
  color: var(--base-red-700);
}
.banner.cola,
.banner.info {
  background: var(--base-amber-50);
  border-color: var(--base-amber-200);
  color: var(--base-amber-700);
}

/* --- Scrollbar ---------------------------------------------------------- */

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: var(--base-slate-300);
  border-radius: 6px;
  border: 2px solid var(--color-bg);
}
::-webkit-scrollbar-thumb:hover {
  background: var(--base-slate-400);
}

/* --- Avisos (toasts) ----------------------------------------------------- */
/* Reemplazan a los banners inline, que eran el punto mas debil de la UX:
   aparecian dentro del formulario, del mismo tamaño que el resto del texto,
   y en Cargas quedaban abajo de todo -- el operario escaneando rapido nunca
   los veia. Estos son fijos arriba al centro, grandes, y NO roban foco:
   el flujo por teclado sigue intacto mientras el aviso esta en pantalla
   (critico para el mostrador, CLAUDE.md seccion 5). */

.toast-zona {
  position: fixed;
  top: 18px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: min(560px, calc(100vw - 32px));
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: 13px;
  padding: 14px 16px;
  border-radius: 10px;
  background: var(--base-white);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-info);
  box-shadow: var(--shadow-lg);
  pointer-events: auto;
  animation: toast-entra 0.18s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes toast-entra {
  from {
    opacity: 0;
    transform: translateY(-14px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.toast.saliendo {
  animation: toast-sale 0.15s ease-in forwards;
}

@keyframes toast-sale {
  to {
    opacity: 0;
    transform: translateY(-10px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .toast,
  .toast.saliendo {
    animation: none;
  }
}

.toast .icono {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--texto-grande);
}

.toast .cuerpo {
  flex: 1;
  min-width: 0;
}

.toast .titulo {
  font-size: 0.7rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 3px;
}

.toast .mensaje {
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--color-text);
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.toast .cerrar {
  flex-shrink: 0;
  background: transparent;
  border: none;
  box-shadow: none;
  color: var(--color-text-faint);
  padding: 2px 6px;
  font-size: var(--texto-grande);
  line-height: 1;
}
.toast .cerrar:hover {
  background: transparent;
  box-shadow: none;
  color: var(--color-text);
}

.toast.ok {
  border-left-color: var(--color-success);
}
.toast.ok .icono {
  background: var(--base-emerald-50);
  color: var(--base-emerald-700);
}
.toast.ok .titulo {
  color: var(--base-emerald-700);
}

.toast.error {
  border-left-color: var(--color-danger);
}
.toast.error .icono {
  background: var(--base-red-50);
  color: var(--base-red-700);
}
.toast.error .titulo {
  color: var(--base-red-700);
}

.toast.cola,
.toast.info {
  border-left-color: var(--color-warning);
}
.toast.cola .icono,
.toast.info .icono {
  background: var(--base-amber-50);
  color: var(--base-amber-700);
}
.toast.cola .titulo,
.toast.info .titulo {
  color: var(--base-amber-700);
}

/* Dato exacto dentro de un aviso (ej. el tracking recien generado) -- se
   muestra grande y monoespaciado porque es lo unico que el operario
   necesita leer para confirmar que la carga salio bien. */
.toast .dato {
  display: block;
  font-family: var(--font-mono);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--color-heading);
  letter-spacing: 0.02em;
  margin-top: 2px;
}

/* --- Login --------------------------------------------------------------- */
/* Centrado real vertical: antes era un margin-top: 100px fijo, que en una
   pantalla de mostrador (monitor chico, resolucion baja) dejaba la caja
   pegada al borde de abajo. */
.login-caja {
  max-width: 400px;
  margin: 0 auto;
  padding: 24px 16px;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* --- Combobox (buscador con autocompletado) ------------------------------ */
/* Ver js/combobox.js. Reemplaza al <select> nativo en los campos con
   catalogo grande (Cliente, Proveedor): con cientos de Clientes el select
   obliga a scrollear, y en un mostrador eso es tiempo perdido por paquete. */

.combo {
  position: relative;
}

.combo-control {
  display: flex;
  gap: 6px;
  align-items: stretch;
}

.combo-control input {
  flex: 1;
  min-width: 0;
}

/* El "+" vive AL LADO del campo, siempre visible -- no escondido abajo ni
   solo cuando la busqueda no encuentra nada. Se puede dar de alta en
   cualquier momento sin cambiar de pantalla. */
.combo-crear {
  flex-shrink: 0;
  width: 42px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
}

.combo-lista {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 50;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: var(--base-white);
  border: 1px solid var(--color-border-strong);
  border-radius: 8px;
  box-shadow: var(--shadow-lg);
  max-height: 260px;
  overflow-y: auto;
}

.combo-item {
  padding: 8px 10px;
  border-radius: 6px;
  font-size: 0.88rem;
  color: var(--color-text);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.combo-item.resaltado {
  background: var(--color-accent);
  color: var(--base-white);
}

.combo-item.combo-vacio {
  color: var(--color-text-faint);
  cursor: default;
  font-style: italic;
}

.combo-crear-item {
  border-top: 1px solid var(--color-border);
  margin-top: 4px;
  padding-top: 10px;
  color: var(--color-accent);
  font-weight: 600;
}
.combo-crear-item.resaltado {
  color: var(--base-white);
}

/* Aviso de campo -- para cosas como "el Cliente que tenias elegido es de
   otra Empresa". Va pegado al campo, no en un toast: es contexto de ESE
   campo, y el operario necesita verlo mientras lo corrige. */
.campo-aviso {
  display: none;
  align-items: flex-start;
  gap: 7px;
  margin-top: 6px;
  padding: 8px 10px;
  border-radius: 7px;
  font-size: var(--texto-denso);
  font-weight: 500;
  line-height: 1.4;
  background: var(--base-amber-50);
  border: 1px solid var(--base-amber-200);
  color: var(--base-amber-800);
}
.campo-aviso.visible {
  display: flex;
}

/* Desambiguadores de homonimo dentro del combobox. Solo aparecen cuando el
   nombre esta repetido en el catalogo -- en el caso normal la fila queda
   limpia (ver js/combobox.js::detalleDesambiguador). */
.combo-item {
  display: flex;
  align-items: center;
  gap: 8px;
}

.combo-desambigua {
  font-family: var(--font-mono);
  font-size: 0.74rem;
  color: var(--color-text-faint);
  flex-shrink: 0;
}
.combo-item.resaltado .combo-desambigua {
  color: rgba(255, 255, 255, 0.75);
}

.combo-homonimo {
  margin-left: auto;
  flex-shrink: 0;
  font-size: var(--texto-micro);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--base-amber-50);
  border: 1px solid var(--base-amber-200);
  color: var(--base-amber-700);
}
.combo-item.resaltado .combo-homonimo {
  background: rgba(255, 255, 255, 0.18);
  border-color: rgba(255, 255, 255, 0.35);
  color: var(--base-white);
}

/* Contexto de tenant dentro del campo -- de que Empresa es esta lista.
   Cuando hay varias Empresas conviviendo (que es el caso del SaaS), el
   operario no puede tener que mirar arriba para acordarse. */
.combo-contexto {
  display: block;
  margin-top: 5px;
  font-size: 0.72rem;
  color: var(--color-text-dim);
}
.combo-contexto strong {
  color: var(--color-heading);
  font-weight: 700;
}

/* Cartel de consolidacion multiproveedor (solicitudes, 0035) */
/* Un aviso: algo que no impide seguir pero que conviene saber antes.
   `.aviso-multi` era el unico y tenia el estilo escrito para su caso (mezcla
   de proveedores en una caja). Ahora hay mas de uno, asi que la definicion es
   una sola y el nombre viejo queda como alias -- no cambia como se ve nada. */
/* Los dos unicos hex que quedaban fuera de la capa base eran estos, y eran
   un ambar CASI igual al de `.campo-aviso` -- dos amarillos distintos para la
   misma idea. Pasan a los tokens: un solo aviso, un solo color. */
.aviso,
.aviso-multi { margin: 6px 0; padding: 6px 10px; border-radius: 6px; background: var(--base-amber-50); color: var(--base-amber-800); font-size: var(--texto-base); }
.aviso i,
.aviso-multi i { margin-right: 6px; }

/* (La casita "Inicio" de las pantallas sin barra lateral, `.volver-erp`, se
   saco el 28/09/2026: la reemplaza la barra angosta, `.riel`, mas abajo.) */

/* Quien esta adentro + Salir, en las pantallas sin barra lateral.
   Lo dibuja /js/sesion-mostrador.js dentro de [data-sesion]. */
.sesion-mostrador {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  flex-shrink: 0;
}
.sesion-mostrador .sesion-quien {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--color-text-dim);
  white-space: nowrap;
  max-width: 14ch;
  overflow: hidden;
  text-overflow: ellipsis;
}
.salir-erp {
  /* auto: paletizado.css pone todos sus botones a width 100% y este se comia
     el nombre de la persona ("Revi..."). */
  width: auto;
  height: 32px;
  padding: 0 12px;
  border: 1px solid var(--color-border-strong);
  border-radius: 8px;
  background: var(--color-surface);
  color: var(--color-text-dim);
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
}
.salir-erp:hover {
  border-color: var(--color-danger);
  color: var(--color-danger);
}
.salir-erp:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}
/* En pantallas angostas el nombre se va: lo que no puede faltar es Salir. */
@media (max-width: 560px) {
  .sesion-mostrador .sesion-quien { display: none; }
}

/* Cartel de "función de prueba" -----------------------------------------
   Decision del dueño (21/09/2026): las pantallas que existen pero todavia no
   se usan de verdad lo tienen que DECIR, para que nadie -- ni el programador
   que viene a auditar, ni un empleado nuevo -- crea que ya son parte del dia
   a dia. Un solo lugar: las pantallas con shell lo reciben solo (shell.js lo
   inyecta segun NAV_GRUPOS); las que no tienen shell lo escriben a mano.
   Amarillo de aviso, no rojo: no esta roto, esta sin estrenar. */
.cartel-prueba {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0 0 18px;
  padding: 12px 14px;
  border: 1px solid var(--color-warning);
  border-left-width: 4px;
  border-radius: var(--card-radius);
  background: color-mix(in srgb, var(--color-warning) 10%, var(--color-bg-elevated));
  color: var(--color-text);
  font-size: 0.92rem;
  line-height: 1.45;
}
.cartel-prueba i {
  color: var(--color-warning);
  margin-top: 2px;
  flex-shrink: 0;
}
.cartel-prueba strong {
  display: block;
  margin-bottom: 2px;
}

/* La marquita del menu, al lado del nombre de la pantalla. */
.tag-prueba {
  margin-left: auto;
  padding: 1px 6px;
  /* `currentColor` y no un color propio, a proposito: esta marquita vive en
     DOS contextos opuestos -- el menu oscuro (y ENCIMA del amarillo del item
     activo) y las tarjetas claras del Inicio. Con `--color-warning` quedaba
     ambar sobre amarillo, ~2,3:1, justo cuando estas parado en la pantalla que
     advierte. Heredando el color del contenedor es legible en los dos y en
     cualquier contexto que se agregue despues, sin tener que acordarse. */
  border: 1px solid currentColor;
  border-radius: 999px;
  background: transparent;
  color: inherit;
  opacity: 0.75;
  font-size: var(--texto-micro);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

/* ========================================================================= */
/* GRILLA DE FORMULARIO -- que el formulario use el monitor que hay          */
/* ========================================================================= */
/* El defecto que mas molesta, dicho por el dueño sobre sus propias capturas:
   "esta todo para abajo y dejas un monton en blanco... para cargar clientes o
   cargas no es necesario que sea para abajo, si se puede cuando apreto enter
   puede ir al costado".

   Medido a 1920 px: Cargas era UNA columna de ~870 px con 11 campos hacia
   abajo -- habia que scrollear para llegar al peso -- y medio monitor vacio al
   lado. Es el mismo reclamo de siempre: el programa DOS que usaban antes metia
   los 10 campos en una pantalla sin scroll, y por eso era mas rapido.

   COMO SE USA:

     <div class="grilla-campos">            2 columnas (el default)
     <div class="grilla-campos tres">       3 columnas
     <div class="grilla-campos cuatro">     4 columnas (datos cortos: medidas)
     <div class="grilla-campos una">        1 columna (forzada)

     Adentro van los `.campo` de siempre. Un campo que necesita toda la fila
     (una descripcion larga, un titulo de grupo, una fila de acciones) lleva
     `.campo-ancho-total` -- que ya es el idioma del proyecto, viene de Cargas
     -- o su alias `.fila-completa`.

   POR QUE auto-fit + minmax Y NO columnas fijas: en Guias los campos 12 a 16
   estan en una grilla de 5 columnas FIJAS y por eso un campo se sale de la
   tarjeta. Aca cada columna declara un ancho MINIMO: cuando no entra, la
   grilla saca columnas sola y termina en una sola columna en un celular. No
   hay ancho que se desborde porque no hay ancho impuesto.

   El truco del `max(...)` es lo que le pone TECHO al numero de columnas sin
   perder eso: el minimo de cada pista es "el ancho minimo del campo, o el que
   le tocaria si fueran N, lo que sea mas grande". Con el contenedor ancho da
   exactamente N; con el contenedor angosto da menos. Sin media queries. */

/* `.form-grid` es un alias de `.grilla-campos`: el nombre en ingles aparece en
   los apuntes de diseño, y un formulario no se puede romper porque alguien
   escribio el otro. El canonico es `.grilla-campos`. */
.grilla-campos,
.form-grid {
  --columnas: 2;
  --campo-min: 240px;
  --grilla-gap: 18px;
  display: grid;
  column-gap: var(--grilla-gap);
  /* El hueco vertical lo pone el `margin-bottom` que `.campo` ya trae; si lo
     pusieramos tambien aca los campos quedarian al doble de separados. */
  row-gap: 0;
  /* `auto-fill` y no `auto-fit`: con auto-fit, una tarjeta de DOS campos en una
     grilla de tres dejaria colapsar la columna sobrante y los dos campos se
     estirarian a media pantalla cada uno -- un input de 700 px para escribir un
     nombre, que es otra cara del mismo "se ve feo". Con auto-fill la columna
     vacia se queda ahi y los campos conservan el ancho que les toca. */
  grid-template-columns: repeat(
    auto-fill,
    minmax(
      max(
        var(--campo-min),
        calc((100% - (var(--columnas) - 1) * var(--grilla-gap)) / var(--columnas))
      ),
      1fr
    )
  );
}

.grilla-campos.una,
.form-grid.una {
  --columnas: 1;
}
.grilla-campos.tres,
.form-grid.tres {
  --columnas: 3;
  --campo-min: 200px;
}
.grilla-campos.cuatro,
.form-grid.cuatro {
  --columnas: 4;
  --campo-min: 150px;
}

/* Ocupar la fila entera. `.campo-ancho-total` ya existia en cargas.css con
   esta misma regla; se sube aca para que sirva en las 25 pantallas y no solo
   en una. Que este declarada dos veces igual no molesta -- pero la de Cargas
   ya no es la unica. */
.grilla-campos > .campo-ancho-total,
.grilla-campos > .fila-completa,
.form-grid > .campo-ancho-total,
.form-grid > .fila-completa {
  grid-column: 1 / -1;
}

/* Un campo que ocupa dos columnas sin llegar a la fila entera (una direccion
   al lado de un codigo postal, por ejemplo). */
/* Dos columnas solo cuando hay lugar para dos: en una grilla que ya bajo a
   una sola columna (celular), `span 2` inventaba una columna de mas y la
   tarjeta desbordaba. */
.grilla-campos > .campo-doble,
.form-grid > .campo-doble {
  grid-column: 1 / -1;
}
@media (min-width: 700px) {
  .grilla-campos > .campo-doble,
  .form-grid > .campo-doble {
    grid-column: span 2;
  }
}

/* Titulo que parte un formulario en secciones ("Datos del envio", "Medidas").
   Es una etiqueta de orientacion, no un encabezado de documento: por eso no es
   un h2/h3 -- no tiene que competir con el titulo de la pantalla.

   El aspecto venia de cargas.css, o sea que solo existia en UNA pantalla; se
   sube aca para que las demas puedan partir un formulario largo en tramos con
   sentido en vez de tirar quince campos seguidos. Cargas no cambia: su propio
   CSS se carga despues y sigue mandando. El menu tampoco: `.shell-nav
   .grupo-titulo` es mas especifico. */
.grupo-titulo {
  margin: 0 0 14px;
  font-size: var(--texto-chico);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-accent);
}

.grilla-campos > .grupo-titulo,
.form-grid > .grupo-titulo {
  grid-column: 1 / -1;
}

/* Separador entre tramos de un formulario largo: una linea fina arriba del
   grupo, no un borde de caja. Se pone en el `.grupo-titulo` que abre el tramo
   -- salvo el primero, que no separa de nada. */
.grilla-campos > .grupo-titulo.separa,
.form-grid > .grupo-titulo.separa {
  margin-top: 6px;
  padding-top: 18px;
  border-top: 1px solid var(--color-border);
}

/* ========================================================================= */
/* ESTADO VACIO -- una tabla sin filas tiene que DECIR que no hay nada        */
/* ========================================================================= */
/* Hoy, cuando no hay datos, quedan los encabezados de la tabla flotando sobre
   la nada: en Retiros eso es ~70 % de la pantalla en blanco, y en Estantes
   ~65 % -- con cero estantes cargados en produccion, o sea que es lo que ve
   alguien la primera vez que entra. Para el que recien empieza, una tabla
   vacia y una tabla rota se ven exactamente igual.

   COMO SE USA -- dentro de una tabla:

     <tr class="fila-vacia"><td colspan="7">
       <div class="vacio">
         <div class="vacio-icono"><i class="fa-solid fa-box-open"></i></div>
         <p class="vacio-titulo">Todavia no hay retiros</p>
         <p class="vacio-texto">Cuando alguien pase a buscar un paquete y lo
            registres aca, te va a aparecer en esta lista.</p>
         <div class="vacio-accion"><button>Registrar un retiro</button></div>
       </div>
     </td></tr>

   -- y suelta, fuera de una tabla, agregandole `.en-tarjeta`:

     <div class="vacio en-tarjeta"> ... lo mismo ... </div>

   Reglas de redaccion (el test de lenguaje las hace cumplir): el titulo dice
   QUE no hay, el texto dice QUE HACER para que haya. Nunca "sin resultados",
   nunca un id ni un nombre de tabla. Un filtro que no encuentra nada NO es lo
   mismo que una tabla vacia: ahi el texto tiene que ofrecer limpiar el filtro.

   `.vacio-icono` y `.vacio-accion` son opcionales; titulo y texto no. */

.vacio {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 40px 20px;
  text-align: center;
  color: var(--color-text-dim);
}

.vacio.compacto {
  padding: 22px 16px;
}

/* Suelto, fuera de una tabla: se le da superficie propia para que no parezca
   que la pantalla se corto a la mitad. */
.vacio.en-tarjeta {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: var(--card-radius);
  box-shadow: var(--shadow-sm);
}

/* El circulo punteado dice "acá va a haber algo" sin gritar que falta algo:
   borde discontinuo, gris, nunca rojo ni un triangulo de advertencia. Una
   lista vacia es un estado NORMAL del negocio -- mismo criterio que el Cliente
   con perfil incompleto (CLAUDE.md seccion 11). */
.vacio-icono {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  margin-bottom: 4px;
  border-radius: 50%;
  border: 1px dashed var(--color-border-strong);
  background: var(--color-surface-sunken);
  color: var(--color-text-dim);
  font-size: var(--texto-titulo);
}

.vacio-titulo {
  margin: 0;
  font-size: var(--texto-grande);
  font-weight: 700;
  color: var(--color-heading);
}

.vacio-texto {
  margin: 0;
  /* En ch y no en px: el limite real de una linea comoda es la cantidad de
     caracteres, no los pixeles. */
  max-width: 52ch;
  font-size: var(--texto-base);
  line-height: 1.5;
  color: var(--color-text-dim);
}

.vacio-accion {
  margin-top: 10px;
}

/* La fila vacia adentro de una tabla densa: sin el rayado ni el hover de las
   filas de datos (no es una fila que se pueda elegir) y sin el `white-space:
   nowrap` que la tabla le pone a cada celda, que le impediria al texto cortar
   en varias lineas. */
table.tabla-densa tr.fila-vacia:hover,
table.tabla-densa tr.fila-vacia td {
  background: var(--card-bg);
}
/* Variante de error: mismo lugar, tono del aviso de error. */
.vacio.error .vacio-titulo {
  color: var(--color-danger);
}

table.tabla-densa tr.fila-vacia td,
table.tabla-densa td.celda-vacia {
  padding: 0;
  white-space: normal;
  border-bottom: none;
}

/* ========================================================================= */
/* LAYOUT DE TRABAJO -- el formulario a un lado, lo que hay al otro           */
/* ========================================================================= */
/* La otra mitad del "deja un monton en blanco": Retiros es una tarjeta de DOS
   campos sola arriba de una tabla; Facturas USA mete el emisor -- que bloquea
   toda la facturacion -- en una columna de 380 px con el 70 % vacio al lado.
   Cuando una pantalla es "un formulario chico + una lista", los dos entran uno
   al lado del otro y se ven juntos, que es como se trabaja de verdad: cargar y
   ver lo cargado sin scrollear.

     <div class="columnas-trabajo">
       <section> el formulario </section>
       <section> la tabla </section>
     </div>

   `.pareja` los hace iguales; `.angosta-a-la-derecha` invierte cual es el
   chico. Abajo de 1000 px se apilan solos. */
.columnas-trabajo {
  display: grid;
  grid-template-columns: minmax(320px, 400px) minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}
.columnas-trabajo.pareja {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.columnas-trabajo.angosta-a-la-derecha {
  grid-template-columns: minmax(0, 1fr) minmax(320px, 400px);
}

/* Pantalla grande (la del duenio es de 2560): la columna del formulario
   crece hasta 600 px, que es donde entran DOS campos por renglon. Con 400 iba
   uno solo y un formulario de seis campos quedaba mas alto que la pantalla. */
@media (min-width: 1600px) {
  .columnas-trabajo {
    grid-template-columns: minmax(380px, 600px) minmax(0, 1fr);
  }
  .columnas-trabajo.angosta-a-la-derecha {
    grid-template-columns: minmax(0, 1fr) minmax(380px, 600px);
  }
}

@media (max-width: 1000px) {
  .columnas-trabajo,
  .columnas-trabajo.pareja,
  .columnas-trabajo.angosta-a-la-derecha {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* El resultado de mover bultos: uno por renglon, lo que fallo en rojo. */
.resultado-mover {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  font-size: var(--texto-base);
}
.resultado-mover li {
  padding: 3px 0;
  border-bottom: 1px solid var(--color-border);
}
.resultado-mover li.no_encontrado,
.resultado-mover li.no_se_puede {
  color: var(--color-danger);
}

/* Dos tarjetas de trabajo lado a lado (buscar | dar de alta). Abajo de
   1200 px se apilan. */
.dos-tarjetas {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 14px;
  margin-bottom: 14px;
  align-items: start;
}
@media (min-width: 1200px) {
  .dos-tarjetas {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  }
}

/* Auditoria: el detalle corta en varias lineas en vez de estirar la tabla. */
table.tabla-densa td.detalle-auditoria {
  white-space: normal;
  min-width: 320px;
  color: var(--color-text-dim);
  font-size: var(--texto-chico);
}

/* El logo del login: el ancho ocupa el renglon; el redondo, un circulo. */
img.logo-login {
  display: inline-block;
  width: 100%;
  max-width: 210px;
  height: auto;
}
img.logo-login.logo-redondo {
  max-width: 120px;
}

/* ---------------------------------------------------------------------------
   Pestañas (Inventario, Publicación, Pedidos del Portal).
   Una sola pieza: antes cada pantalla tenia la suya con otro nombre y otras
   medidas. La activa va en azul CLARO con el borde azul, no en el azul lleno:
   ese es el de la accion principal, y con los dos iguales uno lado del otro
   no se sabia que era "donde estoy" y que era "que hago".
   --------------------------------------------------------------------------- */
.subtabs,
.filtro-estados {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 14px;
}
.subtabs a,
.filtro-estados button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border-radius: 8px;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-dim);
  font-size: var(--texto-base);
  font-weight: 600;
  text-decoration: none;
  box-shadow: none;
}
.subtabs a:hover,
.filtro-estados button:hover:not(:disabled):not([aria-pressed="true"]) {
  background: var(--color-surface);
  border-color: var(--color-border-strong);
  color: var(--color-text);
  box-shadow: none;
}
.subtabs a.activo,
.subtabs a.activo:hover,
.filtro-estados button[aria-pressed="true"],
.filtro-estados button[aria-pressed="true"]:hover {
  background: color-mix(in srgb, var(--color-accent) 12%, var(--color-bg-elevated));
  border-color: var(--color-accent);
  color: var(--color-accent-hover);
  font-weight: 700;
}

/* ---------------------------------------------------------------------------
   Piezas de texto que se repetian con otro nombre en cada pantalla.
   El nombre canonico va primero; los demas son alias de pantallas viejas.
   --------------------------------------------------------------------------- */

/* El parrafo que explica la pantalla, debajo del titulo. */
.bajada,
.intro-pantalla,
.explicacion {
  margin: -6px 0 18px;
  max-width: 80ch;
  color: var(--color-text-dim);
  font-size: var(--texto-base);
  line-height: 1.5;
}

/* La nota chica debajo de un campo o de una fila de botones. */
.nota-ayuda,
.ayuda-campo,
.guias-ayuda,
.guias-nota {
  margin: 4px 0 10px;
  color: var(--color-text-dim);
  font-size: var(--texto-chico);
  line-height: 1.45;
}

/* Un dato que esta pero no importa ahora ("sin estante", "-", la fecha
   secundaria). Gris legible, nunca el de un error. */
.dato-tenue,
.dato-vacio,
.celda-tenue,
.dato-apagado,
.apagado {
  color: var(--color-text-dim);
}

/* Titulo de una lista con su contador al lado. */
.cabecera-lista,
.tabla-cabecera {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  margin: 2px 0 8px;
}

/* ---------------------------------------------------------------------------
   Desplegable propio (js/controles.js).
   El <select> sigue existiendo, escondido: es la fuente del valor. Esto lo
   dibuja. La lista que se abre es nuestra y no la de Windows: se puede
   buscar, se ve igual en todos lados y se maneja con el teclado.
   --------------------------------------------------------------------------- */
.desplegable {
  position: relative;
  display: inline-block;
  min-width: 10rem;
  max-width: 100%;
  vertical-align: middle;
}
.campo .desplegable,
.grilla-campos .desplegable,
.form-grid .desplegable {
  display: block;
  width: 100%;
}
.desplegable-nativo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  pointer-events: none;
}
.desplegable-boton {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  min-height: 40px;
  padding: 9px 12px;
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: 8px;
  box-shadow: none;
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: 0.9rem;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.desplegable-boton:hover:not(:disabled) {
  background: var(--input-bg);
  border-color: var(--base-slate-400);
  box-shadow: none;
}
.desplegable-boton:focus-visible,
.desplegable-boton[aria-expanded="true"] {
  outline: none;
  border-color: var(--color-focus);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-focus) 18%, transparent);
}
.desplegable-boton:disabled {
  background: var(--base-slate-100);
  color: var(--color-text-faint);
  border-color: var(--color-border);
  cursor: not-allowed;
}
.desplegable-boton[data-mono] .desplegable-texto {
  font-family: var(--font-mono);
}
.desplegable-texto {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.desplegable-boton.vacio-elegido .desplegable-texto {
  color: var(--color-text-dim);
}
.desplegable-flecha {
  flex-shrink: 0;
  width: 7px;
  height: 7px;
  margin: -3px 2px 0 0;
  border-right: 2px solid var(--color-text-dim);
  border-bottom: 2px solid var(--color-text-dim);
  transform: rotate(45deg);
  transition: transform 0.15s ease;
}
.desplegable-boton[aria-expanded="true"] .desplegable-flecha {
  margin-top: 3px;
  transform: rotate(-135deg);
}

.desplegable-panel {
  position: fixed;
  z-index: 1000;
  max-width: min(420px, calc(100vw - 16px));
  max-height: 340px;
  display: flex;
  flex-direction: column;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: 10px;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  animation: desplegable-entra 0.12s ease-out;
}
@keyframes desplegable-entra {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .desplegable-panel { animation: none; }
}
.desplegable-buscar {
  margin: 8px;
  padding: 8px 10px;
  font-size: var(--texto-base);
}
.desplegable-lista {
  list-style: none;
  margin: 0;
  padding: 4px;
  overflow-y: auto;
}
.desplegable-lista [role="option"] {
  padding: 8px 10px;
  border-radius: 6px;
  font-size: var(--texto-base);
  color: var(--color-text);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.desplegable-lista [role="option"].vacia {
  color: var(--color-text-dim);
}
.desplegable-lista [role="option"].resaltada {
  background: color-mix(in srgb, var(--color-accent) 10%, var(--color-bg-elevated));
}
.desplegable-lista [role="option"].elegida {
  font-weight: 700;
  color: var(--color-accent-hover);
}
.desplegable-lista [role="option"].elegida::after {
  content: "✓";
  float: right;
  margin-left: 12px;
}
.desplegable-lista [role="option"][aria-disabled="true"] {
  color: var(--color-text-faint);
  cursor: not-allowed;
}
.desplegable-grupo {
  padding: 8px 10px 4px;
  font-size: var(--texto-micro);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-dim);
}
.desplegable-nada {
  padding: 10px;
  font-size: var(--texto-base);
  color: var(--color-text-dim);
}

/* --- La barra angosta de las pantallas de mostrador (28/09/2026) ----------
   Cargas, Guias, Agrupar y Paletizado no llevan el menu completo (le roba
   lugar al trabajo) y tenian una casita "Inicio" pegada al titulo. El dueño
   pidio "una version solo con logos": es el "navigation rail" de Material
   Design 3. Vive aca y no en shell.css porque esas pantallas no cargan
   shell.css (o lo cargan solo para la tabla del manifiesto). Los colores son
   los del menu completo: el amarillo sigue significando "estas aca". */
body.con-riel {
  padding-left: 60px;
}

.riel {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: 60px;
  z-index: 30;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 10px 0 12px;
  background: var(--sidebar-bg);
  overflow-y: auto;
  scrollbar-width: none;
}

.riel-marca {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-bottom: 6px;
  border-radius: 50%;
  flex-shrink: 0;
}

.riel-marca img {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  object-fit: contain;
  background: var(--base-white);
}

/* El logo ANCHO (ShipAirGlobal) se invierte como en el menu completo. */
.riel-marca.logo-ancho img {
  width: 44px;
  height: auto;
  border-radius: 0;
  background: none;
  filter: brightness(0) invert(1);
}

.riel-grupo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  width: 100%;
  padding: 6px 0;
  border-top: 1px solid var(--color-dark-border);
}

.riel-item {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 36px;
  flex-shrink: 0;
  border-radius: 8px;
  color: var(--color-dark-text-dim);
  text-decoration: none;
  font-size: var(--texto-base);
  transition: background 0.12s ease, color 0.12s ease;
}

.riel-item:hover {
  background: var(--color-dark-hover);
  color: var(--color-dark-text);
}

.riel-item.activo {
  background: var(--base-yellow);
  color: var(--base-navy-deep);
}

.riel-item:focus-visible,
.riel-marca:focus-visible {
  outline: 2px solid var(--base-yellow);
  outline-offset: 2px;
}

.riel-tip {
  position: fixed;
  z-index: 1000;
  padding: 5px 10px;
  border-radius: 6px;
  background: var(--base-navy-deep);
  color: var(--base-white);
  font-size: var(--texto-chico);
  font-weight: 600;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: var(--shadow-sm);
}

.riel-tip[hidden] {
  display: none;
}

@media (max-width: 560px) {
  body.con-riel {
    padding-left: 48px;
  }
  .riel {
    width: 48px;
  }
  .riel-item {
    width: 36px;
    height: 34px;
  }
}

@media print {
  .riel,
  .riel-tip {
    display: none;
  }
  body.con-riel {
    padding-left: 0;
  }
}
