/* =============================================================
   7. App — login, paneles, POS
   ============================================================= */

/* Cuando estamos dentro de la app, la topbar pública se oculta y
   el layout ocupa toda la altura. */
body.in-app .topbar__nav,
body.in-app .topbar__actions .cartbtn,
body.in-app .topbar__actions [data-nav-store],
body.in-app [data-static-store] { display: none !important; }

/* ---------- Login ---------- */
.auth {
  /* Tarjeta VERTICAL (alto > ancho) de ANCHO fijo pero alto AUTOMÁTICO —
     antes el alto era también fijo (igual en Login y Registro, para que
     cambiar de uno a otro no saltara de tamaño), pero con Login (2 campos)
     esa altura dejaba un hueco vacío debajo de los chips de demo bien
     notorio — y ese hueco solo va a crecer el día que esos chips de
     demostración se quiten. Con alto automático la tarjeta siempre mide
     justo lo que su contenido necesita, en cualquier modo: sin espacio
     muerto y sin necesidad de tocar esto de nuevo si el contenido cambia.
     El pequeño salto de tamaño al cambiar Login ⇄ Registro no se nota:
     ocurre con la tarjeta ya encogida a un punto (.is-squashed, ver
     abajo), invisible de lo chica que queda. */
  --auth-w: min(460px, 88vw);
  /* Cierre/apertura del modal (Login ⇄ Registro), acomodado en
     mascot-debug.html: cierra en 360ms con ease-in-out fuerte (arranca y
     frena suave, como un jalón), abre en 300ms con ease-out fuerte (sale
     rápido y aterriza suave). Los triángulos crecen de 32px a --tri-end
     mientras se cierra, y la tarjeta termina del ancho de ese cuadro
     (escondida debajo), no en un punto. */
  --pinch-in: 360ms;
  --pinch-out: 300ms;
  --pinch-ease-in: cubic-bezier(0.77, 0, 0.175, 1);
  --pinch-ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --tri-end: 110px;
  position: relative;
  min-height: calc(100svh - var(--topbar-h));
  display: grid; place-items: center; padding: 2rem var(--gutter);
  /* El personaje (ver .auth__mascot) es mucho más grande que la tarjeta a
     propósito, para lograr el agarre real de las esquinas, y se sale del
     viewport en pantallas normales — eso está bien, PUEDE recortarse.
     Lo que NO puede pasar es que ese desbordamiento estire el documento y
     genere scroll: .auth ya mide exactamente el alto disponible (min-height
     de arriba, sin contenido en flujo que lo haga crecer, el personaje es
     position:absolute y no cuenta para ese alto), así que recortar aquí
     (no en .auth__composition, que es chica y taparía al personaje entero)
     mantiene el viewport fijo sin ocultar el brazo derecho: su punto de
     agarre cae muy adentro de esta caja, muy lejos del borde de recorte. */
  overflow: hidden;
}
/* Tarjeta + personaje EN FILA: tarjeta primero (izquierda), personaje
   después (derecha) — el orden en el DOM ya es ese (ver login.js), así
   que una fila normal sin reordenar basta. .auth__mascot se saca del
   flujo (position:absolute) para poder anclarla con precisión sobre las
   esquinas — ver esa regla más abajo. */
.auth__composition {
  position: relative;
  display: flex; align-items: flex-end; justify-content: center;
  flex-wrap: wrap;
}
.auth__card {
  position: relative; z-index: 1;
  width: var(--auth-w); padding: 1.5rem 1.7rem;
  background: var(--surface); border-radius: var(--radius-lg);
  box-shadow: var(--nm-out), var(--glow-violet);
  transform-origin: 100% 100%; will-change: transform, opacity;   /* se cierra hacia la esquina inferior-derecha, ver pellizco abajo */
}
.auth__card h1 { font-size: 1.5rem; margin-bottom: .3rem; }
/* Botón "paso anterior" (paso 2 de Registro): reutiliza .btn/.btn--ghost
   (fondo transparente, YA existe en components.css) + .btn--sm, anclado
   ARRIBA A LA DERECHA junto a "← Volver a la tienda" (arriba a la
   izquierda) con position:absolute — así no agrega una línea al
   formulario ni agranda la tarjeta. Ver login.js stepBackButtonHTML(). */
.auth__stepback {
  position: absolute; top: 1.3rem; right: 1.3rem; z-index: 2;
  margin: 0; border-radius: 999px;
}
.auth__sub { color: var(--muted); font-size: .86rem; margin-bottom: 1rem; line-height: 1.4; }
.auth__switch { font-size: .82rem; color: var(--muted); text-align: center; margin-top: .6rem; }
.auth__switch a { color: var(--accent-2-text); font-weight: 700; margin-left: .25rem; }
.auth__card .field { margin-bottom: .55rem; gap: .22rem; }
.auth__card .field > label { font-size: .74rem; }
.auth__card .input { padding: .55rem .75rem; font-size: .9rem; }
.auth__card .btn--lg { padding: .7rem 1.4rem; font-size: .92rem; }

/* ---------- Transición Login ⇄ Registro: pellizco diagonal a la esquina inferior-derecha ----------
   transform-origin: 100% 100% (declarado arriba en .auth__card) + `scale()`
   UNIFORME (misma proporción en X y en Y, NO scaleY solo) es justo lo que
   hace que la tarjeta se cierre en línea recta hacia su esquina
   inferior-DERECHA: esa esquina se queda QUIETA (es el punto fijo del
   scale) y la superior-izquierda viaja en diagonal ↘ hasta alcanzarla
   (las otras dos igual, en línea recta hacia ese mismo punto) — es la
   pose que va a hacer el personaje: su mano derecha sostiene la esquina
   inferior-derecha y la izquierda arrastra la superior-izquierda.
     1. .is-closing  → scale 1 → --pinch-end: la esquina superior-izquierda
        viaja hasta la inferior-derecha y la tarjeta termina del ancho del
        cuadro que forman los dos triángulos ya crecidos (--tri-end),
        escondida debajo de él. --pinch-end = --tri-end / ancho de la
        tarjeta; lo calcula switchTo() en login.js (CSS no puede dividir
        longitudes).
     2. .is-squashed → se queda así ~0.5s (SIN animación: clase estática)
        mientras switchTo() repinta el otro formulario por debajo
     3. .is-opening  → --pinch-end → 1 (se expande otra vez desde la
        esquina inferior-derecha, revelando el contenido ya repintado)
   Mientras tanto la mano izquierda del personaje lleva su esquina y la
   derecha sostiene la otra sin moverse (ver syncHandRotation() en
   login.js). Ver switchTo() en login.js, que encadena estas 3 clases con
   setTimeout para la pausa. */
