/* =============================================================
   5. Componentes compartidos (tienda + sistema, vía variables)
   ============================================================= */

/* ---------- Splash ---------- */
.splash {
  position: fixed; inset: 0; z-index: var(--z-splash);
  display: grid; place-content: center; gap: 1.4rem;
  background: var(--paper);
  transition: opacity .5s var(--ease-out), visibility .5s;
  animation: splashSafety .01s 4.5s forwards;
}
.splash.is-out { opacity: 0; visibility: hidden; pointer-events: none; }
@keyframes splashSafety { to { opacity: 0; visibility: hidden; pointer-events: none; } }
.splash__mark { font-family: var(--comic); font-size: clamp(2.4rem, 9vw, 4rem); letter-spacing: .04em; color: var(--ink); display: flex; align-items: center; gap: .5rem; }
.splash__mark b { color: var(--ink-fixed); -webkit-text-stroke: 2px var(--ink-fixed); background: var(--panini); padding: 0 .25em; box-shadow: var(--shadow-hard-sm); }
.splash__bar { width: 220px; height: 8px; border: 2px solid var(--ink); overflow: hidden; }
.splash__bar i { display: block; height: 100%; width: 38%; background: var(--ink); animation: load 1s var(--ease-soft) infinite; }
@keyframes load { 0% { transform: translateX(-110%); } 100% { transform: translateX(360%); } }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- Top bar (chrome público) ---------- */
.topbar {
  position: sticky; top: 0; z-index: var(--z-topbar);
  min-height: var(--topbar-h);
  display: flex; align-items: center; gap: 1rem;
  padding: .5rem var(--gutter);
  background: var(--paper-2);
  border-bottom: 3px solid var(--ink);
}
/* Dentro de login/POS/admin (tema cyber oscuro) el topbar sigue viéndose
   igual que en la tienda (fondo claro fijo, arriba) — así que su texto e
   iconos también deben resolver a los tokens CLAROS de la tienda aquí
   dentro, no a los --text/--faint/--line oscuros de body.in-app (que
   quedarían casi invisibles sobre un fondo blanco). Mismo patrón que la
   "isla" del .hero en tokens.css: re-tematizado local, sin tocar el resto
   del panel. */
body.in-app .topbar {
  --text: var(--ink);
  --muted: #63636d;
  --faint: #8a8a93;
  --surface-2: var(--paper-3);
  --line: var(--ink);
}
/* El selector/idioma y "Mi panel" también tienen versión "cyber" (píldoras
   redondeadas, sin borde) para el resto de login/POS/admin — dentro del
   topbar se cancela esa variante y se repite el estilo "cómic" exacto de
   la tienda (esquinas rectas, borde de 2px, sombra dura), en vez de
   duplicar los mismos botones con clases nuevas. */
body.in-app .topbar .lang-toggle { border-color: var(--ink); background: var(--paper-2); border-radius: 0; box-shadow: 3px 3px 0 var(--ink); }
body.in-app .topbar .lang-toggle button { border-radius: 0; }
body.in-app .topbar .lang-toggle button.is-active {
  color: var(--neon-cyan); background: var(--ink-fixed); border-color: var(--ink-fixed); box-shadow: 3px 3px 0 var(--neon-cyan);
}
body.in-app .topbar .btn {
  border-radius: 0; border-color: var(--ink); text-transform: uppercase; font-size: .92rem;
  background: var(--paper-2); color: var(--ink); box-shadow: var(--shadow-hard-sm);
}
body.in-app .topbar .btn:hover { transform: translate(-2px,-2px); box-shadow: 6px 6px 0 var(--ink); }
body.in-app .topbar .btn:active { transform: translate(1px,1px); box-shadow: none; }
body.in-app .topbar .btn--panini { background: var(--panini); color: var(--ink-fixed); border-color: var(--ink-fixed); }
body.in-app .topbar .btn--ink { background: var(--ink); color: var(--paper-2); border-color: var(--ink); }
/* El toggle claro/oscuro de la tienda también debe voltear el topbar
   dentro de login/POS/admin (antes se quedaba fijo en claro). Mismos
   valores que usa la tienda en :root[data-theme=dark] body:not(.in-app)
   arriba en tokens.css — --paper-2/--ink son los que de verdad pintan el
   fondo/borde/sombra del topbar y sus botones (ver reglas de arriba), así
   que redefinirlos aquí basta para que todo el bloque se re-tiña. */
:root[data-theme="dark"] body.in-app .topbar {
  --paper-2: #1b1b24;
  --paper-3: #23232f;
  --ink: #f2efe6;
  --text: #f2efe6;
  --muted: #a4a1af;
  --faint: #77757f;
  --surface-2: #23232f;
  --line: #3b3b49;
}

.brand { display: flex; align-items: center; gap: .5rem; font-family: var(--comic); font-size: 1.7rem; letter-spacing: .03em; color: var(--text); line-height: 1; }
.brand__glyph {
  display: inline-grid; place-items: center; width: 1.5em; height: 1.5em;
  background: var(--panini); color: var(--ink-fixed); border: 2px solid var(--ink-fixed);
  font-family: var(--display); font-size: .7em; transform: rotate(-4deg);
}
body.in-app .brand__glyph { background: var(--accent); }
.brand b { color: var(--text); }

.topbar__nav { display: none; gap: 1.15rem; margin-inline: .4rem; }
.topbar__nav a {
  font-family: var(--display); text-transform: uppercase; font-size: .92rem; letter-spacing: .04em;
  color: var(--text); padding: .2rem 0; border-bottom: 3px solid transparent;
  transition: border-color .18s var(--ease-out), color .18s var(--ease-out);
}
.topbar__nav a:hover, .topbar__nav a.is-active { border-color: var(--panini-deep); }
@media (min-width: 1040px) { .topbar__nav { display: flex; } }
body.in-app .topbar__nav { display: none; }

.topbar__actions { margin-inline-start: auto; display: flex; align-items: center; gap: .55rem; }

/* ---------- Lang toggle (brutalist neón, con banderas) ---------- */
.lang-toggle {
  display: inline-flex; gap: 3px; padding: 3px;
  border: 2px solid var(--ink); background: var(--paper-2);
  box-shadow: 3px 3px 0 var(--ink);
}
.lang-toggle button {
  display: inline-flex; align-items: center; gap: .32rem;
  font-family: var(--mono); font-size: .72rem; font-weight: 700; letter-spacing: .06em;
  line-height: 1; padding: .32rem .56rem; color: var(--muted);
  border: 2px solid transparent;
  transition: transform .16s var(--ease-bounce), color .15s var(--ease-out),
              background .15s var(--ease-out), box-shadow .15s var(--ease-out), border-color .15s var(--ease-out);
}
.lang-toggle__flag { font-size: 1rem; line-height: 1; filter: grayscale(.55) contrast(1.05); transition: transform .16s var(--ease-bounce), filter .15s var(--ease-out); }
.lang-toggle button:hover { transform: translateY(-2px) scale(1.05); color: var(--ink); }
.lang-toggle button:hover .lang-toggle__flag { transform: scale(1.18); filter: none; }
.lang-toggle button:active { transform: translateY(0) scale(.98); }
.lang-toggle button.is-active {
  color: var(--neon-cyan); background: var(--ink-fixed);
  border-color: var(--ink-fixed); box-shadow: 3px 3px 0 var(--neon-cyan);
}
.lang-toggle button.is-active .lang-toggle__flag { filter: none; }

