/* RETAIL ERP — hoja de estilo única. Sobria a propósito: es una herramienta de
   trabajo que se mira ocho horas por día, no una landing. */
:root{
  --bd:#dedbd2; --tinta:#16140f; --gris:#625e56; --gris2:#777268;
  --acento:#1d4ed8; --ok:#1d7a34; --mal:#b3261e; --alerta:#8a6d00;
  --fondo:#f6f5f1; --panel:#fff; --sombra:0 1px 2px rgba(22,20,15,.04);
}
*{box-sizing:border-box}
body{margin:0;min-height:100vh;font:14px/1.55 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;background:var(--fondo);color:var(--tinta)}
a{color:var(--acento)}
h1{font-size:23px;line-height:1.2;letter-spacing:-.015em;margin:0 0 4px}
h2{font-size:15px;font-weight:650;letter-spacing:-.005em;color:var(--tinta);margin:0 0 10px}
h3{font-size:14px;font-weight:650;color:var(--tinta);margin:20px 0 8px}
.sub{color:var(--gris);margin:0 0 18px;font-size:13.5px}
.hint{font-size:11.5px;color:var(--gris);margin-top:4px}
.vacio{color:var(--gris);padding:22px 6px}

/* ── Cabecera ── */
.saltar{position:fixed;left:12px;top:8px;z-index:1000;padding:9px 13px;border-radius:8px;background:var(--tinta);color:#fff;text-decoration:none;transform:translateY(-150%)}
.saltar:focus{transform:none}
.top{background:rgba(255,255,255,.96);border-bottom:1px solid var(--bd);padding:0 18px;display:flex;align-items:center;gap:14px;min-height:52px;position:sticky;top:0;z-index:20;backdrop-filter:saturate(160%) blur(10px)}
.marca{font-weight:800;letter-spacing:-.02em;text-decoration:none;color:var(--tinta);font-size:15px;padding:12px 0}
.marca b{color:var(--acento)}
.marca.grande{font-size:22px;display:block;text-align:center;margin-bottom:18px}
.derecha{display:flex;align-items:center;gap:12px;font-size:12.5px;margin-left:auto}
/* La tira de arriba: los sectores del ERP (.menu-mod) y, en el portal del
   cliente, Mis datos / Mis compras. */
.menu{display:flex;gap:2px;flex:1}
.top .menu-mod{gap:0;flex-wrap:nowrap;min-width:0;align-self:stretch}
.top .menu-mod a{display:flex;align-items:center;padding:0 8px;font-size:13px;white-space:nowrap}
/* Para que los nueve sectores entren en una fila en una notebook de 1280-1366:
   el nombre de quien está adentro pasa al cartelito de «Salir». */
@media(max-width:1499px){.top .usr{display:none}}
.menu a{padding:14px 12px;text-decoration:none;color:var(--gris);font-weight:600;font-size:13.5px;border-bottom:2px solid transparent}
.menu a:hover{color:var(--tinta)}
.menu a.on{color:var(--tinta);border-bottom-color:var(--acento)}
.selsuc select{width:auto;max-width:170px;margin:0;padding:6px 28px 6px 10px;border:1px solid var(--bd);border-radius:8px;font:inherit;font-size:12.5px;font-weight:650;color:var(--tinta);background:#fff}
.suc1{color:var(--tinta);font-weight:650;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cot{background:#f2f6ff;border:1px solid #d6e0fb;color:#1d4ed8;padding:4px 10px;border-radius:100px;white-space:nowrap}
.cot.falta{background:#fdecea;border-color:#f5c2c0;color:var(--mal)}
.usr{display:flex;flex-direction:column;line-height:1.2}
.usr small{color:var(--gris);font-size:11px}
.salir{color:var(--gris);text-decoration:none;font-weight:650;padding:7px 0}
.salir-form{margin:0}
.salir-form .salir{appearance:none;background:none;border:0;font:inherit;cursor:pointer}
.cuerpo{max-width:1200px;width:100%;min-width:0;margin:22px auto;padding:0 24px}
#contenido:focus{outline:none}

/* ── Bloques ── */
.card{background:var(--panel);border:1px solid var(--bd);border-radius:12px;padding:18px;box-shadow:var(--sombra)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:16px;align-items:start}
@media(max-width:900px){.grid2{grid-template-columns:1fr}}
.kpis{display:flex;gap:12px;flex-wrap:wrap}
.kpi{background:var(--panel);border:1px solid var(--bd);border-radius:12px;padding:14px 18px;min-width:150px}
.kpi span{display:block;font-size:12.5px;color:var(--gris)}
.kpi b{font-size:24px;font-weight:700}
.accesos{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:10px}
.acc{display:block;padding:14px;border:1px solid var(--bd);border-radius:10px;text-decoration:none;color:var(--tinta);background:#fff}
.acc:hover{border-color:var(--acento);background:#f8faff}
.acc small{display:block;color:var(--gris);font-weight:400;margin-top:2px;font-size:12px}
/* Las tarjetas de un sector (modulo.php): lo primero que se ve al tocar un
   sector de arriba, para elegir a dónde ir. Más grandes que un acceso suelto. */
.tarjetas{grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:12px;margin-bottom:22px}
.tarjetas .acc{padding:18px;border-radius:12px}
.tarjetas .acc b{font-size:15px}
.tarjetas .acc small{font-size:12.5px;margin-top:4px;line-height:1.4}
.tarjetas-grupo{margin:18px 0 10px}

/* ── Formularios ── */
label{display:block;font-size:12.5px;color:var(--gris);margin-bottom:4px}
input,select,textarea{width:100%;padding:9px 11px;border:1px solid var(--bd);border-radius:8px;font:inherit;background:#fff;margin-bottom:10px}
input:focus,select:focus,textarea:focus{outline:2px solid #cfe0ff;border-color:var(--acento)}
.row{display:flex;gap:12px;flex-wrap:wrap}
.row>div{flex:1 1 150px}
.btn{background:var(--tinta);color:#fff;border:0;border-radius:9px;padding:10px 20px;font-weight:650;cursor:pointer;font-size:14px}
.btn:hover{background:#000}
.btn.ancho{width:100%}
.btn2{background:#fff;border:1px solid var(--bd);border-radius:8px;padding:8px 13px;cursor:pointer;font-size:12.5px}
.btn2:hover{border-color:var(--acento)}

/* ── Avisos ── */
.aviso{padding:10px 14px;border-radius:9px;margin-bottom:14px;font-size:13.5px}
.aviso.ok{background:#eaf7ee;color:var(--ok);border:1px solid #bfe3c8}
.aviso.mal{background:#fdecea;color:var(--mal);border:1px solid #f5c2c0}
.aviso.alerta,.aviso.ojo{background:#fffaed;color:var(--alerta);border:1px solid #e6c34a}
.aviso.info{background:var(--lavado);color:var(--acento);border:1px solid #d6e0fb}
.ref{background:#f2f6ff;border:1px solid #d6e0fb;border-radius:8px;padding:8px 12px;font-size:12.5px;color:#1d4ed8}

/* ── Tablas ── */
table{width:100%;border-collapse:collapse;font-size:13px}
th,td{text-align:left;padding:8px 6px;border-bottom:1px solid var(--bd);vertical-align:top}
th{font-size:12px;color:var(--gris);font-weight:600}
tbody tr:hover{background:#fafaf7}

/* ── Login / instalador ── */
.login-body{display:flex;align-items:center;justify-content:center;min-height:100vh;padding:20px}
.login-card{background:var(--panel);border:1px solid var(--bd);border-radius:14px;padding:28px;width:100%;max-width:360px;box-shadow:0 6px 26px rgba(0,0,0,.06)}
.login-card.ancho{max-width:640px}

/* ── Panel de productos ── */
.wrap{display:grid;grid-template-columns:1fr 380px;gap:18px;align-items:start}
@media(max-width:1000px){.wrap{grid-template-columns:1fr}}
.f{margin-bottom:12px}
.err{color:var(--mal);font-size:12px;margin-top:3px}
/* Deslizable de moneda del costo */
.sw{display:inline-flex;align-items:center;gap:9px;cursor:pointer;user-select:none}
.sw-t{width:52px;height:26px;border-radius:100px;background:var(--ok);position:relative;transition:background .15s;flex:0 0 auto}
.sw-t:after{content:'';position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;background:#fff;transition:left .15s;box-shadow:0 1px 3px rgba(0,0,0,.3)}
.sw.ars .sw-t{background:#2b7fff}
.sw.ars .sw-t:after{left:29px}
.sw-l{font-weight:700;font-size:13px;min-width:42px}
.mini{width:34px;height:34px;object-fit:cover;border-radius:6px;border:1px solid var(--bd)}

/* ═══════════════════════════════════════════════════════════════════════
   LISTA PRIMERO + MODAL
   El listado es la pantalla; crear es la excepción. El alta y la edición
   viven en un <dialog> nativo que no guarda nada hasta apretar el botón.
   ═══════════════════════════════════════════════════════════════════════ */
/* ═══════════════════════════════════════════════════════════════════════════
   RETAIL ERP · LIST-FIRST + MODAL
   Se pega al FINAL de public/assets/erp.css. Solo el bloque marcado
   "ENMIENDAS" toca reglas que ya existen.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  --radio:12px;
  --alto-top:53px;                 /* lo mide erp.js del header real; esto es el respaldo */
  --sombra-modal:0 18px 48px rgba(22,20,15,.20), 0 2px 6px rgba(22,20,15,.06);
  --lavado:#f2f6ff;                /* azul lavadísimo: seleccionado, fila activa */
  --hover:#faf9f5;
}

/* ── Utilidades ─────────────────────────────────────────────────────────── */
.sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
.ico{width:16px;height:16px;flex:0 0 auto;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
/* Toda columna de plata, cantidad o fecha. Sin esto las comas no se alinean
   entre filas y comparar dos precios obliga a leer dígito por dígito. */
.num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.junto{display:flex;gap:8px;align-items:center}
.junto>input{flex:1 1 auto;min-width:0}

/* Anillo de foco en TODO lo accionable. Hoy solo lo tienen los inputs: quien
   navega el listado con teclado va literalmente a ciegas. */
:where(a,button,summary,[tabindex]):focus-visible{outline:2px solid var(--acento);outline-offset:2px;border-radius:6px}

/* ── Cabecera de pantalla ───────────────────────────────────────────────── */
.pantalla{display:flex;align-items:flex-end;gap:16px;flex-wrap:wrap;margin:0 0 16px}
.pantalla-tit{flex:1 1 260px;min-width:0}
.pantalla-tit h1{margin:0}
.pantalla-tit .sub{margin:2px 0 0}
/* flex-wrap:wrap NO es cosmético: es la regla del dueño hecha CSS.
   Sin él, una barra con tres botones en un teléfono no tiene dónde meterlos, y
   flex los comprime POR DEBAJO del ancho de su propio texto: «Ver todas las
   sucursales» se salía del botón por 4 px en /stock.php a 375. Con wrap, el que
   no entra baja a la línea de abajo entero — que es lo que hace cualquiera con
   una repisa llena. Va acá y no en cada pantalla porque el bug no era de esa
   pantalla: era de la barra, y la barra la usan todas. */
.pantalla-acc{display:flex;gap:8px;align-items:center;flex:0 1 auto;flex-wrap:wrap;justify-content:flex-end;min-width:0}

/* ── Barra de búsqueda y filtros ────────────────────────────────────────── */
.barra{display:flex;gap:12px;align-items:center;flex-wrap:wrap;padding-bottom:12px;margin-bottom:2px;border-bottom:1px solid var(--bd)}
.buscador{position:relative;flex:1 1 300px;max-width:460px;margin:0}
.buscador input{margin:0;padding-left:34px;padding-right:34px}
.buscador input::-webkit-search-cancel-button{display:none}
.buscador .lupa{position:absolute;left:10px;top:50%;transform:translateY(-50%);color:var(--gris2);pointer-events:none}
.buscador .limpiar{position:absolute;right:8px;top:50%;transform:translateY(-50%);display:grid;place-items:center;width:22px;height:22px;border-radius:6px;color:var(--gris);text-decoration:none}
.buscador .limpiar:hover{background:#f0efe9;color:var(--tinta)}

.chips{display:flex;gap:6px;flex-wrap:wrap}
.chip{display:inline-flex;align-items:center;gap:6px;padding:6px 13px;border:1px solid var(--bd);border-radius:100px;background:#fff;color:var(--gris);font-size:12.5px;font-weight:600;text-decoration:none;white-space:nowrap;cursor:pointer}
/* El hover va solo en lo que se toca. :where() para no subir la especificidad:
   con `.chip:is(a):hover` el `.chip.on` dejaba de ganarle y el filtro vigente
   quedaba con texto oscuro sobre fondo oscuro. */
.chip:where(a,button,label):hover{border-color:var(--gris2);color:var(--tinta)}
.chip.on{background:var(--tinta);border-color:var(--tinta);color:#fff}
/* Un .chip que no es enlace, botón ni label es una ETIQUETA, no un filtro.
   En Línea «cobrada» / «anulada» / «esperando en caja» y en el historial de la
   caja «con devolución» / «por facturar» se veían idénticas a los filtros (borde
   de botón, manito, hover) y la gente las tocaba esperando que filtraran: no
   pasaba nada. Sin borde, fondo suave y más chicas, como .pill.
   El `.on` queda afuera del restyle porque es el filtro vigente de una fila de
   solapas (Caja, Libro IVA): tiene que seguir midiendo lo mismo que sus
   vecinas <a>, pero tampoco es tocable, así que sin manito.
   :where() mantiene la especificidad de `.chip`: `.chip.on` y
   `.pos-hoja .chip.alerta` (pos.css) siguen pisándola como antes. */
.chip:where(:not(a,button,label)){cursor:default}
.chip:where(:not(a,button,label,.on)){padding:3px 10px;border-color:transparent;background:#f3f2ee;font-size:11.5px}
.filtros-avanzados{flex:1 1 100%;border-top:1px solid var(--bd);padding-top:10px}
.filtros-avanzados summary{display:inline-flex;align-items:center;gap:7px;color:var(--gris);font-size:12.5px;font-weight:700;cursor:pointer}
.filtros-avanzados[open] summary{margin-bottom:10px;color:var(--tinta)}
.filtros-contenido{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap}

/* ── Listado ────────────────────────────────────────────────────────────── */
.tabla-wrap{overflow-x:auto;margin:0 -18px;padding:0 18px}
table.lista{width:100%;border-collapse:collapse;font-size:13px}
/* El encabezado se pega al tope de SU contenedor, no de la ventana.
   `.tabla-wrap` tiene overflow-x:auto y eso lo vuelve contenedor de scroll: con
   un `top` positivo, sticky empuja el encabezado ESE tanto hacia abajo dentro de
   la tabla, deja un hueco arriba y se monta sobre la primera fila. Con top:0
   queda donde corresponde. Para que además se pegue a la barra de arriba habría
   que sacarle el scroll horizontal al contenedor, y ese scroll hace falta. */
table.lista thead th{position:sticky;top:0;z-index:2;background:var(--panel);
  padding:9px 10px;font-size:12px;color:var(--gris);font-weight:600;
  border-bottom:1px solid var(--bd);white-space:nowrap}
table.lista td{padding:9px 10px;border-bottom:1px solid var(--bd);vertical-align:middle}
table.lista tbody tr:hover{background:var(--hover)}
table.lista tbody tr:focus-within{background:var(--lavado)}
table.lista tr.inactiva td{opacity:.55}
.principal{font-weight:600;color:var(--tinta);text-decoration:none}
.principal:hover{text-decoration:underline}
.sec{display:block;color:var(--gris);font-size:11.5px;margin-top:1px;font-variant-numeric:tabular-nums}
td.malo{color:var(--mal);font-weight:650}
.recep-diferencia.ok{color:var(--ok);font-weight:700}
.recep-diferencia.malo{color:var(--mal);font-weight:700}
.col-foto{width:34px;padding-right:0!important}
.mini.vacia{display:block;background:#f3f2ee}
.pie-tabla{margin:12px 0 0;font-size:12px;color:var(--gris)}
/* Las columnas que ayudan pero no son la razón por la que se abre la pantalla. */
@media(max-width:1100px){.col-op{display:none}}

/* Acciones de fila: aparecen al pasar por encima, pero SIEMPRE alcanzables
   con teclado (opacity:0 no saca del orden de tabulación) y siempre visibles
   donde no hay hover (tablet, celular). */
th.acciones,td.acciones{width:1%;white-space:nowrap;text-align:right}
td.acciones .btn2{opacity:0;transition:opacity .12s ease-out}
tr:hover td.acciones .btn2,td.acciones .btn2:focus-visible{opacity:1}
@media(hover:none){td.acciones .btn2{opacity:1}}

/* Fila recién guardada: se apaga sola. Continuidad entre el modal y la lista. */
@keyframes recien{from{background:#fff6d6}to{background:transparent}}
tr.recien{animation:recien 2.4s ease-out forwards}

/* La pill es un estado, nunca un botón: flecha y sin hover. Si algún día se
   la mete adentro de un enlace, hereda la manito de ese enlace: con la flecha
   fija, lo tocable se vería como lo que no se toca. */
.pill{display:inline-flex;align-items:center;gap:6px;padding:0;border:0;background:none;font-size:12px;font-weight:600;
      line-height:1.3;vertical-align:middle;cursor:default;white-space:nowrap}
/* Punto y texto, como el «indicador» de ERPNext (15/10/2026, menos ruido):
   una tabla con una pastilla de color en cada fila era una tabla de pastillas.
   Lo que pide que alguien actúe (alerta) conserva el relleno: es lo único que
   tiene que saltar a la vista. */
.pill::before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor;flex:none}
a .pill,button .pill,label .pill,summary .pill{cursor:inherit}
.pill.gris{color:var(--gris)}
.pill.ok{color:var(--ok)}
.pill.info{color:var(--acento)}
.pill.alerta{background:#fff8e6;border:1px solid #e6c34a;color:var(--alerta);padding:1px 8px;border-radius:100px}
.pill.alerta::before{display:none}
.pill.mal{color:var(--mal)}

/* ── Vacíos: tres, no uno ───────────────────────────────────────────────── */
.vacio-caja{text-align:center;padding:52px 20px 46px;color:var(--gris)}
.vacio-caja h3{margin:0 0 6px;font-size:15px;text-transform:none;letter-spacing:0;color:var(--tinta);font-weight:650}
.vacio-caja p{margin:0 auto;max-width:46ch;font-size:13px}
.vacio-acc{display:flex;gap:8px;justify-content:center;margin-top:18px;flex-wrap:wrap}

/* ═══ MODAL ═══════════════════════════════════════════════════════════════
   padding:0 es estructural, no estético: hace que TODO clic sobre el elemento
   <dialog> sea un clic en el backdrop, que es como se detecta el cierre. */
dialog.modal{
  padding:0;border:1px solid var(--bd);border-radius:var(--radio);
  background:var(--panel);color:var(--tinta);
  width:min(720px,calc(100vw - 32px));max-width:none;
  max-height:min(86dvh,900px);
  box-shadow:var(--sombra-modal);
  flex-direction:column;overflow:hidden;
  /* Estado cerrado + duración de SALIDA (130ms, ~68% de la entrada). */
  opacity:0;transform:translateY(8px) scale(.985);
  transition:opacity .13s ease-in, transform .13s ease-in,
             display .13s allow-discrete, overlay .13s allow-discrete;
}
/* display:flex SOLO con [open]: si no, se pisa el display:none del navegador
   y el modal quedaría visible siempre. */
dialog.modal[open]{
  display:flex;opacity:1;transform:none;
  transition:opacity .19s ease-out, transform .19s ease-out,
             display .19s allow-discrete, overlay .19s allow-discrete;
}
@starting-style{dialog.modal[open]{opacity:0;transform:translateY(8px) scale(.985)}}
dialog.modal::backdrop{
  background:rgba(22,20,15,.42);backdrop-filter:blur(2px);
  opacity:0;transition:opacity .13s ease-in, display .13s allow-discrete, overlay .13s allow-discrete;
}
dialog.modal[open]::backdrop{opacity:1;transition-duration:.19s}
@starting-style{dialog.modal[open]::backdrop{opacity:0}}

/* Sin JS el servidor manda <dialog open>: :modal NO matchea y queda como un
   panel normal en el flujo de la página. Único fallback necesario. */
dialog.modal:not(:modal){position:static;margin:0 0 18px;width:auto;max-width:none;max-height:none;opacity:1;transform:none;box-shadow:none}

dialog.modal.chico{width:min(420px,calc(100vw - 32px))}

/* El <form> es el ÚNICO hijo del <dialog>, así que es él quien tiene que repartir
   el alto entre cabecera, cuerpo y pie. Sin esto el form crece con su contenido,
   el dialog lo recorta con overflow:hidden, y el pie —donde está el botón de
   guardar— queda afuera de la pantalla, sin scroll que lo alcance.
   Se notaba solo en los formularios largos: el de contactos perdía el botón, el
   de productos entraba justo y parecía que estaba todo bien. */
dialog.modal > form{
  display:flex;flex-direction:column;
  flex:1 1 auto;min-height:0;overflow:hidden;
}
/* En el fallback sin JS el panel va en el flujo normal y no tiene que recortar
   nada: ahí el alto lo pone el contenido. */
dialog.modal:not(:modal) > form{display:block;overflow:visible}

.modal-cab{flex:0 0 auto;display:flex;align-items:flex-start;gap:12px;padding:16px 18px 13px;border-bottom:1px solid transparent;transition:border-color .15s}
/* Borde de la cabecera SOLO cuando hay contenido desplazado abajo: un divisor
   permanente sobre contenido que no scrollea es ruido. */
dialog.desplazado .modal-cab{border-bottom-color:var(--bd)}
.modal-cab h2{margin:0;font-size:15.5px;font-weight:700;text-transform:none;letter-spacing:-.01em;color:var(--tinta)}
.modal-cab p{margin:3px 0 0;font-size:12.5px;color:var(--gris)}
.cerrar{margin-left:auto;flex:0 0 auto;display:grid;place-items:center;width:32px;height:32px;border:0;border-radius:8px;background:none;color:var(--gris);cursor:pointer;text-decoration:none}
.cerrar:hover{background:#f3f2ee;color:var(--tinta)}

.modal-cuerpo{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:14px 18px 18px}
/* Dentro del modal el espaciado lo manda .f / .grupo, no el margin suelto de
   los inputs (si no queda todo con doble aire). */
.modal-cuerpo :is(input,select,textarea){margin-bottom:0}
.modal-cuerpo .f{margin-bottom:14px}
.modal-cuerpo .row{margin-bottom:14px}
.modal-cuerpo .row>.f{flex:1 1 160px;margin-bottom:0}

.modal-pie{flex:0 0 auto;display:flex;align-items:center;gap:12px;padding:12px 18px;border-top:1px solid var(--bd);background:var(--panel)}
.modal-pie .acciones-pie{margin-left:auto;display:flex;gap:8px;align-items:center}
.btn.peligro{background:var(--mal)}
.btn.peligro:hover{background:#8e1e18}
.btn2.peligro{border-color:#efc1bd;color:var(--mal)}
.btn2.peligro:hover{background:#fff5f4;border-color:var(--mal)}

.grupo{border:0;padding:0;margin:0 0 20px;min-width:0}
.grupo legend{padding:0;margin-bottom:9px;font-size:13.5px;color:var(--tinta);font-weight:650}

/* ── Errores ────────────────────────────────────────────────────────────── */
.errores{border:1px solid #f5c2c0;background:#fdecea;color:var(--mal);border-radius:9px;padding:12px 14px;margin:0 0 18px}
.errores:focus{outline:2px solid var(--mal);outline-offset:2px}
.errores b{display:block;margin-bottom:6px;font-size:13.5px}
.errores ul{margin:0;padding-left:18px;font-size:13px}
.errores li+li{margin-top:3px}
.errores a{color:inherit}
:is(input,select,textarea)[aria-invalid="true"]{border-color:var(--mal);background:#fffafa}
:is(input,select,textarea)[aria-invalid="true"]:focus{outline-color:#f7c9c6}

/* ── Casillas ───────────────────────────────────────────────────────────── */
.check{display:flex;gap:9px;align-items:flex-start;margin:0 0 8px;padding:2px 0;font-size:13px;color:var(--tinta);cursor:pointer;line-height:1.45}
.check input{width:auto;flex:0 0 auto;margin:2px 0 0;accent-color:var(--acento)}
.check small{display:block;color:var(--gris);font-size:11.5px;margin-top:1px}
.check-caja{border:1px solid var(--bd);border-radius:9px;padding:10px 12px;margin-bottom:6px}
.check-caja:has(input:checked){border-color:var(--acento);background:#f8faff}

/* ── Configuración: menú vertical ───────────────────────────────────────── */
.config{display:grid;grid-template-columns:212px minmax(0,1fr);gap:18px;align-items:start}
.config-panel{min-width:0}
.lateral{background:var(--panel);border:1px solid var(--bd);border-radius:var(--radio);padding:8px;position:sticky;top:calc(var(--alto-top) + 18px)}
.lateral h4{margin:14px 10px 4px;font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;color:var(--gris2);font-weight:700}
.lateral h4:first-child{margin-top:2px}
.lateral a{position:relative;display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:8px;color:var(--gris);font-size:13.5px;font-weight:600;text-decoration:none;line-height:1.3}
.lateral a:hover{background:#f3f2ee;color:var(--tinta)}
.lateral a[aria-current="page"]{background:var(--lavado);color:var(--acento)}
.lateral a[aria-current="page"]::before{content:"";position:absolute;left:-8px;top:6px;bottom:6px;width:3px;border-radius:0 3px 3px 0;background:var(--acento)}
.lateral .badge{margin-left:auto;padding:1px 8px;border-radius:100px;font-size:10.5px;font-weight:700;background:#fff8e6;border:1px solid #e6c34a;color:var(--alerta)}
@media(max-width:820px){
  .config{grid-template-columns:1fr}
  .lateral{position:static;display:flex;gap:4px;padding:6px;overflow-x:auto;scrollbar-width:thin}
  .lateral h4{display:none}
  .lateral a{white-space:nowrap;padding:7px 12px}
  .lateral a[aria-current="page"]::before{left:10px;right:10px;top:auto;bottom:3px;width:auto;height:2px;border-radius:2px}
}

/* ── Modal como hoja en celular: entra desde abajo, sale hacia abajo ────── */
@media(max-width:640px){
  dialog.modal{width:100vw;max-width:100vw;max-height:92dvh;margin:auto auto 0;border-radius:16px 16px 0 0;border-bottom:0;transform:translateY(18px)}
  dialog.modal[open]{transform:none}
  @starting-style{dialog.modal[open]{transform:translateY(18px)}}
  .modal-pie{padding-bottom:calc(12px + env(safe-area-inset-bottom))}
  .modal-pie .hint{display:none}
  .modal-pie .acciones-pie{flex:1 1 auto}
  .modal-pie .acciones-pie .btn{flex:1 1 auto}
}

/* ── Preferencias del sistema ───────────────────────────────────────────── */
@media(prefers-reduced-motion:reduce){
  dialog.modal,dialog.modal[open],dialog.modal::backdrop,dialog.modal[open]::backdrop{transition-duration:1ms}
  dialog.modal,dialog.modal[open]{transform:none!important}
  tr.recien{animation:none;background:#fff6d6}
  .btn:active{transform:none}
  td.acciones .btn2{transition:none}
}
@media(prefers-reduced-transparency:reduce){
  dialog.modal::backdrop{backdrop-filter:none;background:rgba(22,20,15,.62)}
}
@media(prefers-contrast:more){
  :root{--bd:#b5b0a4;--gris:#4c4840}
  dialog.modal{border-color:var(--tinta)}
  .chip{border-color:var(--gris)}
  /* Las etiquetas conservan un borde legible, pero más suave que el de los
     filtros: si no, en este modo volverían a parecer botones. */
  .chip:where(:not(a,button,label,.on)){border-color:var(--bd)}
}

/* ═══ ENMIENDAS a reglas que YA existen ═══════════════════════════════════
   Pegar al final: por orden de cascada pisan a las de arriba del archivo. */

/* .btn y .btn2 pasan a inline-flex para poder llevar ícono SVG, y a servir
   igual como <a> que como <button>. */
.btn,.btn2{display:inline-flex;align-items:center;justify-content:center;gap:7px;text-decoration:none;line-height:1.2;white-space:nowrap}
.btn{color:#fff}
.btn2{color:var(--tinta)}
/* Respuesta en el apretón, no en el soltar. */
.btn:active,.btn2:active{transform:scale(.98)}
.btn,.btn2{transition:transform .1s ease-out,background .12s,border-color .12s}

/* El switch de moneda pasa de <span role=switch> a <button>: hoy no es
   alcanzable con teclado. */
.sw{border:0;background:none;padding:0;font:inherit;color:inherit}
.sw-l{color:var(--tinta)}
/* ═══════════════════════════════════════════════════════════════════════
   MENÚ DE LA IZQUIERDA (15/10/2026) — los sectores arriba y las pantallas del
   sector actual a la izquierda, el reparto de Dolibarr que eligió el dueño.
   Reemplaza la segunda barra de arriba y el menú propio de Configuración. En
   el teléfono y en pantallas de menos de 1280 es un cajón detrás de ☰, con
   todos los sectores.
   ═══════════════════════════════════════════════════════════════════════ */
.armazon{display:grid;grid-template-columns:220px minmax(0,1fr);align-items:start}
.lado{position:sticky;top:var(--alto-top,53px);height:calc(100vh - var(--alto-top,53px));overflow-y:auto;
      padding:14px 10px 40px;border-right:1px solid var(--bd);background:var(--panel);scrollbar-width:thin}
.lado-filtro{margin:0 0 10px;padding:8px 11px;font-size:13px}
.lado a{display:block;padding:6px 10px 6px 24px;border-radius:8px;text-decoration:none;color:var(--gris);
        font-size:13.5px;font-weight:500;line-height:1.35}
.lado a:hover{background:var(--hover);color:var(--tinta)}
.lado a.on{background:var(--lavado);color:var(--acento);font-weight:650}
.lado a.lado-solo{padding-left:10px;color:var(--tinta);font-weight:650}
.lado a.lado-solo.on{color:var(--acento)}
.lado-grupo>summary{list-style:none;cursor:pointer;position:relative;padding:7px 10px 7px 24px;border-radius:8px;
                    font-size:13.5px;font-weight:650;color:var(--tinta)}
.lado-grupo>summary::-webkit-details-marker{display:none}
.lado-grupo>summary::before{content:"";position:absolute;left:10px;top:13px;width:5px;height:5px;
  border-right:1.6px solid var(--gris2);border-bottom:1.6px solid var(--gris2);transform:rotate(-45deg);transition:transform .15s}
.lado-grupo[open]>summary::before{transform:rotate(45deg);top:11px}
.lado-grupo>summary:hover{background:var(--hover)}
.lado-grupo[open]{padding-bottom:6px}
.lado-sub{display:block;margin:8px 0 2px 24px;font-size:11.5px;font-weight:600;color:var(--gris2)}
.lado-vacio{margin:6px 10px;color:var(--gris);font-size:12.5px}
.lado-abrir{display:none;align-items:center;justify-content:center;width:40px;height:40px;margin-left:-8px;border:0;
            border-radius:8px;background:none;font-size:20px;color:var(--tinta);cursor:pointer}
.lado-abrir:hover{background:var(--hover)}
.lado-fondo{display:none}
/* En la computadora el sector está arriba: a la izquierda quedan solo SUS
   pantallas, sin repetir el nombre del sector. Mientras se busca aparece todo
   lo que coincide, de cualquier sector. */
@media(min-width:1280px){
  .lado:not(.buscando)>:is(.lado-grupo,a.lado-solo):not(.actual){display:none}
  .lado:not(.buscando)>.lado-grupo.actual>summary{display:none}
  .lado:not(.buscando)>.lado-grupo.actual>a{padding-left:10px}
  .lado:not(.buscando)>.lado-grupo.actual .lado-sub{margin-left:10px}
}
/* Donde los nueve sectores no entran en una fila: la tira de arriba se esconde
   y todo (sectores y pantallas) queda en el cajón de ☰, como en el teléfono. */
@media(max-width:1279px){
  .top .menu-mod{display:none}
  .armazon{display:block}
  .lado-abrir{display:inline-flex}
  /* Sin JS el menú queda a la vista, arriba de la pantalla: un menú escondido
     que no se puede abrir es un menú que no existe. */
  html:not(.js) .lado{position:static;height:auto;border-right:0;border-bottom:1px solid var(--bd)}
  html.js .lado{position:fixed;left:0;top:0;bottom:0;z-index:60;width:min(300px,86vw);height:auto;
                transform:translateX(-102%);transition:transform .2s ease;box-shadow:0 0 30px rgba(22,20,15,.18)}
  html.js body.lado-abierto .lado{transform:none}
  body.lado-abierto .lado-fondo{display:block;position:fixed;inset:0;z-index:55;background:rgba(22,20,15,.32)}
}
@media(max-width:900px){
  .lado a,.lado-grupo>summary{padding-top:10px;padding-bottom:10px}
}
.conf{display:block}
.conf-cuerpo{min-width:0}

/* ── Las SOLAPAS de una pantalla larga (erp.js) ─────────────────────────────
   Una cosa a la vista por vez. En el teléfono se desplazan de costado en vez
   de partirse en tres renglones. */
.solapas{position:relative;display:flex;gap:4px;margin:0 0 14px;padding:4px;border:1px solid var(--bd);border-radius:12px;
         background:var(--panel);overflow-x:auto;scrollbar-width:thin}
.solapas a{flex:0 0 auto;padding:8px 14px;border-radius:9px;text-decoration:none;color:var(--gris);
           font-weight:600;font-size:13.5px;white-space:nowrap}
.solapas a:hover{background:var(--fondo);color:var(--tinta)}
.solapas a.on{background:var(--acento);color:#fff}
[data-solapas] [data-solapa]{margin-top:0 !important}
/* `.lado a` es display:block y eso le gana al hidden del navegador: sin
   esta regla el buscador «filtraba» sin esconder nada. */
.lado [hidden],[data-solapa][hidden]{display:none !important}
/* Volver de un guardado con #depositos o #estructura: con las partes de arriba
   escondidas, el salto del navegador dejaba la solapa pegada al borde y el
   aviso de «guardado» y las solapas quedaban fuera de la vista. Un margen más
   alto que la pantalla hace que el salto termine siempre arriba de todo. Solo
   con las solapas armadas: sin JavaScript se ve todo y el salto es el de siempre. */
.solapas-listo [data-solapa]{scroll-margin-top:100vh}
/* Saltar a un #ancla dejaba el principio de la sección DEBAJO de la barra
   pegajosa de arriba: el título y el aviso de lo guardado quedaban tapados. */
html{scroll-padding-top:calc(var(--alto-pegado, var(--alto-top, 53px)) + 12px)}
/* Sin recargar (erp.js): lo que se está trayendo se apaga un poco y no se
   toca, así un segundo toque no cae sobre una lista que está por cambiar. */
[data-parcial-cargando]{opacity:.55;pointer-events:none;transition:opacity .15s}
a[aria-busy="true"]{opacity:.6;pointer-events:none}

/* ── El número que importa, en grande ──
   La cotización vigente y el TC de un recálculo son EL dato de su pantalla.
   Se muestran del tamaño de su importancia, no del de una fila de tabla. */
.destacado{border:1px solid var(--bd);border-radius:11px;padding:13px 16px;margin-bottom:16px;background:#fbfaf7}
.destacado span{display:block;font-size:12.5px;color:var(--gris)}
.destacado b{display:block;font-size:27px;font-weight:750;letter-spacing:-.02em;line-height:1.15;margin:2px 0}
.destacado small{color:var(--gris);font-size:12.5px}
.destacado.ojo{background:#fffaed;border-color:#e6c34a}

/* ── Referencia de mercado ──
   Deliberadamente discreta: es un dato para mirar de reojo mientras se teclea
   el número propio, no una fuente de verdad. */
.refbar{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-bottom:16px;font-size:12.5px}
.refbar-t{color:var(--gris);font-size:12px}
.refbar small{color:var(--gris2);font-size:11.5px}
.refpill{background:var(--panel);border:1px solid var(--bd);border-radius:100px;padding:4px 11px;white-space:nowrap;cursor:help}
.refpill b{font-weight:650;margin-right:3px}

.tabla-scroll{max-height:420px;overflow:auto;border:1px solid var(--bd);border-radius:10px}
.tabla-scroll table{font-size:12.5px}
.tabla-scroll thead th{position:sticky;top:0;background:var(--panel);z-index:1}
.tabla-scroll th,.tabla-scroll td{padding:7px 10px}

.sube{color:var(--ok);font-weight:600}
.baja{color:var(--mal);font-weight:600}
tr.apagada{opacity:.5}
tr.apagada td{text-decoration:line-through;text-decoration-color:var(--gris2)}

.cot{text-decoration:none}
.cot.viejo{background:#fffaed;border-color:#e6c34a;color:var(--alerta)}

/* ═══ TABLERO OPERATIVO ════════════════════════════════════════════════════
   El inicio prioriza excepciones y números accionables. No repite el menú. */
.tablero-cab{align-items:center;margin-bottom:18px}
.kpis-tablero{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));margin-bottom:18px}
.kpis-tablero .kpi{min-width:0;display:flex;flex-direction:column;color:var(--tinta);text-decoration:none;position:relative;overflow:hidden;transition:transform .12s,border-color .12s,box-shadow .12s}
.kpis-tablero .kpi::before{content:"";position:absolute;inset:0 auto 0 0;width:3px;background:var(--bd)}
/* El levantamiento va solo en las que son enlace (Contabilidad › Tablero). Los
   cuatro números de Entregas son <div> a propósito —describen la tabla de abajo—
   y subían igual al pasar el mouse: parecían un botón que no llevaba a ningún lado. */
.kpis-tablero a.kpi:hover{transform:translateY(-1px);border-color:#c8c4b9;box-shadow:0 5px 18px rgba(22,20,15,.07)}
/* La tarjeta que está filtrando la tabla de abajo (Entregas, Cierres, Reportes):
   se tiene que ver cuál es, si no el número de la tabla no se entiende. */
.kpis-tablero a.kpi[aria-current]{border-color:var(--tinta);box-shadow:inset 0 0 0 1px var(--tinta)}
.kpis-tablero .kpi.ok::before{background:var(--ok)}
.kpis-tablero .kpi.alerta::before{background:#d3a100}
.kpis-tablero .kpi.mal::before{background:var(--mal)}
.kpis-tablero .kpi b{font-size:27px;line-height:1.2;margin:3px 0 1px;font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.kpis-tablero .kpi small{color:var(--gris);font-size:11.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tablero-grid{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(300px,.65fr);gap:18px;align-items:start}
.card-titulo{display:flex;justify-content:space-between;gap:12px;margin-bottom:8px}
.card-titulo h2{margin:0}
.card-titulo p{margin:2px 0 0;color:var(--gris);font-size:12px}
.pendientes{margin:0 -8px -5px}
.pendiente{display:grid;grid-template-columns:58px minmax(0,1fr) 18px;align-items:center;gap:11px;padding:11px 8px;border-top:1px solid var(--bd);color:var(--tinta);text-decoration:none}
.pendiente:hover{background:var(--hover);border-radius:8px}
.pendiente-tipo{display:inline-flex;justify-content:flex-start;padding:0;color:var(--gris);font-size:11.5px;font-weight:600}
.pendiente-tipo.alerta{background:#fff4d5;color:var(--alerta)}
.pendiente b,.pendiente small{display:block}
.pendiente b{font-size:13.5px}
.pendiente small{font-size:11.5px;color:var(--gris);margin-top:1px}
.pendiente-ir{font-size:24px;color:var(--gris2);text-align:right}
.todo-bien{min-height:132px;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;border:1px dashed var(--bd);border-radius:10px;color:var(--gris)}
.todo-bien b{color:var(--ok);font-size:14px}
.todo-bien span{font-size:12px;margin-top:3px}
.accesos-tablero{grid-template-columns:1fr;gap:5px}
.accesos-tablero .acc{display:flex;align-items:center;gap:11px;padding:10px;border-color:transparent;background:transparent}
.accesos-tablero .acc:hover{border-color:var(--bd);background:var(--hover)}
/* Las siglas en un círculo («CC», «CP») no decían nada que el nombre de al lado no dijera (15/10/2026). */
.acc-sigla{display:none}

/* ═══ MI TRABAJO — la portada que se arma con los permisos ════════════════
   Una tarjeta por bloque, y cuántas columnas entran lo decide el ancho: la
   portada de un cajero tiene un bloque y la de un encargado cinco, así que un
   grillado de columnas fijas dejaría media pantalla vacía o apretaría todo.

   `minmax(min(320px,100%),1fr)` y NO `1fr` a secas, por la misma lección que
   está anotada en .tablero-grid: `1fr` es minmax(AUTO,1fr) y ese mínimo
   automático es el ancho del CONTENIDO, así que un nombre largo adentro de una
   tarjeta estira la columna y arrastra el <body>. El `min(320px,100%)` declara
   el piso y además lo baja solo en una pantalla más angosta que 320, donde un
   piso fijo desbordaría la página entera. */
.mt-bloques{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(320px,100%),1fr));gap:18px;align-items:start}
/* El inicio (15/10/2026): una sola fila de números arriba y lo que espera a
   alguien en una lista sin la etiqueta del área adelante. El 22/10/2026 los
   accesos pasaron de enlaces sueltos a botones y «Al día» de tarjeta a renglón
   (el dueño: «esto se ve muy mal»). */
a.kpi{text-decoration:none;color:inherit}
.pendiente.sin-tipo{grid-template-columns:minmax(0,1fr) 18px}
.atajos{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 14px}
.atajos-tit,.al-dia-tit{color:var(--gris);font-size:12.5px;font-weight:600;margin-right:4px}
.atajos .btn2{color:var(--tinta);font-weight:600;font-size:13px;padding:8px 14px}
/* Al día: el tilde verde dice «nada pendiente» y el nombre del área es la puerta. */
.al-dia{display:flex;flex-wrap:wrap;align-items:center;gap:6px 16px;margin:0;color:var(--gris);font-size:13px}
.al-dia>a,.al-dia>span:not(.al-dia-tit){color:var(--gris);text-decoration:none;white-space:nowrap}
.al-dia>a:hover{color:var(--tinta);text-decoration:underline}
.al-dia>a::before,.al-dia>span:not(.al-dia-tit)::before{content:"✓";color:var(--ok);font-weight:700;margin-right:5px}
/* Un bloque al día conserva su puerta de entrada, así que la línea se lee
   entera aunque el resumen sea largo: se parte en dos renglones, no se recorta.
   Y `anywhere` en todo el texto de un bloque porque el que manda el largo es el
   DATO: el nombre de un producto puede ser «CAÑO-PVC-110X4-JUNTA-REFORZADO-2026»
   de un tirón, sin un solo espacio donde cortar, y sin esto se sale del recuadro
   y arrastra la página entera. Medido a 1280 y a 375 con datos así. */
.pendiente.sin-tipo b,.pendiente.sin-tipo small{overflow-wrap:anywhere}

/* ═══ ÁLBUM DE FOTOS DEL PRODUCTO ═════════════════════════════════════════
   Varias fotos por producto: miniaturas, cuál es la portada, cuál se borra y en
   qué orden van. Sin arrastrar y soltar: flechas, que funcionan con teclado y no
   piden ninguna librería. */
.galeria{list-style:none;display:flex;flex-wrap:wrap;gap:10px;margin:0 0 10px;padding:0}
.gfoto{width:112px;border:1px solid var(--bd);border-radius:10px;padding:7px;background:#fff}
.gfoto.principal{border-color:var(--acento);background:var(--lavado)}
.gfoto img{display:block;width:96px;height:96px;object-fit:cover;border-radius:7px;border:1px solid var(--bd);background:#f3f2ee}
.gfoto-orden{display:flex;align-items:center;justify-content:space-between;gap:4px;margin-top:6px;min-height:26px}
.gflecha{width:28px;height:26px;padding:0;border:1px solid var(--bd);border-radius:6px;background:#fff;color:var(--tinta);cursor:pointer;font-size:13px;line-height:1}
.gflecha:hover:not(:disabled){border-color:var(--acento)}
.gflecha:disabled{opacity:.3;cursor:default}
.gpos{font-size:11px;color:var(--gris);font-variant-numeric:tabular-nums}
.gopt{display:flex;align-items:center;gap:6px;margin:5px 0 0;font-size:11.5px;color:var(--gris);cursor:pointer;line-height:1.3}
.gopt input{width:auto;flex:0 0 auto;margin:0;accent-color:var(--acento)}
.gfoto.principal .gprincipal span{color:var(--acento);font-weight:650}
/* Tildar Borrar tiene que verse ANTES de guardar: descubrirlo al volver a la
   lista es descubrirlo cuando ya no hay nada que cancelar. */
.gfoto.a-borrar{border-color:#f5c2c0;background:#fdecea}
.gfoto.a-borrar img{opacity:.35}
.gfoto.a-borrar .gborrar span{color:var(--mal);font-weight:650}
/* Aire entre las aclaraciones del álbum y el campo de subir: pegados se leen
   como un solo bloque y el "Agregar más fotos" pasa por renglón de la ayuda. */
.galeria ~ .f{margin-top:14px}

/* Aclaración chica bajo un encabezado: la columna «Margen» muestra el recargo
   sobre el costo, y sin decirlo el 100% del listado y el 50% de la ficha
   parecen contradecirse. */
table.lista thead th small{display:block;font-size:9.5px;font-weight:600;letter-spacing:.02em;text-transform:none;color:var(--gris2)}
/* Sin existencias: cero o negativo se ve de lejos recorriendo la lista. */
.sin-stock{color:var(--mal);font-weight:650}

/* ── Navegación y tableros en pantallas chicas ─────────────────────────── */
@media(max-width:940px){
  .kpis-tablero{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* minmax(0,1fr) y NO 1fr: `1fr` es minmax(AUTO,1fr), y ese mínimo automático
     es el ancho mínimo del contenido de la tarjeta. Con una tabla adentro, la
     columna se estira hasta que la tabla entra y arrastra el <body> a 767 px
     sobre una pantalla de 375 — el mismo desborde de siempre, y el `0` es lo
     mismo que ya arregló .opcion. Recién con el 0 el overflow-x:auto de
     .tabla-wrap hace lo que promete: scrollear ADENTRO del recuadro en vez de
     empujar la página. Apareció en /entregas.php, que fue la primera pantalla
     con una tabla en este grillado. */
  .tablero-grid{grid-template-columns:minmax(0,1fr)}
  .accesos-tablero{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media(max-width:820px){
  .top{gap:0 12px;padding:0 12px}
  .marca{order:1}
  .derecha{order:2;margin-left:auto;gap:9px;flex-wrap:nowrap}
  .usr{display:none}
}
@media(max-width:600px){
  h1{font-size:21px}
  .cuerpo{margin:16px auto;padding:0 12px}
  .cot{display:none}
  .selsuc select{max-width:145px}
  .suc1{max-width:130px}
  .card{padding:14px}
  .pantalla{align-items:center}
  .pantalla-acc{width:100%}
  .pantalla-acc .btn,.pantalla-acc .btn2{flex:1 1 auto;min-height:42px}
  .kpis-tablero{gap:8px}
  .kpis-tablero .kpi{padding:12px 13px}
  .kpis-tablero .kpi b{font-size:21px}
  .kpis-tablero .kpi small{white-space:normal;line-height:1.3}
  .accesos-tablero{grid-template-columns:1fr}
  .pendiente{grid-template-columns:52px minmax(0,1fr) 14px}
  /* 40 px es el blanco para el dedo: sirve a lo que se toca. Una etiqueta de
     estado con esa altura volvía a parecer botón en el celular. */
  .btn,.btn2,.chip:where(a,button,label){min-height:40px}
}

/* ═══ MOVIMIENTOS DE CAJA ══════════════════════════════════════════════════
   Dos marcas y nada más. La familia separa los totales (mostrador, a mano,
   fondo) para que no se lean como una sola bolsa, y el fondo cálido señala los
   movimientos que cargó una persona: una venta se explica con su ticket, un
   egreso con el concepto «varios» hay que ir a preguntarlo. */
tr.caja-fam td{background:var(--hover);font-size:12px;font-weight:650;color:var(--gris);padding-top:11px}
tr.caja-total td{border-top:2px solid var(--bd);background:var(--panel)}
tr.caja-mano td{background:#fffaed}
tr.caja-mano:hover td{background:#fff5da}

/* ═══ ETIQUETAS DE GÓNDOLA ═════════════════════════════════════════════════
   Solo la pantalla de armado. La hoja imprimible NO usa esta hoja de estilos:
   se dibuja sola, en blanco y negro, sin nada del ERP adentro. */
.et-elegidos{list-style:none;margin:0;padding:0}
.et-elegido{display:flex;align-items:center;gap:12px;padding:9px 2px;border-bottom:1px solid var(--bd)}
.et-elegido:last-child{border-bottom:0}
.et-elegido .et-nom{flex:1 1 auto;min-width:0}
.et-elegido .et-nom b{display:block;font-size:13.5px;font-weight:650}
.et-elegido input[type=number]{width:76px;margin:0;text-align:right}
/* El nombre es CÓMO se reconoce la fila, así que no puede ser el que se
   achica. En un teléfono los precios (150 px), la cantidad (76 px) y «Quitar»
   se comen la fila entera y al nombre le quedaban 33 px: medido a 375, la
   palabra más larga pedía 79 y salía cortada. La fila se parte en dos —nombre
   arriba, controles abajo— en vez de exprimir el único texto que identifica el
   renglón. Es el caso de siempre: un flex con un bloque de texto adentro. */
@media (max-width:560px){
  .et-elegido{flex-wrap:wrap}
  .et-elegido .et-nom{flex:1 1 100%}
}
.et-previa{background:#e9e7e0;padding:16px;border-radius:10px;overflow:auto;max-height:70vh}
.et-previa .et-hoja{margin:0 auto;box-shadow:0 2px 14px rgba(22,20,15,.18)}
.cola-etiquetas{border-left:3px solid #d3a100}
.cola-etiquetas input[type=checkbox]{width:auto;margin:0;accent-color:var(--acento)}
.cola-acciones{display:flex;justify-content:flex-end;gap:8px;flex-wrap:wrap;padding-top:13px;margin-top:5px;border-top:1px solid var(--bd)}
.cola-vacia{display:flex;align-items:center;justify-content:center;gap:9px;min-height:78px;color:var(--gris)}
.cola-vacia span{display:grid;place-items:center;width:28px;height:28px;border-radius:50%;background:#eaf7ee;color:var(--ok);font-weight:800}
.cola-vacia p{margin:0}

/* ═══ SALÓN MÓVIL ══════════════════════════════════════════════════════════
   Un dedo, una mano ocupada y luz de góndola: objetivos grandes, contraste y
   el precio como dato dominante. No comparte densidad con una grilla de oficina. */
.salon-app{max-width:820px;margin:0 auto}
.salon-cab{align-items:center;margin-bottom:18px}
.salon-eyebrow{display:block;margin-bottom:3px;color:var(--acento);font-size:11px;font-weight:800;letter-spacing:.075em;text-transform:uppercase}
.salon-camara-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:46px}
.salon-busqueda{background:linear-gradient(135deg,#172033,#111827);padding:18px;border-radius:16px;box-shadow:0 12px 35px rgba(17,24,39,.14)}
.salon-buscar{display:grid;grid-template-columns:22px minmax(0,1fr) auto;align-items:center;gap:10px;background:#fff;border:2px solid transparent;border-radius:12px;padding:5px 5px 5px 13px}
.salon-buscar:focus-within{border-color:#91b5ff;box-shadow:0 0 0 4px rgba(145,181,255,.2)}
.salon-buscar>.ico{color:var(--gris2);width:20px;height:20px}
.salon-buscar input{border:0;outline:0!important;box-shadow:none!important;margin:0;padding:11px 2px;font-size:16px;min-width:0}
.salon-buscar .btn{min-height:44px;padding:10px 18px}
.salon-ayuda{color:#cbd5e1;font-size:12px;margin:9px 2px 0}
.salon-estado{display:none;margin:14px 0 0;padding:10px 13px;border-radius:9px;font-size:13px}
.salon-estado.visible{display:block;background:var(--lavado);color:var(--acento)}
.salon-estado.ok{background:#eaf7ee;color:var(--ok)}
.salon-estado.mal{background:#fdecea;color:var(--mal)}
.salon-estado.alerta{background:#fffaed;color:var(--alerta)}
.salon-estado.cargando{display:block;color:var(--gris)}
.salon-resultados{display:grid;gap:12px;margin-top:16px}
.salon-producto{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"dato precio" "dato boton";align-items:center;gap:4px 20px;background:var(--panel);border:1px solid var(--bd);border-radius:15px;padding:18px;box-shadow:var(--sombra)}
.salon-producto.recien{animation:salon-entra .22s ease-out}
@keyframes salon-entra{from{opacity:.35;transform:translateY(5px)}to{opacity:1;transform:none}}
.salon-producto-dato{grid-area:dato;min-width:0}
.salon-producto-dato h2{margin:4px 0 8px;color:var(--tinta);font-size:18px;line-height:1.25;letter-spacing:-.01em;text-transform:none}
.salon-producto-dato p{margin:0;color:var(--gris);font-size:12px}
.salon-codigo{display:inline-block;color:var(--gris);font-size:11px;font-weight:700;letter-spacing:.04em;font-variant-numeric:tabular-nums}
/* El precio se amolda al ancho que le toca en vez de desbordar: con clamp()
   un artículo de seis cifras entra igual que uno de tres, y sin una línea de
   JavaScript. nowrap queda —el «$» bajándose de renglón parece un número
   roto— pero ahora el tamaño cede antes que el recuadro. */
.salon-precio{grid-area:precio;color:var(--tinta);font-size:clamp(22px,4.4vw,36px);line-height:1.05;letter-spacing:-.035em;font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap;min-width:0}
.salon-precios{grid-area:precio;text-align:right;min-width:0}.salon-precios .salon-precio{display:block}.salon-precios .sec{font-weight:750;color:var(--acento);overflow-wrap:anywhere}
/* Los dos botones del artículo comparten UNA celda de la grilla. Sin este
   contenedor se dibujarían uno encima del otro, porque dos elementos con el
   mismo grid-area se apilan. */
.salon-acciones{grid-area:boton;display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end;margin-top:7px;min-width:0}
.salon-acciones .btn2{min-height:42px}
.salon-encolar.en-cola{border-color:#bfe3c8;background:#eaf7ee;color:var(--ok)}
.salon-camara{width:min(680px,calc(100vw - 24px));max-width:none;padding:14px;border:1px solid var(--bd);border-radius:16px;background:var(--panel);box-shadow:var(--sombra-modal)}
.salon-camara::backdrop{background:rgba(10,14,22,.72);backdrop-filter:blur(3px)}
.salon-camara-cab{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin-bottom:12px}
.salon-camara-cab h2{margin:0;color:var(--tinta);font-size:17px;text-transform:none;letter-spacing:0}
.salon-camara-cab p{margin:2px 0 0;color:var(--gris);font-size:12px}
.salon-video-wrap{position:relative;overflow:hidden;border-radius:12px;background:#111;aspect-ratio:4/3}
.salon-video-wrap video{display:block;width:100%;height:100%;object-fit:cover}
.salon-mira{position:absolute;left:8%;right:8%;top:35%;height:30%;border:2px solid #fff;border-radius:12px;box-shadow:0 0 0 999px rgba(0,0,0,.28),inset 0 0 18px rgba(0,0,0,.15)}
.salon-camara-msg{margin:10px 2px 0;color:var(--gris);font-size:12.5px;text-align:center}

@media(max-width:600px){
  .salon-app{margin-top:-2px}
  .salon-cab .pantalla-acc{width:100%}
  .salon-camara-btn{width:100%}
  .salon-busqueda{margin:0 -4px;padding:12px;border-radius:14px}
  .salon-buscar{grid-template-columns:20px minmax(0,1fr)}
  .salon-buscar .btn{grid-column:1/-1;width:100%;min-height:46px}
  .salon-producto{grid-template-columns:1fr;grid-template-areas:"dato" "precio" "boton";gap:8px;padding:17px}
  .salon-precio{text-align:left;font-size:42px;margin:3px 0}
  .salon-precios{text-align:left}
  /* En el teléfono los botones ocupan el ancho completo y se apilan: se aprieta
     con el pulgar sin apuntar. */
  .salon-acciones{flex-direction:column;align-items:stretch}
  .salon-acciones .btn2{width:100%;min-height:48px;font-size:14px}
  .salon-camara{padding:10px}
}

/* ═══════════════════════════════════════════════════════════════════════
   ── Depósito en el celular ──
   Recepción de compras, transferencias y consulta de existencias operadas
   PARADO, con el teléfono en una mano y un bulto en la otra. Todo lo de acá
   adentro AGREGA en pantallas chicas; el escritorio no cambia un pixel.

   El mecanismo: la tabla que se OPERA en el piso lleva la clase
   `tabla-apilable`, y cada celda que necesita conservar su título lleva
   data-label="..." — en el teléfono el encabezado real se oculta y el
   título se pinta sobre la celda con ::before. Papeles especiales:
     · .apil-campo  — celda con input/select: el control crece a lo ancho,
                      16px como mínimo para que iOS no haga zoom al enfocar.
     · .apil-mitad  — campo que comparte renglón con otro (cantidad+costo).
     · .apil-total  — EL número de la fila: renglón propio, en grande.
   Una tabla sin la clase no cambia absolutamente nada.
   ═══════════════════════════════════════════════════════════════════════ */

@media(max-width:640px){
  .tabla-apilable{display:block}
  .tabla-apilable thead{display:none}          /* el título viaja en cada data-label */
  .tabla-apilable tbody{display:block;width:100%}
  .tabla-apilable tbody tr{
    display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px;
    padding:12px;margin-bottom:10px;
    border:1px solid var(--bd);border-radius:12px;background:var(--panel);
  }
  .tabla-apilable tbody tr:last-child{margin-bottom:0}
  .tabla-apilable tbody tr:hover{background:var(--panel)}   /* acá no hay mouse */
  .tabla-apilable tbody td{display:block;border:0;padding:0;min-width:0;flex:1 1 100%}
  .tabla-apilable td:first-child .principal{font-size:15px;line-height:1.3}

  /* El título de la columna, pintado sobre la celda. */
  .tabla-apilable td[data-label]::before{
    content:attr(data-label);
    display:block;margin-bottom:1px;
    font-size:11.5px;font-weight:600;
    color:var(--gris);white-space:nowrap;
  }

  /* Números de LECTURA: fichas chicas, para mirar de reojo con el bulto
     todavía en la otra mano. */
  .tabla-apilable td.num[data-label]:not(.apil-campo):not(.apil-total){
    flex:0 1 auto;background:#f3f2ee;border-radius:9px;padding:6px 10px;
    text-align:left;font-size:14px;font-weight:650;
  }

  /* Campos: acá el input manda. 48px de alto para el pulgar. */
  .tabla-apilable td.apil-campo{background:none;padding:0}
  .tabla-apilable td.apil-campo :is(input,select){width:100%;min-height:48px;font-size:16px;margin:0}
  .tabla-apilable td.apil-mitad{flex:1 1 34%}

  /* EL número de la fila (el total de existencias, la cantidad en mano):
     renglón propio, del tamaño de su importancia. */
  .tabla-apilable td.apil-total{
    display:flex;align-items:baseline;justify-content:space-between;gap:10px;
    margin-top:2px;padding-top:8px;border-top:1px dashed var(--bd);
    font-size:21px;font-weight:750;letter-spacing:-.01em;
    font-variant-numeric:tabular-nums;text-align:right;
  }
  .tabla-apilable td.apil-total::before{margin:0}

  /* Quitar renglón: chico pero tocable, y siempre visible (nada de hover). */
  .tabla-apilable td.acciones{flex:0 0 auto;margin-left:auto;width:auto}
  .tabla-apilable td.acciones .btn2{opacity:1;min-width:46px;min-height:44px}

  /* El semáforo de diferencia se lee sin acercarse el teléfono a la cara. */
  .tabla-apilable output.recep-diferencia{font-size:13px}

  /* Formularios que se operan con el camión atrás: botones a lo ancho y
     tipografía de 16px para que el sistema no haga zoom al enfocar. */
  .form-deposito :is(input,select,textarea){font-size:16px;min-height:46px}
  .form-deposito .btn,
  .form-deposito .btn2:not(.quitar){width:100%;min-height:48px}

  /* Despachar/Recibir/Confirmar a lo ancho; Cancelar queda secundario y
     LEJOS, detrás de un separador: tocarlo por error no puede ser fácil. */
  .acciones-piso{flex-direction:column;align-items:stretch;gap:12px}
  .acciones-piso .junto{flex-wrap:wrap}
  .acciones-piso .junto input{flex:1 1 100%;min-height:46px;font-size:16px}
  .acciones-piso .junto .btn,
  .acciones-piso .junto .btn2{flex:1 1 100%;min-height:48px}
  .acciones-piso .cancelar-lejos{margin-top:8px;padding-top:16px;border-top:1px dashed var(--bd)}

  /* Columnas de listado que en el teléfono no entran: mismo criterio que
     .col-op, pero recién en pantalla de celular. */
  .col-cel{display:none}

  /* Los filtros arriba de las grillas, tocables y sin zoom del sistema. */
  .barra select{font-size:16px;min-height:44px}
  .barra .buscador input{font-size:16px;min-height:44px}
}

@media(max-width:600px){
  /* Acá .card baja a 14px de padding, pero .tabla-wrap seguía descontando
     los 18 de escritorio y se pasaba 4px del borde de la tarjeta. */
  .tabla-wrap{margin:0 -14px;padding:0 14px}
}

/* ═══════════════════════════════════════════════════════════════════════════
   EL PLANO DEL LOCAL, DIBUJADO

   Pedido del dueño con croquis: rectángulos sobre papel cuadriculado, como las
   mesas en el plano de un restaurante. Un local no se reconoce por el orden de
   una lista; se reconoce por la forma.

   Todo con grid y un fondo de líneas hecho con gradientes. Sin canvas, sin SVG
   y sin una sola librería: un plano de racks son rectángulos alineados a una
   grilla, y cualquier otra cosa sería un motor de dibujo casero que mantener.
   ═══════════════════════════════════════════════════════════════════════════ */
.plano{position:relative;display:grid;
       /* Con un mínimo por celda: desde schema/062 cada local tiene su tamaño
          de plano, y uno de 40 columnas apretado en el ancho de la pantalla
          dejaba el «1-A» ilegible. Pasado ese mínimo, el plano se desplaza
          adentro de su recuadro (overflow:auto) y la pantalla no se corre. */
       grid-template-columns:repeat(var(--plano-cols,24),minmax(22px,1fr));
       grid-template-rows:repeat(var(--plano-filas,16),minmax(22px,auto));
       gap:2px;padding:10px;border:1px solid var(--bd);border-radius:14px;
       background-color:#fbfaf7;
       /* El papel cuadriculado: dos gradientes repetidos, nada más. */
       background-image:linear-gradient(to right,rgba(22,20,15,.055) 1px,transparent 1px),
                        linear-gradient(to bottom,rgba(22,20,15,.055) 1px,transparent 1px);
       background-size:calc((100% - 20px)/var(--plano-cols,24)) calc((100% - 20px)/var(--plano-cols,24));
       background-position:10px 10px;
       /* `local`: el cuadriculado se mueve con lo dibujado cuando el plano se
          desplaza, en vez de quedarse quieto debajo de los racks. */
       background-attachment:local;
       overflow:auto}

/* El rack: un rectángulo con su número bien grande, que se lee de lejos. */
.plano-rack{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;
            min-width:0;padding:6px 4px;border:1px solid #bcd4bd;border-radius:10px;
            background:#e3ecdd;color:var(--tinta);cursor:pointer;font:inherit;
            box-shadow:0 1px 0 rgba(22,20,15,.05)}
.plano-rack b{font-size:17px;font-weight:700;letter-spacing:-.01em;max-width:100%}
.plano-rack small{font-size:10.5px;color:var(--gris);max-width:100%}
.plano-rack:hover{border-color:var(--acento)}
.plano-rack.elegido{border-color:var(--acento);background:#e6efff;box-shadow:inset 0 0 0 1px var(--acento)}
.plano-rack.inactivo{opacity:.45;background:#f1efe9}

/* ── Un rack de DOS CARAS (schema/062) ────────────────────────────────────
   Partido al medio con una línea punteada, como se ve el mueble desde arriba:
   cada mitad da a un pasillo. A lo largo del rack: uno ancho y bajo se parte
   arriba/abajo, uno alto y angosto, izquierda/derecha. */
.plano-doble-h,.plano-doble-v{position:relative}
.plano-doble-h::after,.plano-doble-v::after{content:"";position:absolute;pointer-events:none;
  border-color:rgba(22,20,15,.32);border-style:dashed;border-width:0}
.plano-doble-h::after{left:6px;right:6px;top:50%;border-top-width:1px}
.plano-doble-v::after{top:6px;bottom:6px;left:50%;border-left-width:1px}
/* ── Las herramientas del plano: zoom (erp.js) ──────────────────────────── */
.plano-herr{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:0 0 8px}
.plano-herr .btn2{min-width:38px;padding:5px 10px;font-weight:700}
.plano-herr-txt{color:var(--gris);font-size:12px;margin-left:4px}
/* Con zoom, celdas CUADRADAS de tamaño fijo: el cuadriculado coincide con la
   grilla (celda + 2 px de separación) y lo que no entra se desplaza. */
.plano.plano-zoom{grid-template-columns:repeat(var(--plano-cols,24),var(--celda,22px));
  grid-template-rows:repeat(var(--plano-filas,16),var(--celda,22px));
  background-size:calc(var(--celda,22px) + 2px) calc(var(--celda,22px) + 2px)}
.plano-zoom .plano-rack b{font-size:clamp(9px,calc(var(--celda,22px) * .55),17px)}
.plano-zoom .plano-rack{padding:2px 3px}
.plano-chico .plano-rack small{display:none}
.plano-chico .plano-rack{border-radius:5px;padding:0 1px}
/* El tirador de la esquina: agrandar arrastrando (solo al armar el local). */
.plano-tirador{position:absolute;right:1px;bottom:1px;width:12px;height:12px;cursor:nwse-resize;
  border-right:2px solid rgba(22,20,15,.38);border-bottom:2px solid rgba(22,20,15,.38);border-radius:0 0 6px 0;
  touch-action:none}
.plano-editable .plano-rack{position:relative}
.plano-editable .plano-rack:not(:hover):not(.elegido) .plano-tirador{opacity:.35}

/* Una góndola de una celda de alto o de ancho: el código solo, y chico. */
.plano-finito{padding:1px 3px;gap:0;border-radius:7px}
.plano-finito b{font-size:13px;line-height:1.1}
.plano-finito small{display:none}
/* El título de cada cara en la lista de niveles: «Lado del pasillo 2». */
.plano-cara-tit{margin:10px 0 6px;font-size:12.5px;font-weight:650;color:var(--gris)}
.plano-cara-tit:first-child{margin-top:0}

/* ── El SECTOR: lo del local que no es una estantería (schema/042) ────────
   Un pallet de cocinas, la fila de termotanques, el rincón de lo fallado. Se
   ve DISTINTO de un rack a propósito: el borde punteado dice «acá está apoyado
   en el piso, no hay estantes», y se reconoce de lejos sin leer nada.

   El nombre NO se recorta con puntos suspensivos como el código de un rack:
   un rack se identifica igual con «1-A» que con «1-A…», pero un sector es la
   palabra —«Termotanques» cortado en «Termota…» deja de ser el sector—. Por
   eso parte en renglones, con la tipografía atada al ancho del rectángulo:
   el texto se amolda al cuadro, nunca al revés. */
.plano-sector{border-style:dashed;border-color:#c9bfa6;background:#f6f1e4}
.plano-sector:hover{border-color:var(--acento)}
.plano-sector.elegido{border-color:var(--acento);background:#eef4ff}
.plano-nombre{min-width:0;max-width:100%;font-size:clamp(11px,1.15vw,15px);line-height:1.15;
              text-align:center;overflow-wrap:anywhere;hyphens:auto}

/* Dónde está el artículo que se está mirando: el plano contesta de un vistazo. */
.plano-rack.aca{border-color:var(--ok);background:#dff0e2}
.plano-aca{color:var(--ok);font-size:11px;line-height:1}
/* El plano de solo mirar (Salón: «¿dónde está?»): el rack del artículo en ROJO,
   que es lo que el dueño pidió para que se encuentre de un vistazo. Verde era
   «acá hay algo»; acá la pregunta es «¿adónde voy?». */
.plano-ver .plano-rack{cursor:default}
.plano-ver .plano-rack.aca{border-color:var(--mal);background:#fde8e6;box-shadow:inset 0 0 0 2px var(--mal);color:var(--mal)}
.plano-ver .plano-aca{color:var(--mal)}
.plano-vacio{grid-column:1/-1;grid-row:1/-1;align-self:center;justify-self:center;
             margin:0;color:var(--gris);font-size:13px}
/* Arrastrando: el rack sigue al dedo y el resto no se mueve. */
.plano-editable .plano-rack{touch-action:none}
.plano-rack.arrastrando{opacity:.85;box-shadow:0 8px 20px rgba(22,20,15,.22);z-index:2}
/* Elegir varios (seguimiento del plano, 13/10/2026): lo elegido se ve con un
   borde punteado del color de la casa, distinto del «abierto» (.elegido) y
   del «está acá» (.aca), para que no se confundan las tres cosas. */
.plano-rack.sel{outline:2px dashed var(--acento);outline-offset:1px;background:#eef3ff}
.plano-lazo{position:absolute;z-index:3;pointer-events:none;border:1.5px dashed var(--acento);
            background:rgba(29,78,216,.08);border-radius:4px}
/* En «Elegir varios», arrastrar el dedo sobre el fondo dibuja el recuadro en
   vez de desplazar el plano. */
.plano.plano-varios{touch-action:none}
[data-plano-varios][aria-pressed="true"]{background:var(--acento);border-color:var(--acento);color:#fff}
.plano-acciones{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 10px}
.plano-acciones form{margin:0}
.plano-sel-aviso{position:fixed;left:50%;bottom:16px;transform:translateX(-50%);z-index:30;max-width:calc(100% - 32px);
                 background:var(--tinta);color:#fff;padding:9px 16px;border-radius:999px;font-size:13px;
                 box-shadow:0 6px 18px rgba(22,20,15,.25);text-align:center;
                 /* Flota sobre el plano: los toques tienen que pasar al rack de abajo. */
                 pointer-events:none;opacity:.94}
.plano-sel-aviso[hidden]{display:none}
.plano-error-aviso{position:fixed;left:50%;bottom:62px;transform:translateX(-50%);z-index:31;max-width:calc(100% - 32px);
                   background:var(--mal);color:#fff;padding:10px 16px;border-radius:12px;font-size:13.5px;font-weight:600;
                   box-shadow:0 6px 18px rgba(22,20,15,.25);text-align:center;pointer-events:none}
.plano-error-aviso[hidden]{display:none}
/* Arrastrar sobre el plano no tiene que pintar el texto de los racks como si
   se estuviera seleccionando para copiar. */
.plano.plano-editable{user-select:none;-webkit-user-select:none}

/* ── Los niveles del rack, al tocarlo ─────────────────────────────────────
   De arriba para abajo como se ve parado enfrente: el estante más alto arriba
   y el piso abajo. Al revés, «el de arriba» daría el de abajo. */
.plano-niveles{margin-top:12px;border:1px solid var(--bd);border-radius:12px;
               background:var(--panel);padding:12px 14px}
.plano-niveles[hidden]{display:none}
.plano-niveles-tit{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px;margin:0 0 10px}
.plano-niveles-tit b{font-size:15px}
.plano-niveles-tit span{color:var(--gris);font-size:12.5px;min-width:0}
.plano-nivel{display:flex;align-items:center;gap:10px;width:100%;min-height:46px;margin-bottom:6px;
             padding:8px 12px;border:1px solid var(--bd);border-radius:10px;background:var(--fondo);
             cursor:pointer;font:inherit;color:inherit;text-align:left}
.plano-nivel:last-child{margin-bottom:0}
.plano-nivel:hover{border-color:var(--acento);background:#eef4ff}
.plano-nivel b{flex:1 1 auto;min-width:0;font-size:14px}
.plano-nivel small{flex:0 0 auto;color:var(--gris);font-size:11.5px;white-space:nowrap}
/* El nivel donde está el artículo que se está mirando. */
.plano-nivel.aca{border-color:var(--ok);background:#eaf7ee}
.plano-nivel.aca small{color:var(--ok);font-weight:700}
.plano-nivel.inactivo{opacity:.5}

@media(max-width:600px){
  /* En el teléfono el plano NO se comprime hasta ser ilegible: las celdas
     tienen un ancho mínimo y el plano scrollea adentro de su propio recuadro.
     Con `minmax(0,1fr)` a secas, 24 columnas en 375 px dejaban 15 px por rack
     y el código «1-A» se recortaba en «1…» — el texto no se desbordaba, pero
     tampoco se podía leer, que para un plano es lo mismo que no estar. El
     scroll horizontal queda ENCERRADO acá adentro: la pantalla no se corre. */
  .plano{grid-template-columns:repeat(var(--plano-cols,24),minmax(26px,1fr));
         grid-template-rows:repeat(var(--plano-filas,16),minmax(18px,auto));padding:8px;gap:2px}
  .plano-rack{padding:4px 3px}
  .plano-rack b{font-size:14px}
  .plano-rack small{display:none}
  .plano-nivel{min-height:52px}
}

/* ═══════════════════════════════════════════════════════════════════════════
   EL TEXTO SE AMOLDA AL CUADRO (regla del dueño, 31/07/2026)

   Un botón, una tarjeta o un KPI tienen que contener su texto sea cual sea:
   el nombre de un producto es largo, el de una sucursal también, y un importe
   de ocho cifras no entra donde entraba el ejemplo de tres.

   `min-width:0` es la regla que arregla el 90% de los casos: por defecto un
   hijo de flex NO se achica por debajo del ancho de su contenido, así que un
   texto largo estira el contenedor y desborda todo lo que esté al lado. Se
   aplica de forma general a los contenedores flex del sistema.
   ═══════════════════════════════════════════════════════════════════════════ */
.row>*,.barra>*,.pantalla-tit>*,.kpi>*{min-width:0}

/* Recorte con puntos suspensivos. Va con title= para que el texto completo
   siga estando a un hover de distancia — recortar sin poder leerlo entero es
   esconder información, no amoldarla. */
.recorta{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Los importes de los KPI: escalan con el ancho disponible en vez de
   desbordar. clamp() resuelve sin una línea de JavaScript lo que antes pedía
   medir y achicar a mano. */
.kpi b{font-size:clamp(17px,2.4vw,22px);font-variant-numeric:tabular-nums;
       overflow-wrap:anywhere;min-width:0}

/* Y CADA COSA EN SU RENGLÓN. El número y su aclaración eran los dos `inline`,
   así que se pegaban uno al otro sin ni un espacio: «$ 14.178.437,00Cobrado
   menos devoluciones». Con importes de tres cifras no se notaba; con la venta
   de un mes de verdad, el KPI dejó de leerse. `.kpis-tablero` ya lo resolvía
   por su lado (es un flex en columna) y el resto del sistema se había quedado
   sin ese arreglo. Es la misma regla del dueño: el texto se amolda al cuadro. */
.kpi b{display:block}
.kpi small{display:block;color:var(--gris);font-size:11.5px;line-height:1.35;
           overflow-wrap:anywhere;min-width:0}

/* Los botones con texto variable (el nombre de una sucursal, un importe)
   parten en dos renglones antes que desbordar. Un botón de 48px de alto tiene
   lugar para dos líneas; no lo tiene para media palabra afuera. */
.btn,.btn2{overflow-wrap:anywhere;min-width:0}

/* El plano cuando se abre para tocarlo desde el salón. Mismo marco que el
   diálogo de la cámara —es la misma pantalla y el mismo pulgar— pero más alto:
   un local con seis pasillos no entra en la altura de un visor de cámara. */
.salon-plano{width:min(680px,calc(100vw - 20px));max-height:calc(100dvh - 40px);overflow:auto;
             max-width:none;padding:14px;border:1px solid var(--bd);border-radius:16px;
             background:var(--panel);box-shadow:var(--sombra-modal)}
.salon-plano::backdrop{background:rgba(22,20,15,.55)}
.salon-plano p{margin:2px 0 0;color:var(--gris);font-size:13px}
@media(max-width:600px){
  .salon-plano{padding:10px;width:calc(100vw - 12px)}
}

/* ── Dónde está el artículo, en el salón ──────────────────────────────────
   Un artículo puede estar en la góndola Y guardado atrás. Los dos se muestran,
   con la góndola primero, porque son dos respuestas a dos preguntas distintas:
   «¿dónde lo agarra el cliente?» y «¿de dónde repongo?». */
.salon-lugares{margin:8px 0 0;display:flex;flex-wrap:wrap;gap:6px 14px}
.salon-lugar{display:inline-flex;align-items:baseline;gap:6px;min-width:0;
             font-size:14px;font-weight:700;color:var(--tinta)}
.salon-lugar .ico{align-self:center;flex:0 0 auto}
.salon-lugar b{min-width:0;font-weight:700}
.salon-lugar small{color:var(--gris);font-weight:600;font-size:11.5px;white-space:nowrap}
/* El guardado se ve un escalón más bajo: es información de apoyo, no la
   respuesta que se le da al cliente parado enfrente. */
.salon-lugar.guardado{color:var(--gris);font-weight:600}
.salon-lugar.guardado b{font-weight:600}

/* Corregir un lugar mal anotado es la excepción: chico y discreto, para que no
   compita con el botón de sumar uno nuevo. */
.salon-sacar{margin:6px 0 0;display:flex;flex-wrap:wrap;gap:6px 12px}
.salon-sacar form{margin:0}
.salon-sacar button{border:0;background:none;padding:0;cursor:pointer;
                    font:600 11.5px/1.3 inherit;color:var(--gris);text-decoration:underline}
.salon-sacar button:hover{color:var(--mal)}

/* El grupo de «para qué es» dentro del plano: separado de los niveles por una
   línea, porque son dos decisiones distintas y una viene después de la otra. */
.salon-para-que{margin:0 0 12px;padding:0 0 12px;border-bottom:1px solid var(--bd)}

/* Las fichas de los racks: están todas en el HTML —son pocas y hay que poder
   editarlas sin ir y volver— pero se muestra la del rack que se tocó. */
.plano-fichas{margin-top:12px}
.plano-ficha[hidden]{display:none}
.plano-ficha{border:1px solid var(--bd);border-radius:12px;background:var(--panel);padding:12px 14px}
.plano-nivel-fila{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:8px}
/* Cada hijo puede achicarse: sin esto, el código del nivel («1-A-Punta de
   góndola») estira la fila y empuja el resto fuera de la tarjeta. */
.plano-nivel-fila>*{min-width:0}
.plano-nivel-fila .plano-nivel{flex:0 1 220px;margin:0;text-decoration:none}
@media(max-width:600px){
  .plano-nivel-fila .plano-nivel{flex:1 1 100%}
}

/* ── Lo que se configura una vez y no se vuelve a mirar ───────────────────
   Regla del dueño: lo que no hace falta el 99% de los días no puede estar a la
   vista compitiendo con lo que sí. Va detrás de un `<details>` que dice con
   todas las letras qué hay adentro — «Configuración avanzada» a secas sería
   otra etiqueta que no le dice nada a nadie. */
.avanzado{margin-top:14px;border-top:1px solid var(--bd);padding-top:12px}
.avanzado>summary{display:block;color:var(--gris);font-size:12.5px;font-weight:700;
                  cursor:pointer;overflow-wrap:anywhere;min-width:0}
.avanzado>summary:hover{color:var(--tinta)}
.avanzado[open]>summary{margin-bottom:12px;color:var(--tinta)}

/* ═══════════════════════════════════════════════════════════════════════════
   .opcion — UNA opción para tocar: marca + título + explicación

   Existe porque este layout lo armamos a mano tres veces y las tres se rompió
   igual: con `display:flex`, el bloque de texto es un hijo que puede encogerse
   hasta CERO y su contenido se desborda fuera del recuadro. Le pasó a los
   motivos de «lo deja», al alcance del descuento y al «góndola / guardado» del
   salón — este último se lo encontró el dueño usándolo.

   La cura es declarar las columnas en vez de dejar que el navegador reparta:
   `auto` para la marca y `minmax(0,1fr)` para el texto. Ese `0` es lo que
   permite que el texto se achique y parta en dos renglones ANTES que desbordar.

   ⚠️ Para una opción con texto se usa ESTA clase. No se arma otro flex a mano:
   la cuarta vez se va a romper igual que las tres anteriores.
   ═══════════════════════════════════════════════════════════════════════════ */
.opcion{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:10px;
        margin:0;padding:10px 12px;border:1px solid var(--bd);border-radius:10px;
        background:var(--panel);cursor:pointer;min-width:0}
.opcion>input{margin:0;justify-self:center}
.opcion>span{min-width:0;display:block;line-height:1.3}
.opcion b{display:block;font-size:13.5px;font-weight:700;overflow-wrap:anywhere}
.opcion small{display:block;color:var(--gris);font-size:11.5px;overflow-wrap:anywhere}
.opcion:hover{border-color:var(--acento)}
.opcion:has(input:checked){border-color:var(--acento);background:#eef4ff}
/* Sin :has() (navegador viejo) la opción elegida igual se distingue por el
   punto del radio; el color es una ayuda, no la única señal. */

/* Un grupo de opciones. Se parten solas cuando no entran, en vez de apretarse
   hasta que el texto se sale. */
.opciones{display:flex;flex-wrap:wrap;gap:8px;margin:0;padding:0;border:0}
.opciones>legend{padding:0;width:100%;margin-bottom:6px;font-size:13px;color:var(--tinta);font-weight:650}
.opciones>.opcion{flex:1 1 200px}
@media(max-width:600px){
  /* En el teléfono una abajo de la otra: dos opciones apretadas en 375px es
     exactamente donde el texto empieza a pelear con el recuadro. */
  .opciones>.opcion{flex:1 1 100%}
}

/* ═══ PIEZAS PARA FICHAS Y LISTAS (15/10/2026, menos ruido) ═══════════════
   Lo que comparten las pantallas que se simplificaron mirando Dolibarr y
   ERPNext. Una ficha: título + estado + acciones en una línea (.pantalla), los
   datos en una grilla (dl.datos), los renglones como contenido principal, y lo
   secundario plegado (details.plegable). */
dl.datos{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:10px 24px;margin:0 0 18px}
dl.datos>div{min-width:0}
/* Un texto largo (las notas de una compra) ocupa la fila entera en vez de una columna de 190. */
dl.datos>.ancho{grid-column:1/-1}
dl.datos dt{margin:0;font-size:12px;color:var(--gris)}
dl.datos dd{margin:2px 0 0;font-weight:600;overflow-wrap:anywhere}
dl.datos dd small{display:block;font-weight:400;color:var(--gris)}
details.plegable{background:var(--panel);border:1px solid var(--bd);border-radius:12px;margin:0 0 16px}
details.plegable>summary{list-style:none;cursor:pointer;position:relative;padding:14px 18px 14px 38px;
                          font-size:15px;font-weight:650;color:var(--tinta);border-radius:12px}
details.plegable>summary::-webkit-details-marker{display:none}
details.plegable>summary::before{content:"";position:absolute;left:19px;top:21px;width:6px;height:6px;
  border-right:1.6px solid var(--gris2);border-bottom:1.6px solid var(--gris2);transform:rotate(-45deg);transition:transform .15s}
details.plegable[open]>summary::before{transform:rotate(45deg);top:19px}
details.plegable>summary:hover{background:var(--hover)}
details.plegable>summary small{font-weight:400;color:var(--gris);font-size:12.5px;margin-left:6px}
details.plegable>.plegable-in{padding:0 18px 18px}
@media(max-width:600px){
  /* En el teléfono, de a dos: una ficha de pedido en una sola columna medía tres
     pantallas, y cuatro números en flex quedaban 2-1-1. */
  dl.datos{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 16px}
  .kpis:not(.kpis-tablero){display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
  .kpis:not(.kpis-tablero) .kpi{min-width:0;padding:11px 12px}
  .kpis:not(.kpis-tablero) .kpi b{font-size:19px;overflow-wrap:anywhere}
}


/* ═══════════════════════════════════════════════════════════════════════════
   FICHA DE PRODUCTO (15/10/2026)
   Se parece a la ficha de «Catálogo» del panel de SPRINT en los criterios, no en
   el código: foto grande a la izquierda y el álbum en grilla de cuadrados;
   secciones con título chico y una línea arriba; lo opcional en gris al lado de
   la etiqueta; interruptores en lugar de casillas; los datos cortos en una grilla
   de 4 columnas; el foco con halo del azul de RETAIL-ERP. Todo cuelga de
   dialog.ficha: ninguna regla de arriba cambia para las otras ventanas.
   ═══════════════════════════════════════════════════════════════════════════ */
dialog.modal.ficha{width:min(1040px,calc(100vw - 32px))}
dialog.modal.ficha:not(:modal){width:auto}

.ficha-cols{display:grid;grid-template-columns:minmax(0,300px) minmax(0,1fr);gap:8px 26px;align-items:start}
.ficha-foto{position:sticky;top:0;align-self:start}
.ficha-datos{min-width:0}

/* Sección: una línea arriba y el título chico apoyado sobre ella. */
.ficha .grupo{border-top:1px solid var(--bd);padding-top:12px;margin:0 0 18px}
.ficha .grupo legend{float:left;width:100%;margin:-24px 0 10px;padding:0}
.ficha .grupo legend::after{content:'';display:block;clear:both}
.ficha .grupo>legend+*{clear:both}
/* En tipo oración, como el resto del sistema (15/10/2026: nada de rótulos en mayúscula). */
.ficha .grupo legend{font-size:13.5px;font-weight:650;color:var(--tinta)}
.ficha .ficha-datos>.grupo:first-child,.ficha .ficha-foto>.grupo:first-child{margin-top:4px}

/* Etiqueta en frase normal; lo opcional (o la aclaración) en gris al lado. */
.ficha label{font-size:12.5px;color:var(--tinta);font-weight:600}
.ficha .opc{color:var(--gris2);font-weight:400;font-size:11.5px;margin-left:3px}
.ficha .interruptor{font-weight:400}
/* En las grillas cortas la etiqueta no envuelve: un renglón de más en una sola
   columna desalinea los campos de al lado. */
.ficha :is(.g4,.g3)>.f>label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* Foco con el azul de la casa. */
.ficha :is(input,select,textarea):focus{outline:0;border-color:var(--acento);box-shadow:0 0 0 3px rgba(29,78,216,.18)}
.ficha :is(input,select,textarea)[aria-invalid="true"]:focus{box-shadow:0 0 0 3px rgba(179,38,30,.18)}

/* Grillas de datos cortos. */
.g4,.g3{display:grid;gap:0 12px;align-items:start}
.g4{grid-template-columns:repeat(4,minmax(0,1fr))}
.g3{grid-template-columns:repeat(3,minmax(0,1fr))}
.g4>.s2{grid-column:span 2}
.ficha .g4>.f,.ficha .g3>.f{margin-bottom:12px}
.ficha .hint-codigos,.ficha .hint-margen{margin:-4px 0 14px}
.ficha .precios{margin-top:4px}

/* Un número que se calcula: se lee, no se tipea. */
.ficha input.calculado,.ficha input[readonly]{background:#f6f5f1;color:var(--tinta);font-variant-numeric:tabular-nums;cursor:default}
.ficha #c-efectivo{font-weight:700}
.ficha #c-precio-lista{font-variant-numeric:tabular-nums}
.ficha #c-precio-lista:not([readonly]){font-weight:700}
.ficha .ref{margin-top:6px;padding:6px 10px;font-size:11.5px}

/* Foto grande. */
.foto-grande{aspect-ratio:1/1;width:100%;border:1px solid var(--bd);border-radius:12px;background:#f3f2ee;overflow:hidden;display:grid;place-items:center;margin-bottom:10px}
.foto-grande img{width:100%;height:100%;object-fit:contain;display:block}
.foto-grande img[hidden],.foto-grande-vacio[hidden]{display:none}
.foto-grande-vacio{color:var(--gris2);font-size:12.5px}

/* Álbum: grilla de cuadrados. */
.ficha .galeria{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:0 0 8px}
.ficha .gfoto{width:auto;padding:5px;border-radius:9px}
.ficha .gfoto img{width:100%;height:auto;aspect-ratio:1/1;object-fit:cover}
.ficha .gfoto-orden{margin-top:4px}
.ficha .gflecha{width:24px;height:22px;font-size:12px}

/* Interruptor: reemplaza a la casilla en Activo, Controla stock y Fijar a mano. */
.interruptor{display:flex;gap:11px;align-items:flex-start;margin:0 0 10px;cursor:pointer;position:relative}
.interruptor input{position:absolute;opacity:0;width:1px;height:1px;margin:0;padding:0;pointer-events:none}
.int-t{flex:0 0 auto;width:36px;height:20px;border-radius:100px;background:#c9c6bc;position:relative;margin-top:1px;transition:background .15s}
.int-t::after{content:'';position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.3);transition:left .15s}
.interruptor input:checked+.int-t{background:var(--acento)}
.interruptor input:checked+.int-t::after{left:18px}
.interruptor input:focus-visible+.int-t{box-shadow:0 0 0 3px rgba(29,78,216,.28)}
.int-x{font-size:13px;color:var(--tinta);line-height:1.4}
.int-x small{display:block;color:var(--gris);font-size:11.5px;margin-top:1px}
@media (prefers-reduced-motion:reduce){.int-t,.int-t::after{transition:none}}

/* Stock por sucursal, de solo lectura. */
.mini-tabla{width:100%;border-collapse:collapse;font-size:13px}
.mini-tabla th{text-align:left;font-size:11.5px;font-weight:600;color:var(--gris);padding:0 8px 5px 0;border-bottom:1px solid var(--bd)}
.mini-tabla th.num{text-align:right}
.mini-tabla td{padding:6px 8px 6px 0;border-bottom:1px solid #eeece6;vertical-align:top}
.mini-tabla td.num{text-align:right;padding-right:14px}
.mini-tabla tr:last-child td{border-bottom:0}

/* Pantallas angostas: todo en una columna. */
@media (max-width:820px){
  .ficha-cols{grid-template-columns:minmax(0,1fr)}
  .ficha-foto{position:static}
  .ficha .galeria{grid-template-columns:repeat(4,minmax(0,1fr))}
  .foto-grande{max-width:200px}
}
@media (max-width:640px){
  .g4,.g3{grid-template-columns:minmax(0,1fr)}
  .g4>.s2{grid-column:auto}
  .ficha .galeria{grid-template-columns:repeat(3,minmax(0,1fr))}
}
