/* ─────────────────────────────────────────────────────────────────────────────
   estilo.css — Campoamor. Vanilla, sin build y sin dependencias externas.

   La paleta y las formas salen de frontend_demo/index.html, que es la
   especificación de UX. Lo que NO se hereda del demo es la tipografía: aquella
   pedía 'DM Sans' a fonts.googleapis.com, y esta caja vive en una LAN sin
   salida garantizada — una fuente que no carga es medio segundo de página en
   blanco por cada pantalla. Se usa la pila del sistema.
   ───────────────────────────────────────────────────────────────────────────── */

:root {
  --campoamor: #6B1530; --campoamor-claro: #8B1F40; --campoamor-palo: #F9EEF1;
  --dorado: #F08C14;
  --negro: #1A0A0D;
  --verde: #1A7A4A; --verde-palo: #E6F4ED;
  --ambar: #B85F0A; --ambar-palo: #FDF2E6;
  --morado: #7B2D8B; --morado-palo: #F5EDF8;
  --rojo: #C0392B; --rojo-palo: #FEF5F5; --rojo-borde: #F5C0C0;
  --gris-50: #F7F8FA; --gris-100: #EDEEF2; --gris-200: #D8DAE2;
  --gris-400: #9299A8; --gris-600: #555E70; --gris-900: #1A1D26;
  --radio: 10px;
  --sombra: 0 1px 3px rgba(0,0,0,.08), 0 1px 2px rgba(0,0,0,.04);
  --fuente: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: var(--fuente); background: var(--gris-50); color: var(--gris-900);
       min-height: 100vh; -webkit-text-size-adjust: 100%; }
[hidden] { display: none !important; }
button, input, select, textarea { font: inherit; }

/* ── LOGIN ─────────────────────────────────────────────────────────────────── */
#pantallaLogin { display: flex; align-items: center; justify-content: center;
  min-height: 100vh; background: var(--negro); padding: 20px; }
.caja-login { background: #fff; border-radius: 16px; padding: 36px 32px;
  width: 100%; max-width: 360px; box-shadow: 0 8px 32px rgba(0,0,0,.3); }
.login-logo { text-align: center; margin-bottom: 28px; }
.login-logo svg { width: 52px; height: 52px; }
.login-titulo { font-size: 20px; font-weight: 600; margin-top: 12px; }
.login-sub { font-size: 13px; color: var(--gris-400); margin-top: 4px; }
.campo { margin-bottom: 14px; }
.campo label { display: block; font-size: 12px; font-weight: 600; color: var(--gris-600);
  margin-bottom: 6px; text-transform: uppercase; letter-spacing: .5px; }
.campo input { width: 100%; height: 44px; padding: 0 14px; font-size: 15px;
  border: 1.5px solid var(--gris-200); border-radius: 8px; outline: none;
  transition: border-color .15s; }
.campo input:focus { border-color: var(--campoamor); }
.btn-login { width: 100%; height: 46px; margin-top: 8px; background: var(--campoamor);
  color: #fff; border: 0; border-radius: 8px; font-size: 15px; font-weight: 600;
  cursor: pointer; transition: background .15s; }
.btn-login:hover { background: var(--campoamor-claro); }
.btn-login:disabled { background: var(--gris-400); cursor: not-allowed; }
.login-error { margin-top: 10px; padding: 10px 14px; background: var(--rojo-palo);
  border: 1px solid var(--rojo-borde); border-radius: 8px; font-size: 13px;
  color: var(--rojo); display: none; }
.login-error.visible { display: block; }

/* ── CABECERA ──────────────────────────────────────────────────────────────── */
header { background: var(--negro); padding: 0 16px; display: flex; align-items: center;
  gap: 16px; height: 54px; position: sticky; top: 0; z-index: 200; }