body.in-app .lang-toggle { border-color: var(--line); background: var(--surface-2); border-radius: 999px; box-shadow: none; }
body.in-app .lang-toggle button { border-radius: 999px; }
body.in-app .lang-toggle button.is-active {
  color: #05060b; background: var(--accent); border-color: transparent;
  box-shadow: 0 0 0 1px var(--accent), 0 0 14px rgba(0,229,255,.45);
}

/* ---------- Cart button ---------- */
.cartbtn {
  position: relative; display: inline-flex; align-items: center; gap: .4rem;
  padding: .5rem .8rem; border: 2px solid var(--ink); background: var(--paper-2);
  font-family: var(--display); text-transform: uppercase; font-size: .82rem; letter-spacing: .04em;
  box-shadow: var(--shadow-hard-sm);
  transition: transform .14s var(--ease-out), box-shadow .18s var(--ease-out);
}
.cartbtn:hover { transform: translate(-1px,-1px); box-shadow: 5px 5px 0 var(--ink); }
.cartbtn:active { transform: translate(2px,2px); box-shadow: none; }
.cartbtn__count {
  box-sizing: border-box;
  min-width: 1.5em; height: 1.5em; padding: 0 .32em;
  display: inline-flex; align-items: center; justify-content: center;
  line-height: 1; text-align: center;
  background: var(--panini); color: var(--ink-fixed); border: 2px solid var(--ink-fixed);
  font-family: var(--mono); font-size: .68rem; font-weight: 700; font-variant-numeric: tabular-nums;
}
.cartbtn__count:empty, .cartbtn__count[data-count="0"] { display: none; }

/* ---------- Nav sign: pictograma "señal de evacuación" (entrada / salida) ----------
   .navsign es la base compartida por el link de acceso (.navsign--enter,
   además .btn) y el botón de logout (.navsign--exit, sin chrome de botón).
   Contención: TODA la escena (puerta + figura) vive dentro de
   .navsign__stage, una caja de tamaño FIJO con overflow:hidden — el
   personaje solo se traduce unos px dentro de esa caja, así que
   estructuralmente no puede desbordar el botón ni superponerse al texto
   (que es un elemento hermano, .navsign__label). El stage nunca cambia de
   tamaño con el hover, así que el botón tampoco.
   Estilo pictograma: placa amarilla (--panini) con puerta y figura en
   negro (--ink) — mismo lenguaje que un pictograma de señalización
   (icono oscuro sobre fondo de contraste), usando solo los tokens de
   marca ya existentes. La figura es un SVG hecho con formas geométricas
   simples (círculo + rectángulos angulados) a propósito: es un
   placeholder fácil de sustituir — reemplaza solo el <svg> dentro de
   .navsign__figure; toda la animación (transform/opacity) está declarada
   sobre esa clase contenedora, no sobre el SVG, así que un sprite/imagen
   futuro la hereda sin tocar una sola línea de CSS.
   Disparo: :hover, :focus-visible (teclado) y .is-touched (tap en
   táctil — ver initNavFx en main.js; usa touchstart SIN preventDefault
   para no bloquear el clic real). Todo por `transition`, no `animation`:
   si el mouse sale a medio camino, revierte suave desde el punto actual
   en vez de saltar o reiniciarse. */
.navsign { position: relative; }
.navsign__label { white-space: nowrap; }
.navsign__stage {
  position: relative; overflow: hidden; flex: 0 0 auto;
  width: 30px; height: 26px;
  background: var(--panini); border: 2px solid var(--ink);
}
.navsign__door { position: absolute; top: 1px; width: 11px; height: 24px; perspective: 140px; }
.navsign__frame { position: absolute; inset: 0; border: 1.5px solid var(--ink-fixed); background: var(--paper-fixed); }
.navsign__leaf {
  position: absolute; inset: 0; background: var(--ink-fixed);
  transform-style: preserve-3d;
  transition: transform .34s var(--ease-bounce);
}
/* Chispazo de impacto: un anillo que se expande y se desvanece pegado al
   marco de la puerta, igual que el "destello" que se ve en el momento en
   que la puerta se cierra/abre de golpe en el video de referencia. Vive
   DENTRO de .navsign__stage (que ya recorta con overflow:hidden), así que
   por más que crezca nunca sale del botón. */
.navsign__door::after {
  content: ""; position: absolute; inset: -1px;
  box-shadow: 0 0 0 0 var(--ink); opacity: 0; pointer-events: none;
}
@keyframes navsignPing {
  0%   { box-shadow: 0 0 0 0 var(--ink); opacity: .55; }
  100% { box-shadow: 0 0 0 5px var(--ink); opacity: 0; }
}
.navsign__figure {
  position: absolute; bottom: 1px; width: 13px; height: 19px; color: var(--ink-fixed);
  transition: transform .26s cubic-bezier(.4,0,.2,1), opacity .16s ease;
}

/* Sacudida de impacto: la placa entera (puerta + figura, ya contenidas en
   .navsign__stage) da un golpecito de rotación justo cuando termina el
   paso por la puerta — como si la puerta acabara de azotarse. Es una
   animación de un solo disparo (no infinite): CSS solo la reproduce
   mientras dura el estado :hover/:focus-visible/.is-touched, así que
   quitar el mouse a medio bamboleo simplemente la corta ahí, sin dejarla
   "colgada" a mitad de un giro (transform vuelve a rotate(0) por la regla
   base de .navsign__stage, ver abajo). El delay hace que arranque justo
   cuando la figura ya casi terminó de desvanecerse/aparecer. */
@keyframes navsignShake {
  0%   { transform: rotate(0deg); }
  25%  { transform: rotate(-3deg); }
  55%  { transform: rotate(2.5deg); }
  80%  { transform: rotate(-1deg); }
  100% { transform: rotate(0deg); }
}
.navsign__stage { transform: rotate(0deg); }

/* Entrada: puerta a la derecha, la figura arranca visible a la izquierda
   y camina HACIA la puerta, encogiéndose/desvaneciendo al "entrar". */
.navsign--enter .navsign__door { right: 1px; transform-origin: left center; }
.navsign--enter .navsign__figure { left: 2px; transform: translateX(0) scale(1); opacity: 1; }
.navsign--enter:hover .navsign__leaf,
.navsign--enter:focus-visible .navsign__leaf,
.navsign--enter.is-touched .navsign__leaf { transform: rotateY(-98deg); }
.navsign--enter:hover .navsign__figure,
.navsign--enter:focus-visible .navsign__figure,
.navsign--enter.is-touched .navsign__figure {
  transform: translateX(8px) scale(.5); opacity: 0;
  transition-delay: .04s, 0s;
}
.navsign--enter:hover .navsign__stage,
.navsign--enter:focus-visible .navsign__stage,
.navsign--enter.is-touched .navsign__stage { animation: navsignShake .3s ease-in-out .18s 1; }
.navsign--enter:hover .navsign__door::after,
.navsign--enter:focus-visible .navsign__door::after,
.navsign--enter.is-touched .navsign__door::after { animation: navsignPing .38s ease-out .16s 1; }

/* Salida: puerta a la izquierda, la figura arranca oculta junto a la
   puerta y aparece/se aleja hacia la derecha — dirección y estado de
   reposo invertidos respecto a la entrada, mismo lenguaje visual. */