.auth__card.is-closing { animation: authCardPinch var(--pinch-in) var(--pinch-ease-in) forwards; }
.auth__card.is-squashed { transform: scale(var(--pinch-end, .24)); }
.auth__card.is-opening { animation: authCardUnpinch var(--pinch-out) var(--pinch-ease-out) forwards; }
@keyframes authCardPinch {
  from { transform: scale(1); }
  to   { transform: scale(var(--pinch-end, .24)); }
}
@keyframes authCardUnpinch {
  from { transform: scale(var(--pinch-end, .24)); }
  to   { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .auth__card.is-closing, .auth__card.is-squashed, .auth__card.is-opening { animation: none; transform: none; }
}

/* ---------- Stage: envuelve la tarjeta 1:1 ----------
   inline-block → siempre mide EXACTAMENTE el tamaño real renderizado de
   .auth__card (fijo vía --auth-h desde 640px, automático/por-contenido
   debajo de eso). Los triángulos usan esto para posicionarse sin
   necesitar --auth-w/--auth-h ni ningún cálculo propio (ver abajo). */
.auth__stage { position: relative; display: inline-block; }

/* ---------- Triángulos de esquina ----------
   EXACTAMENTE DOS (arriba-izquierda y abajo-derecha) — permanentes: nunca
   display:none ni ocultos por media query, visibles en cualquier
   resolución. Cada uno es una caja que cubre TODO .auth__stage
   (inset: 0 → mismo tamaño que la tarjeta en cada momento, fijo o
   automático), y dentro de ella el triángulo real vive en un ::before de
   32x32 FIJO (ver más abajo) — así nunca cambia de tamaño/forma sea cual
   sea el tamaño de pantalla o del modal. Para el pellizco, se trasladan
   con transform: translate(): un porcentaje ahí es relativo al tamaño de
   la PROPIA caja (= tamaño real de .auth__stage en ese instante), así que
   sin importar si la tarjeta mide 500px fijos o una altura automática en
   móvil, el destino siempre es exacto — sin calc() sobre --auth-w/--auth-h.
   Reaccionan solo por CSS (:has()) a las mismas clases is-closing/
   is-squashed/is-opening que ya pone switchTo() en login.js — esa lógica
   no se tocó, igual que su duración/curva.

   Igual que la tarjeta (ver pellizco arriba), el punto de cierre es la
   esquina INFERIOR-DERECHA: el triángulo --br se queda QUIETO (--tx/--ty
   en 0) y solo el --tl viaja en diagonal ↘ hasta quedar EXACTAMENTE
   superpuesto a él — por eso su destino es 100% menos --tri-end (el
   tamaño que alcanzan los triángulos al cerrar), no el 100% entero, que lo sacaría por
   fuera de la esquina. Como --tl y --br ya usan la MISMA
   diagonal (ver los clip-path del ::before: ambos cortan de la esquina
   superior-derecha a la inferior-izquierda de su propia caja, sin rotar
   nada), al superponerse sus dos mitades encajan perfecto y forman un
   cuadrado sólido pegado por esa diagonal — como pediste, "como si fueran
   un cubo": nada de puntas sueltas ni huecos. */
.auth__corner {
  --tx: 0%; --ty: 0%;
  position: absolute; inset: 0;
  pointer-events: none; z-index: 2;
  transform: translate(0, 0);
}
/* El triángulo visible vive en un ::before de 32x32 FIJO (no en la caja
   gigante de arriba) — así el borde nunca dibuja "patas" largas hasta el
   borde del modal que luego viajen sueltas hacia el centro durante el
   pellizco (eso era lo que producía el efecto "aspa/pinwheel" al
   comprimirse). Al ser un elemento pequeño y autocontenido, el borde
   queda siempre pegado a sus propios 32px, sin importar dónde esté. */
.auth__corner::before {
  content: "";
  position: absolute; width: 32px; height: 32px;
  background: var(--panini); border: 2px solid var(--ink);
}
.auth__corner--tl {
  /* Destino: justo encima del triángulo inferior-derecho YA crecido
     (--tri-end), no del de 32px — ver el crecimiento más abajo. */
  --tx: calc(100% - var(--tri-end)); --ty: calc(100% - var(--tri-end));
}
.auth__corner--tl::before {
  top: 0; left: 0;
  clip-path: polygon(0 0, 100% 0, 0 100%);
}
.auth__corner--br {
  --tx: 0%; --ty: 0%;                             /* punto de cierre: no se mueve */
}
.auth__corner--br::before {
  bottom: 0; right: 0;
  clip-path: polygon(100% 100%, 0 100%, 100% 0);
}
.auth:has(.auth__card.is-closing) .auth__corner { animation: authCornerIn var(--pinch-in) var(--pinch-ease-in) forwards; }
.auth:has(.auth__card.is-squashed) .auth__corner { transform: translate(var(--tx), var(--ty)); }
.auth:has(.auth__card.is-opening) .auth__corner { animation: authCornerOut var(--pinch-out) var(--pinch-ease-out) forwards; }
/* Los dos triángulos crecen de 32px a --tri-end mientras se cierra (mismo
   tiempo y curva que la tarjeta y el traslado), y al quedar encimados
   forman un cuadro amarillo que tapa la tarjeta ya encogida. width/height
   en un ::before chiquito: no hay forma con transform sin que también
   engorde el borde. */
.auth:has(.auth__card.is-closing) .auth__corner::before { animation: authTriGrow var(--pinch-in) var(--pinch-ease-in) forwards; }
.auth:has(.auth__card.is-squashed) .auth__corner::before { width: var(--tri-end); height: var(--tri-end); }
.auth:has(.auth__card.is-opening) .auth__corner::before { animation: authTriShrink var(--pinch-out) var(--pinch-ease-out) forwards; }
@keyframes authTriGrow {
  from { width: 32px; height: 32px; }
  to   { width: var(--tri-end); height: var(--tri-end); }
}
@keyframes authTriShrink {
  from { width: var(--tri-end); height: var(--tri-end); }
  to   { width: 32px; height: 32px; }
}
@keyframes authCornerIn {
  from { transform: translate(0, 0); }
  to   { transform: translate(var(--tx), var(--ty)); }
}
@keyframes authCornerOut {
  from { transform: translate(var(--tx), var(--ty)); }
  to   { transform: translate(0, 0); }
}

/* ---------- Personaje animado ----------
   Chica-gato armada por partes (cadera -> torso -> cabeza/brazos), MISMA
   pose/proporciones que el HTML de referencia (personaje-animado.html):
   nunca se deforma, nunca se gira como bloque, nunca se estira un brazo
   con scale(). HERMANA de .auth__stage dentro de .auth__composition (no
   hija de .auth__card).

   AGARRE REAL POR CAPAS — el cuerpo (cadera/torso/cabeza/brazo izquierdo,
   todavía anidados exactamente igual que siempre) queda DETRÁS de la
   tarjeta; el brazo derecho es la ÚNICA excepción: se sacó del anidado
   (ver MASCOT_HTML en login.js) para poder pintarse POR ENCIMA de la
   tarjeta y cruzar visualmente sobre ella hasta la esquina inferior-
   derecha, tal como se agarra desde el frente. El brazo levantado se
   queda detrás, hacia la esquina superior-izquierda, como si la
   agarrara desde atrás (la propia tarjeta lo tapa en parte — a
   propósito, no es un error).

   Por qué el brazo derecho SÍ puede separarse sin que se note "pieza
   suelta": .auth__mascot-arm-r ahora es hijo directo de .auth__mascot
   (no de .auth__mascot-torso), pero sigue viviendo en el MISMO marco de
   referencia en % que la cadera (mismo padre), así que su posición de
   abajo es la equivalente ya "aplanada" de cadera->torso->brazo (mismas
   matemáticas de porcentaje anidado, resueltas a mano) — visualmente cae
   exactamente en el mismo sitio de siempre, solo cambia de capa.

   z-index en juego (de atrás hacia adelante):
     .auth__mascot-hip (-1, cuerpo completo) < .auth__card (1) <
     .auth__corner (2) < .auth__mascot-arm-r (3) */
.auth__mascot {
  position: absolute; left: -39.2%; top: -35.42%;   /* login: sin las cuentas demo mide lo mismo que Registro (394.8px) → mismo desplazamiento */ pointer-events: none;
  /* Tamaño FIJO (no en vw): la tarjeta también es ancho fijo (460px) por
     encima de 523px de viewport (ver --auth-w), así que un tamaño fijo
     aquí es lo que mantiene el agarre pixel-preciso y la presencia visual
     ESTABLES sin importar el ancho de pantalla — un tamaño en vw se
     encogería/crecería constantemente respecto a una tarjeta que NO se
     mueve, rompiendo el ajuste y "desinflando" al personaje cada vez que
     la ventana se achica. Por eso el único límite es el aviso de abajo:
     una red de seguridad para anchos absurdamente angostos (por debajo
     de los 900px donde igual se oculta), nunca un encogimiento gradual.
     1215px = 1350px - 10% (ligera reducción pedida, manteniendo el agarre;
     ver .auth overflow:hidden arriba: lo que no quepa se recorta, no
     empuja la página). */
  width: min(1215px, 160vw); aspect-ratio: 3000 / 2500;
}
/* Cada modo del formulario (login / paso 1 de registro / paso 2 de
   registro) tiene una cantidad de campos distinta y por lo tanto una
   ALTURA distinta de tarjeta (alto automático, ver .auth__card). Como la
   posición del personaje es en % de ese mismo alto (composition = tamaño
   real de la tarjeta en cada momento), cada modo necesita su propio
   desplazamiento vertical para que la mano derecha siga cayendo justo en
   la esquina inferior-derecha — login.js pone data-auth-mode en
   .auth__composition, sin tocar el pellizco ni su timing. */
.auth__composition[data-auth-mode="register"] .auth__mascot {
  top: -35.42%;   /* paso 1: nombre + correo (tarjeta corta) */
}
.auth__composition[data-auth-mode="register2"] .auth__mascot {
  top: -35.42%;   /* paso 2: contraseña + confirmar (el botón "paso anterior" es position:absolute, no suma alto) */
}
.auth__mascot img {
  display: block; width: 100%; height: auto;
  -webkit-user-drag: none; user-select: none;
}
/* Los % de cada parte son recortes 1:1 de un mismo lienzo de referencia
   (3000x2500) expresados como porcentaje relativo a SU PADRE en esta
   misma jerarquía — no los toques sueltos, están calculados en conjunto
   para que las piezas encajen exactamente por su punto de unión. */
.auth__mascot-hip {
  position: absolute; left: 41.07%; top: 66.40%; width: 51.30%;
  z-index: -1;                                    /* cuerpo: detrás de la tarjeta */
  transform-origin: 50% 19%;                      /* une con el torso */
  animation: mascotHipSway 6s ease-in-out infinite;
}
.auth__mascot-torso {
  position: absolute; left: -4.68%; top: -89.64%; width: 57.57%;
  transform-origin: 50% 85%;                      /* une con la cadera */
  animation: mascotBreathe 4s ease-in-out infinite;
}
.auth__mascot-head {
  position: absolute; left: 12.53%; top: -71.53%; width: 111.96%;
  transform-origin: 50% 89%;                      /* une con el cuello */
  animation: mascotHeadMove 5s ease-in-out infinite;
}
/* Brazo izquierdo: DOS imágenes (brazo2.png = hombro/manga, manos2.png =
   antebrazo y mano) dentro de un marco común, .auth__mascot-arm-l, que
   sigue anidado en el torso (detrás del torso/pelo, z-index:-1 LOCAL
   dentro de la cadera) y es lo ÚNICO que lleva la animación — así ambas
   piezas se balancean juntas, como un solo brazo, alrededor del mismo
   pivote (el hombro). El marco no se ve: solo fija el sistema de
   coordenadas; sus medidas y el aspect-ratio (793/586) son los de
   mascot-debug.html (.mascot-rig-1), donde se acomodaron.
   isolation: la mano (z -1) queda DETRÁS del brazo sin escaparse detrás
   del torso. Valores de brazo/mano = "Guardar como valor actual" del
   debug; ahí están en % de ESTE marco, no del torso. */
.auth__mascot-arm-l {
  position: absolute; left: -6.4%; top: 1.3%; width: 89.5%; z-index: -1;
  aspect-ratio: 793 / 586; isolation: isolate;
  transform-origin: 38.2648% 18.9052%;            /* hombro = origin del brazo2 */
  /* Su balanceo propio (lento a propósito: la mano está a ~450px del
     hombro y cualquier giro se nota mucho ahí) + la rotación CONTRARIA a
     la de la cadera y el torso (mismas duraciones y curva, así se
     cancelan): el brazo no hereda el giro del cuerpo y la mano, que agarra
     la esquina, casi no se mueve — solo la acompaña lo que se mueve el
     hombro. animation-composition: add SUMA las tres en vez de que la
     última pise a las otras. Medido en mascot-debug.html: la mano pasó de
     ~71px de recorrido (55px/s) a ~33px (22px/s). */
  animation: mascotArmL 6.6s ease-in-out infinite,
             mascotHipCounter 6s ease-in-out infinite,
             mascotBreatheCounter 4s ease-in-out infinite;
  animation-composition: replace, add, add;
}
.auth__mascot-upper-l {
  position: absolute; left: -8%; top: -23.4%; width: 88.8%;
  rotate: 43.8deg; transform-origin: 52.1% 55.3%;
}
.auth__mascot-forearm-l {
  position: absolute; left: -101.5%; top: -102.8%; width: 122%; z-index: -1;
  transform-origin: 98% 88%;
}
/* Brazo derecho: posición EQUIVALENTE aplanada de cadera->torso->brazo
   (mismo resultado visual que antes de sacarlo del anidado), pero ahora
   hijo directo de .auth__mascot con su propio z-index por encima de la
   tarjeta — ver la nota de capas más arriba. */
.auth__mascot-arm-r {
  position: absolute; left: 43.87%; top: 41.95%; width: 35.42%;
  z-index: 3;                                     /* por encima de la tarjeta: agarre visible */
  transform-origin: 69% 47%;
  animation: mascotArmR 3.8s ease-in-out infinite;
}
/* Dedos de la mano izquierda (brazo_izquierdo_dedos.png, el recorte
   complementario de arriba): hijo directo de .auth__mascot (como el
   brazo derecho) para poder pintarse POR ENCIMA de la tarjeta — el
   agarre visible de la esquina superior-izquierda, desde el FRENTE,
   mientras el brazo (arriba) se queda detrás.
   Posición: como este elemento cuelga directo de .auth__mascot (no del
   torso), un cálculo puramente geométrico a partir de las coordenadas
   del recorte original no bastó para hacerlo encajar (dejaba un hueco
   visible entre la mano y el brazo) — el left/top de abajo están
   AJUSTADOS A OJO comparando ambos recortes en vivo en el navegador
   hasta que la muñeca de los dedos conecta con la muñeca del brazo sin
   hueco.
   transform-origin: punto de giro de los dedos. syncHandRotation() pone
   su marcador de referencia DENTRO del brazo, en este MISMO punto
   absoluto (lo calcula al montar), así que los dedos se mueven rígidos
   con el brazo nuevo sea cual sea este valor — ya no hay que
   recalcularlo a mano si se mueve el brazo o los dedos.
   SIN "animation" a propósito — a diferencia de todas las demás partes,
   estos dedos NO tienen su propia animación CSS. Los gira JS en vivo
   (ver syncHandRotation() en login.js): el brazo hereda gratis el
   balanceo de la cadera Y del torso por estar anidado dentro de ambos
   (cadera->torso->brazo), pero los dedos son hermanos de la cadera (no
   están anidados, por la capa — ver notas de arriba), así que una
   animación CSS propia —aunque fuera "igual" a la del brazo— solo
   replica el giro PROPIO del brazo, nunca el que además le suman la
   cadera y el torso: por eso se veían despegar en ciertos puntos del
   ciclo, no por un problema de tiempo entre animaciones. syncHandRotation()
   lee en cada frame cuánto están rotados cadera+torso+brazo
   (getComputedStyle) y le aplica la SUMA a los dedos, así siempre giran
   EXACTO lo mismo que el brazo sin importar de dónde venga ese giro. */
.auth__mascot-hand-l {
  position: absolute; left: 10%; top: 13.1%; width: 8.2%;
  z-index: 3;                                     /* por encima de la tarjeta: agarre visible */
  transform-origin: 441.9% 260.9%;
}
/* Ángulos chicos a propósito: las piezas encajan pixel a pixel en su
   punto de unión, un giro grande se ve "despegado". */
@keyframes mascotHipSway { 0%, 100% { transform: rotate(-.6deg); } 50% { transform: rotate(.6deg); } }
@keyframes mascotBreathe {
  0%, 100% { transform: translateY(0)    rotate(-.5deg) scaleY(1); }
  50%      { transform: translateY(-3px) rotate(.5deg)  scaleY(1.012); }
}
@keyframes mascotHeadMove {
  0%, 100% { transform: rotate(.8deg)  translateY(0); }
  30%      { transform: rotate(-1.4deg) translateY(-1px); }
  60%      { transform: rotate(1.6deg)  translateY(.5px); }
}
/* Brazo izquierdo más quieto que el resto: 1.8° en total (antes 4.5°) —
   en la punta, donde la mano agarra la esquina, eso ya son ~14px de ida y
   vuelta; con 4.5° eran ~36px y los dedos se veían resbalar sobre la
   tarjeta. Misma proporción ida/vuelta de antes (55% / 45%). */
@keyframes mascotArmL { 0%, 100% { transform: rotate(-1deg); } 50% { transform: rotate(.8deg); } }
/* Inversos exactos del giro de mascotHipSway y mascotBreathe (solo la
   rotación), para el brazo izquierdo — ver .auth__mascot-arm-l. */
@keyframes mascotHipCounter     { 0%, 100% { transform: rotate(.6deg); } 50% { transform: rotate(-.6deg); } }
@keyframes mascotBreatheCounter { 0%, 100% { transform: rotate(.5deg); } 50% { transform: rotate(-.5deg); } }
@keyframes mascotArmR { 0%, 100% { transform: rotate(1.8deg); } 50% { transform: rotate(-1.5deg); } }
@media (prefers-reduced-motion: reduce) {
  .auth__mascot-hip, .auth__mascot-torso, .auth__mascot-head,
  .auth__mascot-arm-l, .auth__mascot-arm-r, .auth__mascot-hand-l { animation: none; }
}
/* Bajo ~900px ya no hay ancho cómodo para la fila tarjeta+personaje sin
   desbordar o apretar el formulario — se oculta, prioridad al formulario. */
@media (max-width: 900px) {
  .auth__mascot { display: none; }
}

/* ---------- App shell ---------- */
.shell { display: grid; grid-template-columns: 1fr; min-height: calc(100svh - var(--topbar-h)); }
@media (min-width: 900px) { .shell { grid-template-columns: 248px 1fr; } }

.side {
  background: var(--surface); border-right: 1px solid var(--line-soft);
  padding: 1.2rem .9rem; display: flex; flex-direction: column; gap: .3rem;
}
/* Escritorio: la barra lateral queda FIJA bajo la topbar y solo desplaza el
   contenido. Antes, con listas largas o al hacer scroll, "Inicio" y
   "Cerrar sesión" (que van al pie) quedaban fuera de vista. */
@media (min-width: 900px) {
  .side {
    position: sticky;
    top: var(--topbar-h);
    align-self: start;                       /* sin esto el grid la estira y sticky no aplica */
    height: calc(100svh - var(--topbar-h));
    overflow-y: auto;                        /* si el menú no cupiera, scrollea dentro de la barra */
  }
}
.side__user { padding: .9rem; border-radius: var(--radius-sm); background: var(--surface-2); box-shadow: var(--nm-in-sm); margin-bottom: 1rem; }
.side__user b { display: block; font-family: var(--display); }
.side__user span { font-size: .76rem; color: var(--muted); }
.side__link {
  display: flex; align-items: center; gap: .7rem;
  padding: .62rem .8rem; border-radius: 10px; font-size: .9rem; color: var(--muted);
  transition: background .18s var(--ease-out), color .18s var(--ease-out);
}
.side__link:hover { color: var(--text); background: var(--surface-2); }
.side__link.is-active { color: #05060b; background: linear-gradient(180deg, var(--neon-cyan), #16b6cc); font-weight: 600; }
.side__link .ico { width: 18px; text-align: center; }
.side__spacer { flex: 1; }
/* "Cerrar sesión" es una ACCIÓN, no una ruta más del menú — mismo trato
   "cómic" de la tienda (borde recto, relleno amarillo al hover) que ya
   usan el topbar y la fila de acciones del POS, para que se distinga
   claramente de Dashboard/Productos/etc. y de paso quede consistente en
   todo el panel. */
.side__link[data-logout] { border: 2px solid var(--line); margin-top: .4rem; }
.side__link[data-logout]:hover { background: var(--panini); color: var(--ink-fixed); border-color: var(--ink-fixed); }
@media (max-width: 899px) {
  .side { flex-direction: row; overflow-x: auto; gap: .5rem; padding: .7rem; }
  .side__user, .side__spacer { display: none; }
  .side__link { white-space: nowrap; }
}

.content { padding: clamp(1.1rem, 3vw, 2rem); overflow: hidden; }
.content__head { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; margin-bottom: 1.6rem; }
.content__head h1 { font-size: clamp(1.3rem, 3vw, 1.8rem); }
.content__head .spacer { flex: 1; }

/* ---------- KPI cards ---------- */
.kpis { display: grid; gap: .9rem; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); margin-bottom: 1.6rem; }
.kpi { padding: 1.1rem; border-radius: var(--radius); background: var(--surface); box-shadow: var(--nm-out-sm); }
.kpi__label { font-size: .72rem; text-transform: uppercase; letter-spacing: .1em; color: var(--faint); font-family: var(--mono); }
.kpi__value { font-family: var(--display); font-weight: 800; font-size: 1.7rem; margin-top: .3rem; }
.kpi__value.num { font-family: var(--mono); }
.kpi__foot { font-size: .76rem; color: var(--muted); margin-top: .25rem; }
.kpi--accent { border-bottom: 2px solid var(--neon-cyan); }
.kpi--warn { border-bottom: 2px solid var(--warning); }

/* KPI navegable: lleva a su sección del panel (Sucursales, Usuarios, Inventario). */
a.kpi--link { display: block; position: relative; color: inherit; text-decoration: none; cursor: pointer; transition: transform .14s var(--ease-out), box-shadow .14s var(--ease-out); }
a.kpi--link:hover { transform: translateY(-2px); box-shadow: var(--nm-out); }
a.kpi--link:focus-visible { outline: 2px solid var(--neon-violet); outline-offset: 2px; }
.kpi__go { position: absolute; top: .9rem; right: 1rem; font-family: var(--mono); font-size: .9rem; color: var(--faint); opacity: 0; transform: translateX(-4px); transition: opacity .14s var(--ease-out), transform .14s var(--ease-out); }
a.kpi--link:hover .kpi__go { opacity: 1; transform: translateX(0); }

/* ---------- Bar chart (CSS puro) ---------- */
.barchart { display: flex; align-items: flex-end; gap: 6px; height: 140px; padding: .6rem 0; }
.barchart .bar { flex: 1 1 0; min-width: 0; background: linear-gradient(180deg, var(--neon-cyan), var(--neon-violet)); border-radius: 5px 5px 2px 2px; position: relative; opacity: .85; transition: height .5s var(--ease-out); }
.barchart .bar:hover { opacity: 1; filter: brightness(1.12); }
.barchart .bar { cursor: default; }
.barchart .bar span { position: absolute; inset-inline: 0; top: -1.3rem; text-align: center; font-family: var(--mono); font-size: .6rem; color: var(--faint); }

/* Tooltip propio de la gráfica de barras (lo posiciona shell.js -> bindBarTip). */
.barchart-tip {
  position: fixed; z-index: 9999; pointer-events: none;
  display: flex; flex-direction: column; gap: .05rem;
  min-width: 4.5rem;
  background: var(--surface-3); color: var(--text);
  border-radius: 9px; padding: .45rem .6rem;
  box-shadow: var(--nm-out), 0 8px 22px rgba(0, 0, 0, .45);
  font-family: var(--mono); line-height: 1.25;
  opacity: 0; transform: translateY(4px);
  transition: opacity .09s var(--ease-out), transform .09s var(--ease-out);
}
.barchart-tip.is-visible { opacity: 1; transform: translateY(0); }
.barchart-tip b { font-size: .62rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--faint); }
.barchart-tip span { font-size: .98rem; font-weight: 700; color: var(--accent-2-text); }
.barchart-tip em { font-size: .66rem; font-style: normal; color: var(--muted); }

