/* POS de Sisintec — misma paleta y tipografía que sisintec.com
   ---------------------------------------------------------------------------
   El ancho de referencia es la Sunmi V3: 720x1600 a 320 dpi, o sea unos 360 dp.
   Eso es tamaño TELÉFONO, no tableta, y es donde se cobra todos los días. Las
   pantallas grandes son el caso fácil y salen bien solas; la V3 es la que manda
   las decisiones de tamaño.

   REGLA FIJA: en la V3, la pantalla de venta cabe sin scroll. Lo único que se
   desplaza es la lista de productos y la lista de partidas, cada una en su
   propio contenedor. La barra del total y los botones de cobro NO se van nunca
   de la vista: si el cajero tiene que buscar el botón de cobrar, se pierde el
   tiempo que este sistema existe para ahorrar.
*/

:root{
  /* Del sitio, sin retocar: es la misma marca. */
  --teal:#00b4d8; --blue:#0077b6; --deep:#005f8e;
  --ink:#10233a; --muted:#6b7280; --line:#e5e7eb; --soft:#f0f4f8; --white:#fff;
  --dark:#002136; --dark-2:#00263f;
  --grad:linear-gradient(120deg,#00b4d8 0%,#0077b6 52%,#005f8e 100%);
  --grad-dark:linear-gradient(160deg,#001624 0%,#003554 52%,#0077b6 100%);
  --ok:#149c4e; --warn:#b45309; --mal:#c0392b;
  --radius:18px;
  --shadow:0 24px 60px rgba(20,10,50,.14);
  --shadow-sm:0 8px 26px rgba(20,10,50,.08);
}

*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}

/* ─── NADA DE dvh COMO BASE ─────────────────────────────────────────────────
   El WebView de la Sunmi V3 NO soporta unidades dvh. Se comprobó en el
   aparato: CSS.supports("height","100dvh") devuelve false.

   Y una unidad que el navegador no entiende no cae a un valor razonable: la
   declaración entera se descarta. `.app{height:100dvh}` dejaba a .app SIN
   altura, así que crecía con su contenido hasta 2,377 px dentro de una ventana
   de 728 — y el total y el botón de cobrar quedaban a mil doscientos píxeles
   por debajo de la pantalla.
   En el navegador de escritorio se veía perfecto, porque ahí dvh sí existe.

   Base: `%` y `vh`, que funcionan en todo. `dvh` sólo como mejora, dentro de
   un @supports, para navegadores donde la barra de direcciones se encoge —
   caso que en una terminal ni siquiera existe. */
@supports (height: 100dvh) {
  .app{height:100dvh}
  .acceso{min-height:100dvh}
}
body{
  font-family:'Inter',system-ui,-apple-system,'Segoe UI',sans-serif;
  color:var(--ink); background:var(--soft);
  -webkit-font-smoothing:antialiased;
  /* En una terminal táctil, el resaltado azul al tocar y la selección de texto
     por arrastre sólo estorban: nadie copia texto de una caja registradora. */
  -webkit-tap-highlight-color:transparent; user-select:none;
}
h1,h2,h3{font-family:'Sora','Inter',system-ui,sans-serif;line-height:1.12;letter-spacing:-.025em;font-weight:800}
input,button,select{font-family:inherit;font-size:inherit;color:inherit}
button{cursor:pointer;border:0;background:none}

/* ===========================================================================
   ACCESO POR PIN
   =========================================================================== */

/* El fondo va también en <body>. En el WebView de la terminal, 100dvh se
   queda unos píxeles corto y por debajo asomaba el gris claro del body: una
   franja blanca al pie de una pantalla que es toda azul oscuro. En el
   navegador de escritorio no se ve; en el aparato, sí. */
body.pantalla-acceso{background:#002136}

.acceso{
  min-height:100%; display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:clamp(10px,1.8vh,18px);
  background:var(--grad-dark); padding:24px 20px; text-align:center;
}
/* El logotipo SIEMPRE se muestra. Si algo choca con él, se mueve lo otro.
   Se sirve al doble de su tamaño en pantalla para que en los 320 dpi de la V3
   no se vea suave: 640 px de archivo para unos 200 de caja. */
.acceso .marca img{width:min(190px,50vw);height:auto;display:block}
.acceso .sub{color:rgba(255,255,255,.72);font-size:14px;letter-spacing:.01em}

.puntos{display:flex;gap:16px;justify-content:center;margin:2px 0 4px}
.punto{
  width:15px;height:15px;border-radius:50%;
  border:2px solid rgba(255,255,255,.45); background:transparent;
  transition:transform .12s ease, background .12s ease, border-color .12s ease;
}
.punto.on{background:var(--teal);border-color:var(--teal);transform:scale(1.18)}

.tecla{
  width:100%; aspect-ratio:1/1; max-width:86px;
  border-radius:16px; background:rgba(255,255,255,.10);
  border:1px solid rgba(255,255,255,.16);
  color:#fff; font-size:26px; font-weight:600; font-variant-numeric:tabular-nums;
  display:flex;align-items:center;justify-content:center;
  transition:background .12s ease, transform .08s ease;
}
.tecla:active{background:rgba(255,255,255,.26);transform:scale(.95)}
.tecla.plana{background:transparent;border-color:transparent;font-size:15px;font-weight:500;
  color:rgba(255,255,255,.75)}
.tecla.plana:active{background:rgba(255,255,255,.12)}
.teclado{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;width:min(300px,84vw)}

.aviso{
  /* Alto reservado aunque esté vacío: si el mensaje empujara el teclado hacia
     abajo al aparecer, el dedo que ya iba al «1» acabaría en el «4». */
  min-height:20px;font-size:13.5px;color:#ffd0c9;font-weight:600;
  max-width:300px;line-height:1.45;margin-bottom:2px;
}
.acceso .pie{position:fixed;bottom:max(14px,env(safe-area-inset-bottom));
  color:rgba(255,255,255,.38);font-size:11.5px;letter-spacing:.03em}

/* ===========================================================================
   VENTA
   =========================================================================== */

.app{height:100%;display:flex;flex-direction:column;overflow:hidden}

.barra{
  background:var(--dark); color:#fff; display:flex; align-items:center; gap:10px;
  padding:0 12px; height:52px; flex-shrink:0;
}
.barra .iso{height:28px;width:auto;flex-shrink:0}
.barra .marca-txt{font-family:'Sora',sans-serif;font-weight:800;font-style:italic;
  font-size:15px;letter-spacing:-.03em;color:#fff;flex-shrink:0}
@media(max-width:430px){
  /* En la terminal el nombre sobra: quien está frente al aparato ya sabe quién
     es, y con tres botones al lado quedaba cortado en «Alejandr…». El logotipo
     del producto se muestra SIEMPRE; lo que se mueve es lo demás. */
  .barra .marca-txt{display:none}
  .barra .quien{display:none}
}

/* Los enlaces sueltos y el menú son excluyentes: nunca se ven los dos.
   El corte está en 700 px y no más abajo porque lo que importa no es que
   quepan, es que se puedan TOCAR: cinco enlaces exprimidos en 360 px dan
   objetivos de 44 px de ancho por 30 de alto, y el pulgar de quien cobra con
   prisa falla. Antes de esto, en la V3 «Ajustes» salía cortado a la mitad y
   «Salir» no aparecía. */
.barra .enlaces{display:flex;gap:8px;align-items:center;margin-left:auto}
.barra .menu{display:none;position:relative;margin-left:auto}
@media(max-width:700px){
  .barra .enlaces{display:none}
  .barra .menu{display:block}
}

.barra .menu>summary{
  list-style:none; cursor:pointer;
  /* 44 × 44: el mínimo con el que un dedo acierta a la primera. */
  width:44px;height:44px;display:flex;align-items:center;justify-content:center;
  border:1px solid rgba(255,255,255,.28);border-radius:10px;
  color:#fff;font-size:19px;line-height:1;
}
.barra .menu>summary::-webkit-details-marker{display:none}
.barra .menu[open]>summary{background:rgba(255,255,255,.14)}

.menu-panel{
  position:absolute; right:0; top:calc(100% + 8px); z-index:40;
  background:var(--white); border:1px solid var(--line); border-radius:14px;
  box-shadow:0 18px 44px rgba(0,33,54,.28);
  padding:6px; min-width:190px; display:flex; flex-direction:column; gap:2px;
}
.menu-panel a{
  color:var(--ink)!important; border:0!important; border-radius:10px;
  padding:14px 16px!important; font-size:15px!important; font-weight:600;
  text-decoration:none;
}
.menu-panel a:active{background:var(--soft)}
/* Salir va separado y en rojo: es el único del menú que interrumpe el trabajo,
   y tocarlo por error en medio de una venta obliga a volver a teclear el PIN. */
.menu-panel a[href="salir.php"]{
  color:var(--mal)!important;margin-top:4px;border-top:1px solid var(--line)!important;
  border-radius:0 0 10px 10px;
}
.barra .quien{font-size:12.5px;color:rgba(255,255,255,.72);margin-left:auto;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:40%}
.barra a,.barra button{color:rgba(255,255,255,.9);font-size:12.5px;font-weight:600;
  border:1px solid rgba(255,255,255,.28);padding:7px 12px;border-radius:9px;
  text-decoration:none;white-space:nowrap}

/* El aviso de día sin cerrar. Va arriba de todo y en ámbar: es lo que impide
   que las ventas de tres días acaben apiladas en una sola fecha. */
.pendiente{
  background:#fff4e5;color:#7a4a08;font-size:12.5px;font-weight:600;
  padding:9px 14px;border-bottom:1px solid #f0d9b5;flex-shrink:0;
  display:flex;gap:10px;align-items:center;line-height:1.4;
}
.pendiente a{color:#7a4a08;font-weight:800;margin-left:auto;white-space:nowrap}

/* En vertical, DOS renglones con tamaños declarados: el catálogo se estira y
   la cuenta toma lo que necesita. Sin `grid-template-rows`, las dos filas son
   `auto` y el catálogo —que tiene 29 productos dentro— empuja la cuenta fuera
   de la pantalla. En el navegador de escritorio no se nota porque hay alto de
   sobra; en la V3 desaparecía el total y el botón de cobrar. */
.cuerpo{flex:1;display:grid;grid-template-columns:minmax(0,1fr);
  grid-template-rows:minmax(0,1fr) auto;min-height:0}
@media(min-width:820px){
  .cuerpo{grid-template-columns:minmax(0,1fr) 380px;grid-template-rows:minmax(0,1fr)}
}

/* POR QUÉ minmax(0,1fr) Y NO 1fr A SECAS
   `1fr` es en realidad `minmax(auto, 1fr)`: la fila NO puede encoger por debajo
   del contenido mínimo de lo que lleva dentro. Con 29 productos en el catálogo,
   esa fila crecía hasta empujar la cuenta —el total y el botón de cobrar—
   fuera de la pantalla.
   En el navegador de escritorio no se veía porque sobra alto. En la V3
   desaparecía justo lo único que no puede desaparecer. */

/* --- catálogo --- */
.catalogo{display:flex;flex-direction:column;min-height:0;background:var(--white)}
.buscador{padding:10px 12px;border-bottom:1px solid var(--line);flex-shrink:0;display:flex;gap:8px}
.buscador input{
  flex:1;border:1.5px solid var(--line);border-radius:12px;padding:12px 14px;
  font-size:16px;      /* 16 px o menos hace que iOS acerque la pantalla al enfocar */
  outline:none;background:var(--white);user-select:text;
}
.buscador input:focus{border-color:var(--blue);box-shadow:0 0 0 3px rgba(0,119,182,.12)}

.rejilla{
  flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;
  display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
  gap:9px;padding:12px;align-content:start;
}
.prod{
  background:var(--white);border:1px solid var(--line);border-radius:14px;
  padding:11px 12px;text-align:left;display:flex;flex-direction:column;gap:5px;
  box-shadow:var(--shadow-sm);transition:transform .08s ease,border-color .15s ease;
  min-height:104px;
}
.prod:active{transform:scale(.97);border-color:var(--blue)}
.prod .nom{font-size:12.5px;font-weight:600;line-height:1.35;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.prod .precio{font-family:'Sora',sans-serif;font-weight:800;font-size:16px;
  color:var(--blue);margin-top:auto;font-variant-numeric:tabular-nums}
.prod .stock{font-size:10.5px;color:var(--muted)}
.prod .stock.poco{color:var(--warn);font-weight:700}
.prod .stock.nada{color:var(--mal);font-weight:700}

.vacio{grid-column:1/-1;text-align:center;padding:44px 20px;color:var(--muted);
  font-size:13.5px;line-height:1.6}

/* --- la cuenta --- */
.cuenta{display:flex;flex-direction:column;min-height:0;background:var(--white);
  border-left:1px solid var(--line)}
@media(max-width:819px){
  .cuenta{border-left:0;border-top:1px solid var(--line);
    /* Alto acotado pero con mínimo: sin el mínimo, tres partidas dejaban la
       última cortada a la mitad y parecía que el sistema había perdido un
       renglón. Con él, la lista se desplaza dentro de su propia caja. */
    max-height:52vh;min-height:210px}
}
.cuenta .cab{padding:10px 14px;border-bottom:1px solid var(--line);display:flex;
  align-items:baseline;gap:8px;flex-shrink:0}
.cuenta .cab .folio{font-family:'Sora',sans-serif;font-weight:800;font-size:14px}
.cuenta .cab .n{font-size:12px;color:var(--muted);margin-left:auto}

.partidas{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:4px 0;min-height:0}
.linea{display:grid;grid-template-columns:1fr auto;gap:4px 10px;padding:10px 14px;
  border-bottom:1px solid #f4f5f7;align-items:start}
.linea .nom{font-size:12.5px;font-weight:600;line-height:1.35;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.linea .imp{font-weight:700;font-variant-numeric:tabular-nums;font-size:13.5px;white-space:nowrap}
.linea .ctrl{display:flex;align-items:center;gap:8px;grid-column:1/-1;margin-top:3px}
.linea .ctrl button{width:30px;height:30px;border-radius:9px;background:var(--soft);
  font-size:17px;font-weight:700;color:var(--ink);display:flex;align-items:center;justify-content:center}
.linea .ctrl button:active{background:var(--line)}
.linea .ctrl .cant{min-width:34px;text-align:center;font-weight:700;font-variant-numeric:tabular-nums}
.linea .ctrl .uni{font-size:11px;color:var(--muted);margin-left:auto}

.totales{flex-shrink:0;border-top:1px solid var(--line);padding:12px 14px 14px;background:var(--white)}
.fila{display:flex;justify-content:space-between;font-size:13px;color:var(--muted);padding:2px 0;
  font-variant-numeric:tabular-nums}
.fila.total{font-family:'Sora',sans-serif;font-size:26px;font-weight:800;color:var(--ink);
  padding-top:8px;margin-top:6px;border-top:1px solid var(--line);letter-spacing:-.02em}

.acciones{display:grid;grid-template-columns:auto 1fr;gap:9px;margin-top:12px}
.acciones-3{grid-template-columns:auto auto 1fr}
.fila.desc{color:var(--mal)}
.btn{border-radius:13px;font-weight:700;font-size:15px;padding:15px 18px;
  display:flex;align-items:center;justify-content:center;gap:8px;transition:transform .08s ease,filter .15s}
.btn:active{transform:scale(.98)}
.btn:disabled{opacity:.42;pointer-events:none}
.btn.cobrar{background:var(--grad);color:#fff;box-shadow:0 10px 24px rgba(0,119,182,.28)}
.btn.gris{background:var(--soft);color:var(--muted);padding:15px 16px}

/* --- avisos flotantes --- */
/* z-index 90: POR ENCIMA del velo (70).
   Estaba en 60, debajo. Como casi todo lo que sale mal se avisa desde dentro
   de una hoja abierta —el cobro que falla, el descuento rechazado, la terminal
   sin vincular—, esos avisos se pintaban DETRÁS del velo y no los veía nadie.
   El botón volvía a su estado y el motivo no aparecía en ninguna parte. */
.tostadas{position:fixed;left:50%;bottom:18px;transform:translateX(-50%);z-index:90;
  display:flex;flex-direction:column;gap:8px;width:min(420px,92vw)}
.tostada{background:var(--dark);color:#fff;border-radius:12px;padding:12px 15px;
  font-size:13px;line-height:1.45;box-shadow:var(--shadow);animation:sube .18s ease}
.tostada.mal{background:var(--mal)} .tostada.ok{background:var(--ok)} .tostada.wa{background:var(--warn)}
@keyframes sube{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* --- hoja de cobro --- */
.velo{position:fixed;inset:0;background:rgba(0,20,35,.55);z-index:70;display:flex;
  align-items:flex-end;justify-content:center}
@media(min-width:820px){ .velo{align-items:center} }
.hoja{background:var(--white);width:min(460px,100%);border-radius:20px 20px 0 0;
  padding:20px;max-height:100%;overflow-y:auto;animation:sube .2s ease;
  /* 100% del velo, NO 92vh.
     `vh` mide la pantalla ORIGINAL. Cuando sube el teclado, el WebView se
     encoge (adjustResize en el manifiesto) pero `vh` no se entera: la hoja
     sigue midiendo lo de antes y sus botones quedan DEBAJO del teclado.
     En la V3 eso dejaba «Cancelar» y «Aplicar» fuera de alcance — el descuento
     no se podía aplicar. Con 100% la hoja se acota al velo, que sí encogió, y
     lo que sobra se desplaza dentro. */
  overscroll-behavior:contain}
@media(min-width:820px){ .hoja{border-radius:20px} }
.hoja h2{font-size:19px;margin-bottom:3px}
.hoja .apagado{color:var(--muted);font-size:13px;margin-bottom:16px}
.formas{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:14px}
.forma{border:1.5px solid var(--line);border-radius:12px;padding:13px 10px;font-size:13.5px;
  font-weight:600;text-align:center}
.forma.on{border-color:var(--blue);background:rgba(0,119,182,.07);color:var(--blue)}
.campo{margin-bottom:12px}
.campo label{display:block;font-size:11px;font-weight:700;color:var(--muted);
  text-transform:uppercase;letter-spacing:.05em;margin-bottom:5px}
.campo input{width:100%;border:1.5px solid var(--line);border-radius:12px;padding:13px 14px;
  font-size:17px;font-variant-numeric:tabular-nums;outline:none;user-select:text}
.campo input:focus{border-color:var(--blue)}
.cambio{background:var(--soft);border-radius:12px;padding:12px 14px;margin-bottom:14px;
  display:flex;justify-content:space-between;align-items:baseline}
.cambio b{font-family:'Sora',sans-serif;font-size:22px;font-weight:800}

/* ===========================================================================
   CAJA
   =========================================================================== */

.hoja-larga{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:16px 14px 40px;
  max-width:620px;width:100%;margin:0 auto}
.cargando{color:var(--muted);text-align:center;padding:40px 0;font-size:14px}

.tarjeta{background:var(--white);border:1px solid var(--line);border-radius:var(--radius);
  padding:18px;margin-bottom:14px;box-shadow:var(--shadow-sm)}
.tarjeta h2{font-size:17px;margin-bottom:3px}
.tarjeta .apagado{color:var(--muted);font-size:13px;line-height:1.5}

.dia-cab{display:flex;align-items:baseline;gap:10px;margin-bottom:14px;flex-wrap:wrap}
.dia-cab .fecha{font-family:'Sora',sans-serif;font-size:20px;font-weight:800}
.marca-estado{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;
  padding:4px 10px;border-radius:20px}
.marca-estado.abierto{background:#e7f8ee;color:#0f7a3d}
.marca-estado.cerrado{background:var(--soft);color:var(--muted)}

.numeros{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:14px 0}
.num{background:var(--soft);border-radius:12px;padding:12px 14px}
.num .n{font-family:'Sora',sans-serif;font-size:19px;font-weight:800;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums}
.num .t{font-size:11px;color:var(--muted);margin-top:2px;line-height:1.35}

.desglose{border-top:1px solid var(--line);margin-top:12px;padding-top:10px}
.desglose .fila{display:flex;justify-content:space-between;padding:5px 0;font-size:13.5px;
  font-variant-numeric:tabular-nums}
.desglose .fila span:first-child{color:var(--muted)}

.aciegas{background:linear-gradient(135deg,#00263f,#003554);color:#fff;border-radius:var(--radius);
  padding:18px;margin-bottom:14px}
.aciegas h2{color:#fff;font-size:17px;margin-bottom:4px}
.aciegas p{color:rgba(255,255,255,.72);font-size:12.5px;line-height:1.5;margin-bottom:14px}
.aciegas input{width:100%;border:1.5px solid rgba(255,255,255,.28);background:rgba(255,255,255,.10);
  color:#fff;border-radius:12px;padding:15px 16px;font-size:24px;font-weight:700;
  font-variant-numeric:tabular-nums;text-align:center;outline:none;user-select:text}
.aciegas input::placeholder{color:rgba(255,255,255,.35);font-weight:400}
.aciegas input:focus{border-color:var(--teal)}
.aciegas .btn{margin-top:12px;width:100%;background:var(--teal);color:#002136}

.resultado{text-align:center;padding:8px 0 4px}
.resultado .dif{font-family:'Sora',sans-serif;font-size:34px;font-weight:800;letter-spacing:-.02em}
.resultado .dif.cuadra{color:var(--ok)} .resultado .dif.falta{color:var(--mal)}
.resultado .dif.sobra{color:var(--warn)}
.resultado .que{font-size:13px;color:var(--muted);margin-top:4px}

.mov{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:12px}
.mov .btn{padding:12px;font-size:13.5px;background:var(--soft);color:var(--ink)}
.lista-pend{list-style:none}
.lista-pend li{display:flex;gap:10px;align-items:center;padding:10px 0;border-top:1px solid var(--line);
  font-size:13.5px}
.lista-pend li:first-child{border-top:0}
.lista-pend a{margin-left:auto;color:var(--blue);font-weight:700;text-decoration:none;white-space:nowrap}

/* El ticket en pantalla, cuando no hay impresora conectada. Monoespaciada y al
   ancho real: si aquí se ve descuadrado, en papel también. */
pre.ticket{font-family:ui-monospace,'SF Mono',Menlo,Consolas,monospace;font-size:11.5px;
  line-height:1.35;background:var(--soft);border-radius:12px;padding:14px;overflow-x:auto;
  white-space:pre;user-select:text;margin-bottom:4px}
@media print{
  .barra,.pendiente,.acciones,.tostadas{display:none!important}
  .velo{position:static;background:none;display:block}
  .hoja{box-shadow:none;max-height:none;width:auto;padding:0}
  pre.ticket{background:none;padding:0;font-size:12px}
}

/* ===========================================================================
   REPORTES
   =========================================================================== */

.rango{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:14px}
.rango input[type=date]{border:1.5px solid var(--line);border-radius:10px;padding:9px 11px;
  font-size:13.5px;background:var(--white);outline:none}
.rango input:focus{border-color:var(--blue)}
.atajos{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px}
.atajo{border:1.5px solid var(--line);border-radius:20px;padding:6px 13px;font-size:12.5px;
  font-weight:600;color:var(--muted);background:var(--white)}
.atajo.on{border-color:var(--blue);background:rgba(0,119,182,.07);color:var(--blue)}

.grandes{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px;margin-bottom:14px}
.grande{background:var(--white);border:1px solid var(--line);border-radius:14px;padding:14px 16px;
  box-shadow:var(--shadow-sm)}
.grande .n{font-family:'Sora',sans-serif;font-size:22px;font-weight:800;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;line-height:1.15}
.grande .t{font-size:11.5px;color:var(--muted);margin-top:3px;line-height:1.35}
.grande.bueno .n{color:var(--ok)} .grande.malo .n{color:var(--mal)}

table.rep{width:100%;border-collapse:collapse;font-size:13px}
table.rep th{text-align:left;font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;
  color:var(--muted);font-weight:800;padding:0 6px 8px;border-bottom:1px solid var(--line);white-space:nowrap}
table.rep td{padding:9px 6px;border-top:1px solid #f4f5f7;vertical-align:top}
table.rep td.num,table.rep th.num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
table.rep tr.clic{cursor:pointer}
table.rep tr.clic:active{background:var(--soft)}
.scroll-x{overflow-x:auto;-webkit-overflow-scrolling:touch}
.nombre-corto{display:block;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chip{display:inline-block;font-size:10.5px;font-weight:700;padding:2px 8px;border-radius:20px;
  background:var(--soft);color:var(--muted)}
.chip.dev{background:#fdecea;color:var(--mal)}
.lineas-dev{margin:4px 0 14px}
.linea-dev{display:grid;grid-template-columns:1fr auto;gap:6px 10px;padding:10px 0;
  border-top:1px solid var(--line);align-items:center}
.linea-dev:first-child{border-top:0}
.linea-dev .nom{font-size:12.5px;font-weight:600;line-height:1.35}
.linea-dev .sub{font-size:11px;color:var(--muted);margin-top:2px}
.linea-dev input[type=number]{width:70px;border:1.5px solid var(--line);border-radius:9px;
  padding:8px;text-align:right;font-size:14px;font-variant-numeric:tabular-nums}
.linea-dev label.almacen{grid-column:1/-1;font-size:11.5px;color:var(--muted);display:flex;
  gap:7px;align-items:center;margin-top:2px}

/* --------------------------------------------------------------- ajustes */
.renglon{display:grid;grid-template-columns:auto auto 1fr auto;gap:10px;align-items:baseline;
  padding:10px 0;border-bottom:1px solid var(--line);font-size:13.5px}
.renglon:last-of-type{border-bottom:0}
.renglon b{color:var(--ink);font-weight:600}
.renglon .apagado{font-size:12.5px;line-height:1.45}
.renglon.apagado b{opacity:.5}
/* Se llama `sello` y NO `marca`: `.marca` es el contenedor del logotipo en la
   pantalla del PIN. La primera versión se llamaba `.marca` y le puso 18 × 18 px
   a esa caja: el logotipo se desbordaba encima de «Punto de venta», y el
   circulito gris de fondo de la palomita aparecía bajo el lazo del logotipo.
   Estuvo así en la V3 desde el 26 de agosto; no se notaba porque la sesión
   dura 12 horas y el PIN casi no se ve. */
.sello{width:18px;height:18px;border-radius:50%;background:var(--soft);color:var(--muted);
  font-size:11px;display:flex;align-items:center;justify-content:center;flex:0 0 auto}
.sello.ok{background:var(--teal);color:#fff}
.campo small{display:block;margin-top:5px;font-size:12px;line-height:1.45}

/* ------------------------------------------------- terminal Mercado Pago */
/* El logotipo se deja respirar: es marca registrada de un tercero y no se
   recorta ni se recolorea. Va sobre blanco siempre, incluso en el botón
   activo, que es como Mercado Pago pide que se use.

   El margen de alrededor no es decoración: su guía exige un área libre
   alrededor del logotipo del alto de la letra «d». Por eso el ancho se topa
   antes de llegar al borde del botón. */
.forma .logo-mp{display:block;width:100%;max-width:134px;height:auto;margin:0 auto}
.forma:has(.logo-mp){background:#fff;padding:11px 10px}
.forma.on:has(.logo-mp){background:#fff;border-color:var(--teal);box-shadow:0 0 0 2px var(--teal) inset}

.terminal{display:flex;flex-direction:column;align-items:center;gap:14px;
  padding:26px 16px;margin:10px 0;border-radius:14px;background:var(--soft);text-align:center}
.terminal-txt{font-size:15px;font-weight:600;color:var(--ink);margin:0;line-height:1.4}
.terminal-luz{width:52px;height:52px;border-radius:50%;
  border:4px solid var(--line);border-top-color:var(--teal);
  animation:girar 1s linear infinite}
.terminal.ok .terminal-luz{animation:none;border-color:var(--teal)}
.terminal.mal .terminal-luz{animation:none;border-color:var(--mal)}
.terminal.mal .terminal-txt{color:var(--mal)}
@keyframes girar{to{transform:rotate(360deg)}}
/* Quien tenga el movimiento reducido activado ve un círculo quieto: la
   información está en el texto, no en el giro. */
@media (prefers-reduced-motion:reduce){.terminal-luz{animation:none}}

/* -------------------------------------------------- botones de categoría */
/* Una sola fila que se desplaza a lo ancho. En vertical ocuparían media
   pantalla de la terminal y dejarían al catálogo sin sitio. */
.categorias{
  /* align-items:center y no el «stretch» que trae flex de fábrica: si un botón
     creciera de alto —un logotipo con proporción rara, un nombre que no cabe—
     estiraría a TODOS los demás hasta su altura. */
  display:flex; align-items:center;
  gap:7px; overflow-x:auto; overscroll-behavior-x:contain;
  padding:9px 14px; flex:0 0 auto;
  border-bottom:1px solid var(--line);
  scrollbar-width:none; -webkit-overflow-scrolling:touch;
}
/* Antes de la primera búsqueda no hay categorías. Vacío se esconde entero para
   no dejar una franja gris con una raya debajo esperando a llenarse. */
.categorias:empty{display:none}
.categorias::-webkit-scrollbar{display:none}
.chip-cat{
  flex:0 0 auto; white-space:nowrap;
  border:1.5px solid var(--line); border-radius:999px;
  background:#fff; color:var(--muted);
  /* 34 px de alto y 13 de texto: es un filtro, no la acción principal. Los
     botones de producto y el de cobrar tienen que seguir ganando el pulgar. */
  padding:8px 13px; font-size:13px; font-weight:600;
  display:flex; align-items:center; gap:6px;
  transition:background .12s ease, color .12s ease, border-color .12s ease;
}
/* Se llama n-cat y NO cuenta: `.cuenta` ya es, en esta misma pantalla, el panel
   de la venta —display:flex, columna, y con min-height en móvil—. Al reutilizar
   el nombre, la insignia heredaba ese min-height y salía de 210 px de alto,
   estirando toda la fila de botones. */
.chip-cat .n-cat{
  flex:0 0 auto; align-self:center;
  font-size:11px; font-weight:700; font-variant-numeric:tabular-nums;
  background:var(--soft); color:var(--muted);
  border-radius:999px; padding:1px 6px; min-width:19px; text-align:center;
  line-height:1.5;
}
.chip-cat.on{background:var(--grad);border-color:transparent;color:#fff}
.chip-cat.on .n-cat{background:rgba(255,255,255,.24);color:#fff}
.chip-cat:active{transform:scale(.97)}
.vacio .btn{margin-top:12px}
@media (prefers-reduced-motion:reduce){.chip-cat{transition:none}}
.sub-bloque{margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
.sub-bloque h3{font-family:'Sora',sans-serif;font-size:15px;font-weight:600;
  color:var(--ink);margin:0 0 8px}
.sub-bloque .btn{margin-top:10px}

/* Logotipos de marca en los botones de categoría.
   Los logotipos son marcas registradas de terceros: van sobre blanco, sin
   recortar y sin recolorear, igual que el de Mercado Pago. Por eso el botón
   con logotipo NO toma el degradado cuando está activo: teñir la marca de azul
   sería alterarla. Se marca con el aro, que dice lo mismo sin tocarla. */
.chip-cat.con-logo{padding:7px 11px;background:#fff}
.chip-cat .logo-marca{
  display:block; height:18px; width:auto; max-width:104px;
  object-fit:contain;   /* nunca se deforma para caber */
}
.chip-cat.con-logo.on{
  background:#fff; border-color:var(--teal);
  box-shadow:0 0 0 2px var(--teal) inset;
}
.chip-cat.con-logo.on .n-cat{background:var(--teal);color:#fff}

/* Débito / Crédito dentro del botón de Mercado Pago. Se ven como lo que son:
   una elección hija, no una forma de pago más. */
.sub-formas{
  margin-top:-4px; padding-left:14px;
  border-left:3px solid var(--teal);
}

/* Mercado Pago sin terminal vinculada. Se ve, pero se nota que no está listo.
   El logotipo NO se pone en gris: es marca registrada y desaturarla es
   alterarla. Se baja la opacidad del botón entero, que es un efecto de
   presentación y no un cambio de la marca. */
.forma.sin-terminal{opacity:.55;border-style:dashed}
.forma.sin-terminal::after{
  content:'sin vincular';
  position:absolute; bottom:3px; left:0; right:0;
  font-size:9.5px; font-weight:700; letter-spacing:.04em;
  text-transform:uppercase; color:var(--muted); text-align:center;
}
.forma{position:relative}

/* El ojo para revisar una clave pegada. En una terminal táctil, pegar un token
   de setenta caracteres a ciegas y que falle sin poder mirarlo es donde se
   atasca cualquiera. */
.campo{position:relative}
.ojo-clave{
  position:absolute; right:10px; top:31px;
  background:var(--soft); color:var(--muted);
  border-radius:8px; padding:7px 11px; font-size:12px; font-weight:700;
}
.opcional{margin-top:14px;border-top:1px solid var(--line);padding-top:12px}
.opcional>summary{
  cursor:pointer; font-size:13.5px; font-weight:600; color:var(--muted);
  padding:6px 0; list-style:none;
}
.opcional>summary::-webkit-details-marker{display:none}
.opcional>summary::before{content:'▸ ';font-size:11px}
.opcional[open]>summary::before{content:'▾ '}


/* -------------------------------------------------------------- diagnóstico */
/* El resumen dice UNA cosa y va arriba. Quien abre esta pantalla ya tiene un
   problema; leer 25 renglones para saber si hay algo roto sería el problema. */
.resumen{
  display:flex; flex-direction:column; gap:3px;
  padding:16px 18px; border-radius:14px; margin-bottom:4px;
  border:1px solid var(--line); background:var(--white);
}
.resumen b{font-family:'Sora',sans-serif; font-size:17px; font-weight:600}
.resumen span{font-size:13px; color:var(--muted); line-height:1.45}
.resumen.ok{border-color:var(--teal); background:rgba(44,156,196,.07)}
.resumen.ok b{color:var(--teal)}
.resumen.wa{border-color:#e0a44a; background:#fff8ee}
.resumen.wa b{color:#8a5a12}
.resumen.mal{border-color:var(--mal); background:rgba(190,60,60,.06)}
.resumen.mal b{color:var(--mal)}

/* Cuatro estados, no dos. «No se pudo saber» no es un fallo, y pintarlo rojo
   mandaría a buscar un problema que no existe. */
.renglon.dx{grid-template-columns:22px auto 1fr}
.sello.na{background:var(--soft); color:var(--muted)}
.sello.wa{background:#fdf0dc; color:#8a5a12}
.sello.mal{background:rgba(190,60,60,.12); color:var(--mal)}
.hoja-larga > .btn.gris{margin-top:6px}

/* --------------------------------------------------------- concepto libre */
/* Junto al buscador, discreto. Es la salida de emergencia del catálogo, no la
   forma normal de cobrar: si compitiera visualmente con el buscador, invitaría
   a teclear precios en lugar de escanear. */
.btn-libre{
  flex:0 0 auto; padding:12px 15px; border-radius:12px;
  border:1.5px solid var(--line); background:var(--white);
  color:var(--muted); font-size:14px; font-weight:700;
}
.btn-libre:active{background:var(--soft)}

/* ------------------------------------------------------- importe exacto */
/* Ancho completo y alto de dedo. Va DEBAJO del campo y no al lado: al lado
   quedaría de 70 px y compite con el teclado que acaba de subir. */
.btn-exacto{
  width:100%; margin-top:8px; padding:12px;
  border:1.5px dashed var(--line); border-radius:12px;
  background:var(--soft); color:var(--muted);
  font-size:14px; font-weight:700; font-variant-numeric:tabular-nums;
}
.btn-exacto:active{background:var(--white); border-style:solid; color:var(--blue)}

/* La tostada que ofrece la copia lleva un botón dentro, así que necesita más
   sitio y no puede desaparecer sola sin que se pueda tocar. */
.tostada.copia{
  display:flex; align-items:center; gap:12px;
  background:var(--dark); color:#fff; padding:12px 14px;
}
.tostada.copia button{
  background:rgba(255,255,255,.16); color:#fff;
  border-radius:9px; padding:12px 14px; font-size:13.5px; font-weight:700;
  white-space:nowrap; min-height:44px;   /* se toca con prisa, con cliente delante */
}
.tostada.copia button:disabled{opacity:.5}

/* ------------------------------------------------------------- reimpresión */
/* En la V3 (360 px) los tres bloques en un renglón dejaban el nombre del cajero
   partido en tres líneas y el botón en 70×37 px — por debajo de los 44 con los
   que un dedo acierta a la primera. Se parte en dos renglones: los datos
   arriba, el importe y el botón abajo. */
.renglon.tk{grid-template-columns:1fr auto; gap:10px 12px; align-items:center}
.tk-dat{display:flex; flex-direction:column; gap:2px; min-width:0; grid-column:1 / -1}
.tk-dat b{font-size:15px}
.tk-dat .apagado{font-size:12.5px; line-height:1.4}
.tk-total{font-weight:700; font-size:16px; font-variant-numeric:tabular-nums; white-space:nowrap}
.renglon.tk .btn{padding:12px 20px; font-size:14px; min-height:44px}
.tk-botones{display:flex; gap:8px; justify-content:flex-end}
.renglon.tk .btn.peligro{padding:12px 14px}

/* ---------------------------------------------------------- eliminar venta */
/* Rojo apagado y no rojo lleno: está al lado de «Copia», que se toca a diario,
   y no debe gritar más que él. El PIN es lo que protege, no el color. */
.btn.peligro{background:#fdecec; color:var(--mal)}
.hoja .btn.peligro{background:var(--mal); color:#fff}
.lista-elim{margin:8px 0 12px 18px; font-size:14px; line-height:1.5}
.lista-elim li{margin:2px 0}
.interruptor{display:flex; align-items:center; gap:10px; font-weight:600; font-size:14.5px;
  margin:6px 0 8px; min-height:44px; cursor:pointer}
.interruptor input{width:22px; height:22px; accent-color:var(--blue); flex-shrink:0}
.aviso-mal{color:var(--mal); font-size:14px; line-height:1.45; margin:6px 0 4px}
.hoja-larga > .btn.gris + .btn.gris, .hoja-larga > .tarjeta + .btn.gris{margin-top:10px; width:100%}
.elim{display:flex; flex-direction:column; gap:3px; padding:12px 0; border-top:1px solid var(--line)}
.elim-cab{display:flex; justify-content:space-between; align-items:baseline; gap:10px}

@media(min-width:560px){
  /* Con sitio de sobra vuelve a un solo renglón, que se escanea más rápido. */
  .renglon.tk{grid-template-columns:1fr auto auto}
  .tk-dat{grid-column:auto}
}

/* El papel tal como saldría. Monoespaciada porque el ticket está maquetado en
   columnas: con una tipografía proporcional los importes no cuadran y el
   formato se ve roto sin estarlo. */
.papel{
  font-family:ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  font-size:12px; line-height:1.35; white-space:pre;
  background:var(--soft); border:1px solid var(--line); border-radius:12px;
  padding:14px; margin:10px 0 0; overflow-x:auto;
}

/* ------------------------------------------------ cotizaciones por cobrar */
.lista-cot{display:flex;flex-direction:column;gap:8px;margin-bottom:14px}
.lista-cot .vacio{color:var(--muted);text-align:center;padding:24px 0;font-size:14px}
.cot-item{text-align:left;border:1.5px solid var(--line);border-radius:14px;padding:12px 14px;
  background:var(--white);width:100%}
.cot-item:active{background:var(--soft)}
.cot-item:disabled{opacity:.55}
.cot-fila{display:flex;justify-content:space-between;align-items:baseline;gap:10px}
.cot-fila b{font-size:14.5px}
.cot-total{font-variant-numeric:tabular-nums;white-space:nowrap}
.cot-cliente{font-size:13px;color:var(--ink);margin-top:2px;line-height:1.35}
.cot-sub{display:flex;justify-content:space-between;align-items:center;gap:8px;
  font-size:11.5px;color:var(--muted);margin-top:4px}
.cot-nota{font-size:11.5px;color:var(--warn);font-weight:600;margin-top:5px}
.chip.cot{background:rgba(0,119,182,.1);color:var(--blue);white-space:nowrap}

/* ===========================================================================
   iPHONE: la isla y la barra de inicio
   ---------------------------------------------------------------------------
   En la app de iPhone la página ocupa TODA la pantalla, también detrás de la
   isla de arriba y de la barra de inicio de abajo, y es ella la que se aparta.
   Así el fondo de cada pantalla —azul en el PIN, blanco en la venta— llega
   hasta el borde, en vez de dejar franjas de otro color.

   `env(safe-area-inset-*)` vale CERO en la V3, en el navegador de escritorio
   y en cualquier aparato sin isla: estas reglas no cambian nada ahí. Sólo
   funcionan porque todas las pantallas llevan `viewport-fit=cover`.
   =========================================================================== */
.barra{
  height:calc(52px + env(safe-area-inset-top, 0px));
  padding-top:env(safe-area-inset-top, 0px);
}
.app{padding-bottom:env(safe-area-inset-bottom, 0px)}
.acceso{
  padding-top:calc(24px + env(safe-area-inset-top, 0px));
  padding-bottom:calc(24px + env(safe-area-inset-bottom, 0px));
}
.hoja{padding-bottom:calc(20px + env(safe-area-inset-bottom, 0px))}
.tostadas{bottom:calc(18px + env(safe-area-inset-bottom, 0px))}