.navsign--exit .navsign__door { left: 1px; transform-origin: right center; }
.navsign--exit .navsign__figure { right: 2px; transform: translateX(-8px) scale(.5); opacity: 0; }
.navsign--exit:hover .navsign__leaf,
.navsign--exit:focus-visible .navsign__leaf,
.navsign--exit.is-touched .navsign__leaf { transform: rotateY(98deg); }
.navsign--exit:hover .navsign__figure,
.navsign--exit:focus-visible .navsign__figure,
.navsign--exit.is-touched .navsign__figure {
  transform: translateX(0) scale(1); opacity: 1;
  transition-delay: .06s, .06s;
}
.navsign--exit:hover .navsign__stage,
.navsign--exit:focus-visible .navsign__stage,
.navsign--exit.is-touched .navsign__stage { animation: navsignShake .3s ease-in-out .18s 1; }
.navsign--exit:hover .navsign__door::after,
.navsign--exit:focus-visible .navsign__door::after,
.navsign--exit.is-touched .navsign__door::after { animation: navsignPing .38s ease-out .16s 1; }

/* .navsign--enter reutiliza .btn (borde, sombra, mismo hover que el resto
   de la navegación). .navsign--exit es deliberadamente SIN contorno de
   botón: solo la placa/figura son el elemento interactivo, con área de
   clic ampliada por el padding. */
.navsign--exit {
  display: inline-flex; align-items: center; justify-content: center;
  padding: .3rem; flex: 0 0 auto;
  background: transparent; border: 0; box-shadow: none; cursor: pointer;
}

/* ---------- Tooltip de los signos de nav ----------
   Mismo lenguaje visual que el tooltip existente (.tip::after en este
   archivo: burbuja + flecha, activado por :hover/:focus-visible), pero
   anclado hacia ABAJO (estos elementos están pegados arriba, en la
   topbar) y alineado al borde derecho (están pegados al borde derecho de
   la página, centrado se saldría del viewport). No reutiliza el toggle
   táctil de UI.bindTips() a propósito: ese handler llama
   preventDefault() en cada tap, lo que bloquearía la navegación/el
   logout real en pantallas táctiles — aquí el toque se resuelve con
   .is-touched (initNavFx en main.js), que NO bloquea el clic. */
.navsign[data-tip]::after {
  content: attr(data-tip);
  position: absolute; top: calc(100% + 9px); right: 0; transform: translateY(-6px) scale(.92);
  width: max-content; max-width: 190px; padding: .5rem .65rem;
  background: var(--ink); color: var(--paper-2); border: 2px solid var(--panini);
  font: 700 .68rem/1.3 var(--sans); text-transform: none; letter-spacing: normal; text-align: left;
  box-shadow: 3px 3px 0 var(--ink); opacity: 0; visibility: hidden; pointer-events: none;
  transform-origin: top right; z-index: 30;
  transition: opacity .16s var(--ease-out), transform .18s var(--ease-bounce), visibility 0s linear .18s;
}
.navsign[data-tip]::before {
  content: ""; position: absolute; top: calc(100% + 3px); right: 10px;
  border: 6px solid transparent; border-bottom-color: var(--ink);
  opacity: 0; visibility: hidden; pointer-events: none; z-index: 31;
  transition: opacity .16s var(--ease-out), visibility 0s linear .18s;
}
.navsign[data-tip]:hover::after, .navsign[data-tip]:focus-visible::after, .navsign[data-tip].is-touched::after,
.navsign[data-tip]:hover::before, .navsign[data-tip]:focus-visible::before, .navsign[data-tip].is-touched::before {
  opacity: 1; visibility: visible; transition-delay: 0s;
}
.navsign[data-tip]:hover::after, .navsign[data-tip]:focus-visible::after, .navsign[data-tip].is-touched::after {
  transform: translateY(0) scale(1);
}

@media (prefers-reduced-motion: reduce) {
  .navsign__leaf, .navsign__figure { transition: none !important; }
  .navsign__stage, .navsign__door::after { animation: none !important; }
  .navsign[data-tip]::after, .navsign[data-tip]::before { transition: opacity .12s linear !important; }
}

/* ---------- Header compacto en móvil ----------
   Nunca se ocultan: marca, idioma (ES/EN), carrito y "Mi panel"/"Login". */
@media (max-width: 768px) {
  .topbar { gap: .45rem; padding: .5rem .8rem; }
  .brand { font-size: 1.15rem; gap: .35rem; }
  .topbar__actions { gap: .35rem; flex-wrap: nowrap; }

  /* Carrito: sólo ícono + contador (se oculta la palabra) */
  .cartbtn { padding: .46rem .55rem; gap: .2rem; font-size: .8rem; }
  .cartbtn > span[data-i18n] { display: none; }

  .lang-toggle { box-shadow: 2px 2px 0 var(--ink); }
  .lang-toggle button { padding: .3rem .4rem; font-size: .62rem; gap: .25rem; }
  .lang-toggle__flag { font-size: .9rem; }

  /* Botón de acceso / panel */
  .topbar__actions .btn { padding: .38rem .55rem; font-size: .68rem; letter-spacing: 0; }
}

@media (max-width: 400px) {
  .topbar { gap: .3rem; padding: .5rem .6rem; }
  .brand span:not(.brand__glyph) { display: none; }   /* deja sólo el glifo "G" */
  .topbar__actions .btn { padding: .36rem .44rem; font-size: .64rem; }
  .lang-toggle__code { display: none; }               /* deja sólo la bandera */
  .lang-toggle button { padding: .3rem .34rem; }
}

/* El texto "Iniciar sesión / Registrarse" + la placa del pictograma no
   caben juntos por debajo de ~560px (se verificó con el navegador: el
   topbar se desbordaba y el pictograma quedaba recortado fuera de
   pantalla). Mismo patrón que .cartbtn arriba: se oculta solo la palabra,
   el pictograma (ya con su propio tooltip accesible) pasa a ser el botón.
   El texto NO se quita del DOM (sigue siendo el nombre accesible del
   link) — se oculta visualmente con la misma técnica de .sr-only. */