/* ---------- Grid de 2 columnas ---------- */
.grid-2 { display: grid; gap: 1.2rem; grid-template-columns: 1fr; }
@media (min-width: 1000px) { .grid-2 { grid-template-columns: 1.3fr 1fr; } }

/* ---------- POS ---------- */
.pos { display: grid; gap: 1.1rem; grid-template-columns: 1fr; }
@media (min-width: 980px) { .pos { grid-template-columns: 1fr 380px; align-items: start; } }

.pos__search { position: relative; margin-bottom: 1rem; }
.pos__search .input { padding-left: 2.6rem; font-size: 1rem; }
.pos__search::before { content: "🔎"; position: absolute; left: .9rem; top: 50%; transform: translateY(-50%); opacity: .6; }

.pos__cats { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: 1rem; }

.pos__grid { display: grid; gap: .8rem; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); max-height: 66vh; overflow-y: auto; padding: 2px; }
/* Tarjeta de producto del POS — estilo tienda: portada arriba, datos abajo. */
.prod {
  text-align: left; border-radius: var(--radius-sm); overflow: hidden;
  background: var(--surface); box-shadow: var(--nm-out-sm);
  display: flex; flex-direction: column;
  transition: transform .16s var(--ease-out), box-shadow .2s var(--ease-out);
}
.prod:hover { transform: translateY(-2px); box-shadow: var(--nm-out); }
.prod:active { transform: scale(.98); }
.prod__media { position: relative; aspect-ratio: 3 / 4; background: #0b0c10; }
.prod__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.prod__art { position: absolute; inset: 0; display: grid; place-items: center; font-size: 2.4rem; opacity: .5; }
.prod__badge {
  position: absolute; top: .4rem; right: .4rem;
  font-family: var(--mono); font-size: .62rem; font-weight: 700;
  padding: .12rem .4rem; border-radius: 999px;
  background: rgba(11,12,16,.82); color: var(--faint);
}
.prod.is-low .prod__badge { color: var(--warning); }
.prod.is-out .prod__badge { color: var(--danger); background: rgba(11,12,16,.9); }
.prod__body { padding: .55rem .65rem .7rem; display: flex; flex-direction: column; gap: .25rem; flex: 1; }
.prod__name { font-size: .82rem; font-weight: 600; line-height: 1.22; }
.prod__price { font-family: var(--mono); font-size: .9rem; font-weight: 700; color: var(--accent-2-text); margin-top: auto; }
.prod.is-out { opacity: .5; pointer-events: none; }

/* ---------- Cart ---------- */
.cart { position: sticky; top: calc(var(--topbar-h) + 1rem); background: var(--surface); border-radius: var(--radius); box-shadow: var(--nm-out); padding: 1.1rem; display: flex; flex-direction: column; gap: .8rem; }
.cart h2 { font-size: 1rem; }
.cart__items { display: flex; flex-direction: column; gap: .5rem; max-height: 40vh; overflow-y: auto; }
.citem { display: grid; grid-template-columns: 1fr auto; gap: .3rem .6rem; padding: .6rem; border-radius: 10px; background: var(--surface-2); }
.citem__name { font-size: .82rem; font-weight: 600; }
.citem__sub { font-size: .7rem; color: var(--faint); font-family: var(--mono); }
.citem__qty { display: flex; align-items: center; gap: .3rem; }
.qbtn { width: 24px; height: 24px; border-radius: 7px; display: grid; place-items: center; background: var(--surface); box-shadow: var(--nm-out-sm); font-family: var(--mono); }
.citem__line { font-family: var(--mono); font-size: .82rem; align-self: center; }
.citem__rm { color: var(--faint); font-size: .9rem; }
.citem__rm:hover { color: var(--danger); }

.cart__totals { border-top: 1px dashed var(--line); padding-top: .7rem; display: flex; flex-direction: column; gap: .3rem; font-family: var(--mono); font-size: .86rem; }
.cart__totals .row { display: flex; justify-content: space-between; color: var(--muted); }
.cart__totals .row--total { color: var(--text); font-size: 1.15rem; font-weight: 700; margin-top: .2rem; }

.pay-methods { display: grid; grid-template-columns: repeat(3, 1fr); gap: .4rem; }
.pay-methods .chip { justify-content: center; cursor: pointer; }

/* ---------- Ticket ---------- */
.ticket-wrap { display: grid; place-items: center; padding: 2rem var(--gutter); }
.ticket {
  width: min(360px, 100%); background: #f7f7fb; color: #14151d;
  border-radius: 10px; padding: 1.5rem; font-family: var(--mono); font-size: .8rem;
  box-shadow: var(--nm-out);
}
.ticket h2 { font-family: var(--mono); text-align: center; color: #14151d; letter-spacing: .1em; }
.ticket .muted { color: #666; }
.ticket hr { border: 0; border-top: 1px dashed #bbb; margin: .7rem 0; }
.ticket .t-row { display: flex; justify-content: space-between; gap: .5rem; }
.ticket .t-row--total { font-weight: 700; font-size: 1rem; }
.ticket__actions { margin-top: 1.2rem; display: flex; gap: .6rem; justify-content: center; align-items: center; flex-wrap: wrap; }
.ticket-print-opts { display: inline-flex; align-items: center; gap: .4rem; font-size: .74rem; color: var(--muted); }
.ticket-print-opts span { font-family: var(--mono); text-transform: uppercase; letter-spacing: .06em; font-size: .64rem; }
.select--sm { width: auto; padding: .38rem 1.8rem .38rem .6rem; font-size: .78rem; }

/* ---------------------------------------------------------------
   Impresión de tickets — mini-impresora térmica (80 mm por defecto,
   58 mm o A4 opcionales).  El @page real lo inyecta UI.setPrintMode()
   en <style id="gp-print-page">; esto es sólo la red de seguridad.
   --------------------------------------------------------------- */
@page { size: 80mm auto; margin: 0mm; }

@media print {
  html, body {
    width: auto !important; height: auto !important; min-height: 0 !important;
    margin: 0 !important; padding: 0 !important;
    background: #fff !important; overflow: visible !important;
  }

  /* 1. Toda la app se oculta por defecto (nav, sidebars, modales de fondo…). */
  body * { visibility: hidden !important; box-shadow: none !important; }

  /* 2. Solo el ticket (venta POS o apartado) y su contenido quedan visibles. */
  .ticket, .ticket *,
  .rk, .rk * { visibility: visible !important; }

  /* 3. El ticket = 1 tira continua, anclada arriba-izquierda, sin cortes. */
  .ticket, .rk {
    position: absolute !important; left: 0 !important; top: 0 !important;
    box-sizing: border-box !important;
    width: 80mm !important; max-width: 80mm !important;
    margin: 0 !important; padding: 3mm 3.5mm !important;
    background: #fff !important; color: #000 !important;
    border: 0 !important; border-radius: 0 !important;
    font-family: "JetBrains Mono", ui-monospace, "Courier New", monospace !important;
    font-size: 11px !important; line-height: 1.35 !important;
    break-inside: avoid !important; page-break-inside: avoid !important;
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .ticket h2, .rk .rk__folio { font-size: 13px !important; }
  .ticket img, .rk img, .rk__barcode svg { max-width: 100% !important; height: auto !important; }

  /* 3b. Anchos alternativos según el modo elegido en el POS. */
  html[data-printmode="58"] .ticket, html[data-printmode="58"] .rk {
    width: 58mm !important; max-width: 58mm !important; font-size: 10px !important; padding: 2mm 2.5mm !important;
  }
  html[data-printmode="a4"] .ticket, html[data-printmode="a4"] .rk {
    position: relative !important; width: 72mm !important; max-width: 72mm !important; margin: 0 auto !important;
  }

  /* 4. Contenedores que, si conservan su alto/scroll, generan páginas en blanco. */
  body, #main, [data-app], .app-root, .ticket-wrap,
  .modal, .modal__card, .modal__body {
    position: static !important; display: block !important;
    width: auto !important; height: auto !important; max-height: none !important;
    overflow: visible !important; padding: 0 !important; margin: 0 !important;
    transform: none !important; animation: none !important;
  }

  /* 5. Chrome que nunca va al papel. */
  .modal__backdrop, .modal__close, .modal__title,
  .ticket__actions, .printbtn, .ticket-print-opts,
  .topbar, .api-banner, .foot,
  .cart-drawer, .cart-drawer__backdrop, .toasts, .splash { display: none !important; }
}

/* ---------- Toolbar / filtros ---------- */
.toolbar { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; margin-bottom: 1rem; }
.toolbar .input, .toolbar .select { width: auto; min-width: 160px; }

/* ---------- Row actions ---------- */
.rowacts { display: flex; gap: .4rem; }
.iconbtn { width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center; background: var(--surface-2); box-shadow: var(--nm-out-sm); font-size: .85rem; }
.iconbtn:hover { color: var(--accent-2-text); }
.iconbtn--danger:hover { color: var(--danger); }

/* ---------- Inventario: grilla de tarjetas (panel del gerente) ---------- */
/* Mismo formato visual que el catálogo de la tienda, pero cada tarjeta AJUSTA
   el stock del producto (no lo agrega a un carrito). */
.invgrid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); }
.invcard {
  display: flex; flex-direction: column;
  background: var(--surface-2); border-radius: var(--radius-sm);
  box-shadow: var(--nm-out-sm); overflow: hidden;
  transition: transform .14s var(--ease-out), box-shadow .14s var(--ease-out);
}
.invcard:hover { transform: translateY(-2px); box-shadow: var(--nm-out); }
.invcard.is-inactive { opacity: .6; }
.invcard__main { cursor: pointer; display: flex; flex-direction: column; flex: 1; }
.invcard__media { position: relative; aspect-ratio: 3 / 4; background: #0b0c10; }
.invcard__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.invcard__stock { position: absolute; top: .5rem; right: .5rem; font-family: var(--mono); font-weight: 700; }
.invcard__off {
  position: absolute; left: 0; bottom: 0; width: 100%; text-align: center;
  font-family: var(--mono); font-size: .6rem; letter-spacing: .12em; text-transform: uppercase;
  background: rgba(11, 12, 16, .82); color: var(--muted); padding: .25rem 0;
}
.invcard__body { padding: .6rem .7rem .35rem; display: flex; flex-direction: column; gap: .16rem; flex: 1; }
.invcard__cat { font-family: var(--mono); font-size: .58rem; letter-spacing: .14em; text-transform: uppercase; color: var(--faint); }
.invcard__name { font-family: var(--display); font-size: .92rem; line-height: 1.12; text-transform: uppercase; }
.invcard__sku { font-size: .64rem; color: var(--muted); }
.invcard__foot { margin-top: auto; padding-top: .35rem; display: flex; align-items: baseline; justify-content: space-between; gap: .4rem; }
.invcard__price { font-weight: 700; font-size: .92rem; color: var(--accent-2-text); }
.invcard__min { font-size: .6rem; color: var(--faint); text-transform: lowercase; }
.invcard__acts { display: flex; align-items: center; gap: .4rem; padding: .55rem .7rem .7rem; }
.invcard__adjust { flex: 1; white-space: nowrap; }
.invcard__cat .promo-badge { margin-left: .25rem; font-size: .58rem; }
.discount-editor {
  margin: .9rem 0; padding: .9rem; border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: var(--surface-2);
}
.discount-editor h3 { font-size: .95rem; margin: 0 0 .65rem; }
.discount-toggle { display: flex; align-items: center; gap: .5rem; cursor: pointer; }
.discount-toggle input { width: 1.1rem; height: 1.1rem; accent-color: var(--panini); }
.discount-editor [data-discount-fields] { margin-top: .75rem; }
.discount-preview { display: flex; gap: .6rem; flex-wrap: wrap; margin: .6rem 0; }
.discount-preview span { padding: .45rem .6rem; border-radius: 8px; background: var(--surface); font-size: .76rem; }
.discount-preview b { display: block; font-family: var(--mono); color: var(--accent-2-text); }
.discount-editor--readonly p { margin: 0; color: var(--muted); }
.prod__price { display: flex; flex-direction: column; align-items: flex-start; }
.prod__price del { color: var(--muted); font-size: .72rem; }
.prod__price strong { color: var(--accent-text); }
.prod__price small { color: var(--accent-text); font-weight: 800; }
.citem__sub del { color: var(--muted); }
.cart__discount { color: var(--panini); font-weight: 700; }
.ticket .t-row small { display: block; color: var(--muted); font-size: .66rem; margin-top: .08rem; }
@media (max-width: 480px) {
  .invgrid { gap: .7rem; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
  .invcard__name { font-size: .82rem; }
}

/* ---------- Importar Pokémon TCG ---------- */
.pkm-import { display: flex; flex-direction: column; gap: .9rem; }
.pkm-search { display: flex; gap: .6rem; flex-wrap: wrap; }
.pkm-search .input { flex: 1 1 220px; }
.pkm-search .select { flex: 1 1 200px; width: auto; }
.pkm-results { max-height: 56vh; overflow-y: auto; }
.pkm-grid { display: grid; gap: .8rem; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.pkm-card {
  display: flex; flex-direction: column; background: var(--surface-2);
  border-radius: var(--radius-sm); overflow: hidden; box-shadow: var(--nm-out-sm);
}
.pkm-card__img { width: 100%; aspect-ratio: 63/88; object-fit: contain; background: #0b0c10; }
.pkm-card__body { padding: .55rem .6rem .65rem; display: flex; flex-direction: column; gap: .3rem; flex: 1; }
.pkm-card__name { font-size: .82rem; font-weight: 700; line-height: 1.15; }
.pkm-card__meta { font-size: .68rem; color: var(--muted); font-family: var(--mono); }
.pkm-rarity {
  align-self: flex-start; font-size: .62rem; font-weight: 700; letter-spacing: .04em;
  padding: .12rem .45rem; border-radius: 999px;
  background: linear-gradient(180deg, var(--neon-cyan), #16b6cc); color: #05060b;
}
.pkm-card__price { font-family: var(--mono); font-weight: 700; font-size: .84rem; color: var(--accent-2-text); margin-top: auto; }
.pkm-card .btn { margin-top: .2rem; }

.pkm-selected { display: flex; gap: 1rem; margin: .8rem 0; flex-wrap: wrap; }
.pkm-selected img { width: 150px; aspect-ratio: 63/88; object-fit: contain; background: #0b0c10; border-radius: var(--radius-sm); }
.pkm-selected__info { flex: 1 1 220px; min-width: 0; }
.pkm-selected__info h3 { font-size: 1.1rem; }
.pkm-form__h { font-family: var(--mono); font-size: .7rem; letter-spacing: .1em; text-transform: uppercase; color: var(--faint); margin: .8rem 0 .5rem; }
.pkm-branches { display: grid; gap: .5rem; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.pkm-branch { display: flex; align-items: center; justify-content: space-between; gap: .6rem; background: var(--surface-2); padding: .5rem .7rem; border-radius: var(--radius-sm); }
.pkm-branch span { font-size: .82rem; }
.pkm-branch .input { width: 5rem; text-align: right; }

/* ---------- Campo de imagen: URL o archivo local ---------- */
.uplfield { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin-top: .4rem; }
.uplfield__btn {
  display: inline-flex; align-items: center; gap: .4rem;
  font-size: .78rem; color: var(--muted); cursor: pointer;
  padding: .35rem .6rem; border: 1px dashed var(--line); border-radius: var(--radius-sm);
  transition: border-color .15s, color .15s, background .15s;
}
.uplfield__btn:hover { color: var(--text); border-color: var(--accent); background: var(--surface-2); }
.uplfield__btn input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; }
.uplfield__prev { display: flex; gap: .4rem; flex-wrap: wrap; }
.uplfield__prev img {
  width: 46px; height: 46px; object-fit: cover;
  border: 2px solid var(--line); border-radius: var(--radius-sm); background: #0b0c10;
}

/* ---------- Misc ---------- */
.stack-list { display: flex; flex-direction: column; gap: .6rem; }
.linerow { display: flex; justify-content: space-between; align-items: center; padding: .8rem 1rem; border-radius: 12px; background: var(--surface-2); font-size: .88rem; }
.muted { color: var(--muted); }
.mono { font-family: var(--mono); }
.right { text-align: right; }
.center { text-align: center; }
.mt { margin-top: 1.2rem; }

/* ---------- Mi cuenta (cliente) ----------
   Info personal + Mis pedidos + Seguridad. Vista != "store" -> router.js
   agrega body.in-app, así que reutiliza los mismos tokens/--nm-out/.card
   que ya usan admin/manager/pos (mismo lenguaje visual que login/registro,
   que también corre bajo in-app). */
.account { max-width: 880px; margin: 0 auto; padding: 2rem var(--gutter) 3rem; }
.account__head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 1.2rem; flex-wrap: wrap; }
.account__head h1 { font-size: 1.4rem; }
.account__back { font-size: .72rem; letter-spacing: .1em; color: var(--muted); white-space: nowrap; }

.account__tabs { display: flex; gap: .4rem; margin-bottom: 1rem; flex-wrap: wrap; border-bottom: 1px solid var(--line-soft); padding-bottom: .6rem; }
.account__tab {
  font: inherit; font-size: .82rem; font-weight: 600; padding: .5rem .9rem; border-radius: var(--radius-sm);
  border: 1px solid transparent; background: none; color: var(--muted); cursor: pointer;
  transition: background .12s var(--ease-out), color .12s var(--ease-out);
}
.account__tab:hover { color: var(--text); }
.account__tab.is-active { background: var(--surface-2); color: var(--accent-text); box-shadow: var(--nm-out-sm); }
.account__tab--logout { margin-left: auto; color: var(--danger); border-radius: 0; border-color: var(--danger); text-transform: uppercase; font-weight: 700; }
.account__tab--logout:hover { background: var(--danger); color: #fff; }

.account__row { display: flex; justify-content: space-between; gap: 1rem; padding: .55rem 0; border-bottom: 1px dashed var(--line-soft); font-size: .88rem; }
.account__row:last-of-type { border-bottom: 0; }
.account__row-label { color: var(--muted); }
.account__row-value { font-weight: 600; text-align: right; }
.account__edit .field { margin-bottom: .7rem; }

.myorders__filters { display: flex; gap: .4rem; flex-wrap: wrap; margin-bottom: 1rem; }
.myorders__filter {
  font: inherit; font-size: .7rem; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  padding: .35rem .7rem; border-radius: 999px; border: 1px solid var(--line-soft);
  background: var(--surface-2); color: var(--muted); cursor: pointer;
}
.myorders__filter.is-active { background: var(--accent); color: var(--ink); border-color: var(--accent); }
.myorders__list { display: flex; flex-direction: column; gap: .8rem; }

/* Badge de estado de pedido — clase PROPIA (no ".badge") a propósito: la
   regla compartida "body.in-app .badge" (2 clases) le gana en especificidad
   a cualquier ".badge--color" (1 clase) y aplasta el color a gris siempre
   que se usan juntas bajo in-app, así que un modificador de color sobre
   ".badge" no se vería aquí. Aislarlo evita ese problema sin tocar el
   sistema ".badge" compartido con admin/manager/pos. */
.ordbadge { display: inline-flex; align-items: center; padding: .16rem .55rem; border-radius: 999px; font-size: .7rem; font-weight: 700; letter-spacing: .02em; white-space: nowrap; }
.ordbadge--preventa { background: var(--neon-magenta); color: #fff; }
.ordbadge--confirmed { background: var(--neon-cyan); color: var(--ink); }
.ordbadge--ready { background: var(--warning); color: #fff; }
.ordbadge--pickedUp { background: var(--success); color: #fff; }
.ordbadge--cancelled { background: var(--danger); color: #fff; }

.ordercard { border: 1px solid var(--line-soft); border-radius: var(--radius-sm); background: var(--surface-2); padding: .9rem 1rem; box-shadow: var(--nm-out-sm); }
.ordercard__top { display: flex; align-items: center; justify-content: space-between; gap: .6rem; flex-wrap: wrap; }
.ordercard__folio { font-weight: 700; font-size: .95rem; letter-spacing: .03em; }
.ordercard__date { font-size: .74rem; margin-top: .15rem; }
.ordercard__items { display: flex; flex-direction: column; gap: .5rem; margin-top: .7rem; }
.ordercard__item { display: flex; align-items: center; gap: .6rem; }
.ordercard__img { width: 40px; height: 40px; object-fit: cover; border-radius: 6px; flex: none; background: var(--surface-3); }
.ordercard__img--ph { display: flex; align-items: center; justify-content: center; font-size: 1.1rem; }
.ordercard__item-info { display: flex; justify-content: space-between; align-items: center; flex: 1; min-width: 0; gap: .5rem; font-size: .84rem; }
.ordercard__item-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ordercard__item-qty { color: var(--muted); flex: none; }
.ordercard__foot { display: flex; align-items: center; justify-content: space-between; gap: .6rem; margin-top: .8rem; padding-top: .7rem; border-top: 1px dashed var(--line-soft); flex-wrap: wrap; }
.ordercard__total { font-weight: 700; font-size: .86rem; }

.orderdetail__head { display: flex; align-items: center; justify-content: space-between; gap: .6rem; flex-wrap: wrap; }
.orderdetail__folio { font-weight: 700; font-size: 1.05rem; }
.orderdetail__items { display: flex; flex-direction: column; gap: .6rem; margin: .6rem 0; }
.orderdetail__item { display: flex; align-items: center; gap: .7rem; }
.orderdetail__item-info { flex: 1; min-width: 0; }
.orderdetail__item-title { font-size: .88rem; font-weight: 600; }
.orderdetail__code { margin-top: 1rem; padding-top: 1rem; border-top: 1px dashed var(--line-soft); text-align: center; }
.orderdetail__history { display: flex; flex-direction: column; gap: .3rem; margin-top: .6rem; }
.orderdetail__step { display: flex; align-items: center; gap: .6rem; font-size: .82rem; padding: .15rem 0; }
.orderdetail__step-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--accent); flex: none; }
.orderdetail__step-label { flex: 1; }
@media (max-width: 560px) {
  .account__tab--logout { margin-left: 0; }
  .ordercard__foot { flex-direction: column; align-items: stretch; }
  .ordercard__foot .btn { width: 100%; }
}