.logo { display: flex; align-items: center; gap: 10px; }
.logo svg { width: 30px; height: 30px; }
.logo-texto { font-size: 15px; font-weight: 600; color: #fff; }
.logo-sub { font-size: 11px; color: rgba(255,255,255,.45); }
/* 🔴 `min-width: 0` NO es decorativo: sin él, `overflow-x` de aquí abajo no
   hace NADA. Un flex item no se encoge por debajo del ancho de su contenido
   (min-width: auto es el defecto), así que la barra empujaba la cabecera y la
   página entera se desplazaba en horizontal en vez de desplazarse ella. Con
   siete pestañas eso pasa mucho antes que en un móvil: pasa en un PC con la
   ventana a media pantalla, que es como se usa esto de verdad.
   La barra de scroll se esconde —queda fea sobre el negro— pero el arrastre y
   la rueda siguen funcionando. */
.pestanas { display: flex; gap: 4px; margin-left: auto; min-width: 0;
  overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none; }
.pestanas::-webkit-scrollbar { display: none; }
/* Que no se estrujen: antes de deformarse, que la barra se desplace. */
.pestana { padding: 6px 12px; border-radius: 7px; font-size: 13px; text-decoration: none;
  color: rgba(255,255,255,.6); white-space: nowrap; flex-shrink: 0; }
/* Y el logo cede primero: es lo único de la cabecera que no se pulsa. */
.logo { flex-shrink: 0; }
/* El texto va en su propio span para poder esconderlo en móvil sin perderlo:
   el nombre sigue en el title y en el aria-label. */
.pestana-texto { margin-left: 5px; }
.pestana:hover { background: rgba(255,255,255,.1); color: #fff; }
.pestana.activa { background: rgba(255,255,255,.16); color: #fff; font-weight: 600; }
.cabecera-dcha { display: flex; align-items: center; gap: 8px;
  flex-shrink: 0; white-space: nowrap; }
.usuario-chip { font-size: 12px; color: rgba(255,255,255,.6); background: rgba(255,255,255,.08);
  border: 0; border-radius: 6px; padding: 6px 10px; cursor: pointer; transition: background .15s; }
.usuario-chip:hover { background: rgba(255,255,255,.15); }
.usuario-chip strong { color: #fff; }
.btn-icono { position: relative; background: rgba(255,255,255,.1); border: 0; border-radius: 8px;
  color: #fff; width: 38px; height: 38px; font-size: 18px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; transition: background .15s; }
.btn-icono:hover { background: rgba(255,255,255,.2); }
.badge { position: absolute; top: -4px; right: -4px; background: #E8401C; color: #fff;
  font-size: 10px; font-weight: 700; min-width: 16px; height: 16px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center; padding: 0 3px; }

/* ── BÚSQUEDA Y FILTROS ────────────────────────────────────────────────────── */
.barra-busqueda { background: #fff; border-bottom: 1px solid var(--gris-100);
  padding: 10px 16px; position: sticky; top: 54px; z-index: 190; }
.busqueda-inner { max-width: 820px; margin: 0 auto; position: relative; }
.lupa { position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  color: var(--gris-400); font-size: 15px; pointer-events: none; }
#busqueda { width: 100%; height: 42px; padding: 0 40px; font-size: 14px;
  background: var(--gris-50); border: 1.5px solid var(--gris-200); border-radius: 21px;
  outline: none; transition: border-color .15s; -webkit-appearance: none; }
#busqueda:focus { border-color: var(--campoamor); background: #fff; }
/* Chromium pinta su propia ✕ en los input[type=search]; con la nuestra salían
   dos, pegadas. Se quita la del navegador, no la nuestra: la nuestra además
   relanza la búsqueda. */
#busqueda::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.btn-limpiar { position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  width: 22px; height: 22px; border-radius: 50%; background: var(--gris-200); border: 0;
  cursor: pointer; font-size: 12px; color: var(--gris-600); line-height: 1; }

.barra-filtros { background: #fff; border-bottom: 1px solid var(--gris-100); padding: 0 16px 10px; }
.filtros-inner { max-width: 820px; margin: 0 auto; display: flex; gap: 8px;
  flex-wrap: wrap; align-items: center; }
.filtro { height: 32px; padding: 0 10px; font-size: 13px; color: var(--gris-900);
  background: var(--gris-50); border: 1.5px solid var(--gris-200); border-radius: 8px;
  outline: none; max-width: 210px; }
.filtro:focus { border-color: var(--campoamor); }
.filtro-check { font-size: 12px; color: var(--gris-600);
  display: flex; align-items: center; gap: 6px; }
.filtro-reset { height: 32px; padding: 0 10px; font-size: 12px; background: none;
  border: 0; color: var(--campoamor); cursor: pointer; }

.conteo { max-width: 820px; margin: 0 auto; padding: 10px 16px 0; font-size: 12px;
  color: var(--gris-400); }
.conteo strong { color: var(--campoamor); }

/* ── LISTA Y TARJETAS DE PRODUCTO ──────────────────────────────────────────── */
/* OJO con el nombre: .lista es el CONTENEDOR de resultados de búsqueda, con su
   padding de 100px abajo. Las cestas de la consolidación tuvieron un rato la
   clase de estado «lista» y heredaron todo esto sin que nadie lo pidiera:
   flex, gap y un pie de 100px de aire dentro de la tarjeta. Los estados de
   cesta van prefijados (.est-lista, .est-consolidando) justo por eso. */
.lista { max-width: 820px; margin: 0 auto; padding: 8px 16px 100px;
  display: flex; flex-direction: column; gap: 8px; }
.producto { background: #fff; border: 1px solid var(--gris-100); border-radius: var(--radio);
  box-shadow: var(--sombra); display: flex; align-items: center; gap: 12px; padding: 12px 14px; }
.producto:hover { border-color: var(--gris-200); }
.hueco-img { width: 52px; height: 52px; min-width: 52px; background: var(--gris-100);
  border-radius: 8px; display: flex; align-items: center; justify-content: center;
  font-size: 20px; color: var(--gris-400); overflow: hidden; }
/* `contain` y no `cover`: las fotos del distribuidor van de un bolígrafo muy
   estrecho a un puzle apaisado, y recortar al cuadrado deja al boli en una raya
   negra sin forma. Cabe entera aunque sobre fondo. */
.hueco-img img { width: 100%; height: 100%; object-fit: contain; display: block; }
.producto-info { flex: 1; min-width: 0; }
.producto-nombre { font-size: 14px; font-weight: 600; line-height: 1.3; margin-bottom: 3px; }
.producto-meta { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.etiqueta-ean { font-size: 11px; font-family: var(--mono); color: var(--gris-400); }
.etiqueta { font-size: 11px; font-weight: 500; padding: 1px 7px; border-radius: 4px; }
.etiqueta.marca { background: var(--gris-100); color: var(--gris-600); }
/* La marca se pincha para filtrar por ella: que se note que es pulsable, sin
   convertirla en un boton — sigue siendo sobre todo un dato del articulo. */
.etiqueta.marca-pinchable { cursor: pointer; }
.etiqueta.marca-pinchable:hover { background: var(--campoamor-palo); color: var(--campoamor); }
/* El desplegable de marca lleva el conteo dentro de la opción («SAFTA (5.537)»),
   así que necesita más caja que los otros filtros; y tope, para que una casa de
   nombre largo no empuje la fila entera. Se encoge (min-width: 0) porque es un
   hijo flex y sin eso no baja de su contenido — el fallo que desbordó la barra
   de incidencias a lo ancho el 21-ago. */
#filtroMarca { max-width: 240px; min-width: 0; }
.etiqueta.familia { background: var(--campoamor-palo); color: var(--campoamor); }
.etiqueta.urgente { background: var(--rojo-palo); color: var(--rojo); }
.etiqueta.normal { background: var(--gris-100); color: var(--gris-600); }
.etiqueta.diferible { background: var(--ambar-palo); color: var(--ambar); }
.precio { font-size: 13px; font-weight: 600; color: var(--gris-900); white-space: nowrap; }
.precio small { font-weight: 400; color: var(--gris-400); }
.precio.sin { color: var(--gris-400); font-weight: 400; font-size: 12px; }

/* ── Sin existencias ─────────────────────────────────────────────────────── */
/* El 30% del catalogo son articulos que los proveedores listan pero hoy no
   tienen. Se esconden por defecto; cuando se piden, tienen que cantar. */
.producto.agotado { opacity: .82; background: #FFFBFB; }
.etiqueta.sin-existencias { background: var(--rojo-palo); color: var(--rojo);
  border: 1px solid var(--rojo-borde); font-weight: 700; }
.aviso-agotados { margin-left: 10px; padding: 2px 8px; font-size: 11px;
  font-weight: 600; border: 1px solid var(--gris-200); border-radius: 999px;
  background: #fff; color: var(--gris-600); cursor: pointer; }
.aviso-agotados:hover { border-color: var(--campoamor); color: var(--campoamor); }

.producto-accion { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.paso { display: flex; align-items: center; border: 1.5px solid var(--gris-200);
  border-radius: 8px; overflow: hidden; }
.paso button { width: 30px; height: 30px; border: 0; background: #fff; cursor: pointer;
  font-size: 16px; color: var(--campoamor); font-weight: 600; line-height: 1; }
.paso button:hover { background: var(--campoamor-palo); }
.paso input { width: 44px; height: 30px; border: 0; text-align: center; font-family: var(--mono);
  font-size: 13px; font-weight: 600; outline: none; -moz-appearance: textfield; }
.paso input::-webkit-outer-spin-button, .paso input::-webkit-inner-spin-button {
  -webkit-appearance: none; margin: 0; }
.prioridad-linea { height: 30px; padding: 0 6px; font-size: 12px; color: var(--gris-600);
  background: var(--gris-50); border: 1.5px solid var(--gris-200); border-radius: 8px;
  outline: none; cursor: pointer; }
.prioridad-linea:focus { border-color: var(--campoamor); }

.btn-anadir { height: 34px; padding: 0 12px; border-radius: 8px; background: var(--campoamor);
  border: 0; color: #fff; font-size: 13px; font-weight: 600; cursor: pointer;
  transition: background .15s; white-space: nowrap; }
.btn-anadir:hover { background: var(--campoamor-claro); }
.btn-anadir:disabled { background: var(--gris-400); cursor: not-allowed; }

/* ── ESTADOS VACÍOS ────────────────────────────────────────────────────────── */
.vacio { text-align: center; padding: 48px 24px; color: var(--gris-400); }
.vacio-icono { font-size: 34px; margin-bottom: 10px; }
.vacio-titulo { font-size: 15px; font-weight: 600; color: var(--gris-600); margin-bottom: 4px; }
.vacio p { font-size: 13px; max-width: 380px; margin: 0 auto; line-height: 1.5; }

/* ── PANEL LATERAL (cesta) ─────────────────────────────────────────────────── */
.velo { position: fixed; inset: 0; background: rgba(0,0,0,.45); z-index: 300; }
.panel { position: fixed; top: 0; right: 0; bottom: 0; width: min(420px, 100%);
  background: #fff; z-index: 301; display: flex; flex-direction: column;
  box-shadow: -4px 0 24px rgba(0,0,0,.18); }
.panel-cabecera { display: flex; justify-content: space-between; align-items: flex-start;
  padding: 16px; border-bottom: 1px solid var(--gris-100); }
.panel-titulo { font-size: 16px; font-weight: 600; }
.panel-sub { font-size: 12px; color: var(--gris-400); margin-top: 2px; }
.panel-cerrar { background: var(--gris-100); border: 0; border-radius: 8px; width: 32px;
  height: 32px; cursor: pointer; font-size: 14px; color: var(--gris-600); }
.panel-cuerpo { flex: 1; overflow-y: auto; padding: 12px 16px; }
.panel-pie { border-top: 1px solid var(--gris-100); padding: 12px 16px;
  background: var(--gris-50); font-size: 13px; }
.linea-cesta { display: flex; gap: 10px; align-items: center; padding: 10px 0;
  border-bottom: 1px solid var(--gris-100); }
.linea-cesta:last-child { border-bottom: 0; }
.linea-info { flex: 1; min-width: 0; }
.linea-nombre { font-size: 13px; font-weight: 600; line-height: 1.3; }
.linea-nombre.huerfana { color: var(--ambar); }
.linea-meta { font-size: 11px; color: var(--gris-400); display: flex; gap: 6px;
  align-items: center; flex-wrap: wrap; margin-top: 2px; }
.linea-cant { font-family: var(--mono); font-size: 13px; font-weight: 600; }
.btn-borrar { background: none; border: 0; color: var(--gris-400); cursor: pointer;
  font-size: 15px; padding: 4px; border-radius: 6px; }
.btn-borrar:hover { background: var(--rojo-palo); color: var(--rojo); }
.total-linea { display: flex; justify-content: space-between; align-items: baseline; }
.total-linea strong { font-size: 16px; }

/* ── VISTA ALMACÉN ─────────────────────────────────────────────────────────── */
.almacen-cabecera { max-width: 900px; margin: 0 auto; padding: 20px 16px 8px;
  display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }
.almacen-cabecera h1 { font-size: 20px; font-weight: 600; }
.almacen-cabecera .sub { font-size: 13px; color: var(--gris-400); margin-top: 3px;
  max-width: 520px; line-height: 1.45; }
.almacen-cuerpo { max-width: 900px; margin: 0 auto; padding: 8px 16px 100px;
  display: flex; flex-direction: column; gap: 14px; }

.aviso-modo { max-width: 900px; margin: 8px auto 0; padding: 10px 14px; border-radius: var(--radio);
  font-size: 13px; line-height: 1.45; }
.aviso-modo.ensayo { background: var(--gris-100); color: var(--gris-600);
  border: 1px solid var(--gris-200); }
.aviso-modo.armada { background: var(--ambar-palo); color: var(--ambar);
  border: 1px solid #F5C88A; font-weight: 600; }
.aviso-modo.demo { background: var(--morado-palo); color: var(--morado);
  border: 1px solid #D8B4E2; font-weight: 600; }

.cesta-dist { background: #fff; border: 1px solid var(--gris-100); border-radius: var(--radio);
  box-shadow: var(--sombra); overflow: hidden; }
.cesta-dist.cruza { border-color: var(--verde); }
.cesta-cabecera { display: flex; justify-content: space-between; align-items: center;
  gap: 12px; padding: 14px 16px; border-bottom: 1px solid var(--gris-100); flex-wrap: wrap; }
.cesta-nombre { font-size: 15px; font-weight: 600; }
.cesta-datos { font-size: 12px; color: var(--gris-400); margin-top: 2px; }
.estado { font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 4px;
  text-transform: uppercase; letter-spacing: .4px; }
.estado.est-lista { background: var(--verde-palo); color: var(--verde); }
.estado.est-consolidando { background: var(--ambar-palo); color: var(--ambar); }
.cesta-total { font-size: 18px; font-weight: 700; }
.tabla { width: 100%; border-collapse: collapse; font-size: 13px; }
.tabla th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .4px;
  color: var(--gris-400); font-weight: 600; padding: 8px 16px; background: var(--gris-50);
  border-bottom: 1px solid var(--gris-100); }
.tabla td { padding: 8px 16px; border-bottom: 1px solid var(--gris-100); vertical-align: middle; }
.tabla tr:last-child td { border-bottom: 0; }
.tabla td.num { text-align: right; font-family: var(--mono); white-space: nowrap; }
.tabla .nombre-art { font-weight: 600; }
.tabla .ean-mini { font-family: var(--mono); font-size: 11px; color: var(--gris-400); }
.cant-edit { width: 62px; height: 30px; text-align: right; font-family: var(--mono);
  font-size: 13px; border: 1.5px solid var(--gris-200); border-radius: 6px; padding: 0 6px;
  outline: none; }
.cant-edit:focus { border-color: var(--campoamor); }
.cant-edit.guardando { border-color: var(--dorado); }
.cesta-pie { display: flex; justify-content: flex-end; gap: 8px; align-items: center;
  padding: 12px 16px; background: var(--gris-50); border-top: 1px solid var(--gris-100);
  flex-wrap: wrap; }
/* ── Cesta de la tienda: borrador vs enviado ─────────────────────────────── */
/* Lo enviado se apaga un poco: sigue ahi para consultarlo, pero ya no es una
   tarea de la dependienta. No se esconde, que entonces no sabria que paso. */
.linea-cesta.enviada { opacity: .72; }
.separador-cesta { font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--gris-400); padding: 14px 0 6px;
  border-top: 1px solid var(--gris-100); margin-top: 10px; }
.paso-cesta { flex-shrink: 0; }
.paso-cesta button { width: 26px; height: 26px; font-size: 14px; }
.paso-cesta input { width: 38px; height: 26px; font-size: 12px; }
/* «No lo tiene nadie» va en ambar: no es un fallo, es una respuesta, y ademas
   es lo unico que la tienda puede resolver por su cuenta (quitandolo). */
.etiqueta.sin-proveedor { background: #FFFBEB; color: #92400E;
  border: 1px solid #FDE68A; font-weight: 600; }
.etiqueta.enviada { background: var(--gris-100); color: var(--gris-600); }
.btn-enviar { width: 100%; height: 42px; margin-top: 10px; border: 0; border-radius: 8px;
  background: var(--campoamor); color: #fff; font-size: 14px; font-weight: 700;
  cursor: pointer; }
.btn-enviar:hover { background: var(--campoamor-claro); }
.btn-enviar:disabled { opacity: .55; cursor: not-allowed; }

/* ── Vista de pedidos de la tienda ───────────────────────────────────────── */
.pedidos-acciones { display: flex; gap: 8px; align-items: center; }
/* De que tienda es la linea. Solo se pinta mirando varias a la vez. */
.etiqueta.tienda-origen { background: var(--campoamor-palo); color: var(--campoamor);
  font-weight: 600; }
.bloque-cabecera { display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; }
.bloque-cuenta { font-size: 12px; color: var(--gris-400); white-space: nowrap; }
/* Un filete de color a la izquierda dice de un vistazo si algo esta parado, en
   curso o hecho, sin tener que leer el titulo. */
.bloque.sit-parado { border-left: 3px solid #B45309; }
.bloque.sit-curso  { border-left: 3px solid var(--gris-200); }
.bloque.sit-hecho  { border-left: 3px solid var(--verde, #15803D); }

/* ── Reparto (bloque 4b) ─────────────────────────────────────────────────── */
/* La casilla y el nombre de la tienda van juntos y se pulsan juntos: es un
   <label>, así que el área de pulsación es el nombre entero y no un cuadradito
   de 13 px, que con el dedo es una pulsación fallida esperando. */
.reparto-tienda { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.reparto-tienda input { width: 18px; height: 18px; cursor: pointer; }
.reparto-tienda h2 { margin-bottom: 0; }
/* Una tienda destildada no se esconde: se apaga. Que siga viéndose es lo que
   dice que su mercancía no se pierde, solo espera a la siguiente hoja. */
.reparto-fuera { opacity: .45; }
.reparto-fuera .linea-cesta { display: none; }
.reparto-detalle { margin-top: 10px; padding-left: 10px;
                   border-left: 2px solid var(--gris-100); }
.reparto-separador { margin-top: 22px; }

/* El editor de «a qué tienda va esto», en las líneas del almacén. */
.reparto-asignar { margin: 0 0 10px 12px; padding-left: 10px;
                   border-left: 2px solid var(--gris-100); }
.reparto-asignar-fila { display: flex; gap: 6px; align-items: center;
                        margin-bottom: 5px; }
.reparto-asignar-fila select { flex: 1 1 auto; min-width: 0; }
.reparto-cantidad { width: 74px; flex: 0 0 auto; }
.reparto-asignar-pie { display: flex; gap: 10px; align-items: center;
                       flex-wrap: wrap; }

/* Lo que el repartidor se lleva. Otro color porque es el gesto contrario, y va
   separado dentro de la misma hoja. */
.recibir-recogidas { margin-top: 12px; padding: 10px 12px; border-radius: 8px;
                     background: #FDF3EE; border: 1px solid #F0D6C6; }
.recibir-recogidas h2 { font-size: 13px; color: #9A3412; }
/* La cantidad, grande: es el número que se lee con la caja delante. */
.linea-cant.grande { font-size: 20px; font-weight: 700; }

/* El «no cuadra» de cada línea. Está SIEMPRE, así que tiene que pesar poco:
   discreto de color y de tamaño, pero con 44 px de alto, que es lo que hace
   falta para acertarle con el dedo. */
.btn-avisar { background: #fff; border: 1px solid var(--gris-100);
              color: var(--gris-400); border-radius: 7px; font-size: 12px;
              padding: 6px 10px; min-height: 44px; cursor: pointer;
              white-space: nowrap; }
.btn-avisar:hover { border-color: #F0D6C6; background: #FDF3EE; color: #9A3412; }

/* ── Aviso de que el reparto cambio ──────────────────────────────────────── */
/* Una barra, no un repintado. La primera version repintaba la pantalla sola cada
   30 s y era inusable: movia la tabla bajo quien trabajaba encima. */
.aviso-cambios { max-width: 900px; margin: 8px auto 0; padding: 8px 14px;
  border-radius: var(--radio); background: var(--campoamor-palo);
  border: 1px solid var(--campoamor); color: var(--campoamor); font-size: 13px;
  display: flex; align-items: center; gap: 10px; }
.aviso-cambios span { margin-right: auto; }
.btn-ver-cambios { height: 28px; padding: 0 12px; border: 0; border-radius: 6px;
  background: var(--campoamor); color: #fff; font-size: 12px; font-weight: 700;
  cursor: pointer; }
.btn-descartar { width: 26px; height: 26px; border: 0; border-radius: 6px;
  background: none; color: var(--campoamor); font-size: 14px; cursor: pointer; }
.btn-descartar:hover { background: rgba(0,0,0,.06); }

/* ── Agrupacion por tienda dentro de cada proveedor ──────────────────────── */
/* Plegado y con las filas construidas solo al abrir: una cesta puede traer
   cientos de lineas y montarlas todas de golpe es lo que hace que la aplicacion
   parezca pesada aunque el backend conteste rapido. */
.grupos-tienda { padding: 4px 0; }
.grupo-tienda { border-top: 1px solid var(--gris-100); }
.grupo-tienda > summary { display: flex; align-items: center; gap: 10px;
  padding: 9px 16px; cursor: pointer; font-size: 13px; list-style: none; }
.grupo-tienda > summary::-webkit-details-marker { display: none; }
.grupo-tienda > summary::before { content: '▸'; color: var(--gris-400);
  font-size: 11px; transition: transform .12s; }
.grupo-tienda[open] > summary::before { transform: rotate(90deg); }
.grupo-tienda > summary:hover { background: var(--gris-50); }
.grupo-cuenta { margin-left: auto; color: var(--gris-400); font-size: 12px; }

/* ── Sin distribuidor: ahora con boton para que Olaya pueda quitarlas ────── */
.sin-asignar-linea { display: flex; align-items: flex-start; gap: 10px; }
.sin-asignar-info { flex: 1; min-width: 0; }

/* ── Sello del ultimo reparto ────────────────────────────────────────────── */
/* Con la pantalla refrescandose sola, "esto es de hace 40 segundos" es
   informacion; "de hace tres horas" es que la tarea del minuto se ha caido. */
.sello-calculo { font-size: 11px; color: var(--gris-400); margin-top: 4px; }
.sello-calculo.viejo { color: #92400E; font-weight: 600; }

/* ── Cantidad editable en consolidacion ──────────────────────────────────── */
/* Hasta el 19-ago no habia forma de saber que quedaba algo por confirmar: el
   campo parecia guardado sin estarlo. Ahora se marca y aparece el boton. */
.cant-caja { display: inline-flex; align-items: center; gap: 4px; }
.cant-edit.pendiente { border-color: #B45309; background: #FFFBEB; }
.btn-confirmar-cant { width: 26px; height: 26px; border: 0; border-radius: 6px;
  background: var(--campoamor); color: #fff; font-size: 13px; font-weight: 700;
  cursor: pointer; line-height: 1; }
.btn-confirmar-cant:hover { background: var(--campoamor-claro); }

.btn-secundario { height: 36px; padding: 0 14px; border-radius: 8px; background: #fff;
  border: 1.5px solid var(--gris-200); color: var(--gris-600); font-size: 13px;
  font-weight: 600; cursor: pointer; }
.btn-secundario:hover { border-color: var(--gris-400); }
/* Forzar el bajo minimo es una decision, no la accion normal: va en secundario y
   en ambar, el mismo color con el que el 409 dice «no procede». No en rojo, que
   es lo irreversible, ni en el color del boton bueno, que invitaria a pulsarlo. */
.btn-forzar { border-color: #B45309; color: #B45309; }
.btn-forzar:hover { border-color: #B45309; background: #FFFBEB; }
/* Boton apagado mientras falte el motivo obligatorio: que se vea que espera algo,
   no que esta roto. */
.btn-disparo:disabled { opacity: .45; cursor: not-allowed; }

.btn-disparo { height: 36px; padding: 0 16px; border-radius: 8px; border: 0; color: #fff;
  font-size: 13px; font-weight: 600; cursor: pointer; background: var(--gris-600); }
.btn-disparo.ensayo { background: var(--gris-600); }
.btn-disparo.ensayo:hover { background: var(--gris-900); }
.btn-disparo.demo { background: var(--morado); }
.btn-disparo.demo:hover { background: #6A2578; }
.btn-disparo.real { background: var(--rojo); }
.btn-disparo.real:hover { background: #A5281B; }
.btn-disparo:disabled { background: var(--gris-400); cursor: not-allowed; }
.selector-modo { height: 36px; padding: 0 8px; font-size: 13px; border-radius: 8px;
  border: 1.5px solid var(--gris-200); background: #fff; }

.bloque { background: #fff; border: 1px solid var(--gris-100); border-radius: var(--radio);
  box-shadow: var(--sombra); padding: 14px 16px; }
.bloque.gris { border-left: 4px solid var(--gris-400); }
.bloque.tecnica { border-left: 4px solid var(--morado); }
.bloque h2 { font-size: 14px; font-weight: 600; margin-bottom: 4px; }
.bloque .sub { font-size: 12px; color: var(--gris-400); margin-bottom: 8px; line-height: 1.45; }
.bloque ul { list-style: none; font-size: 13px; }
.bloque li { padding: 6px 0; border-bottom: 1px solid var(--gris-100); }
.bloque li:last-child { border-bottom: 0; }
.motivo { font-size: 12px; color: var(--ambar); }

/* Resultado del disparo, dentro de la tarjeta del distribuidor. */
.resultado { margin: 0 16px 14px; padding: 12px 14px; border-radius: var(--radio);
  font-size: 13px; line-height: 1.5; }
.resultado.ok { background: var(--verde-palo); border: 1px solid #A9D8BF; color: #14603A; }
.resultado.demo { background: var(--morado-palo); border: 1px solid #D8B4E2;
  color: var(--morado); }
.resultado.noprocede { background: var(--ambar-palo); border: 1px solid #F5C88A; color: var(--ambar); }
.resultado.ambiguo { background: var(--rojo-palo); border: 1px solid var(--rojo-borde); color: var(--rojo); }
.resultado .titulo-res { font-weight: 700; margin-bottom: 4px; }
.resultado dl { display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; margin-top: 6px; }
.resultado dt { color: inherit; opacity: .75; }
.resultado dd { font-family: var(--mono); }

/* ── MODAL ─────────────────────────────────────────────────────────────────── */
.modal { position: fixed; z-index: 301; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: min(480px, calc(100% - 32px)); background: #fff; border-radius: 14px; padding: 20px;
  box-shadow: 0 12px 40px rgba(0,0,0,.3); }
.modal-titulo { font-size: 17px; font-weight: 600; margin-bottom: 10px; }
.modal-cuerpo { font-size: 13px; line-height: 1.5; color: var(--gris-600); }
.modal-cuerpo .resumen { background: var(--gris-50); border-radius: 8px; padding: 10px 12px;
  margin: 10px 0; display: grid; grid-template-columns: auto 1fr; gap: 3px 10px; }
.modal-cuerpo .resumen dd { font-family: var(--mono); color: var(--gris-900); text-align: right; }
/* El bajo minimo NO es rojo: es ambar, como el 409. Rojo es lo irreversible. */
.modal-cuerpo .peligro.bajo-minimo { background: #FFFBEB; border-color: #FDE68A;
  color: #92400E; }
.modal-cuerpo .peligro { background: var(--rojo-palo); border: 1px solid var(--rojo-borde);
  color: var(--rojo); border-radius: 8px; padding: 10px 12px; font-weight: 600; margin: 10px 0; }
.modal-cuerpo label { display: block; font-size: 12px; font-weight: 600; color: var(--gris-600);
  margin: 10px 0 4px; }
.modal-cuerpo textarea { width: 100%; min-height: 60px; padding: 8px 10px; font-size: 13px;
  border: 1.5px solid var(--gris-200); border-radius: 8px; outline: none; resize: vertical;
  font-family: var(--fuente); }
.modal-cuerpo textarea:focus { border-color: var(--campoamor); }
.modal-acciones { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }

/* ── AVISOS (toast) ────────────────────────────────────────────────────────── */
.avisos { position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%);
  z-index: 400; display: flex; flex-direction: column; gap: 8px; align-items: center;
  width: min(520px, calc(100% - 24px)); pointer-events: none; }
.aviso { background: var(--gris-900); color: #fff; padding: 10px 16px; border-radius: 10px;
  font-size: 13px; line-height: 1.4; box-shadow: 0 4px 16px rgba(0,0,0,.25);
  max-width: 100%; pointer-events: auto; }
.aviso.ok { background: var(--verde); }
.aviso.aviso-error { background: var(--rojo); }
.aviso.noprocede { background: var(--ambar); }

/* ── RECEPCIÓN (4a) ────────────────────────────────────────────────────────── */
.tabla-recepcion td { vertical-align: top; }
.tabla-recepcion .cant-edit { width: 56px; }

/* El aviso del proveedor va en GRIS y no en ámbar a propósito: que él avisara
   de que mandaba menos NO es un fallo suyo detectado en el muelle. El ámbar se
   reserva para lo que sí se le reclama. */
.recepcion-anuncio { font-size: 11px; color: var(--gris-600); margin-top: 4px; }

.recepcion-nota { font-size: 11px; margin-top: 4px; min-height: 14px; }
.recepcion-nota.falta { color: #B45309; font-weight: 600; }

/* Rojo solo aquí dentro: un ejemplar roto es pérdida de verdad, a diferencia de
   una diferencia de recuento, que es ámbar. */
.cant-edit.rota { border-color: var(--rojo); background: var(--rojo-palo); }

.recepcion-sobrante { margin-top: 12px; }
.recepcion-sobrante-form { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.recepcion-sobrante-form .filtro { flex: 1 1 180px; }

/* La tabla desliza DENTRO de su bloque; la página nunca se mueve en horizontal. */
.tabla-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* 44 px de alto: esto se usa con el dedo y con prisa, no con el ratón. */
.tabla-recepcion .cant-edit { height: 44px; }
.recepcion-sobrante .btn-secundario { min-height: 44px; }

/* ── El escaneo (la pistola) ───────────────────────────────────────────────── */
/* Sticky arriba: mientras se baja por una lista larga, el campo y el eco tienen
   que seguir a la vista — es donde se lee qué acaba de entrar. */
.recepcion-escaneo { position: sticky; top: 0; z-index: 5; display: flex;
                     align-items: center; gap: 12px; flex-wrap: wrap;
                     padding: 10px 16px; background: var(--gris-50);
                     border-bottom: 1px solid var(--gris-200); }
#codigoEscaneado { flex: 0 0 240px; height: 44px; font-family: var(--mono);
                   font-size: 15px; }

/* La casilla de paquetes, que es donde cae el TAB del lector. Más alta y más
   ancha que el ± del catálogo: aquí se teclea con prisa y a veces con guantes. */
.escaneo-paso { flex: 0 0 auto; }
.escaneo-paso button { width: 40px; height: 44px; font-size: 18px; }
.escaneo-paso input { width: 64px; height: 44px; font-size: 17px; font-weight: 700; }
/* Enfocada, se ve desde el otro lado del muelle: es la señal de «te toca contar». */
.escaneo-paso input:focus { outline: 3px solid var(--campoamor);
                            background: var(--campoamor-palo); }

/* 44 px de alto: se pulsa con el dedo, no con el ratón. */
.escaneo-ok { height: 44px; padding: 0 18px; font-size: 15px; font-weight: 700; }
.escaneo-ok:disabled { background: var(--gris-200); color: var(--gris-600);
                       cursor: default; }
.escaneo-deshacer { height: 44px; }
.escaneo-deshacer:disabled { opacity: .45; cursor: default; }

/* La línea escaneada y a la espera de su cantidad. No está tachada todavía
   —eso solo pasa al confirmar— pero tiene que saltar a la vista para que se vea
   cuál se está contando. */
.tabla-recepcion tr.linea-en-curso { background: var(--campoamor-palo); }
.tabla-recepcion tr.linea-en-curso td:first-child {
  box-shadow: inset 3px 0 0 var(--campoamor); }

/* El eco es la otra mitad del sonido: dice QUÉ acaba de leer la pistola, y es
   lo único que queda cuando el sonido está apagado. */
.escaneo-eco { flex: 1 1 240px; font-size: 13px; min-height: 20px;
               font-weight: 600; }
.escaneo-eco[data-caso="apuntado"]    { color: var(--verde); }
.escaneo-eco[data-caso="contando"]    { color: var(--gris-600); }
.escaneo-eco[data-caso="completo"]    { color: var(--verde); }
/* Ámbar y no rojo: que llegue algo sin pedir es una discrepancia que hay que
   mirar, no una pérdida irreversible. Misma semántica que el 409. */
.escaneo-eco[data-caso="desconocido"] { color: #B45309; }
.escaneo-eco[data-caso="error"]       { color: var(--rojo); }

/* Lo ya contado: tachado y atenuado, pero legible. Se BAJA al segundo tbody, no
   se esconde: lo que se ha contado tiene que poder revisarse. */
.tabla-recepcion tr.linea-escaneada .linea-nombre { text-decoration: line-through; }
.tabla-recepcion tr.linea-escaneada { opacity: .62; }
.tabla-recepcion tbody.recepcion-hechas tr:first-child td { border-top: 2px solid var(--gris-200); }

.recepcion-sobrantes { border-left: 3px solid #B45309; }
/* El aviso de lo que falta por escanear, en el pie. */
.sub.aviso-pendiente { color: #B45309; font-weight: 600; }

/* Mientras recarga se atenúa, no se vacía: ver el porqué en recepcion.js. */
.almacen-cuerpo.cargando { opacity: .55; pointer-events: none; }

.recepcion-pie { position: sticky; bottom: 0; }
.recepcion-resumen { font-size: 13px; color: var(--gris-600); margin-bottom: 8px;
                     font-family: var(--mono); }

/* ── INCIDENCIAS (nivel 2: lo que se le reclama al distribuidor) ──────────── */
/* El contador de la pestaña cuenta lo VIVO —sin reclamar + reclamado—, no lo
   abierto: una incidencia reclamada sigue siendo trabajo hasta que contesten. */
.pestana-cuenta { margin-left: 6px; padding: 0 6px; border-radius: 9px;
  background: var(--ambar); color: #fff; font-size: 11px; font-weight: 700;
  line-height: 17px; display: inline-block; min-width: 17px; text-align: center; }

/* La campanita de las incidencias de tienda. Va en rojo y no en ámbar porque
   dice otra cosa: no es «hay trabajo pendiente», es «hay un bulto parado en la
   tienda equivocada esperando una decisión tuya». Y late, porque Olaya no vive
   en esa pantalla — se entera de esto mientras está en otra.
   Sin animación para quien la haya desactivado en el sistema: un parpadeo que
   no se puede parar es una barrera de accesibilidad, no un aviso. */
.pestana-campana { background: var(--rojo, #C0392B); animation: campana-late 2s ease-in-out infinite; }
@keyframes campana-late {
  0%, 70%, 100% { transform: scale(1); }
  35%           { transform: scale(1.18); }
}
@media (prefers-reduced-motion: reduce) {
  .pestana-campana { animation: none; }
}

.incidencia { align-items: flex-start; }
/* La descripción es el texto que se copia y se pega en la reclamación del
   proveedor: lleva las cantidades y el número de albarán. Por eso se pinta
   entera y en el cuerpo, no recortada en un title. */
.incidencia-descripcion { margin-top: 2px; line-height: 1.45; }
.incidencia-nota { margin-top: 4px; padding-left: 8px; white-space: pre-line;
  border-left: 2px solid var(--gris-200); color: var(--gris-600); }
.incidencia-acciones { display: flex; gap: 6px; align-items: center;
  flex-shrink: 0; flex-wrap: wrap; justify-content: flex-end; }
/* Lo cerrado se atenúa pero NO se esconde: el histórico es la respuesta a «¿en
   qué quedó aquello?», que es la única pregunta que se le hace. */
.incidencia-cerrada { opacity: .6; }

.etiqueta.abierta   { background: var(--rojo-palo); color: var(--rojo); font-weight: 700; }
.etiqueta.reclamada { background: var(--ambar-palo); color: var(--ambar); }
.etiqueta.cerrada   { background: var(--gris-100); color: var(--gris-600); }

.cierre-campo { width: 100%; margin-bottom: 4px; }

/* ── ANCHOS INTERMEDIOS: pantalla partida, ventana sin maximizar ────────────
   Aram, 27-ago: «al ir al móvil o no estando en pantalla completa se cortan».
   El salto de 620 px no cubría esto — a 900 px el texto seguía puesto y con
   SIETE pestañas (Olaya las ve todas) la barra medía más que la cabecera.
   Se sueltan en dos escalones, del elemento menos útil al más útil, para no
   quitar los nombres antes de tiempo: quien tiene sitio los sigue leyendo. */
@media (max-width: 1400px) {
  /* Lo primero que sobra: el subtítulo del logo no lo lee nadie dos veces. */
  .logo-sub { display: none; }
}
/* 1250 y no 900: MEDIDO el 27-ago con las siete pestañas de Olaya. A 1100 px
   los nombres todavía «cabían» en el sentido de que la barra hacía scroll y la
   página no se desplazaba —la comprobación automática pasaba—, pero la última
   pestaña salía CORTADA por la mitad y con ella su campanita. Un aviso que
   queda fuera del encuadre es un aviso que no existe. El umbral es el ancho al
   que dejan de caber ENTERAS, no aquel en el que empieza a haber scroll. */
@media (max-width: 1250px) {
  /* Y ahora sí, solo emoji. El nombre no se pierde: sigue en el `title` y en
     el `aria-label` de cada pestaña, así que el lector de pantalla lo dice
     igual y el ratón lo enseña al pasar por encima. */
  .pestana-texto { display: none; }
  .pestana { padding: 6px 10px; }
}

/* ── MÓVIL ─────────────────────────────────────────────────────────────────── */
@media (max-width: 620px) {
  header { gap: 8px; padding: 0 10px; }
  .logo-sub, .logo-texto { display: none; }
  /* ⚠️ Con CUATRO pestañas ya NO caben en un móvil: medido el 20-ago, la barra
     ocupaba 407 px en una pantalla de 390 y la de Recepción se salía —la página
     entera se desplazaba en horizontal, que es lo que nunca debe pasar—. Hoy
     son SIETE. Esconder el texto y el overflow-x ya los resuelven los bloques
     de 900 y 1100; aquí solo queda apretar el tamaño. */
  /* MEDIDO, no estimado: a 390 px el contenido de la barra ocupaba 227 y el
     hueco era 218 — faltaban NUEVE píxeles para que cupieran las siete. De ahí
     salen estos dos números y no de un ojímetro: 7×2 px de padding menos y 6×1
     de gap menos dan 20, que deja 11 de margen. */
  .pestana { font-size: 12px; gap: 0; padding: 6px 5px; }
  .pestanas { gap: 2px; }
  /* La campanita ensancha SU pestaña, y esa es la que no puede quedar fuera.
     Se aprieta aquí para que quepa también con dos cifras: el caso en que más
     importa verla es justo el que más sitio ocupa. */
  .pestana-cuenta { margin-left: 3px; padding: 0 4px; }
  /* 🔴 En un móvil de 390 px las SIETE no caben, y lo que se quedaba fuera del
     encuadre eran las dos ÚLTIMAS —Proveedores y Tiendas— con la campanita
     dentro. Medido el 27-ago: se veían cinco y media. Un aviso que hay que
     descubrir deslizando no avisa.
     Se recorta por donde no duele: el texto de «Cerrar» pasa a ser solo la
     flecha. Cerrar sesión se hace una vez al día y el nombre sigue en el
     `title` y en el `aria-label`; la campanita se mira cada vez que suena. */
  .usuario-chip strong { display: none; }
  .usuario-chip { padding: 6px 10px; }
  /* 44 px también aquí, y es el control MÁS pulsado de la aplicación: medido
     el 21-ago, las pestañas tenían 26 de alto. Con `display:flex` para centrar
     el emoji dentro del alto nuevo, que si no se queda arriba. */
  .pestana { flex-shrink: 0; min-height: 44px; display: flex;
             align-items: center; justify-content: center; }
  .producto { flex-wrap: wrap; }
  /* Antes esto era `display: none`, y escondía la foto justo en el móvil, que
     es donde compran las tiendas.
     Y va MÁS GRANDE que en escritorio, que es lo contrario de lo que parece:
     aquí la tarjeta se apila (flex-wrap) y su alto lo manda el bloque de
     cantidad/prioridad/añadir, no la foto. Medido el 27-ago: la tarjeta mide
     204 px lo mismo con 52 que con 72, y solo a partir de 72 empieza a costar
     scroll. Hasta ahí la foto sale gratis, así que se coge entera. */
  .hueco-img { width: 72px; height: 72px; min-width: 72px; }
  .producto-accion { width: 100%; justify-content: flex-end; flex-wrap: wrap; }
  /* La incidencia se lee de arriba abajo: el artículo, lo que pasó, y los
     botones al final. En una fila, «Cerrar» estrujaría la descripción —que es
     justo lo que hay que leer antes de decidir— hasta dejarla ilegible. */
  .incidencia { flex-wrap: wrap; }
  .incidencia-acciones { width: 100%; }
  .prioridad-linea { min-width: 0; }
  /* La 4ª columna es «tienda origen» en la consolidación, pero en la recepción
     es «Recibido» —la casilla que Olaya viene a rellenar—, así que la regla se
     acota. Ahí lo que sobra en un móvil es la tienda, que va la última. */
  .tabla:not(.tabla-recepcion) th:nth-child(4),
  .tabla:not(.tabla-recepcion) td:nth-child(4) { display: none; }
  /* Y la de recepción no esconde ninguna: a qué TIENDA va cada cosa es lo que
     se necesita para repartir después, y una columna oculta se convierte en una
     caja que acaba en el sitio equivocado. Se estrecha y, si aun así no cabe,
     desliza dentro de su propio contenedor. */
  /* El campo del código ocupa una fila entera, y debajo la cantidad y el OK
     juntos: es el orden en que se usan, y el OK cae donde llega el pulgar.
     Aquí el botón no es un adorno — el teclado del móvil no tiene TAB. */
  .recepcion-escaneo { gap: 8px; padding: 8px 10px; }
  #codigoEscaneado { flex: 1 1 100%; }
  .escaneo-paso { flex: 1 1 auto; }
  .escaneo-paso input { width: 100%; }
  .escaneo-ok { flex: 0 0 auto; }
  .escaneo-eco { flex: 1 1 100%; order: 9; }
  .tabla-recepcion { min-width: 460px; }
  .tabla-recepcion th, .tabla-recepcion td { padding: 8px; }
  .tabla-recepcion .cant-edit { width: 44px; }
  .almacen-cabecera { flex-direction: column; }

  /* ── 44 px, que es el ancho de un dedo ──────────────────────────────────
     Era el punto 14 del plan del 19-ago y seguía pendiente: medido el
     21-ago en un móvil de 390, los botones tenían 36 px, los desplegables
     32 y la ✕ de quitar un destino 26. Con eso se falla la pulsación, y la
     dependienta está de pie y con una caja delante.

     Va SOLO en el móvil: en un ratón, 36 px sobran y estirar todo dejaría
     la consolidación de Olaya —que sí se mira en un PC— con las filas del
     doble de altas. Y se hace con min-height y no con height, para que un
     texto que se parta en dos líneas no se salga del botón. */
  .btn-secundario, .btn-disparo, .btn-anadir, .btn-avisar,
  .filtro, .panel-cerrar, .escaneo-ok {
    min-height: 44px;
    height: auto;
  }
  /* Los de icono suelto necesitan además ancho: un ✕ de 26×26 es un fallo de
     pulsación esperando, y no se arregla solo con la altura. */
  .btn-borrar, .panel-cerrar, .btn-icono, .usuario-chip {
    min-width: 44px; min-height: 44px;
  }
  /* «Hoy voy a esta tienda». El área de pulsación es el <label> ENTERO —el
     cuadrito y el nombre—, así que es él quien tiene que medir 44, no solo el
     checkbox: medido a 390 px, el label se quedaba en 24 de alto. */
  .reparto-tienda { min-height: 44px; padding: 4px 0; }
  .reparto-tienda input { width: 24px; height: 24px; }

  /* ⚠️ La barra de acciones DESBORDABA la página a lo ancho: medido el
     21-ago en incidencias, 478 px en una pantalla de 390 —dos desplegables
     largos y un botón en una fila que no envolvía—. La página entera se
     desplazaba en horizontal, que es lo que nunca debe pasar. Envuelve, y los
     desplegables pueden encogerse (`min-width: 0`, que es lo que le falta a un
     flex hijo para poder achicarse por debajo de su contenido). */
  .pedidos-acciones { flex-wrap: wrap; }
  .pedidos-acciones .filtro { flex: 1 1 140px; min-width: 0; }

  /* Lo mismo, en las pantallas de antes de hoy, que nunca se habían medido:
     el buscador se quedaba en 42, las casillas de filtro en 13 (con su label
     en 14, así que el área de pulsación era la casilla y poco más) y las
     cantidades de la consolidación en 30. */
  #busqueda, .busqueda-inner { min-height: 44px; }
  .filtro-check { min-height: 44px; }
  .filtro-check input { width: 22px; height: 22px; }
  .cant-edit { min-height: 44px; }
}

/* Los resultados del buscador dentro del diálogo del sobrante. Alto fijo y
   scroll propio: si la lista empujara el diálogo, el botón de confirmar se
   saldría de la pantalla en un móvil justo cuando hace falta. */
.sobrante-resultados { max-height: 190px; overflow-y: auto; margin: 6px 0 2px; }
.sobrante-resultados:empty { display: none; }
.sobrante-op { display: block; width: 100%; text-align: left; padding: 8px 10px;
  border: 1px solid var(--gris-300, #DDD); border-radius: 8px; background: #fff;
  margin-bottom: 4px; cursor: pointer; font: inherit; min-height: 44px; }
.sobrante-op:hover, .sobrante-op:focus { border-color: var(--gris-400, #BBB); }
.sobrante-op[aria-pressed="true"] { border-color: var(--verde, #2E7D32); background: #F3FAF4; }
.sobrante-op small { display: block; color: var(--gris-600, #666); }