@media (max-width: 560px) {
  .navsign--enter .navsign__label {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  /* Sin la palabra, el contorno de .btn (fondo negro, borde, sombra) se
     queda como un cuadro suelto alrededor del pictograma — desentona con
     el resto del topbar, que en esta anchura ya solo muestra íconos
     sueltos (carrito, tema, idioma). Se le quita el chrome de botón y
     queda igual que .navsign--exit: solo la placa amarilla/negra del
     pictograma, con el padding como área de toque. */
  .navsign--enter.btn {
    gap: 0; padding: .3rem; background: transparent; border: 0; box-shadow: none;
  }
  /* Dentro de login/POS/admin, "body.in-app .topbar .btn" (más específica)
     le vuelve a poner fondo/sombra a CUALQUIER .btn del topbar, incluido
     este — hay que repetirlo con esa misma cadena para ganarle. */
  body.in-app .topbar .navsign--enter.btn {
    background: transparent; border: 0; box-shadow: none;
  }
}

/* ---------- Botones ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .62rem 1.05rem;
  font-family: var(--display); text-transform: uppercase; letter-spacing: .03em;
  font-weight: 400; font-size: .92rem;
  color: var(--btn-fg); background: var(--btn-bg);
  border: 2px solid var(--btn-border);
  box-shadow: var(--btn-shadow);
  border-radius: 0;
  transition: transform .14s var(--ease-out), box-shadow .18s var(--ease-out), background .18s var(--ease-out), color .18s var(--ease-out), opacity .2s;
  white-space: nowrap;
}
body.in-app .btn { border-radius: var(--radius-sm); border-color: transparent; text-transform: none; font-size: .9rem; }
.btn:hover { transform: translate(-2px,-2px); box-shadow: 6px 6px 0 var(--ink); }
body.in-app .btn:hover { transform: translateY(-2px); box-shadow: var(--nm-out); }
.btn:active { transform: translate(1px,1px); box-shadow: none; }
body.in-app .btn:active { transform: translateY(0); box-shadow: var(--nm-in-sm); }

.btn--lg { padding: .9rem 1.6rem; font-size: 1.05rem; }
.btn--sm { padding: .4rem .7rem; font-size: .78rem; }
.btn--block { display: flex; width: 100%; }

.btn--panini, .btn--neon { background: var(--panini); color: var(--ink-fixed); border-color: var(--ink-fixed); }
body.in-app .btn--neon { background: var(--accent); color: #05060b; box-shadow: var(--glow-cyan), 4px 4px 14px var(--nm-dark); border-color: transparent; }
.btn--ink, .btn--violet { background: var(--ink); color: var(--paper-2); border-color: var(--ink); }
body.in-app .btn--violet { background: linear-gradient(180deg, var(--neon-violet), #6a3ee0); color: #fff; box-shadow: var(--glow-violet), 4px 4px 14px var(--nm-dark); }
.btn--ghost { background: transparent; box-shadow: none; }
body.in-app .btn--ghost { box-shadow: inset 0 0 0 1px var(--line); }
.btn--ghost:hover { background: var(--panini); }
body.in-app .btn--ghost:hover { background: transparent; box-shadow: inset 0 0 0 1px var(--accent); color: #fff; }
.btn--danger { background: var(--danger); color: #fff; border-color: var(--ink); }

/* Fila de acciones del POS (Apartados / Inicio / Cerrar sesión): mismo
   trato "cómic" de la tienda que ya tiene el topbar (esquinas rectas,
   borde visible, relleno amarillo al hover) en vez de los botones
   fantasma redondeados y sin borde del resto del panel. Van sobre el
   fondo suelto de la página (no una barra propia como el topbar), así
   que usan --text/--line — que SÍ siguen el claro/oscuro del toggle
   dentro de in-app — en vez de --ink/--paper-2 (fijos), para que
   se sigan leyendo bien en ambos modos. Escopado a .pos-view para no
   tocar los botones de admin/gerente que comparten .content__head. */
body.in-app .pos-view .content__head .btn {
  border-radius: 0; border-color: var(--line); text-transform: uppercase; font-size: .82rem;
}
body.in-app .pos-view .content__head .btn--ghost { background: transparent; box-shadow: none; color: var(--text); }
body.in-app .pos-view .content__head .btn--ghost:hover { background: var(--panini); color: var(--ink-fixed); border-color: var(--ink-fixed); }
body.in-app .pos-view .content__head .btn--ghost:active { transform: translate(1px,1px); }

.btn[disabled], .btn.is-loading { opacity: .5; pointer-events: none; }
.btn.is-loading::after {
  content: ""; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent; animation: spin .7s linear infinite;
}

/* ---------- Card / panel ---------- */
.card {
  background: var(--surface);
  border: 2px solid var(--line);
  box-shadow: var(--shadow-hard-sm);
  border-radius: 0;
  padding: 1.3rem;
}
body.in-app .card { border: 0; border-radius: var(--radius); box-shadow: var(--nm-out); }
.panel { background: var(--surface-2); border: 2px solid var(--line); border-radius: 0; }
body.in-app .panel { border: 1px solid var(--line-soft); border-radius: var(--radius); }

/* ---------- Formularios ---------- */
.field { display: flex; flex-direction: column; gap: .4rem; margin-bottom: 1rem; }
.field > label { font-size: .74rem; font-weight: 700; color: var(--muted); letter-spacing: .06em; text-transform: uppercase; font-family: var(--mono); }
.input, .select, .textarea {
  width: 100%; padding: .7rem .85rem;
  background: var(--surface); color: var(--text);
  border: 2px solid var(--line); border-radius: 0;
  transition: box-shadow .15s var(--ease-out), border-color .15s var(--ease-out);
}
body.in-app .input, body.in-app .select, body.in-app .textarea {
  border: 1px solid transparent; border-radius: 12px; box-shadow: var(--nm-in-sm);
}
.input::placeholder, .textarea::placeholder { color: var(--faint); }
.input:focus, .select:focus, .textarea:focus {
  outline: none; border-color: var(--neon-cyan);
  box-shadow: 4px 4px 0 var(--neon-cyan);
}
body.in-app .input:focus, body.in-app .select:focus, body.in-app .textarea:focus {
  box-shadow: var(--nm-in-sm), 0 0 0 3px rgba(0,229,255,.16);
}
.select { appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--text) 50%), linear-gradient(135deg, var(--text) 50%, transparent 50%); background-position: right 1rem center, right .78rem center; background-size: 6px 6px, 6px 6px; background-repeat: no-repeat; }
.textarea { min-height: 84px; resize: vertical; }
.field__error { font-size: .74rem; color: var(--danger); font-weight: 600; }
.field.has-error .input, .field.has-error .select { border-color: var(--danger); box-shadow: 3px 3px 0 var(--danger); }

/* ---------- Tooltip informativo (icono "i" junto a un label) ----------
   Solo necesita el botón <button class="tip" data-tip="texto…">i</button> —
   la burbuja se pinta con ::after/::before (contenido = data-tip + flechita),
   sin nodos extra. Estética "brutal" (inspirada en un botón de Uiverse.io de
   ratue1256) hecha con los tokens de siempre: mismo golpe duro y el mismo
   translate al pasar el mouse que ya usa .btn, nada nuevo que aprender.
   Hover/foco de teclado la muestran por CSS solo; en táctil, UI.bindTips()
   (ui.js) agrega toggle al tocar el icono y cierre al tocar fuera. */
.tip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 17px; height: 17px; margin-left: .35rem; vertical-align: middle;
  border-radius: 0; border: 2px solid var(--ink-fixed); background: var(--panini);
  color: var(--ink-fixed); font: 800 .64rem/1 var(--mono); text-transform: none;
  letter-spacing: 0; cursor: help; position: relative; flex: 0 0 auto;
  box-shadow: 2px 2px 0 var(--ink-fixed);
  transition: transform .12s var(--ease-out), box-shadow .12s var(--ease-out);
}
body.in-app .tip {
  border-radius: 50%; border-color: transparent; background: var(--surface-2);
  color: var(--faint); box-shadow: var(--nm-out-sm);
}
.tip:hover, .tip:focus-visible, .tip.is-open { transform: translate(-1px,-1px); box-shadow: 3px 3px 0 var(--ink); }
.tip:active { transform: translate(1px,1px); box-shadow: 0 0 0 var(--ink); }
body.in-app .tip:hover, body.in-app .tip:focus-visible, body.in-app .tip.is-open { transform: translateY(-1px); box-shadow: var(--nm-out); }
body.in-app .tip:active { transform: translateY(0); box-shadow: var(--nm-in-sm); }

