/* ==========================================================================
   iGEA LOGI :: design system
   Material / Flat 2.0 + acento por rol + glass en las capas flotantes.
   --------------------------------------------------------------------------
   TRES REGLAS QUE MANDAN SOBRE EL GUSTO PERSONAL

   1. SE USA CON UNA MANO Y CON GUANTES.
      Nada accionable mide menos de 48px. La navegacion y las acciones
      principales viven abajo, al alcance del pulgar; arriba solo va lo que se
      lee, nunca lo que se toca.

   2. EL COLOR ES INFORMACION, NO DECORACION.
      --acc lo inyecta el rol al abrir sesion. Verde = entra stock, rojo =
      sale, ambar = conteo fisico. Si un color no significa algo, es gris.

   3. EL GLASS VA SOLO EN LO QUE FLOTA.
      Barra superior, barra inferior y hojas modales. En una tarjeta con
      numeros el desenfoque solo estorba la lectura, y en tablets baratas
      cuesta frames.
   ========================================================================== */

/* --------------------------------------------------------------------------
   TOKENS
   -------------------------------------------------------------------------- */
:root{
  /* Acento: lo pisa JS con el color del rol. Este es el de reserva. */
  --acc:        #5B4FE9;
  --acc-ink:    #ffffff;
  --acc-soft:   rgba(91,79,233,.10);
  --acc-line:   rgba(91,79,233,.28);

  /* Semanticos. Fijos: no dependen del rol porque significan una operacion. */
  --ok:         #12855A;
  --ok-soft:    rgba(18,133,90,.10);
  --bad:        #C62828;
  --bad-soft:   rgba(198,40,40,.10);
  --warn:       #B26A00;
  --warn-soft:  rgba(178,106,0,.12);

  /* Superficies */
  --bg:         #F4F5F7;
  --surface:    #FFFFFF;
  --surface-2:  #FAFBFC;
  --line:       #E3E6EA;
  --line-soft:  #EEF0F3;

  /* Tinta */
  --ink:        #16191D;
  --ink-2:      #5A6068;
  --ink-3:      #8A9099;

  /* Glass */
  --glass:      rgba(255,255,255,.72);
  --glass-line: rgba(255,255,255,.55);
  --glass-blur: saturate(180%) blur(20px);

  /* Elevacion: sombras cortas y de baja opacidad. Flat 2.0 sugiere el
     relieve, no lo dibuja. */
  --e1: 0 1px 2px rgba(16,24,40,.06), 0 1px 3px rgba(16,24,40,.05);
  --e2: 0 2px 6px rgba(16,24,40,.07), 0 4px 12px rgba(16,24,40,.06);
  --e3: 0 8px 24px rgba(16,24,40,.12), 0 2px 6px rgba(16,24,40,.08);

  /* Geometria: escala de 4, radios generosos */
  --r-s: 10px;
  --r:   14px;
  --r-l: 20px;
  --r-xl:28px;

  /* Alturas fijas que otros calculos necesitan */
  --h-top: 56px;
  --h-nav: 68px;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

/* --------------------------------------------------------------------------
   TEMA CLARO / OSCURO
   --------------------------------------------------------------------------
   Tres estados, no dos: automatico (sigue al sistema), claro forzado y oscuro
   forzado. El automatico no basta porque la tablet del almacen suele quedarse
   en oscuro por la configuracion del turno de noche, y de dia bajo luz
   fluorescente el oscuro se lee peor, no mejor.

   JS pone data-theme en <html>. Sin ese atributo manda el sistema.
   -------------------------------------------------------------------------- */

/* Los valores oscuros, en una sola lista reutilizada por las dos reglas de
   abajo. Si se cambian, se cambian una vez. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="claro"]){
    --bg:         #0F1216;
    --surface:    #171B21;
    --surface-2:  #1D222A;
    --line:       #262C35;
    --line-soft:  #1F242C;
    --ink:        #EDEFF2;
    --ink-2:      #A2AAB4;
    --ink-3:      #6F7883;
    --glass:      rgba(23,27,33,.72);
    --glass-line: rgba(255,255,255,.08);
    --e1: 0 1px 2px rgba(0,0,0,.4);
    --e2: 0 2px 8px rgba(0,0,0,.45);
    --e3: 0 10px 30px rgba(0,0,0,.55);
    --ok-soft:   rgba(18,133,90,.18);
    --bad-soft:  rgba(198,40,40,.18);
    --warn-soft: rgba(178,106,0,.20);
  }
}

/* Oscuro forzado: gana esté como esté el sistema. */
:root[data-theme="oscuro"]{
  --bg:         #0F1216;
  --surface:    #171B21;
  --surface-2:  #1D222A;
  --line:       #262C35;
  --line-soft:  #1F242C;
  --ink:        #EDEFF2;
  --ink-2:      #A2AAB4;
  --ink-3:      #6F7883;
  --glass:      rgba(23,27,33,.72);
  --glass-line: rgba(255,255,255,.08);
  --e1: 0 1px 2px rgba(0,0,0,.4);
  --e2: 0 2px 8px rgba(0,0,0,.45);
  --e3: 0 10px 30px rgba(0,0,0,.55);
  --ok-soft:   rgba(18,133,90,.18);
  --bad-soft:  rgba(198,40,40,.18);
  --warn-soft: rgba(178,106,0,.20);
}

/* Claro forzado: repite los valores de :root porque el @media de arriba ya
   los piso. El :not() de esa regla evita la pelea de especificidad. */
:root[data-theme="claro"]{
  --bg:         #F4F5F7;
  --surface:    #FFFFFF;
  --surface-2:  #FAFBFC;
  --line:       #E3E6EA;
  --line-soft:  #EEF0F3;
  --ink:        #16191D;
  --ink-2:      #5A6068;
  --ink-3:      #8A9099;
  --glass:      rgba(255,255,255,.72);
  --glass-line: rgba(255,255,255,.55);
  --e1: 0 1px 2px rgba(16,24,40,.06), 0 1px 3px rgba(16,24,40,.05);
  --e2: 0 2px 6px rgba(16,24,40,.07), 0 4px 12px rgba(16,24,40,.06);
  --e3: 0 8px 24px rgba(16,24,40,.12), 0 2px 6px rgba(16,24,40,.08);
  --ok-soft:   rgba(18,133,90,.10);
  --bad-soft:  rgba(198,40,40,.10);
  --warn-soft: rgba(178,106,0,.12);
}

/* Selector de tema de la pantalla Cuenta. */
.tema{ display:grid; grid-template-columns:repeat(3,1fr); gap:8px; }
.tema-b{
  padding:12px 6px; border-radius:var(--r);
  border:1.5px solid var(--line); background:var(--surface);
  display:flex; flex-direction:column; align-items:center; gap:5px;
  font-size:12px; font-weight:620; color:var(--ink-2);
}
.tema-b svg{ width:22px; height:22px; }
.tema-b.on{ border-color:var(--acc); background:var(--acc-soft); color:var(--acc); }

/* --------------------------------------------------------------------------
   BASE
   -------------------------------------------------------------------------- */
*,*::before,*::after{ box-sizing:border-box; }

html,body{ height:100%; }

body{
  margin:0;
  font-family:var(--font);
  font-size:15px;
  line-height:1.45;
  color:var(--ink);
  background:var(--bg);
  -webkit-font-smoothing:antialiased;
  -webkit-tap-highlight-color:transparent;
  overscroll-behavior-y:none;          /* sin "pull to refresh" accidental */
}

/* Nada de zoom por doble toque ni seleccion de texto al arrastrar: en el piso
   eso solo produce toques fantasma. Los campos de datos si son seleccionables. */
body{ touch-action:manipulation; user-select:none; -webkit-user-select:none; }
input,textarea,[data-sel]{ user-select:text; -webkit-user-select:text; }

button{ font:inherit; color:inherit; border:0; background:none; cursor:pointer; }
a{ color:var(--acc); text-decoration:none; }

/* Tamanio por defecto de CUALQUIER icono.
   Un <svg> con viewBox pero sin width/height no tiene tamanio intrinseco:
   dentro de un flex se estira hasta ocupar la fila entera. Casi todos los
   iconos reciben medida de una regla del padre (.btn svg, .mod-ic svg...),
   pero los que se usan sueltos —como el chevron de las filas— se quedaban
   sin ninguna. Esta linea cierra ese agujero de una vez; las reglas por
   clase siguen mandando porque tienen mas especificidad. */
svg{ width:20px; height:20px; flex:none; }

/* Los numeros de cantidad se leen en columna: cifras de ancho fijo. */
.num{ font-variant-numeric:tabular-nums; font-feature-settings:"tnum"; }

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

/* --------------------------------------------------------------------------
   LAYOUT
   -------------------------------------------------------------------------- */
#app{ min-height:100%; display:flex; flex-direction:column; }

.view{
  flex:1;
  padding:calc(var(--h-top) + 8px) 14px calc(var(--h-nav) + 24px);
  max-width:760px;              /* en tablet no se estira hasta ser ilegible */
  width:100%;
  margin:0 auto;
}
.view.sin-nav{ padding-bottom:24px; }
.view.sin-top{ padding-top:16px; }

/* --------------------------------------------------------------------------
   BARRA SUPERIOR  (glass)
   -------------------------------------------------------------------------- */
.top{
  position:fixed; inset:0 0 auto 0; z-index:40;
  height:var(--h-top);
  display:flex; align-items:center; gap:10px;
  padding:0 12px;
  background:var(--glass);
  -webkit-backdrop-filter:var(--glass-blur);
  backdrop-filter:var(--glass-blur);
  border-bottom:1px solid var(--line);
}
/* Hilo de acento: identifica el rol sin ocupar espacio ni pedir atencion. */
.top::after{
  content:''; position:absolute; left:0; right:0; bottom:-1px; height:2px;
  background:var(--acc);
}
.top-t{ flex:1; min-width:0; }
.top-t b{ display:block; font-size:15px; font-weight:650; letter-spacing:-.01em;
          white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.top-t span{ display:block; font-size:11.5px; color:var(--ink-2);
             white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

.icon-btn{
  width:42px; height:42px; flex:none;
  display:flex; align-items:center; justify-content:center;
  border-radius:12px; color:var(--ink-2);
  transition:background .15s;
}
.icon-btn:active{ background:var(--line-soft); }
.icon-btn svg{ width:22px; height:22px; }

/* --------------------------------------------------------------------------
   BARRA INFERIOR  (glass)
   -------------------------------------------------------------------------- */
.nav{
  position:fixed; inset:auto 0 0 0; z-index:40;
  height:calc(var(--h-nav) + env(safe-area-inset-bottom));
  padding-bottom:env(safe-area-inset-bottom);
  display:flex;
  background:var(--glass);
  -webkit-backdrop-filter:var(--glass-blur);
  backdrop-filter:var(--glass-blur);
  border-top:1px solid var(--line);
}
.nav-i{
  flex:1; min-width:0;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:3px;
  color:var(--ink-3); font-size:10.5px; font-weight:550;
  position:relative;
}
.nav-i svg{ width:23px; height:23px; }
.nav-i span{ max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; padding:0 2px; }
.nav-i.on{ color:var(--acc); }
/* La pastilla de fondo marca la pestaña activa mejor que un color de icono
   solo, que a contraluz en el almacen casi no se distingue. */
.nav-i.on::before{
  content:''; position:absolute; top:6px; width:52px; height:30px;
  border-radius:15px; background:var(--acc-soft);
}
.nav-i svg,.nav-i span{ position:relative; }

/* Contador del carrito sobre su pestania.
   Es lo que queda del aviso "tienes un carrito a medias" cuando la barra
   flotante dejo de invadir las demas pantallas: informa desde cualquier sitio
   y, al vivir dentro de la pestania, no se pone encima de ningun control.

   Se escribe `.nav-i .nav-n` y no `.nav-n` a secas por la regla de arriba:
   `.nav-i span` empata en clases y gana por el elemento, asi que le devolvia
   el `position:relative` al globo. Volvia a la corriente del flex, se colocaba
   como un tercer renglon debajo del rotulo y empujaba la pestania entera. */
.nav-i .nav-n{
  position:absolute; top:3px; left:calc(50% + 5px);
  min-width:18px; height:18px; padding:0 5px; box-sizing:border-box;
  border-radius:999px;
  background:var(--acc); color:var(--acc-ink);
  font-size:10.5px; font-weight:700; line-height:18px; text-align:center;
  overflow:visible; max-width:none;
  /* Sobre la pastilla de la pestania activa, que es un ::before del mismo
     contenedor y si no le gana el apilado. */
  z-index:2;
  /* El toque es de la pestania entera: el globo no debe partirlo en dos. */
  pointer-events:none;
}

/* --------------------------------------------------------------------------
   TARJETAS
   -------------------------------------------------------------------------- */
.card{
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r);
  box-shadow:var(--e1);
  overflow:hidden;
}
.card + .card{ margin-top:10px; }
.card-p{ padding:14px; }

.card-btn{ width:100%; text-align:left; display:block; }
.card-btn:active{ transform:scale(.985); }
.card,.card-btn{ transition:transform .12s ease, box-shadow .15s ease; }

/* Tarjeta de modulo del inicio: la franja de color la ata al rol. */
.mod{
  display:flex; align-items:center; gap:13px; padding:15px 14px;
  border-left:3px solid var(--acc);
}
.mod-ic{
  width:42px; height:42px; flex:none; border-radius:12px;
  display:flex; align-items:center; justify-content:center;
  background:var(--acc-soft); color:var(--acc);
}
.mod-ic svg{ width:22px; height:22px; }
.mod-t{ flex:1; min-width:0; }
.mod-t b{ display:block; font-size:15px; font-weight:620; }
.mod-t span{ display:block; font-size:12.5px; color:var(--ink-2); line-height:1.35; }
.mod-go{ width:20px; height:20px; flex:none; color:var(--ink-3); }

/* --------------------------------------------------------------------------
   FILA DE ARTICULO
   -------------------------------------------------------------------------- */
.item{ display:flex; align-items:center; gap:12px; padding:11px 13px; }
.item + .item{ border-top:1px solid var(--line-soft); }

.thumb{
  width:46px; height:46px; flex:none; border-radius:11px;
  object-fit:cover; background:var(--surface-2);
  border:1px solid var(--line-soft);
}
.item-t{ flex:1; min-width:0; }
.item-t b{
  display:block; font-size:14px; font-weight:600; line-height:1.3;
  /* Dos lineas: los nombres de repuestos y abarrotes rara vez caben en una. */
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
}
.item-t span{ display:block; font-size:11.5px; color:var(--ink-3); margin-top:2px; }

/* Stock a la derecha, siempre en el mismo sitio: se escanea la columna sin leer. */
.item-s{ flex:none; text-align:right; min-width:62px; }
.item-s b{ display:block; font-size:17px; font-weight:680; letter-spacing:-.02em; }
.item-s span{ display:block; font-size:10.5px; color:var(--ink-3); text-transform:uppercase; letter-spacing:.04em; }
.item-s.cero b{ color:var(--ink-3); }
.item-s.neg  b{ color:var(--bad); }

/* --------------------------------------------------------------------------
   CHIPS  ::  filtros y estados
   -------------------------------------------------------------------------- */
.chips{ display:flex; gap:7px; overflow-x:auto; padding:2px 0 8px; margin:0 -14px; padding-left:14px; padding-right:14px; }
.chips::-webkit-scrollbar{ display:none; }
.chip{
  flex:none; height:34px; padding:0 13px; border-radius:17px;
  display:inline-flex; align-items:center; gap:6px;
  background:var(--surface); border:1px solid var(--line);
  font-size:12.5px; font-weight:550; color:var(--ink-2);
  white-space:nowrap;
}
.chip.on{ background:var(--acc); border-color:var(--acc); color:var(--acc-ink); }
.chip svg{ width:15px; height:15px; }

.tag{
  display:inline-flex; align-items:center; gap:5px;
  height:22px; padding:0 8px; border-radius:6px;
  font-size:11px; font-weight:650; letter-spacing:.02em;
}
.tag.ok  { background:var(--ok-soft);   color:var(--ok);   }
.tag.bad { background:var(--bad-soft);  color:var(--bad);  }
.tag.warn{ background:var(--warn-soft); color:var(--warn); }
.tag.mute{ background:var(--line-soft); color:var(--ink-2); }

/* --------------------------------------------------------------------------
   BOTONES
   -------------------------------------------------------------------------- */
.btn{
  height:50px; padding:0 20px; border-radius:var(--r-s);
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  font-size:15px; font-weight:620; letter-spacing:-.01em;
  background:var(--surface); color:var(--ink); border:1px solid var(--line);
  transition:transform .1s, opacity .15s;
}
.btn:active{ transform:scale(.97); }
.btn:disabled{ opacity:.45; pointer-events:none; }
.btn svg{ width:19px; height:19px; }

.btn.pri{ background:var(--acc); color:var(--acc-ink); border-color:transparent; box-shadow:var(--e2); }
.btn.ok { background:var(--ok);  color:#fff; border-color:transparent; }
.btn.bad{ background:var(--bad); color:#fff; border-color:transparent; }
.btn.ghost{ background:transparent; border-color:transparent; color:var(--ink-2); }
.btn.full{ width:100%; }
.btn.lg{ height:56px; font-size:16px; }

/* Boton flotante del escaner. Es la accion mas repetida del turno y por eso
   es la unica que tiene tamaño propio. */
.fab{
  position:fixed; right:16px; z-index:45;
  bottom:calc(var(--h-nav) + env(safe-area-inset-bottom) + 16px);
  width:58px; height:58px; border-radius:19px;
  display:flex; align-items:center; justify-content:center;
  background:var(--acc); color:var(--acc-ink); box-shadow:var(--e3);
}
.fab:active{ transform:scale(.93); }
.fab svg{ width:26px; height:26px; }

/* --------------------------------------------------------------------------
   CAMPOS
   -------------------------------------------------------------------------- */
.field{ margin-bottom:13px; }
.field > label{
  display:block; font-size:12px; font-weight:620; color:var(--ink-2);
  margin:0 0 6px 2px; letter-spacing:.01em;
}
.inp{
  width:100%; height:50px; padding:0 14px;
  border:1.5px solid var(--line); border-radius:var(--r-s);
  background:var(--surface); color:var(--ink);
  font-size:16px;                 /* 16px o iOS hace zoom al enfocar */
  font-family:inherit;
  transition:border-color .15s, box-shadow .15s;
  appearance:none; -webkit-appearance:none;
}
.inp:focus{ outline:0; border-color:var(--acc); box-shadow:0 0 0 3.5px var(--acc-soft); }
.inp::placeholder{ color:var(--ink-3); }
textarea.inp{ height:auto; min-height:86px; padding:12px 14px; resize:vertical; line-height:1.45; }
select.inp{
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' fill='none' stroke='%238A9099' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M5 8l5 5 5-5'/></svg>");
  background-repeat:no-repeat; background-position:right 12px center; padding-right:40px;
}
.hint{ font-size:11.5px; color:var(--ink-3); margin:5px 2px 0; line-height:1.4; }
.hint.bad{ color:var(--bad); }

/* Buscador con lupa e icono de camara integrados. */
.search{ position:relative; margin-bottom:10px; }
.search .inp{ padding-left:44px; padding-right:50px; }
.search-ic{ position:absolute; left:13px; top:15px; color:var(--ink-3); pointer-events:none; }
.search-ic svg{ width:20px; height:20px; }
.search-cam{ position:absolute; right:5px; top:5px; width:40px; height:40px;
             display:flex; align-items:center; justify-content:center;
             border-radius:9px; color:var(--acc); }

/* --------------------------------------------------------------------------
   SELECTOR DE MODO  ::  ingresar / retirar / ajustar
   --------------------------------------------------------------------------
   Los tres modos son la decision mas delicada de todo el flujo: equivocarse
   aqui mueve stock al reves. Por eso no es un <select>, sino tres bloques
   grandes, con color propio y verbo en infinitivo.
   -------------------------------------------------------------------------- */
.modos{ display:grid; grid-template-columns:repeat(3,1fr); gap:8px; margin-bottom:14px; }
.modo{
  padding:13px 6px 11px; border-radius:var(--r);
  border:1.5px solid var(--line); background:var(--surface);
  display:flex; flex-direction:column; align-items:center; gap:5px;
  font-size:12px; font-weight:640; color:var(--ink-2);
  transition:all .15s;
}
.modo svg{ width:24px; height:24px; }
.modo small{ font-size:10px; font-weight:500; color:var(--ink-3); line-height:1.2; text-align:center; }

.modo.on{ color:#fff; border-color:transparent; box-shadow:var(--e2); }
.modo.on small{ color:rgba(255,255,255,.82); }
.modo[data-m="entrada"].on{ background:var(--ok);   }
.modo[data-m="salida"].on { background:var(--bad);  }
.modo[data-m="fisico"].on { background:var(--warn); }

/* --------------------------------------------------------------------------
   TECLADO NUMERICO  ::  cantidades y PIN
   -------------------------------------------------------------------------- */
.pad{ display:grid; grid-template-columns:repeat(3,1fr); gap:9px; }
.pad-k{
  height:60px; border-radius:var(--r);
  background:var(--surface); border:1px solid var(--line);
  font-size:23px; font-weight:600; color:var(--ink);
  display:flex; align-items:center; justify-content:center;
  box-shadow:var(--e1);
}
.pad-k:active{ background:var(--acc-soft); transform:scale(.95); }
.pad-k.fn{ background:transparent; box-shadow:none; border-color:transparent; color:var(--ink-2); }
.pad-k svg{ width:24px; height:24px; }

/* Visor de la cantidad tecleada. */
.pad-vis{
  text-align:center; padding:16px 0 20px;
  font-size:46px; font-weight:700; letter-spacing:-.03em; line-height:1;
}
.pad-vis small{ display:block; font-size:12px; font-weight:600; color:var(--ink-3);
                letter-spacing:.06em; text-transform:uppercase; margin-top:8px; }

/* Puntos del PIN */
.pin-dots{ display:flex; justify-content:center; gap:13px; padding:22px 0 26px; }
.pin-dot{ width:14px; height:14px; border-radius:50%; background:var(--line);
          transition:transform .15s, background .15s; }
.pin-dot.on{ background:var(--acc); transform:scale(1.18); }
@keyframes shake{ 10%,90%{transform:translateX(-2px)} 30%,70%{transform:translateX(4px)} 50%{transform:translateX(-6px)} }
.pin-dots.err{ animation:shake .4s; }
.pin-dots.err .pin-dot{ background:var(--bad); }

/* --------------------------------------------------------------------------
   HOJA INFERIOR  (glass)  ::  reemplaza a los modales
   --------------------------------------------------------------------------
   Sube desde abajo, se cierra arrastrando y deja ver el contexto detras. En
   una tablet sostenida con una mano llega al pulgar; un modal centrado no.
   -------------------------------------------------------------------------- */
.sheet-bg{
  position:fixed; inset:0; z-index:60;
  background:rgba(10,12,16,.42);
  -webkit-backdrop-filter:blur(2px); backdrop-filter:blur(2px);
  opacity:0; transition:opacity .22s;
}
.sheet-bg.on{ opacity:1; }

.sheet{
  position:fixed; inset:auto 0 0 0; z-index:61;
  max-height:92vh; display:flex; flex-direction:column;
  background:var(--surface);
  border-radius:var(--r-xl) var(--r-xl) 0 0;
  box-shadow:var(--e3);
  padding-bottom:env(safe-area-inset-bottom);
  transform:translateY(100%); transition:transform .28s cubic-bezier(.22,1,.36,1);
}
.sheet.on{ transform:translateY(0); }
.sheet.glass{
  background:var(--glass);
  -webkit-backdrop-filter:var(--glass-blur); backdrop-filter:var(--glass-blur);
  border-top:1px solid var(--glass-line);
}
.sheet-grip{ width:38px; height:4px; border-radius:2px; background:var(--line);
             margin:9px auto 4px; flex:none; }
.sheet-h{
  padding:8px 16px 12px; border-bottom:1px solid var(--line-soft); flex:none;
  display:flex; align-items:flex-start; gap:10px;
}
.sheet-h b{ flex:1; font-size:17px; font-weight:660; letter-spacing:-.01em; }
.sheet-b{ padding:16px; overflow-y:auto; -webkit-overflow-scrolling:touch; flex:1; }
.sheet-f{
  padding:12px 16px calc(12px + env(safe-area-inset-bottom));
  border-top:1px solid var(--line-soft); flex:none;
  display:flex; gap:9px;
}
.sheet-f .btn{ flex:1; }

/* --------------------------------------------------------------------------
   CARRITO  ::  la barra que resume lo acumulado
   -------------------------------------------------------------------------- */
.cart-bar{
  position:fixed; left:12px; right:12px; z-index:44;
  bottom:calc(var(--h-nav) + env(safe-area-inset-bottom) + 12px);
  display:flex; align-items:center; gap:12px;
  padding:11px 13px; border-radius:var(--r-l);
  background:var(--acc); color:var(--acc-ink); box-shadow:var(--e3);
  transform:translateY(140%); transition:transform .3s cubic-bezier(.22,1,.36,1);
}
.cart-bar.on{ transform:translateY(0); }

/* Vacia = fuera de la pantalla, de verdad.
   translateY(140%) es relativo a la ALTURA del elemento: sin contenido la
   barra mide lo que su padding, se desplaza tres dedos y se queda asomando
   abajo como una franja de color. Ocultarla es la unica forma de que no
   estorbe entre pantallas. */
.cart-bar:empty{ display:none; }
.cart-n{
  width:34px; height:34px; flex:none; border-radius:11px;
  background:rgba(255,255,255,.22);
  display:flex; align-items:center; justify-content:center;
  font-size:15px; font-weight:700;
}
.cart-t{ flex:1; min-width:0; font-size:13px; line-height:1.3; }
.cart-t b{ display:block; font-size:14.5px; font-weight:650; }
.cart-t span{ opacity:.85; font-size:11.5px; }
.cart-go{ flex:none; display:flex; align-items:center; gap:4px;
          font-size:13.5px; font-weight:650; padding:8px 12px;
          border-radius:11px; background:rgba(255,255,255,.2); }

/* Linea del carrito con delta a la vista. */
.line{ display:flex; align-items:center; gap:11px; padding:11px 0; }
.line + .line{ border-top:1px solid var(--line-soft); }
.line-t{ flex:1; min-width:0; }
.line-t b{ display:block; font-size:13.5px; font-weight:600; line-height:1.3;
           display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
.line-t span{ font-size:11px; color:var(--ink-3); }
.line-q{ flex:none; text-align:right; font-size:16px; font-weight:680; }
.line-q.mas  { color:var(--ok);  }
.line-q.menos{ color:var(--bad); }
.line-x{ flex:none; width:34px; height:34px; display:flex; align-items:center;
         justify-content:center; border-radius:9px; color:var(--ink-3); }
.line-x:active{ background:var(--bad-soft); color:var(--bad); }

/* --------------------------------------------------------------------------
   ESTADOS
   -------------------------------------------------------------------------- */
.empty{ text-align:center; padding:52px 24px; color:var(--ink-3); }
.empty svg{ width:52px; height:52px; margin-bottom:14px; opacity:.5; }
.empty b{ display:block; font-size:15px; color:var(--ink-2); font-weight:600; margin-bottom:5px; }
.empty p{ margin:0; font-size:13px; line-height:1.5; }

/* Esqueletos: la lista mantiene su forma mientras carga, asi la pantalla no
   salta cuando llegan los datos. */
@keyframes sk{ 0%{opacity:.55} 50%{opacity:1} 100%{opacity:.55} }
.sk{ background:var(--line-soft); border-radius:7px; animation:sk 1.3s ease-in-out infinite; }
.sk-row{ display:flex; align-items:center; gap:12px; padding:12px 13px; }
.sk-row + .sk-row{ border-top:1px solid var(--line-soft); }

.spin{ width:19px; height:19px; border:2.5px solid var(--line);
       border-top-color:var(--acc); border-radius:50%; animation:sp .7s linear infinite; }
@keyframes sp{ to{ transform:rotate(360deg) } }

/* Avisos flotantes. Arriba, para no tapar la barra de acciones. */
.toast-wrap{
  position:fixed; top:calc(var(--h-top) + 10px); left:12px; right:12px; z-index:80;
  display:flex; flex-direction:column; gap:8px; pointer-events:none;
}
.toast{
  padding:12px 15px; border-radius:var(--r);
  background:var(--surface); border:1px solid var(--line);
  box-shadow:var(--e3); font-size:13.5px; font-weight:550;
  display:flex; align-items:flex-start; gap:10px;
  animation:tin .25s cubic-bezier(.22,1,.36,1);
}
@keyframes tin{ from{ transform:translateY(-14px); opacity:0 } }
.toast svg{ width:19px; height:19px; flex:none; margin-top:1px; }
.toast.ok  { border-left:3px solid var(--ok);   }
.toast.ok svg  { color:var(--ok);   }
.toast.bad { border-left:3px solid var(--bad);  }
.toast.bad svg { color:var(--bad);  }
.toast.warn{ border-left:3px solid var(--warn); }
.toast.warn svg{ color:var(--warn); }
.toast.out{ animation:tout .2s forwards; }
@keyframes tout{ to{ transform:translateY(-14px); opacity:0 } }

/* Franja de sin conexion: informa sin bloquear, porque consultar el stock en
   cache sigue siendo util aunque no haya senal. */
.offline{
  position:fixed; left:0; right:0; top:var(--h-top); z-index:50;
  padding:6px 14px; text-align:center;
  background:var(--warn); color:#fff; font-size:12px; font-weight:620;
}

/* --------------------------------------------------------------------------
   LOGIN / PIN  ::  pantallas a cara completa
   -------------------------------------------------------------------------- */
.auth{
  min-height:100vh; min-height:100dvh;
  display:flex; flex-direction:column; justify-content:center;
  padding:32px 22px calc(32px + env(safe-area-inset-bottom));
  max-width:420px; margin:0 auto; width:100%;
}
.auth-logo{
  width:66px; height:66px; border-radius:21px; margin:0 auto 20px;
  display:flex; align-items:center; justify-content:center;
  background:var(--acc); color:var(--acc-ink); box-shadow:var(--e2);
}
.auth-logo svg{ width:34px; height:34px; }
.auth h1{ text-align:center; font-size:23px; font-weight:700; letter-spacing:-.02em; margin:0 0 5px; }
.auth p.sub{ text-align:center; font-size:13.5px; color:var(--ink-2); margin:0 0 28px; }

/* Fondo con dos halos del color del rol: da identidad sin costar rendimiento
   (son gradientes, no filtros). */
.auth-bg{ position:fixed; inset:0; z-index:-1; overflow:hidden; background:var(--bg); }
.auth-bg::before,.auth-bg::after{
  content:''; position:absolute; border-radius:50%;
  background:var(--acc); opacity:.13; filter:blur(70px);
}
.auth-bg::before{ width:290px; height:290px; top:-90px; right:-70px; }
.auth-bg::after { width:230px; height:230px; bottom:-70px; left:-60px; opacity:.09; }

/* Tarjeta del usuario recordado: el operario reconoce su nombre y solo pone
   el PIN, sin volver a escribir el usuario cada turno. */
.who{
  display:flex; align-items:center; gap:12px; padding:13px;
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r); margin-bottom:20px; box-shadow:var(--e1);
}
.who-av{
  width:44px; height:44px; flex:none; border-radius:14px;
  background:var(--acc); color:var(--acc-ink);
  display:flex; align-items:center; justify-content:center;
  font-size:17px; font-weight:700;
}
.who-t{ flex:1; min-width:0; }
.who-t b{ display:block; font-size:14.5px; font-weight:640;
          white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.who-t span{ display:block; font-size:11.5px; color:var(--acc); font-weight:600; }

/* --------------------------------------------------------------------------
   UTILIDADES
   -------------------------------------------------------------------------- */
.row{ display:flex; align-items:center; gap:10px; }
.row.wrap{ flex-wrap:wrap; }
.grow{ flex:1; min-width:0; }

/* Boton que ocupa todo el ancho y alinea a la izquierda: los selectores del
   formulario de guia son botones, no <select>, porque abren un buscador. Sin
   esto se veen centrados y cortos, como si fueran acciones. */
.btn.ancho{ width:100%; }
.center{ text-align:center; }
.right{ text-align:right; }
.mt-0{margin-top:0}   .mt-1{margin-top:8px}  .mt-2{margin-top:16px} .mt-3{margin-top:24px}
.mb-0{margin-bottom:0}.mb-1{margin-bottom:8px}.mb-2{margin-bottom:16px}
.hide{ display:none !important; }

.sec-t{
  font-size:11.5px; font-weight:700; color:var(--ink-3);
  text-transform:uppercase; letter-spacing:.07em;
  margin:20px 2px 9px;
}
.kv{ display:flex; justify-content:space-between; gap:14px; padding:9px 0; font-size:13.5px; }
.kv + .kv{ border-top:1px solid var(--line-soft); }
.kv b{ font-weight:620; text-align:right; }
.kv span{ color:var(--ink-2); }

/* Quien prefiera menos movimiento, menos movimiento. */
@media (prefers-reduced-motion: reduce){
  *{ animation-duration:.01ms !important; transition-duration:.01ms !important; }
}

/* ==========================================================================
   iGEA POS  ::  anexo al design system
   --------------------------------------------------------------------------
   Todo lo de arriba es el app.css de iGEA Logi, copiado SIN TOCAR. Se mantiene
   asi a proposito: cuando el sistema evolucione, se reemplaza ese bloque y
   este anexo sigue valiendo. Dos apps, un solo lenguaje.

   Aqui abajo va unicamente lo que el POS necesita y el almacen no: vender
   tiene piezas propias —precio, carrito con importes, medios de pago, vuelto—
   que en logi no existen.

   Se respetan las tres reglas de la casa:
     1. Nada accionable por debajo de 48px.
     2. El color informa: verde cobra, rojo falta, ambar avisa. Nunca decora.
     3. El glass solo en lo que flota.
   ========================================================================== */

/* --------------------------------------------------------------------------
   ACENTO DEL POS
   --------------------------------------------------------------------------
   En logi el acento lo inyecta el rol al abrir sesion. El POS tiene un solo
   rol —se vende— asi que lo fija aqui y no cambia nunca. Se mantiene el indigo
   de la familia: quien usa las dos apps reconoce que son la misma casa.
   -------------------------------------------------------------------------- */
:root{
  --acc:      #5B4FE9;
  --acc-ink:  #FFFFFF;
  --acc-soft: rgba(91,79,233,.10);
  --acc-line: rgba(91,79,233,.28);
}

/* --------------------------------------------------------------------------
   FILA DE PRODUCTO EN VENTA
   --------------------------------------------------------------------------
   Reusa .item del sistema. Lo unico propio es la columna derecha: en el
   almacen ahi va el stock, aqui va el PRECIO, que es lo que el cajero busca
   con la mirada. El stock baja a una etiqueta pequena bajo el nombre.
   -------------------------------------------------------------------------- */
.item-p{ flex:none; text-align:right; min-width:74px; }
.item-p b{ display:block; font-size:16px; font-weight:680; letter-spacing:-.02em; }
.item-p span{ display:block; font-size:10.5px; color:var(--ink-3);
              text-transform:uppercase; letter-spacing:.04em; }
/* Sin precio en la lista activa: no se puede vender y hay que verlo de lejos. */
.item-p.nop b{ font-size:12px; font-weight:620; color:var(--bad); letter-spacing:0; }

/* La foto del producto no siempre existe. El hueco gris con icono evita que
   la lista baile cuando unas filas traen imagen y otras no. */
.thumb-vacio{
  display:flex; align-items:center; justify-content:center;
  color:var(--ink-3);
}
.thumb-vacio svg{ width:22px; height:22px; }

/* --------------------------------------------------------------------------
   LINEA DEL CARRITO
   --------------------------------------------------------------------------
   .line del sistema, mas el escalon de cantidad. Los tres controles (menos,
   cifra, mas) miden 48 y estan pegados: se opera con el pulgar sin mirar.
   -------------------------------------------------------------------------- */
.paso{ display:flex; align-items:center; gap:6px; flex:none; }
.paso-b{
  width:48px; height:48px; flex:none; border-radius:var(--r-s);
  display:flex; align-items:center; justify-content:center;
  background:var(--surface-2); border:1px solid var(--line); color:var(--ink);
}
.paso-b:active{ background:var(--acc-soft); border-color:var(--acc-line); transform:scale(.94); }
.paso-b svg{ width:20px; height:20px; }
.paso-n{
  width:62px; height:48px; flex:none; text-align:center;
  border:1.5px solid var(--line); border-radius:var(--r-s);
  background:var(--surface); color:var(--ink);
  font-size:16px; font-weight:680; font-family:inherit;
  font-variant-numeric:tabular-nums;
  appearance:none; -webkit-appearance:none;
}
.paso-n:focus{ outline:0; border-color:var(--acc); box-shadow:0 0 0 3.5px var(--acc-soft); }

/* El importe de la linea, alineado a la derecha con las demas. */
.line-i{ flex:none; text-align:right; min-width:76px;
         font-size:15px; font-weight:680; letter-spacing:-.02em;
         font-variant-numeric:tabular-nums; }

/* --------------------------------------------------------------------------
   TOTAL
   --------------------------------------------------------------------------
   El numero mas importante de la pantalla. Grande, tabular y separado del
   resto por una linea: el cajero lo canta en voz alta sin equivocarse.
   -------------------------------------------------------------------------- */
.total{
  display:flex; align-items:baseline; justify-content:space-between; gap:14px;
  padding-top:12px; margin-top:6px; border-top:1px solid var(--line);
}
.total span{ font-size:12px; font-weight:700; color:var(--ink-3);
             text-transform:uppercase; letter-spacing:.07em; }
.total b{ font-size:30px; font-weight:720; letter-spacing:-.03em;
          font-variant-numeric:tabular-nums; }

/* --------------------------------------------------------------------------
   MEDIOS DE PAGO
   --------------------------------------------------------------------------
   Cada fila es medio + cuenta + importe. En movil se apilan medio y cuenta y
   el importe queda solo en su linea: escribir un monto en un campo de 90px
   con el teclado numerico abierto es como no tenerlo.
   -------------------------------------------------------------------------- */
.pago{
  display:grid; gap:8px;
  grid-template-columns:1fr 1fr auto;
  grid-template-areas:"medio cuenta quitar" "monto monto monto";
  padding:12px; margin-bottom:10px;
  background:var(--surface-2); border:1px solid var(--line); border-radius:var(--r);
}
.pago .p-medio { grid-area:medio;  margin:0; }
.pago .p-cuenta{ grid-area:cuenta; margin:0; }
.pago .p-monto { grid-area:monto;  margin:0; text-align:right;
                 font-size:19px; font-weight:680; font-variant-numeric:tabular-nums; }
.pago .p-x{
  grid-area:quitar; width:48px; height:50px;
  display:flex; align-items:center; justify-content:center;
  border-radius:var(--r-s); color:var(--ink-3);
}
.pago .p-x:active{ background:var(--bad-soft); color:var(--bad); }
.pago .p-aviso{ grid-column:1 / -1; font-size:11.5px; color:var(--bad); line-height:1.4; }

@media (min-width:560px){
  .pago{ grid-template-columns:1fr 1.4fr 130px auto;
         grid-template-areas:"medio cuenta monto quitar"; }
}

/* Boton de anadir una linea de pago: punteado para leerse como "hay mas sitio"
   y no como una accion principal. */
.mas-linea{
  width:100%; height:48px; border-radius:var(--r-s);
  border:1.5px dashed var(--line); background:transparent;
  color:var(--ink-2); font-size:14px; font-weight:600;
  display:flex; align-items:center; justify-content:center; gap:8px;
}
.mas-linea:active{ background:var(--acc-soft); border-color:var(--acc-line); color:var(--acc); }

/* Resumen del cobro. El vuelto y lo que falta son las dos cifras que deciden
   si la venta se cierra, y por eso son las unicas con color. */
.res{ margin-top:14px; padding:13px; border-radius:var(--r);
      background:var(--surface-2); border:1px solid var(--line); }
.res .kv{ padding:7px 0; }
.res .kv:first-child{ padding-top:0; }
.res .kv.fuerte b{ font-size:16px; }
.res .kv.vuelto b{ color:var(--ok);  font-size:16px; }
.res .kv.falta  b{ color:var(--bad); font-size:16px; }

/* --------------------------------------------------------------------------
   BARRA DE COBRO
   --------------------------------------------------------------------------
   Es la .cart-bar del sistema con el total dentro. Flota sobre la navegacion
   porque cobrar es lo unico que el cajero hace mil veces al dia.
   -------------------------------------------------------------------------- */
.cart-bar .cart-t b{ font-variant-numeric:tabular-nums; }
.cart-go{ min-height:48px; }

/* --------------------------------------------------------------------------
   ESTADO DE LA LECTORA
   --------------------------------------------------------------------------
   Encendida, el foco vuelve solo al buscador. Hay que saberlo de un vistazo:
   si el cajero cree que esta apagada y escanea, el codigo se pierde.
   -------------------------------------------------------------------------- */
.search-cam.on{ background:var(--acc); color:var(--acc-ink); }

/* --------------------------------------------------------------------------
   ACTUALIZACION Y VERSION
   -------------------------------------------------------------------------- */

/* La barra de "hay version nueva" que ocupaba el ancho de la pantalla se
   retiro: interrumpia a media venta y se cerraba sin leer. Ahora el aviso es
   el punto del icono de arriba a la derecha (.icon-btn.upd, al final de este
   archivo) mas la pastilla de version en Cuenta. */

/* Numero de version. Discreto, pero legible: el cajero tiene que poder
   dictarlo por telefono cuando llama a soporte. */
.ver{ margin-top:18px; text-align:center;
      font-size:11px; letter-spacing:.05em; color:var(--ink-3); }

/* --------------------------------------------------------------------------
   AJUSTES DE LA FAMILIA PARA EL POS
   -------------------------------------------------------------------------- */

/* Sin barra de navegacion la vista no necesita reservar sitio abajo, pero si
   el de la barra de cobro cuando esta visible.

   El hueco se calcula con las mismas piezas con las que se posiciona la barra
   —`bottom: --h-nav + safe-area + 12px`— mas su altura (56px) y un respiro.
   Antes eran 96px planos: en un telefono con indicador de inicio la barra sube
   los 34px del area segura y el ultimo control se quedaba justo debajo de
   ella, visible y sin responder al dedo. Un hueco que se calcula distinto de
   lo que tapa es un hueco que tarde o temprano se queda corto. */
.view.con-cobro{
  padding-bottom:calc(var(--h-nav) + env(safe-area-inset-bottom) + 12px + 56px + 20px);
}

/* Cabecera de seccion pegajosa dentro de una hoja larga (medios de pago). */
.sheet-b .sec-t:first-child{ margin-top:0; }

/* --------------------------------------------------------------------------
   DOS ACCESOS EN EL BUSCADOR
   --------------------------------------------------------------------------
   La lectora de mano y la camara son dos caminos distintos y conviven: en el
   mostrador se usa la pistola, en el pasillo el telefono. Se distinguen por
   posicion fija —pistola a la izquierda, camara a la derecha— para que el
   dedo aprenda el sitio y no haya que leer el icono.
   -------------------------------------------------------------------------- */
.search.doble .inp{ padding-right:94px; }
.search .search-cam.izq{ right:49px; }

/* ==========================================================================
   PANTALLA ANCHA  ::  Surface, tablet apaisada, laptop, escritorio
   --------------------------------------------------------------------------
   El diseno base es de una mano y en vertical, que es como se usa un telefono
   en el pasillo. En un mostrador la postura es otra: el aparato esta apoyado,
   se toca con las dos manos y sobra ancho. Aplicar ahi el mismo layout deja
   una columna estrecha en medio de un desierto gris y obliga a cambiar de
   pestania para ver el carrito, que es justo lo que un cajero mira todo el
   rato.

   Asi que a partir de 900px cambian tres cosas:

     1. EL CARRITO NO SE OCULTA NUNCA. Pasa a ser una columna fija a la
        derecha. Es la mitad del trabajo: ver lo que llevas mientras buscas.
     2. LA NAVEGACION SE PONE DE PIE. Un raíl a la izquierda en vez de una
        barra abajo: con el aparato apoyado, el borde inferior queda lejos y
        el lateral cae bajo el pulgar izquierdo.
     3. LAS HOJAS SE CENTRAN. Una hoja de 1300px de ancho pegada abajo no se
        lee; a esa anchura el patron correcto es una tarjeta centrada.

   El corte va por ANCHO y no por orientacion a proposito: un iPad en vertical
   tiene 1024px y agradece el carrito lateral igual que una Surface apaisada.
   ========================================================================== */

@media (min-width: 900px) {

  :root{
    --rail:  96px;    /* raíl de navegacion */
    --carro: 400px;   /* columna del carrito */
  }

  /* --- Rejilla general ---------------------------------------------------
     La barra superior deja de flotar: con el layout en rejilla ya no hay
     nada que se le meta debajo, y siendo estatica se acaban los calculos de
     padding contra su altura. */
  #app{
    display:grid;
    grid-template-columns: var(--rail) minmax(0,1fr) var(--carro);
    grid-template-rows: auto 1fr;
    height:100vh; height:100dvh;
    overflow:hidden;                /* cada columna scrollea por su cuenta */
  }
  .top{ position:static; grid-column:1 / -1; grid-row:1; }

  /* --- Raíl de navegacion ------------------------------------------------ */
  .nav{
    position:static; grid-column:1; grid-row:2;
    flex-direction:column; justify-content:flex-start;
    height:auto; padding:14px 0 0; gap:2px;
    border-top:0; border-right:1px solid var(--line);
    background:var(--surface);      /* sin glass: no flota sobre nada */
    -webkit-backdrop-filter:none; backdrop-filter:none;
  }
  .nav-i{ flex:none; height:68px; gap:5px; font-size:11px; }
  .nav-i.on::before{ top:8px; width:60px; height:38px; border-radius:13px; }

  /* En ancho el carrito esta siempre visible: su pestania sobra. */
  .nav-i[data-vista="carrito"]{ display:none; }

  /* --- Columna central --------------------------------------------------- */
  .view{
    grid-column:2; grid-row:2;
    max-width:none; margin:0;
    padding:18px 20px 28px;
    overflow-y:auto; -webkit-overflow-scrolling:touch;
  }
  .view.con-cobro{ padding-bottom:28px; }   /* la barra de cobro ya no existe */

  /* --- Columna del carrito -----------------------------------------------
     El id gana a .hide aunque .hide lleve !important (100 > 010), asi que el
     JS puede seguir marcandolo oculto sin que aqui se note. Un solo layout
     que mandar, sin ramas en el codigo. */
  #v-carrito{
    display:flex !important; flex-direction:column;
    grid-column:3; grid-row:2;
    padding:18px 16px 20px;
    overflow-y:auto;
    background:var(--surface);
    border-left:1px solid var(--line);
  }
  #v-carrito .sec-t{ margin-top:0; }
  /* La tarjeta crece y empuja el total abajo del todo: el importe queda
     siempre en el mismo sitio, no bailando segun cuantas lineas haya. */
  #v-carrito #carro-card{ flex:1; display:flex; flex-direction:column; }
  /* En columna manda la altura disponible, no un porcentaje de la pantalla.
     min-height:0 es lo que permite que un hijo flexible se ENCOJA y llegue a
     desplazarse; sin el crece y empuja el total fuera de la vista. */
  #v-carrito #carro-lineas{ flex:1; max-height:none; min-height:0; }
  #v-carrito .total b{ font-size:34px; }

  /* La barra flotante de cobro sobra: el boton vive en la columna. */
  .cart-bar{ display:none !important; }

  /* --- Avisos ------------------------------------------------------------
     Sigue fijo porque es transitorio, pero sin taparle el raíl. */
  .offline{ top:var(--h-top); left:var(--rail); }

  /* --- Hojas centradas ---------------------------------------------------- */
  .sheet{
    left:50%; right:auto; bottom:auto; top:50%;
    width:min(620px, 92vw);
    max-height:88vh;
    border-radius:var(--r-xl);
    transform:translate(-50%, -44%) scale(.98); opacity:0;
    transition:transform .24s cubic-bezier(.22,1,.36,1), opacity .2s;
  }
  .sheet.on{ transform:translate(-50%, -50%) scale(1); opacity:1; }
  /* Arrastrar para cerrar no aplica con raton: el asa solo confundiria. */
  .sheet-grip{ display:none; }
  .sheet-h{ padding-top:16px; }

  /* La hoja del escaner necesita mas sitio: el video manda. */
  #sheet-cliente, .sheet.ancha{ width:min(720px, 92vw); }

  /* --- Retoques de densidad ----------------------------------------------
     Con raton el objetivo puede ser mas pequeno, pero estos aparatos tambien
     se tocan con el dedo (una Surface es las dos cosas), asi que las areas
     tactiles NO se reducen. Solo se aprovecha el ancho. */
  .row2 > *{ min-width:0; }
  .pago{ grid-template-columns:1fr 1.4fr 140px auto;
         grid-template-areas:"medio cuenta monto quitar"; }
}


/* --------------------------------------------------------------------------
   MUY ANCHO  ::  monitor de escritorio
   --------------------------------------------------------------------------
   Pasado cierto punto estirar mas la lista de productos no ayuda: las filas
   quedan kilometricas y el ojo pierde el renglon. Se ensancha el carrito, que
   si aprovecha el sitio, y la lista se topa.
   -------------------------------------------------------------------------- */
@media (min-width: 1440px) {
  :root{ --carro: 460px; }
  .view > *{ max-width:1000px; }
}


/* --------------------------------------------------------------------------
   APAISADO Y BAJO  ::  telefono girado
   --------------------------------------------------------------------------
   Un telefono en horizontal tiene ancho de sobra pero apenas 380px de alto.
   Ahi la rejilla de tres columnas no cabe —el carrito quedaria de dos lineas—
   y lo que hay que hacer es lo contrario: recortar altura. La barra superior
   y la inferior encogen para dejar sitio a la lista.
   -------------------------------------------------------------------------- */
@media (max-width: 899px) and (orientation: landscape) and (max-height: 480px) {
  :root{ --h-top:48px; --h-nav:56px; }
  .nav-i{ flex-direction:row; gap:7px; font-size:12px; }
  .nav-i svg{ width:20px; height:20px; }
  .nav-i.on::before{ width:100%; height:40px; top:8px; border-radius:12px; }
  .sheet{ max-height:96vh; }
  .sheet-b{ padding:12px 16px; }
  /* El video del escaner se come toda la pantalla en apaisado si se le deja. */
  #cam-zona [style*="aspect-ratio"]{ aspect-ratio:16/7 !important; }
}

/* --------------------------------------------------------------------------
   MINIATURA EN LA LINEA DEL CARRITO
   --------------------------------------------------------------------------
   Algo mas chica que en la busqueda: la linea del carrito ya carga con el
   escalon de cantidad debajo, y a 46px el bloque queda demasiado alto.

   Se alinea arriba, no al centro: la linea envuelve y la fila superior es la
   del nombre. Centrada, la foto se descolgaria respecto al texto.
   -------------------------------------------------------------------------- */
.line > .thumb{ width:42px; height:42px; border-radius:10px; align-self:flex-start; }
.line > .thumb-vacio svg{ width:20px; height:20px; }

/* ==========================================================================
   HOJA CERRADA = INVISIBLE **E INTANGIBLE**
   --------------------------------------------------------------------------
   El sistema oculta las hojas solo con opacity y transform. En logi eso basta
   porque alli las hojas se crean al abrirlas y se borran del DOM al cerrarlas:
   cuando no estan, no estan.

   Aqui son estaticas —viven en index.html desde el primer momento— y eso
   cambia las reglas. Una capa con `position:fixed; inset:0; opacity:0` no se
   ve, pero sigue cubriendo la pantalla entera y se traga todos los clics. El
   sintoma es de los que desesperan: la interfaz se ve perfecta y no responde
   a nada, sin ningun error en consola.

   En movil pasaba desapercibido porque la hoja se desplaza fuera de la
   pantalla (translateY(100%)) y la de sede se cierra al arrancar. En pantalla
   ancha la hoja se centra —para que no salga una tarjeta de 1300px pegada
   abajo— y entonces las tres hojas quedan flotando invisibles justo encima de
   la interfaz.

   La solucion no es tocar el JS para que las borre: es declarar lo que de
   verdad se quiere. Cerrada, una hoja no debe existir para el puntero (clics)
   ni para el foco (tabulador). `visibility` cubre las dos cosas, y se demora
   lo que dura la animacion para que la salida se siga viendo.
   ========================================================================== */

.sheet-bg{
    visibility:hidden;
    pointer-events:none;
    /* La demora en visibility deja terminar el fundido antes de desaparecer. */
    transition:opacity .22s, visibility 0s linear .22s;
}
.sheet-bg.on{
    visibility:visible;
    pointer-events:auto;
    transition:opacity .22s, visibility 0s;
}

.sheet{
    visibility:hidden;
    pointer-events:none;
    transition:transform .28s cubic-bezier(.22,1,.36,1), visibility 0s linear .28s;
}
.sheet.on{
    visibility:visible;
    pointer-events:auto;
    transition:transform .28s cubic-bezier(.22,1,.36,1), visibility 0s;
}

/* En ancho la hoja ademas se desvanece, asi que la transicion lleva opacity.
   Va aqui y no en el bloque de pantalla ancha para que las cuatro reglas de
   este arreglo se lean juntas: separadas, la proxima vez que alguien toque
   una animacion volvera a dejar una a medias. */
@media (min-width: 900px) {
    .sheet{
        transition:transform .24s cubic-bezier(.22,1,.36,1), opacity .2s,
                   visibility 0s linear .24s;
    }
    .sheet.on{
        transition:transform .24s cubic-bezier(.22,1,.36,1), opacity .2s,
                   visibility 0s;
    }
}

/* ==========================================================================
   BLINDAJE DE LA GUARDA
   --------------------------------------------------------------------------
   Las reglas de arriba funcionan, pero dependen del ORDEN: `.sheet` tiene
   especificidad 0-1-0 y cualquier otro `.sheet { }` escrito mas abajo —o
   dentro de un @media que se anada despues— puede volver a dejar la hoja
   tangible sin que nadie se de cuenta. Ya paso una vez y costo caro.

   `:not(.on)` sube la especificidad a 0-2-0 y ademas dice exactamente lo que
   se quiere: una hoja que NO esta abierta no existe para el dedo, ni para el
   raton, ni para el tabulador. Ninguna regla suelta puede desmentirlo por
   accidente de orden.
   ========================================================================== */
.sheet:not(.on),
.sheet-bg:not(.on){
    visibility:hidden;
    pointer-events:none;
}


/* ==========================================================================
   BANDEJA DE DOCUMENTOS
   --------------------------------------------------------------------------
   Casi todo sale de las piezas que ya existen (.chips, .item, .tag, .kv), que
   es la idea: una pantalla nueva no deberia traer un lenguaje nuevo. Aqui solo
   queda lo que no tenia sitio.
   ========================================================================== */

/* Aviso de "estas corrigiendo un documento", encima del carrito.
   Va en ambar y no en el color de acento a proposito: no es la accion
   principal de la pantalla, es una advertencia sobre lo que hara el boton de
   guardar. Y ocupa el ancho entero porque pasarla por alto sale caro. */
.editbar{
  display:flex; align-items:center; gap:11px;
  padding:11px 13px; margin-bottom:12px;
  border-radius:var(--r);
  background:var(--warn-soft);
  border:1px solid var(--warn);
  color:var(--warn);
}
.editbar svg{ width:21px; height:21px; flex:none; }
.editbar b{ display:block; font-size:13.5px; font-weight:660; line-height:1.3; }
.editbar span{ display:block; font-size:11.5px; opacity:.85; line-height:1.35; }
.editbar .btn{
  height:36px; padding:0 13px; font-size:13px; flex:none;
  color:var(--warn);
}

/* Un saldo pendiente se lee como cifra, no como texto: en el listado es lo
   unico que decide si hay algo que hacer con esa fila.

   Se limita a <b> a proposito. Ya existe `.res .kv.falta b`, donde la clase
   va en la FILA entera; una regla suelta `.falta` tenniria tambien su
   etiqueta y el resumen del cobro saldria todo en rojo. */
b.falta{ color:var(--bad); }


/* --------------------------------------------------------------------------
   INTERRUPTOR
   --------------------------------------------------------------------------
   El unico control de encendido/apagado de la app. La pastilla mide 28px de
   alto, muy por debajo de los 48 que pide el sistema para el pulgar, asi que
   quien recibe el clic es la BARRA entera; el interruptor solo dibuja.
   -------------------------------------------------------------------------- */
.swbar{
  display:flex; align-items:center; gap:11px;
  padding:12px 2px; cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.swbar > svg{ width:20px; height:20px; flex:none; color:var(--ink-3); }
.swbar b{ display:block; font-size:13.5px; font-weight:620; line-height:1.3; }
.swbar span{ display:block; font-size:11.5px; color:var(--ink-3); }

.sw{
  flex:none; width:46px; height:28px; padding:3px;
  border:none; border-radius:14px; background:var(--line);
  display:flex; align-items:center;
  transition:background .18s;
}
.sw i{
  width:22px; height:22px; border-radius:50%;
  background:#fff; box-shadow:var(--e1);
  transition:transform .18s;
}
.sw[aria-checked="true"]      { background:var(--acc); }
.sw[aria-checked="true"] i    { transform:translateX(18px); }


/* --------------------------------------------------------------------------
   AVISO DE VERSION NUEVA
   --------------------------------------------------------------------------
   Sustituye a la barra que ocupaba el ancho de la pantalla. Un cartel grande a
   media venta se lee como un error y la reaccion es cerrarlo sin leerlo; un
   punto no interrumpe y no se va hasta que se actualiza.

   Ambar y no rojo: no hay nada roto, hay algo pendiente.
   -------------------------------------------------------------------------- */
.icon-btn.upd{ position:relative; color:var(--warn); }
.icon-btn.upd::after{
  content:''; position:absolute; top:9px; right:9px;
  width:9px; height:9px; border-radius:50%;
  background:var(--warn);
  border:2px solid var(--bg);
  animation:latir 2.4s ease-in-out infinite;
}
/* Un latido lento y corto: llama la atencion al mirar, no mientras se cobra. */
@keyframes latir{
  0%,70%,100% { transform:scale(1);    opacity:1;   }
  85%         { transform:scale(1.25); opacity:.75; }
}
@media (prefers-reduced-motion: reduce){
  .icon-btn.upd::after{ animation:none; }
}

/* La version, en la ficha del usuario. Al pie no la veia nadie y es el primer
   dato que se pide por telefono cuando algo va raro. */
.ver-pill{
  display:inline-flex; align-items:center; gap:5px;
  margin-top:5px; padding:2px 8px; border-radius:999px;
  background:var(--line-soft); color:var(--ink-3);
  font-size:11px; font-weight:650; letter-spacing:.02em;
}
/* Con actualizacion pendiente deja de ser un dato y pasa a ser una accion. */
.ver-pill.hay{
  background:var(--warn-soft); color:var(--warn); cursor:pointer;
}
.ver-pill.hay::after{ content:' · toca para actualizar'; font-weight:600; }


/* --------------------------------------------------------------------------
   CONVERSION DE UNIDADES (editor de linea)
   --------------------------------------------------------------------------
   Segmentado pequenio, alineado con el titulo "Cantidad". Solo cambia en que
   unidad se TECLEA; el almacen siempre recibe su unidad de stock.
   -------------------------------------------------------------------------- */
.con-uni{ display:flex; align-items:center; gap:10px; }

.uni{
  display:inline-flex; flex:none;
  padding:2px; border-radius:999px;
  background:var(--line-soft);
}
.uni-b{
  padding:5px 12px; border-radius:999px;
  font-size:11.5px; font-weight:650; letter-spacing:.01em;
  color:var(--ink-3); white-space:nowrap;
}
.uni-b.on{
  background:var(--surface); color:var(--acc);
  box-shadow:var(--e1);
}

/* Precio y descuento comparten fila: sin esto las dos columnas se estiran
   distinto segun cuanto ocupe cada texto de ayuda. */
#item-pd{ align-items:flex-start; gap:12px; }
#item-pd > div{ min-width:0; }


/* Fecha de vencimiento del credito. No es un campo editable: es la cuenta ya
   hecha, al lado de los dias. Se le da la misma altura que un input para que
   la fila no baile. */
.vence{
  display:flex; align-items:center;
  height:50px; padding:0 14px;
  border-radius:var(--r-s);
  background:var(--surface-2); border:1px solid var(--line);
  font-size:15px; font-weight:620; color:var(--ink);
  font-variant-numeric:tabular-nums;
}


/* --------------------------------------------------------------------------
   FILA RESALTADA CON EL TECLADO
   --------------------------------------------------------------------------
   Tiene que verse de un vistazo desde medio metro y sin buscarla: barra de
   acento a la izquierda mas fondo suave. Solo con el fondo no se distingue
   bajo la luz del local.
   -------------------------------------------------------------------------- */
#grid .item.sel{
  background:var(--acc-soft);
  box-shadow:inset 3px 0 0 var(--acc);
}
#grid .item.sel .item-t b{ color:var(--acc); }


/* --------------------------------------------------------------------------
   CONFIRMACION AL ANADIR SIN LIMPIAR
   --------------------------------------------------------------------------
   Con el ajuste "Mantener la lista" la grilla no desaparece al anadir, y lo
   unico que cambia en la fila es el "Quedan N" — un numero de 11px que no se
   ve desde la altura a la que se trabaja. Sin senial, tocar dos veces se
   siente como que la app no respondio, y el cajero toca una tercera.

   Verde y corto: confirma, no interrumpe. Se respeta a quien pidio menos
   movimiento en el sistema.
   -------------------------------------------------------------------------- */
@keyframes entro{ from{ background:var(--ok-soft) } to{ background:transparent } }
#grid .item.entro{ animation:entro .55s ease-out; }

@media (prefers-reduced-motion: reduce){
  #grid .item.entro{ animation:none; }
}


/* --------------------------------------------------------------------------
   EL CARRITO SE DESPLAZA, EL TOTAL NO
   --------------------------------------------------------------------------
   Solo las lineas llevan scroll. El total vive fuera de el, asi que sigue a la
   vista con veinte articulos igual que con uno: es la cifra que el cajero dice
   en voz alta, no puede depender de cuanto haya bajado.

   overscroll-behavior evita que al llegar al final el gesto siga arrastrando
   la pagina de detras, que en un movil se siente como si la app se moviera
   sola.
   -------------------------------------------------------------------------- */
#carro-lineas{
  max-height:50vh;
  overflow-y:auto;
  overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;
}


/* --------------------------------------------------------------------------
   CONTADOR DE PEDIDOS EN ESPERA
   --------------------------------------------------------------------------
   Numero sobre el icono de la barra superior. Lleva cifra y no un punto como
   el aviso de version: ahi solo importa que HAY algo; aqui importa CUANTOS,
   porque de eso depende si el cajero recuerda a quien esta atendiendo.
   -------------------------------------------------------------------------- */
.icon-btn.cola{
  position:relative;
  /* Color de acento y fondo suave, no el gris de los demas iconos: mientras
     haya pedidos esperando es informacion viva, no una accion mas de la barra.
     Con el gris de .icon-btn se perdia contra el fondo, en claro y en oscuro. */
  color:var(--acc);
  background:var(--acc-soft);
}
.icon-btn.cola .cnt{
  position:absolute; top:4px; right:2px;
  min-width:17px; height:17px; padding:0 4px;
  border-radius:9px;
  background:var(--acc); color:var(--acc-ink);
  border:2px solid var(--bg);
  font-size:10px; font-weight:720; line-height:13px;
  display:flex; align-items:center; justify-content:center;
  font-variant-numeric:tabular-nums;
}


/* --------------------------------------------------------------------------
   PRODUCTOS MAS VENDIDOS  (globitos de la pantalla de venta)
   --------------------------------------------------------------------------
   Ocupan el sitio del cartel "Busca o escanea" mientras el buscador esta
   vacio. Son globitos y no filas a proposito: una fila por articulo llena la
   pantalla con cuatro sugerencias y obliga a bajar; en globitos entran doce
   sin scroll y se reconocen por la foto, que es como se busca de verdad en un
   mostrador.

   Nada de colores, radios ni sombras escritos a mano: todo sale de las
   variables, y por eso el modo oscuro no necesita una sola linea aqui.
   -------------------------------------------------------------------------- */
.sug{ padding:2px 0 4px; }

.sug-h{
  display:flex; align-items:baseline; gap:8px;
  padding:0 4px; margin-bottom:10px;
}
.sug-h b{ font-size:13px; font-weight:660; color:var(--ink-2); letter-spacing:.01em; }
.sug-h span{ font-size:11px; color:var(--ink-3); }

/* auto-fill y no un numero fijo de columnas: el mismo bloque tiene que servir
   en un telefono de 360px y en la tablet apaisada donde el carrito ya ocupa
   media pantalla. */
.sug-g{
  display:grid;
  grid-template-columns:repeat(auto-fill, minmax(100px, 1fr));
  gap:10px;
}

.bub{
  display:flex; flex-direction:column; align-items:center;
  gap:2px; padding:12px 8px 10px;
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r-lg);
  box-shadow:var(--e1);
  cursor:pointer; text-align:center;
  font:inherit; color:inherit;
  transition:transform var(--fast), box-shadow var(--fast);
  /* Muy por encima del minimo tactil: aqui se toca con el pulgar y sin mirar. */
  min-height:132px;
  /* Sin esto la cuadricula se sale de la pantalla: en un grid, la anchura
     minima de cada celda es la de su palabra mas larga —"INTIPALKA"— y no el
     1fr que se le pidio. Con min-width:0 manda la columna. */
  min-width:0;
  overflow:hidden;
}
.bub:active{ transform:scale(.96); box-shadow:var(--e2); }

.bub-img{
  width:56px; height:56px; margin-bottom:6px;
  border-radius:var(--pill);
  object-fit:cover;
  background:var(--surface-2);
  border:1px solid var(--line-soft);
}
.bub-vacio{ display:flex; align-items:center; justify-content:center; color:var(--ink-3); }
.bub-vacio svg{ width:24px; height:24px; }

/* Dos lineas y el resto abreviado en el JS: con tres, los globitos de una
   misma fila dejan de tener la misma altura y la cuadricula se descuadra. */
.bub-n{
  font-size:11.5px; font-weight:600; line-height:1.25; color:var(--ink);
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
  overflow:hidden; word-break:break-word;
}
.bub-p{
  margin-top:auto; padding-top:5px;
  font-size:13.5px; font-weight:720; letter-spacing:-.02em; color:var(--ink);
}

/* Sin stock no se esconde: se puede vender igual —o no, segun la empresa— y
   esconderlo obligaria a buscarlo a mano para descubrir lo mismo. */
.bub.sin{ opacity:.68; }
.bub-x{
  margin-top:3px; padding:1px 7px;
  border-radius:var(--pill);
  background:var(--bad-soft); color:var(--bad);
  font-size:9.5px; font-weight:700; text-transform:uppercase; letter-spacing:.03em;
}

@media (min-width:900px){
  .sug-g{ grid-template-columns:repeat(auto-fill, minmax(118px, 1fr)); }
  .bub-img{ width:64px; height:64px; }
  .bub-n{ font-size:12px; }
}