.tip::after {
  content: attr(data-tip);
  position: absolute; left: 50%; bottom: calc(100% + 13px); transform: translate(-50%, 6px) scale(.92);
  width: max-content; max-width: 230px; padding: .6rem .75rem; border-radius: 0;
  background: var(--ink); color: var(--paper-2); border: 2px solid var(--neon-cyan);
  font: 700 .7rem/1.4 var(--sans); text-transform: none; letter-spacing: normal; text-align: left;
  box-shadow: 4px 4px 0 var(--ink); opacity: 0; visibility: hidden; pointer-events: none;
  transform-origin: bottom center; z-index: 20;
  transition: opacity .18s var(--ease-out), transform .2s var(--ease-bounce), visibility 0s linear .2s;
}
.tip::before {
  content: ""; position: absolute; left: 50%; bottom: calc(100% + 7px); transform: translateX(-50%);
  border: 6px solid transparent; border-top-color: var(--ink);
  opacity: 0; visibility: hidden; pointer-events: none; z-index: 21;
  transition: opacity .18s var(--ease-out), visibility 0s linear .2s;
}
body.in-app .tip::after { border-radius: var(--radius-sm); border-color: var(--accent-2); box-shadow: var(--nm-out); }
.tip:hover::after, .tip:focus-visible::after, .tip.is-open::after,
.tip:hover::before, .tip:focus-visible::before, .tip.is-open::before {
  opacity: 1; visibility: visible; transition-delay: 0s;
}
.tip:hover::after, .tip:focus-visible::after, .tip.is-open::after { transform: translate(-50%, 0) scale(1); }
@media (prefers-reduced-motion: reduce) {
  .tip, .tip::after { transition: opacity .12s linear; }
  .tip:hover, .tip:focus-visible, .tip.is-open, .tip:active { transform: none; }
}
@media (max-width: 480px) {
  .tip::after { left: auto; right: -.5rem; transform: translateY(6px) scale(.92); }
  .tip::before { left: auto; right: .55rem; transform: none; }
  .tip:hover::after, .tip:focus-visible::after, .tip.is-open::after { transform: translateY(0) scale(1); }
}

/* ---------- Badges / chips ---------- */
.badge {
  display: inline-flex; align-items: center; gap: .35rem;
  font-family: var(--mono); font-size: .66rem; font-weight: 700; letter-spacing: .08em;
  padding: .2rem .5rem; text-transform: uppercase;
  background: var(--ink); color: var(--paper-2); border-radius: 0;
}
body.in-app .badge { background: var(--surface-3); color: var(--muted); border-radius: 999px; }
.badge--ok { background: var(--success); color: #fff; }
.badge--warn { background: var(--warning); color: #fff; }
.badge--danger { background: var(--danger); color: #fff; }
.badge--cyan { background: var(--neon-cyan); color: var(--ink-fixed); }
.badge--violet { background: var(--neon-violet); color: #fff; }
.badge--panini { background: var(--panini); color: var(--ink-fixed); }

.chip {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .4rem .75rem; border: 2px solid var(--line);
  background: var(--surface); font-size: .82rem; font-weight: 600;
  transition: background .15s var(--ease-out), color .15s var(--ease-out), transform .12s var(--ease-out);
}
body.in-app .chip { border: 0; border-radius: 999px; box-shadow: var(--nm-out-sm); color: var(--muted); }
.chip:hover { transform: translateY(-1px); }
.chip.is-active { background: var(--panini); color: var(--ink-fixed); }
body.in-app .chip.is-active { background: var(--accent); color: #05060b; box-shadow: var(--glow-cyan); }

/* ---------- Selector de etiquetas (novedad / oferta / preventa) ---------- */
.tagpick { display: flex; flex-wrap: wrap; gap: .5rem; }
.tagpick__opt {
  padding: .42rem .9rem; border: 2px solid var(--line); background: var(--surface);
  font-family: var(--mono); font-size: .72rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted); cursor: pointer; border-radius: 0;
  transition: background .15s var(--ease-out), color .15s var(--ease-out),
              border-color .15s var(--ease-out), transform .12s var(--ease-out);
}
.tagpick__opt:hover { transform: translateY(-1px); }
.tagpick__opt.is-on { background: var(--panini); color: var(--ink-fixed); border-color: var(--panini); }
body.in-app .tagpick__opt { border: 0; border-radius: 999px; box-shadow: var(--nm-out-sm); }
body.in-app .tagpick__opt.is-on { background: var(--accent); color: #05060b; box-shadow: var(--glow-cyan); }

/* ---------- Tablas ---------- */
.table-wrap { overflow-x: auto; border: 2px solid var(--line); }
body.in-app .table-wrap { border: 1px solid var(--line-soft); border-radius: var(--radius); }
table.data { width: 100%; border-collapse: collapse; font-size: .88rem; min-width: 560px; }
table.data thead th {
  text-align: left; font-family: var(--mono); font-size: .66rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--faint); padding: .8rem 1rem; background: var(--surface-2);
  border-bottom: 2px solid var(--line);
  white-space: nowrap;               /* encabezados en una sola línea */
}
body.in-app table.data thead th { border-bottom: 0; }
/* El encabezado sigue la alineación de su columna (si no, el título queda a la
   izquierda y el valor centrado/derecha -> se ven "descuadrados"). */
table.data thead th.right { text-align: right; }
table.data thead th.center { text-align: center; }
table.data tbody td { padding: .8rem 1rem; border-top: 1px solid var(--line-soft); }
table.data tbody tr { transition: background .12s var(--ease-out); }
table.data tbody tr:hover { background: var(--surface-2); }
.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }
/* Las columnas numéricas (importes, contadores) nunca parten a 2 líneas:
   así el valor y su encabezado quedan alineados. */
table.data th.num, table.data td.num { white-space: nowrap; }

/* Tabla de cotización dentro del modal: sin min-width, columnas ajustadas,
   los importes no se desbordan a la derecha. */
table.data.quote-table { min-width: 0; width: 100%; font-size: .84rem; table-layout: fixed; }
.quote-table tbody td { padding: .55rem .55rem; }
.quote-table td:first-child { width: auto; overflow-wrap: anywhere; }
.quote-table td.qcol-qty { width: 3rem; text-align: right; white-space: nowrap; }
.quote-table td.qcol-total { width: 6.25rem; text-align: right; white-space: nowrap; }
.quote-table .quote-total td { border-top: 2px solid var(--line); }
.modal .table-wrap:has(.quote-table) { overflow-x: visible; }

/* ---------- Toast ---------- */
/* z-index alto FIJO: los avisos de validación deben quedar SIEMPRE por encima
   del telón borroso (backdrop-filter) de los modales. */
.toasts { position: fixed; right: 1rem; bottom: 1rem; z-index: 10000; display: flex; flex-direction: column; gap: .6rem; max-width: min(92vw, 360px); }
.toast {
  padding: .8rem 1rem; background: var(--surface); color: var(--text);
  border: 2px solid var(--ink); border-left-width: 6px;
  box-shadow: var(--shadow-hard-sm); font-size: .88rem; font-weight: 500;
  animation: toastIn .3s var(--ease-out);
}
body.in-app .toast { border: 0; border-left: 3px solid var(--accent); border-radius: 12px; box-shadow: var(--nm-out); }
.toast--ok { border-left-color: var(--success); }
.toast--error { border-left-color: var(--danger); }
.toast--warn { border-left-color: var(--warning); }
@keyframes toastIn { from { opacity: 0; transform: translateX(24px); } }

/* ---------- Modal ---------- */
/* Con un modal abierto, el fondo NO se desplaza (el contenido del modal
   scrollea dentro de .modal__card). */
html.modal-open, html.modal-open body { overflow: hidden; }
.modal { position: fixed; inset: 0; z-index: var(--z-modal); display: grid; place-items: center; padding: 1.2rem; overscroll-behavior: contain; }
.modal__backdrop { position: absolute; inset: 0; background: rgba(12,12,14,.72); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }
.modal__card {
  position: relative; width: min(560px, 100%); max-height: 88vh; overflow-y: auto;
  background: var(--surface); color: var(--text);
  border: 3px solid var(--ink); box-shadow: 10px 10px 0 var(--ink);
  padding: 1.6rem;
}
body.in-app .modal__card { border: 0; border-radius: var(--radius-lg); box-shadow: var(--nm-out), var(--glow-violet); }
.modal__card--wide { width: min(920px, 100%); }

/* El modal de "Cerrar sesión" (login.js/main.js lo marcan con la clase
   .modal--logout al abrirlo, vía UI.confirm) es idéntico al de la tienda
   en TODAS partes donde aparece — no solo el botón que lo dispara, que ya
   quedó unificado antes. Cancela el mismo suavizado "cyber" que
   body.in-app le da a .modal__card/.modal__close/.btn en general (usado
   por el resto de confirmaciones del panel, que SÍ deben seguir con su
   estilo propio) y repite el look "cómic" — borde de 3px, sombra dura,
   esquinas rectas, botones en mayúsculas — con los mismos --surface/--ink
   que usa la tienda en cada modo claro/oscuro. */
body.in-app .modal--logout .modal__card {
  --surface: var(--paper-2);
  border: 3px solid var(--ink); border-radius: 0; box-shadow: 10px 10px 0 var(--ink);
  color: var(--ink);
}
:root[data-theme="dark"] body.in-app .modal--logout .modal__card {
  --surface: #1b1b24; --ink: #f2efe6;
}
body.in-app .modal--logout .modal__close {
  background: var(--panini); color: var(--ink-fixed); border: 2px solid var(--ink-fixed);
  border-radius: 0; box-shadow: none;
}
body.in-app .modal--logout .btn { border-radius: 0; border-color: var(--ink); text-transform: uppercase; font-size: .92rem; }
body.in-app .modal--logout .btn--ghost { background: transparent; box-shadow: none; color: var(--ink); }
body.in-app .modal--logout .btn--ghost:hover { background: var(--panini); color: var(--ink-fixed); }

/* Animación de ENTRADA — inyectada por UI.openModal() como .is-entering */
@keyframes modalScale {
  from { opacity: 0; transform: scale(0.95); }
  to   { opacity: 1; transform: scale(1); }
}
@keyframes modalScaleOut {
  from { opacity: 1; transform: scale(1); }
  to   { opacity: 0; transform: scale(0.96); }
}
@keyframes modalFade { from { opacity: 0; } to { opacity: 1; } }
.modal.is-entering .modal__card { animation: modalScale .22s var(--ease-out); }
.modal.is-entering .modal__backdrop { animation: modalFade .22s ease; }
.modal.is-leaving { pointer-events: none; }
.modal.is-leaving .modal__card { animation: modalScaleOut .16s ease-in forwards; }
.modal.is-leaving .modal__backdrop { animation: modalFade .16s ease reverse forwards; }
@media (prefers-reduced-motion: reduce) {
  .modal.is-entering .modal__card, .modal.is-entering .modal__backdrop,
  .modal.is-leaving .modal__card, .modal.is-leaving .modal__backdrop { animation: none; }
}
.modal__title { font-family: var(--display); text-transform: uppercase; font-size: 1.3rem; margin-bottom: 1rem; }
.modal__close { position: absolute; top: .8rem; right: .8rem; width: 34px; height: 34px; display: grid; place-items: center; background: var(--panini); color: var(--ink-fixed); border: 2px solid var(--ink-fixed); }
body.in-app .modal__close { background: var(--surface-2); color: var(--text); border: 0; border-radius: 10px; box-shadow: var(--nm-out-sm); }

/* ---------- API banner ---------- */
.api-banner {
  position: sticky; top: var(--topbar-h); z-index: var(--z-banner);
  display: flex; align-items: center; justify-content: center; gap: 1rem; flex-wrap: wrap;
  padding: .55rem 1rem; font-size: .82rem; font-weight: 600;
  background: var(--panini); color: var(--ink-fixed); border-bottom: 2px solid var(--ink-fixed);
}
.api-banner button { font-weight: 800; text-decoration: underline; color: inherit; }

/* ---------- Estados ---------- */
.state { padding: 3rem 1rem; text-align: center; color: var(--muted); }
.state__icon { font-size: 2.4rem; margin-bottom: .6rem; }
/* Glifo vectorial (reemplaza los emojis en estados vacío / carga / error) */
svg.state__icon { display: block; margin: 0 auto .7rem; color: var(--accent, #8b5bff); opacity: .9; }
.skeleton { background: linear-gradient(90deg, var(--surface-2), var(--surface-3), var(--surface-2)); background-size: 200% 100%; animation: sk 1.3s linear infinite; }
@keyframes sk { to { background-position: -200% 0; } }

/* ---------- Tilt (funcional; gate solo por hover) ---------- */
.tilt { transform-style: preserve-3d; transition: transform .25s var(--ease-out), box-shadow .25s var(--ease-out); will-change: transform; }
@media (hover: none) { .tilt { transform: none !important; } }

/* =============================================================
   Micro-botones animados (estilo Uiverse, adaptados a GeekPoint)
   ============================================================= */

/* ---- "Eliminar": círculo que se abre en píldora con bote de basura ---- */
/* Botón eliminar — SOLO icono: círculo con la tapa del bote que se abre en hover.
   Sin expansión de ancho ni texto "ELIMINAR" (desacomodaba las tablas). */
.del-slot {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; vertical-align: middle;
}
.del-btn {
  flex: none;
  width: 34px; height: 34px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px;
  position: relative; overflow: visible;
  border: 2px solid var(--ink); border-radius: 50%;
  background: var(--ink);
  box-shadow: var(--shadow-hard-sm);
  cursor: pointer;
  transition: background .2s var(--ease-out), border-color .2s var(--ease-out),
              box-shadow .18s var(--ease-out), transform .12s var(--ease-bounce);
}
body.in-app .del-btn { border-color: transparent; box-shadow: var(--nm-out-sm); }

.del-btn .del-svg { width: 14px; transition: transform .28s var(--ease-bounce); }
.del-btn .del-svg path { fill: #fff; }
.del-btn .del-top { transform-origin: 84% 100%; }   /* bisagra a la derecha */

.del-btn:hover, .del-btn:focus-visible {
  background: var(--danger); border-color: var(--danger);
  outline: none; transform: translateY(-1px);
}
.del-btn:focus-visible { box-shadow: 0 0 0 3px rgba(228, 0, 43, .4), var(--shadow-hard-sm); }
body.in-app .del-btn:focus-visible { box-shadow: 0 0 0 3px rgba(228, 0, 43, .4), var(--nm-out-sm); }
/* la TAPA se abre limpio */
.del-btn:hover .del-top, .del-btn:focus-visible .del-top { transform: translateY(-2px) rotate(-34deg); }
.del-btn:hover .del-bottom, .del-btn:focus-visible .del-bottom { transform: translateY(1px); }
.del-btn:active { transform: scale(.9); }

@media (prefers-reduced-motion: reduce) {
  .del-btn, .del-btn .del-svg { transition-duration: .001s; }
}

/* ---- Impresora que "imprime" al pasar el cursor ---- */
/* Rediseño alto contraste: base amarillo GeekPoint, hover cyan con glow. */
.printbtn.btn {
  align-items: center;
  background: var(--panini); color: var(--ink-fixed);
  border: 2px solid var(--ink-fixed);
  box-shadow: 3px 3px 0 var(--ink-fixed);
  transition: transform .14s var(--ease-out), box-shadow .18s var(--ease-out), background .18s var(--ease-out);
}
.printbtn.btn:hover {
  background: var(--neon-cyan); color: var(--ink-fixed);
  transform: translate(-2px, -2px);
  box-shadow: 6px 6px 0 var(--ink-fixed), 0 0 18px rgba(0, 229, 255, .55);
}
.printbtn.btn:active { transform: translate(1px, 1px); box-shadow: none; }
body.in-app .printbtn.btn {
  border-color: transparent; border-radius: var(--radius-sm);
  box-shadow: var(--nm-out-sm), 0 0 0 1px var(--panini);
}
body.in-app .printbtn.btn:hover {
  background: var(--neon-cyan);
  box-shadow: var(--nm-out), 0 0 16px rgba(0, 229, 255, .5);
}

.printbtn .printer {
  --pr-border: var(--ink);
  --pr-bg: var(--paper-2);
  --pr-state: paused;
  flex: none; position: relative; width: 30px; height: 17px;
}
body.in-app .printbtn .printer { --pr-bg: var(--surface); }
.printbtn:hover .printer, .printbtn:focus-visible .printer { --pr-state: running; }

.printbtn .printer::before, .printbtn .printer::after {
  content: ""; position: absolute;
  box-shadow: inset 0 0 0 2px var(--pr-border);
  background: var(--pr-bg);
}
.printbtn .printer::before { left: 0; right: 0; bottom: 0; height: 13px; border-radius: 3px; z-index: 2; }
.printbtn .printer::after  { width: 24px; height: 6px; top: 0; left: 3px; border-radius: 3px 3px 0 0; }

.printbtn .printer__dot {
  position: absolute; left: 4px; bottom: 4px; width: 22px; height: 2px;
  border-radius: 1px; background: var(--pr-border); z-index: 4;
}
.printbtn .printer__dot::before, .printbtn .printer__dot::after {
  content: ""; position: absolute; background: var(--pr-border);
  border-radius: 1px; height: 2px; top: -5px;
}
.printbtn .printer__dot::before { width: 2px; right: 0; }
.printbtn .printer__dot::after  { width: 4px; right: 3px; }

.printbtn .printer__paper {
  position: absolute; z-index: 1; left: 6px; bottom: 7px;
  width: 17px; height: 14px; border-radius: 2px 2px 0 0;
  box-shadow: inset 0 0 0 2px var(--pr-border); background: var(--pr-bg);
  display: flex; justify-content: center;
  transform: perspective(40px) rotateX(4deg);
  animation: printerFeed 1.2s ease infinite;
  animation-play-state: var(--pr-state);
}
.printbtn .printer__svg { display: block; width: 8px; height: 8px; margin-top: 3px; }
.printbtn .printer__svg path { fill: var(--neon-cyan); }
.printbtn .printer__svg path + path { opacity: .55; }

.printbtn .printer__out {
  position: absolute; z-index: 3; left: 0; top: 11px; width: 30px; height: 15px;
  overflow: hidden; pointer-events: none;
}
.printbtn .printer__paper-out {
  position: absolute; z-index: 1; left: 6px; bottom: 0;
  width: 17px; height: 14px; border-radius: 0 0 2px 2px;
  box-shadow: inset 0 0 0 2px var(--pr-border); background: var(--pr-bg);
  transform: perspective(40px) rotateX(40deg) translateY(-8px) translateZ(4px);
  animation: printerEject 1.2s ease infinite;
  animation-play-state: var(--pr-state);
}
.printbtn .printer__paper-out::before {
  content: ""; position: absolute; left: 3px; top: 4px; right: 3px; height: 2px;
  border-radius: 1px; opacity: .5; background: var(--pr-border);
  box-shadow: 0 3px 0 var(--pr-border);
}

@keyframes printerFeed { 50% { transform: perspective(40px) rotateX(4deg) translateY(7px); } }
@keyframes printerEject { 50% { transform: perspective(40px) rotateX(28deg) translateY(-3px) translateZ(4px); } }

@media (prefers-reduced-motion: reduce) {
  .del-btn, .del-btn .del-svg, .del-btn::before { transition-duration: .001s; }
  .printbtn .printer__paper, .printbtn .printer__paper-out { animation: none; }
}

/* ---- Salida animada de una línea del carrito (slide-out-left) ---- */
.cart-item-leaving {
  animation: slideOutLeft .2s ease forwards;
  pointer-events: none;
}
@keyframes slideOutLeft {
  to { transform: translateX(-110%); opacity: 0; }
}

/* ---- Micro-animaciones "wow" (entrada carrito, pulso del contador) ---- */
@keyframes cartRowIn {
  from { opacity: 0; transform: translateX(18px); }
  to   { opacity: 1; transform: none; }
}
@keyframes countPop {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.45); }
  100% { transform: scale(1); }
}
.cartbtn__count.is-bump { animation: countPop .38s var(--ease-bounce); }

@media (prefers-reduced-motion: reduce) {
  .cart-item-leaving { animation-duration: .001s; }
  .cartbtn__count.is-bump { animation: none; }
}

/* =============================================================
   Toggle de Modo Oscuro (botón SVG sol/luna) + Circular Reveal
   ============================================================= */

/* ---- Animación circular estilo Hostinger ----
   El wipe corre 100% en CSS sobre la instantánea NUEVA (clip-path que
   se expande desde el punto del clic). La instantánea vieja queda
   estática debajo → no hay fotograma "congelado" ni parpadeo.
   theme.js añade la clase .theme-toggle-transition al <html> y define
   --h-theme-toggle-x/y (y --r) justo antes de startViewTransition. */
:root.theme-toggle-transition::view-transition-old(root) {
  mix-blend-mode: normal;
  animation: none;
  z-index: 1;
}
:root.theme-toggle-transition::view-transition-new(root) {
  mix-blend-mode: normal;
  z-index: 9999;
  animation: 0.55s cubic-bezier(0.4, 0, 0.2, 1) h-theme-toggle-reveal;
}
@keyframes h-theme-toggle-reveal {
  0%   { clip-path: circle(0 at var(--h-theme-toggle-x, 50%) var(--h-theme-toggle-y, 50%)); }
  100% { clip-path: circle(var(--h-theme-toggle-r, 150vmax) at var(--h-theme-toggle-x, 50%) var(--h-theme-toggle-y, 50%)); }
}
@media (prefers-reduced-motion: reduce) {
  :root.theme-toggle-transition::view-transition-new(root),
  :root.theme-toggle-transition::view-transition-old(root) { animation: none !important; }
}

/* ---- Botón toggle SVG (sol/luna) ----
   Estado del checkbox:  SIN marcar = modo CLARO → SOL
                          MARCADO   = modo OSCURO → LUNA   */
.themeToggle {
  color: #bbb;
  width: 3em;
  display: inline-block;
}

.st-sunMoonThemeToggleBtn {
  position: relative;
  cursor: pointer;
}

.st-sunMoonThemeToggleBtn .themeToggleInput {
  opacity: 0;
  width: 100%;
  aspect-ratio: 1;
  position: absolute;
  z-index: 1;
}

.st-sunMoonThemeToggleBtn svg {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  transition: transform 0.4s ease;
  transform: rotate(90deg);              /* SOL por defecto (modo claro) */
}

.st-sunMoonThemeToggleBtn svg .sunMoon {
  transform-origin: center center;
  transition: inherit;
  transform: scale(0.55);                /* disco pequeño = cuerpo del sol */
}

.st-sunMoonThemeToggleBtn svg .sunRay {
  transform-origin: center center;
  transition: transform 0.4s ease;
  transform: scale(1);                   /* rayos visibles = sol */
}

.st-sunMoonThemeToggleBtn svg mask > circle {
  transition: transform 0.64s cubic-bezier(0.41, 0.64, 0.32, 1.575);
  transform: translate(16px, -3px);      /* máscara fuera → disco completo */
}

.st-sunMoonThemeToggleBtn svg .sunRay2 { transition-delay: 0.05s; }
.st-sunMoonThemeToggleBtn svg .sunRay3 { transition-delay: 0.1s; }
.st-sunMoonThemeToggleBtn svg .sunRay4 { transition-delay: 0.17s; }
.st-sunMoonThemeToggleBtn svg .sunRay5 { transition-delay: 0.25s; }
.st-sunMoonThemeToggleBtn svg .sunRay6 { transition-delay: 0.29s; }

/* MARCADO = modo OSCURO → LUNA */
.st-sunMoonThemeToggleBtn .themeToggleInput:checked + svg {
  transform: rotate(40deg);
}
.st-sunMoonThemeToggleBtn .themeToggleInput:checked + svg mask > circle {
  transform: translate(0px, 0px);        /* la máscara muerde el disco → media luna */
}
.st-sunMoonThemeToggleBtn .themeToggleInput:checked + svg .sunMoon {
  transform: scale(1);
}
.st-sunMoonThemeToggleBtn .themeToggleInput:checked + svg .sunRay {
  transform: scale(0);                   /* rayos ocultos = luna */
}

/* ---- Ajustes de integración con el header GeekPoint ---- */
.themeToggle {
  aspect-ratio: 1;          /* el input/svg son absolute → el label necesita alto */
  flex: none;
  color: var(--muted);      /* #bbb quedaba muy bajo de contraste sobre el papel */
  transition: color .15s var(--ease-out), transform .16s var(--ease-bounce);
}
.themeToggle:hover { color: var(--text); transform: translateY(-2px); }
.themeToggle:active { transform: translateY(0) scale(.96); }
.st-sunMoonThemeToggleBtn .themeToggleInput:focus-visible + svg {
  outline: 3px solid var(--neon-cyan);
  outline-offset: 2px;
  border-radius: 4px;
}
@media (prefers-reduced-motion: reduce) {
  .st-sunMoonThemeToggleBtn svg,
  .st-sunMoonThemeToggleBtn svg * { transition: none !important; animation: none !important; }
}
@media (max-width: 768px) { .themeToggle { width: 2.25em; } }

/* El toggle ahora también vive en Login/Admin/Manager/POS (antes solo
   existía para la tienda pública): misma preferencia (localStorage
   gp_theme) para todo el sitio — ver el bloque de tokens
   ":root[data-theme=light] body.in-app" en tokens.css. */
body.in-app .themeToggle { color: var(--faint); }
body.in-app .themeToggle:hover { color: var(--text); }

/* =============================================================
   PWA — "Instalar aplicación" (lógica en js/pwa.js)
   Todo nace oculto ([hidden]) y solo aparece cuando el navegador
   permite instalar de verdad; nunca dentro de la app ya instalada.
   ============================================================= */

/* Botón compacto del topbar: mismo lenguaje que .cartbtn (borde de
   tinta + sombra dura). Dentro de login/POS/admin hereda los tokens
   claros del topbar (ver "body.in-app .topbar" arriba). */
.pwa-btn {
  flex: none; display: inline-grid; place-items: center;
  width: 2.35rem; height: 2.35rem;
  color: var(--ink); background: var(--paper-2);
  border: 2px solid var(--ink); box-shadow: var(--shadow-hard-sm);
  transition: transform .14s var(--ease-out), box-shadow .18s var(--ease-out),
              background .15s var(--ease-out), color .15s var(--ease-out);
}
.pwa-btn svg { width: 1.15rem; height: 1.15rem; }
.pwa-btn:hover { transform: translate(-1px,-1px); box-shadow: 5px 5px 0 var(--ink); background: var(--panini); color: var(--ink-fixed); }
.pwa-btn:active { transform: translate(2px,2px); box-shadow: none; }
.pwa-btn:focus-visible { outline: 3px solid var(--neon-cyan); outline-offset: 2px; }
@media (max-width: 768px) {
  .pwa-btn { width: 2.1rem; height: 2.1rem; box-shadow: 2px 2px 0 var(--ink); }
  .pwa-btn svg { width: 1rem; height: 1rem; }
}

/* Aviso discreto (abajo a la izquierda; los toasts viven a la derecha).
   Como mucho una vez por semana; "Ahora no" lo silencia 30 días. */
.pwa-hint {
  position: fixed; z-index: 300;
  left: max(1rem, env(safe-area-inset-left, 0px));
  bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
  width: min(380px, calc(100vw - 2rem));
  display: grid; grid-template-columns: auto 1fr; gap: .55rem .8rem; align-items: center;
  padding: .85rem .95rem;
  background: var(--surface); color: var(--text);
  border: 2px solid var(--ink); box-shadow: var(--shadow-hard);
  opacity: 0; transform: translateY(14px);
  transition: opacity .26s var(--ease-out), transform .26s var(--ease-out);
}
.pwa-hint.is-in { opacity: 1; transform: none; }
.pwa-hint__glyph { font-size: 1.35rem; }
.pwa-hint__text { display: grid; gap: .15rem; min-width: 0; }
.pwa-hint__text b {
  font-family: var(--display); font-weight: 400; text-transform: uppercase;
  letter-spacing: .03em; font-size: 1.02rem; line-height: 1.1;
}
.pwa-hint__text span { font-size: .82rem; line-height: 1.4; color: var(--muted); }
.pwa-hint__actions { grid-column: 1 / -1; display: flex; gap: .5rem; justify-content: flex-end; }
body.in-app .pwa-hint { border: 0; border-left: 3px solid var(--accent); border-radius: 12px; box-shadow: var(--nm-out); }
@media (prefers-reduced-motion: reduce) {
  .pwa-hint { transition: none; transform: none; }
}

/* Instrucciones iOS (Compartir → Añadir a pantalla de inicio) / Safari macOS. */
.pwa-steps__list { list-style: none; padding: 0; margin: 0 0 1rem; display: grid; gap: .85rem; }
.pwa-steps__list li {
  display: grid; grid-template-columns: 2.4rem 1fr; gap: .8rem; align-items: center;
  font-size: .92rem; line-height: 1.45;
}
.pwa-steps__ico {
  width: 2.4rem; height: 2.4rem; display: grid; place-items: center;
  background: var(--panini); color: var(--ink-fixed); border: 2px solid var(--ink-fixed);
}
body.in-app .pwa-steps__ico { background: var(--surface-2); color: var(--accent); border: 0; border-radius: 10px; }
.pwa-steps__note { font-size: .8rem; line-height: 1.45; color: var(--muted); margin: 0 0 .5rem; }
.pwa-steps .btn--block { margin-top: .9rem; }

/* App instalada: con viewport-fit=cover el contenido llega bajo el
   indicador de inicio del iPhone / la barra de gestos de Android.
   env() vale 0 donde no hay muesca, así que fuera de eso no cambia nada. */
[data-display-mode="standalone"] .toasts { bottom: calc(1rem + env(safe-area-inset-bottom, 0px)); }
[data-display-mode="standalone"] .cart-drawer__foot { padding-bottom: calc(1.1rem + env(safe-area-inset-bottom, 0px)); }

@media print { .pwa-hint { display: none !important; } }
