/* =============================================================================
   DropDigitals — Chrome compartido: header, buscador, carrito,
   footer y app-shell de paneles. Cargado por todas las páginas.
   ============================================================================= */

/* ---------------------------------------------------------------- Marca --- */
/* overflow:hidden: si la letra del sistema es enorme, el nombre se recorta en
   vez de montarse encima de la lupa y del menú. */
.brand-lockup { display: inline-flex; align-items: center; gap: 0.6rem; min-width: 0; overflow: hidden; }
.brand-lockup svg { width: 2.1rem; height: 2.1rem; }
.brand-mark { position: relative; display: inline-flex; width: 2.2rem; height: 2.2rem; flex: none; }
.brand-mark__img { width: 100%; height: 100%; object-fit: contain; display: block; }
.brand-mark__img--dark { display: none; }
[data-theme="dark"] .brand-mark__img--light { display: none; }
[data-theme="dark"] .brand-mark__img--dark { display: block; }
/* min() con vw: con la letra del sistema en "Grande" la marca crecía tanto que
   partía en dos líneas y se salía de la cabecera (se veía cortada por arriba). */
.brand-word { font-size: min(1.2rem, 5vw); letter-spacing: -0.02em; color: var(--ink); line-height: 1.1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
@media (min-width: 561px) { .brand-word { font-size: 1.2rem; } }
.brand-word b { font-weight: 800; }
.brand-word span { font-weight: 500; color: var(--ink-muted); }

/* --------------------------------------------------------------- Header --- */
/* Sin backdrop-filter (blur): repintaba el área tras el header en cada frame de scroll
   (jank, sobre todo en móvil). Un fondo opaco se ve igual y es mucho más rápido.
   OPACO del todo (28-jul-2026): con 95% se transparentaba y el titular del hero
   se veía "fantasma" por detrás del logo al desplazar (reportado por un cliente
   desde el navegador de Facebook). Opaco además evita que el navegador tenga que
   mezclar dos capas en cada fotograma de scroll. */
.site-header { position: sticky; top: 0; z-index: var(--z-sticky); background: var(--bg); border-bottom: 1px solid transparent; transition: border-color var(--t), background-color var(--t), box-shadow var(--t); }
.site-header.is-stuck { border-bottom-color: var(--border); box-shadow: var(--shadow-xs); }
/* A sangre completa (estilo Ari): el logo pegado a la esquina superior izquierda
   y las acciones a la derecha, sin el ancho máximo del contenedor. */
/* min-height (no height): si el visitante tiene la letra del sistema en grande,
   la cabecera CRECE en vez de cortar el logo. */
.site-header__inner { display: flex; align-items: center; gap: clamp(0.5rem, 3vw, 1.25rem); min-height: 4.5rem; max-width: none; padding-inline: clamp(0.85rem, 2.5vw, 2.25rem); }
.site-header__inner > .brand-lockup { min-width: 0; }

.main-nav { display: flex; align-items: center; gap: 0.15rem; margin-left: 0.5rem; }
/* En pantallas anchas el menú va CENTRADO en el header (logo izq., acciones der.) */
@media (min-width: 1200px) {
  .site-header__inner { position: relative; }
  .main-nav { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); margin-left: 0; }
}
.nav-link { position: relative; display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.55rem 0.8rem; border-radius: var(--r-sm); font-size: 0.94rem; font-weight: 500; color: var(--ink-body); transition: color var(--t), background-color var(--t); }
.nav-link:hover { color: var(--ink); background: var(--surface-2); }
.nav-link[aria-current="page"] { color: var(--ink); font-weight: 600; }
.nav-link[aria-current="page"]::after { content: ""; position: absolute; left: 0.8rem; right: 0.8rem; bottom: -0.05rem; height: 2px; border-radius: 2px; background: var(--brand); }
.nav-link svg { width: 1rem; height: 1rem; transition: transform var(--t); }
/* En la portada estos cuatro destinos viven DENTRO del hero, en grande y con
   aire de menú de videojuego (.gmenu en hero3d.css). Repetirlos aquí arriba
   dejaba la misma navegación dos veces en la primera pantalla y le quitaba
   fuerza a la de abajo, que es la protagonista. En el resto de páginas el
   header sigue igual, y el menú de hamburguesa del celular los conserva
   siempre: ahí el .gmenu queda por debajo del 3D y hace falta el acceso corto. */
body[data-page="inicio"] .site-header .main-nav { display: none; }

/* --- Portada: la cabecera FLOTA sobre el hero -------------------------------
   Los paracaídas tienen que entrar por el borde de arriba de la pantalla, no
   por debajo de una barra. Así que en la portada la cabecera deja de ocupar
   sitio (pasa de sticky a fixed) y pierde el fondo: el 3D corre por detrás del
   logo y del buscador, y el hero empieza en el píxel cero.

   Lleva un velo corto arriba, no por decoración: si justo pasa una caja clara
   por detrás del logo, sin él se pierde. Y en cuanto el visitante baja, la
   clase .is-stuck (la pone ui.js) le devuelve el fondo negro, porque sobre el
   contenido de las secciones sí tiene que tapar. */
body[data-page="inicio"] .site-header {
  position: fixed;
  left: 0;
  right: 0;
  background: transparent;
  background-image: linear-gradient(180deg, rgb(0 0 0 / 0.75), rgb(0 0 0 / 0.35) 55%, rgb(0 0 0 / 0));
}

body[data-page="inicio"] .site-header.is-stuck {
  background: var(--bg);
  background-image: none;
}
.nav-link[aria-expanded="true"] svg { transform: rotate(180deg); }

.header-actions { margin-left: auto; display: flex; align-items: center; gap: 0.4rem; flex: none; }
/* Los iconos de la cabecera son ICONOS, no texto: no deben crecer cuando el
   visitante tiene la letra del sistema en grande. Si crecen, se comen el sitio
   del nombre de la marca y este acaba con puntos suspensivos. */
@media (max-width: 560px) {
  .site-header .icon-btn,
  .site-header .theme-toggle { width: min(2.5rem, 11vw); height: min(2.5rem, 11vw); }
  .site-header .brand-mark { width: min(2.2rem, 9.5vw); height: min(2.2rem, 9.5vw); }
}
.icon-btn { display: inline-grid; place-items: center; width: 2.5rem; height: 2.5rem; border-radius: var(--r-sm); color: var(--ink-body); position: relative; transition: background-color var(--t), color var(--t); }
.icon-btn:hover { background: var(--surface-2); color: var(--ink); }
.icon-btn svg { width: 1.25rem; height: 1.25rem; }
.cart-count { position: absolute; top: 0.25rem; right: 0.25rem; min-width: 1.05rem; height: 1.05rem; padding: 0 0.25rem; border-radius: var(--r-pill); background: var(--brand-strong); color: #fff; font-size: 0.68rem; font-weight: 700; display: grid; place-items: center; line-height: 1; }
.cart-count[hidden] { display: none; }

.theme-toggle { display: inline-grid; place-items: center; width: 2.5rem; height: 2.5rem; border-radius: var(--r-sm); color: var(--ink-body); transition: background-color var(--t), color var(--t); }
.theme-toggle:hover { background: var(--surface-2); color: var(--ink); }
.theme-toggle svg { width: 1.25rem; height: 1.25rem; }
.theme-toggle .moon { display: none; }
[data-theme="dark"] .theme-toggle .sun { display: none; }
[data-theme="dark"] .theme-toggle .moon { display: block; }

/* Búsqueda expandible */
.search-pop { position: absolute; top: calc(100% + 0.6rem); right: 0; width: min(440px, 88vw); padding: 0.8rem; background: var(--surface-raised); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-lg); z-index: var(--z-dropdown); opacity: 0; visibility: hidden; transform: translateY(6px); transition: opacity var(--t), transform var(--t), visibility var(--t); }
.search-pop.is-open { opacity: 1; visibility: visible; transform: translateY(0); }
.search-pop .quick { margin-top: 0.7rem; display: flex; flex-wrap: wrap; gap: 0.4rem; }
/* En celular/tablet el icono de la lupa NO está pegado al borde derecho (tiene
   la cuenta y el menú al lado), así que anclado al icono el popover se salía
   de la pantalla por la izquierda. Aquí se ancla al header: fijo, centrado y
   siempre dentro del viewport. El JS pone --pop-top en el borde inferior real
   del header. */
@media (max-width: 1239px) {
  .search-pop { position: fixed; left: 50%; right: auto; top: var(--pop-top, 4.5rem); width: min(440px, calc(100vw - 1.25rem)); transform: translate(-50%, 6px); }
  .search-pop.is-open { transform: translate(-50%, 0); }
}

/* Buscador en vivo del header (pantallas anchas; abajo queda el icono+popover).
   El ancho se calcula para NUNCA pisar el menú centrado: mitad del viewport
   menos la mitad del menú (~430px) menos el resto de acciones. */
.hsearch { position: relative; display: none; align-items: center; gap: 0.55rem;
  width: calc(50vw - 460px); max-width: 430px; min-width: 200px; height: 2.6rem;
  padding: 0 0.95rem; border-radius: var(--r-pill);
  /* Centrado en el hueco libre entre el menú (centrado) y los botones de la derecha */
  margin-right: clamp(0px, calc((50vw - 890px) / 2), 230px);
  background: oklch(0.972 0.004 240); border: 1px solid var(--border);
  transition: border-color var(--t), background-color var(--t), box-shadow var(--t); }
.hsearch:focus-within { background: var(--surface-2); border-color: oklch(0.6 0.14 51 / 0.55); box-shadow: 0 0 0 3px oklch(0.6 0.14 51 / 0.12); }
.hsearch > svg { width: 1.05rem; height: 1.05rem; color: var(--ink-faint); flex: none; transition: color var(--t); }
.hsearch:focus-within > svg { color: oklch(0.5 0.14 51); }
.hsearch.is-busy > svg { color: oklch(0.5 0.14 51); animation: hs-pulse 0.65s ease-in-out infinite; }
@keyframes hs-pulse { 50% { transform: scale(1.22); } }
.hsearch__input { flex: 1; min-width: 0; height: 100%; border: 0; background: none; outline: none; font: inherit; font-size: 0.88rem; color: var(--ink); }
.hsearch__input::-webkit-search-cancel-button { -webkit-appearance: none; }
.hsearch__drop { position: absolute; top: calc(100% + 0.55rem); left: 0; right: 0; padding: 0.4rem;
  background: var(--surface-raised); border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg); z-index: var(--z-dropdown); animation: hs-drop 0.22s var(--ease-out); }
@keyframes hs-drop { from { opacity: 0; transform: translateY(6px); } }
.hsearch__item { display: flex; align-items: center; gap: 0.65rem; padding: 0.5rem 0.6rem; border-radius: var(--r-sm); transition: background-color var(--t); }
.hsearch__item:hover { background: var(--surface-2); }
.hsearch__item .brand-glyph { flex: none; }
.hsearch__name { flex: 1; min-width: 0; font-size: 0.88rem; font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hsearch__name i { display: block; font-style: normal; font-size: 0.72rem; font-weight: 500; color: var(--ink-muted); }
.hsearch__item b { font-size: 0.85rem; color: var(--ink); font-variant-numeric: tabular-nums; }
.hsearch__all { display: flex; align-items: center; justify-content: center; gap: 0.4rem; padding: 0.6rem; margin-top: 0.25rem; border-top: 1px solid var(--border); font-size: 0.82rem; font-weight: 700; color: oklch(0.5 0.14 51); }
.hsearch__all svg { width: 0.95rem; height: 0.95rem; }
.hsearch__none { padding: 0.85rem; font-size: 0.85rem; color: var(--ink-muted); text-align: center; }
@media (min-width: 1240px) {
  .hsearch { display: flex; }
  .header-actions .has-search { display: none; }

  /* --- Portada: el buscador va CENTRADO y con brillo -----------------------
     En la portada el menú del header está oculto (vive dentro del hero), así
     que el centro queda libre y el buscador lo ocupa: es la acción que más se
     usa y estaba arrinconada. El cálculo de ancho de más arriba existía para
     esquivar ese menú; aquí ya no hay nada que esquivar y se anula.

     El brillo se hace con los tokens --gloss-* de la casa y NO con
     backdrop-filter: el desenfoque obliga al navegador a repintar lo que hay
     detrás en cada fotograma, y detrás hay una escena 3D corriendo. */
  body[data-page="inicio"] .hsearch {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    margin-right: 0;
    width: min(34vw, 460px);
    max-width: none;
    background:
      linear-gradient(180deg, rgb(255 255 255 / 0.13), rgb(255 255 255 / 0.02) 55%, rgb(0 0 0 / 0.2)),
      rgb(255 255 255 / 0.05);
    border-color: rgb(255 255 255 / 0.15);
    box-shadow: var(--gloss-rim), 0 12px 30px rgb(0 0 0 / 0.5);
  }

  body[data-page="inicio"] .hsearch:focus-within {
    border-color: color-mix(in oklch, var(--brand) 60%, transparent);
    box-shadow: var(--gloss-rim), 0 12px 30px rgb(0 0 0 / 0.5), var(--ring);
  }
}

/* WhatsApp flotante: soporte visible en toda la tienda (abajo a la derecha) */
.wa-fab { position: fixed; right: clamp(1rem, 2.5vw, 2rem); bottom: clamp(1.1rem, 3.5vh, 2rem);
  z-index: var(--z-sticky); width: 3.4rem; height: 3.4rem; border-radius: 50%;
  display: grid; place-items: center; background: #25d366; color: #fff;
  background-image: var(--gloss-face);
  box-shadow: 0 12px 30px rgba(18, 140, 70, 0.42), var(--gloss-rim);
  transition: transform var(--t) var(--ease-out), box-shadow var(--t); }
.wa-fab:hover { transform: translateY(-3px) scale(1.05); box-shadow: 0 16px 36px rgba(18, 140, 70, 0.5), var(--gloss-rim); }
.wa-fab svg { width: 1.65rem; height: 1.65rem; }

/* Carrito flotante: aparece abajo a la derecha SOLO cuando hay productos
   (queda ENCIMA del botón de WhatsApp, apilados) */
.cart-fab { position: fixed; right: clamp(1rem, 2.5vw, 2rem); bottom: calc(clamp(1.1rem, 3.5vh, 2rem) + 4.2rem);
  z-index: var(--z-sticky); width: 3.5rem; height: 3.5rem; border-radius: 50%;
  display: grid; place-items: center; background: var(--brand-strong); color: #fff;
  border: none; cursor: pointer; background-image: var(--gloss-face);
  box-shadow: 0 14px 34px oklch(0.45 0.12 51 / 0.38), var(--gloss-rim);
  animation: fab-in 0.45s var(--ease-out); transition: transform var(--t) var(--ease-out), box-shadow var(--t); }
.cart-fab:hover { transform: translateY(-3px) scale(1.05); box-shadow: 0 18px 40px oklch(0.45 0.12 51 / 0.45), var(--gloss-rim); }
.cart-fab svg { width: 1.35rem; height: 1.35rem; }
.cart-fab .cart-count { top: -0.2rem; right: -0.2rem; background: #fff; color: oklch(0.45 0.13 51); border: 1.5px solid var(--brand-strong); }
.cart-fab[hidden] { display: none; }
@keyframes fab-in { from { opacity: 0; transform: translateY(18px) scale(0.5); } }
@media (prefers-reduced-motion: reduce) { .cart-fab { animation: none; } .hsearch.is-busy > svg { animation: none; } }

/* Botón de cuenta/sesión: en escritorio con el texto completo. En móvil vive
   al costado de la lupa (pedido del dueño, 16-jul-2026): pill compacta
   ("Cuenta"/"Ingresar") y, en pantallas muy angostas, solo el icono para que
   el header no se apriete. Es el ÚNICO acceso a la cuenta en móvil: dentro
   del menú de tres barras ya no se repite. */
.account-btn__short { display: none; }
@media (max-width: 940px) {
  .account-btn__full { display: none; }
  .account-btn__short { display: inline; }
  /* Rótulo de chrome, no de contenido: no crece con la letra del sistema. Si
     crecía, se comía el sitio del nombre de la marca y este salía cortado. */
  .account-btn { font-size: min(0.85rem, 3.4vw); white-space: nowrap; }
}
@media (max-width: 430px) {
  .account-btn__short { display: none; }
  .account-btn { padding: 0.55rem 0.6rem; }
  .account-btn svg { margin: 0; }
}

/* --------------------------------------------------------------- Moneda ---
   Selector soles / dólares. Antes la moneda la decidía el país por IP y no
   había forma de cambiarla: un peruano de viaje veía dólares, y el dueño en su
   propia computadora también (en localhost no hay detección por IP).
   Va en el header en pantallas anchas y dentro del menú en el celular: junto al
   logo, la lupa y la cuenta no cabe a 320 px. */
.curswitch { display: inline-flex; align-items: center; gap: 2px; padding: 2px; border-radius: var(--r-pill); border: 1px solid var(--border); background: var(--surface); flex: none; }
.curswitch__b { border: 0; background: none; color: var(--ink-muted); font: inherit; font-weight: 700; line-height: 1; padding: 0.38rem 0.5rem; border-radius: var(--r-pill); cursor: pointer; min-width: 2.05rem; transition: background-color var(--t), color var(--t); }
/* Rótulo de chrome: tamaño fijo para que no empuje al resto del header cuando
   el visitante tiene la letra del sistema en grande. */
.curswitch--head .curswitch__b { font-size: 0.82rem; }
.curswitch__b:hover { color: var(--ink); }
/* Texto CARBÓN sobre el cobre, no blanco: con blanco el contraste se queda en
   3,6:1 y no llega al mínimo legible. */
.curswitch__b.is-on { background: var(--brand-strong); color: var(--on-brand); }

/* Bloque de moneda al final del menú móvil, con su rótulo: un control que
   cambia todos los precios necesita decir lo que hace. */
.mm-cur { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; margin-top: auto; padding-top: 1rem; border-top: 1px solid var(--border); }
.mm-cur > span { font-size: 0.9rem; color: var(--ink-muted); }
@media (max-width: 940px) { .curswitch--head { display: none; } }

/* Botón menú móvil: hamburguesa que se convierte en X cuando el menú está abierto */
.menu-toggle { display: none; }
.menu-toggle svg + svg { display: none; }
.menu-toggle[aria-expanded="true"] svg:first-child { display: none; }
.menu-toggle[aria-expanded="true"] svg + svg { display: block; }

/* Menú móvil. z-drawer (no z-sticky): tiene que quedar POR ENCIMA del velo
   oscuro; antes el velo lo tapaba y se robaba los taps de los enlaces. */
.mobile-menu { position: fixed; inset: 4.5rem 0 0; background: var(--bg); z-index: var(--z-drawer); padding: 1.25rem var(--gutter) 2rem; overflow-y: auto; transform: translateX(100%); transition: transform var(--t-slow) var(--ease-out); display: flex; flex-direction: column; gap: 0.25rem; }
.mobile-menu.is-open { transform: translateX(0); }
.mobile-menu a { padding: 0.95rem 0.5rem; font-size: 1.05rem; font-weight: 600; color: var(--ink-strong); border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; }
.mobile-menu .mm-actions { margin-top: 1.25rem; display: grid; gap: 0.7rem; }
/* Buscador dentro del menú (arriba de todo, como el buscador del escritorio) */
.mobile-menu .mm-search { margin-bottom: 0.9rem; flex: none; }
/* Con el menú abierto, el header (logo + X) sube por encima del velo con
   fondo sólido; components.js pone body.menu-open. */
body.menu-open .site-header { z-index: calc(var(--z-drawer) + 1); background: var(--bg); }

@media (max-width: 940px) {
  .main-nav, .header-actions .desktop-only { display: none; }
  .menu-toggle { display: inline-grid; }
}
@media (min-width: 941px) { .mobile-menu { display: none; } }

/* --------------------------------------------------------------- Footer --- */
.site-footer { background: var(--bg-subtle); border-top: 1px solid var(--border); padding-block: clamp(3rem, 2rem + 3vw, 4.5rem) 2rem; }
.footer-top { display: grid; grid-template-columns: 1.5fr 1fr 1fr 1fr; gap: clamp(1.5rem, 1rem + 2vw, 3rem); }
.footer-brand p { margin-top: 0.9rem; color: var(--ink-muted); font-size: 0.92rem; max-width: 34ch; }
.footer-social { margin-top: 1.25rem; display: flex; gap: 0.5rem; }
.footer-social a { display: inline-grid; place-items: center; width: 2.3rem; height: 2.3rem; border-radius: var(--r-sm); border: 1px solid var(--border); color: var(--ink-muted); transition: color var(--t), border-color var(--t), transform var(--t); }
.footer-social a:hover { color: var(--brand-ink); border-color: var(--brand); transform: translateY(-2px); }
.footer-social svg { width: 1.15rem; height: 1.15rem; }
.footer-col h5 { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.12em; color: var(--ink); margin-bottom: 1rem; font-weight: 800; }
.footer-col ul { display: flex; flex-direction: column; gap: 0.7rem; }
.footer-col a { color: var(--ink-muted); font-size: 0.93rem; transition: color var(--t); }
.footer-col a:hover { color: var(--brand-ink); }
/* Franja de medios de pago: candado + marcas de tarjeta + sello de la pasarela.
   Aparece en TODAS las páginas, como en cualquier tienda seria. */
.footer-pay { margin-top: 2.25rem; padding-top: 1.5rem; border-top: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; gap: 0.9rem 1.5rem; flex-wrap: wrap; }
.footer-pay__t { display: inline-flex; align-items: center; gap: 0.45rem; color: var(--ink-muted); font-size: 0.88rem; transition: color var(--t); }
.footer-pay__t:hover { color: var(--brand-ink); }
.footer-pay__t svg { width: 1rem; height: 1rem; color: var(--brand); flex: none; }
.footer-pay__marks { display: flex; align-items: center; gap: 0.45rem; flex-wrap: wrap; }
.footer-pay__sep { width: 1px; height: 1.4rem; background: var(--border-strong); margin-inline: 0.3rem; }
.footer-pay__gw { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.82rem; color: var(--ink-faint); }
/* Elegir moneda (30-jul-2026). Va en el pie: es una preferencia, no un paso de
   la compra. `flex-wrap` para que a 320px el título y las dos opciones bajen
   solos en vez de estrujarse. */
.cur-switch { margin-top: 1.5rem; padding-top: 1.4rem; border-top: 1px solid var(--border); display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.cur-switch__t { display: inline-flex; align-items: center; gap: 0.45rem; font-size: 0.84rem; color: var(--ink-muted); }
.cur-switch__t svg { width: 1rem; height: 1rem; flex: none; }
.cur-switch__opts { display: inline-flex; gap: 0.3rem; padding: 0.25rem; border: 1px solid var(--border); border-radius: var(--r-pill); background: var(--surface); }
.cur-switch__opt { min-height: 38px; padding: 0.35rem 0.85rem; border-radius: var(--r-pill); font-size: 0.85rem; font-weight: 600; color: var(--ink-muted); white-space: nowrap; transition: background-color var(--t), color var(--t); }
.cur-switch__opt:hover { color: var(--ink); }
.cur-switch__opt.is-on { background: var(--brand-50); color: var(--brand-ink); }
@media (pointer: coarse) { .cur-switch__opt { min-height: 44px; } }

.footer-bottom { margin-top: 1.5rem; padding-top: 1.5rem; border-top: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; color: var(--ink-faint); font-size: 0.86rem; }
.footer-bottom .links { display: flex; gap: 1.25rem; flex-wrap: wrap; }
.footer-bottom a { color: var(--ink-muted); }
.footer-bottom a:hover { color: var(--ink); }
/* El WhatsApp flotante vive abajo a la derecha: se le reserva su espacio para
   que el último enlace del pie no quede tapado cuando el contenedor (1520px)
   llega casi al borde del viewport. */
@media (max-width: 1680px) { .footer-bottom .links { padding-right: 4.5rem; } }

@media (max-width: 860px) { .footer-top { grid-template-columns: 1fr 1fr; } .footer-brand { grid-column: 1 / -1; } }
/* Móvil: grupos apilados en UNA columna con aire entre secciones (pedido del
   dueño, 17-jul-2026): títulos en negrita bien visibles y enlaces cómodos de tocar. */
@media (max-width: 520px) {
  .site-footer { padding-block: 2.5rem 1.5rem; }
  .footer-top { grid-template-columns: 1fr; gap: 2.25rem; }
  .footer-col h5 { margin-bottom: 0.9rem; }
  .footer-col ul { gap: 0.85rem; }
  .footer-col a { font-size: 0.95rem; }
  .footer-pay { margin-top: 2rem; padding-top: 1.25rem; justify-content: center; text-align: center; }
  .footer-pay__marks { justify-content: center; }
  .footer-bottom { margin-top: 1.25rem; padding-top: 1.25rem; }
}

/* ------------------------------------------------------------ App-shell --- */
.app { display: grid; grid-template-columns: 264px 1fr; min-height: 100dvh; }
.app-sidebar { background: var(--bg-subtle); border-right: 1px solid var(--border); display: flex; flex-direction: column; position: sticky; top: 0; height: 100dvh; }
.app-sidebar__head { padding: 1.25rem 1.35rem; border-bottom: 1px solid var(--border); }
.app-nav { flex: 1; overflow-y: auto; padding: 1rem 0.8rem; display: flex; flex-direction: column; gap: 0.15rem; }
.app-nav .group-label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-faint); font-weight: 700; padding: 0.9rem 0.7rem 0.4rem; }
.side-link { display: flex; align-items: center; gap: 0.75rem; padding: 0.65rem 0.7rem; border-radius: var(--r-sm); color: var(--ink-body); font-weight: 500; font-size: 0.93rem; transition: background-color var(--t), color var(--t); }
.side-link svg { width: 1.2rem; height: 1.2rem; color: var(--ink-faint); transition: color var(--t); }
.side-link:hover { background: var(--surface-2); color: var(--ink); }
.side-link.is-active { background: var(--brand-50); color: var(--brand-ink); font-weight: 600; }
.side-link.is-active svg { color: var(--brand); }
.side-link .tag { margin-left: auto; font-size: 0.72rem; font-weight: 700; background: var(--surface-2); color: var(--ink-muted); padding: 0.1rem 0.45rem; border-radius: var(--r-pill); }
.app-sidebar__foot { padding: 1rem; border-top: 1px solid var(--border); }
.user-card { display: flex; align-items: center; gap: 0.7rem; padding: 0.6rem; border-radius: var(--r); }
.user-card .meta { min-width: 0; }
.user-card .meta b { display: block; font-size: 0.9rem; color: var(--ink); }
.user-card .meta span { font-size: 0.8rem; color: var(--ink-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; }

.app-main { display: flex; flex-direction: column; min-width: 0; background: var(--bg); }
.app-topbar { position: sticky; top: 0; z-index: var(--z-sticky); display: flex; align-items: center; gap: 1rem; height: 4rem; padding: 0 clamp(1.25rem, 3vw, 2rem); background: color-mix(in oklch, var(--bg) 86%, transparent); backdrop-filter: blur(12px); border-bottom: 1px solid var(--border); }
.app-topbar h1 { font-size: 1.25rem; font-weight: 700; }
.app-content { padding: clamp(1.5rem, 1rem + 2vw, 2.5rem); flex: 1; }
.app-content--narrow { max-width: 1100px; width: 100%; margin-inline: auto; }

.app-burger { display: none; }
@media (max-width: 900px) {
  .app { grid-template-columns: 1fr; }
  .app-sidebar { position: fixed; left: 0; top: 0; width: 280px; z-index: var(--z-drawer); transform: translateX(-100%); transition: transform var(--t-slow) var(--ease-out); box-shadow: var(--shadow-lg); }
  .app-sidebar.is-open { transform: translateX(0); }
  .app-burger { display: inline-grid; }
}

/* Page-head reutilizable dentro de paneles */
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.5rem; }
.page-head h2 { font-size: clamp(1.4rem, 1.1rem + 1vw, 1.75rem); }
.page-head p { color: var(--ink-muted); margin-top: 0.25rem; font-size: 0.94rem; }

/* Tarjeta de estadística sobria (sin plantilla "número gigante + degradado") */
.stat-card { display: flex; flex-direction: column; gap: 0.35rem; padding: 1.25rem 1.35rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); min-width: 0; }
/* El rótulo ("Licencias activas") parte línea: si no, fijaba el ancho mínimo de
   la tarjeta y la rejilla del resumen se salía de la pantalla en el celular. */
.stat-card .k { display: inline-flex; align-items: center; gap: 0.5rem; color: var(--ink-muted); font-size: 0.86rem; font-weight: 500; min-width: 0; flex-wrap: wrap; overflow-wrap: anywhere; }
.stat-card .k svg { width: 1.05rem; height: 1.05rem; color: var(--brand); }
.stat-card .v { font-size: 1.7rem; font-weight: 800; color: var(--ink); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.stat-card .delta { font-size: 0.82rem; font-weight: 600; }
.stat-card .delta.up { color: var(--brand-ink); }
.stat-card .delta.down { color: var(--danger-ink); }
@media (max-width: 480px) {
  .stat-card { padding: 0.9rem 1rem; gap: 0.2rem; }
  .stat-card .v { font-size: 1.45rem; }
}

/* Líneas del carrito (drawer) */
.cart-line { display: grid; grid-template-columns: auto 1fr auto; gap: 0.85rem; align-items: start; padding: 0.95rem 0; border-bottom: 1px solid var(--border); }
.cart-line:first-child { padding-top: 0; }
.cart-line:last-child { border-bottom: none; }
.cart-line__info { min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }
.cart-line__info b { font-size: 0.92rem; color: var(--ink); }
/* Se agotó mientras estaba en el carrito: se apaga la miniatura, el nombre y el
   importe para que se vea de un vistazo cuál hay que quitar antes de pagar. La
   insignia "Agotado" y el botón de eliminar NO se atenúan (la opacidad del
   padre no se puede revertir en el hijo, así que se atenúa solo lo justo). */
.cart-line--out .p-thumb,
.cart-line--out .brand-glyph,
.cart-line--out .cart-line__info b,
.cart-line--out .qty,
.cart-line--out .cart-line__end b { opacity: 0.5; }
.qty { display: inline-flex; align-items: center; gap: 0.55rem; margin-top: 0.5rem; }
/* 1.7rem eran 27px: cambiar la cantidad con el pulgar era una lotería. El botón
   se ve igual de compacto (2.05rem) pero el área tocable llega a ~44px con un
   ::after invisible que lo agranda sin mover el diseño. (29-jul-2026) */
.qty button { position: relative; width: 2.05rem; height: 2.05rem; border: 1px solid var(--border-strong); border-radius: var(--r-xs); display: grid; place-items: center; color: var(--ink-body); transition: border-color var(--t), background-color var(--t); }
.qty button::after { content: ""; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 44px; height: 44px; }
.qty button:hover { border-color: var(--ink-faint); background: var(--surface-2); }
.qty button svg { width: 0.85rem; height: 0.85rem; }
.qty span { min-width: 1.4rem; text-align: center; font-weight: 700; font-variant-numeric: tabular-nums; }
.cart-line__end { display: flex; flex-direction: column; align-items: flex-end; gap: 0.6rem; }
.cart-line__end b { font-variant-numeric: tabular-nums; }
.link-danger { color: var(--ink-faint); transition: color var(--t); }
.link-danger:hover { color: var(--danger); }
.link-danger svg { width: 1.05rem; height: 1.05rem; }

/* Empty state reutilizable */
.empty-state { text-align: center; padding: clamp(2rem, 5vw, 3.5rem) 1rem; }
.empty-state .icon-tile { margin: 0 auto 1rem; }
.empty-state h4 { margin-bottom: 0.3rem; }
.empty-state p { color: var(--ink-muted); max-width: 36ch; margin-inline: auto; }

/* =============================================================================
   VALORACIÓN — estrellas compartidas + insignia del pie
   Las estrellas se usan en la insignia (todas las páginas) y en el carrusel de
   reseñas de la portada (home.css). La insignia solo aparece si hay reseñas
   REALES publicadas en el panel: su nota y su conteo se calculan de ellas.
   ============================================================================= */

/* Relleno PARCIAL: la fila gris marca el tamaño y la dorada se recorta al
   porcentaje de la nota (4,9 → 98% pintado). Sirve igual para 5 exactos. */
.rstars { position: relative; display: inline-flex; line-height: 0; }
.rstars__bg, .rstars__on { display: inline-flex; gap: 2px; }
.rstars__bg { color: color-mix(in oklch, var(--ink) 18%, transparent); }
.rstars__on { position: absolute; left: 0; top: 0; height: 100%; overflow: hidden; color: #f5a623; }
.rstar { display: inline-flex; flex: 0 0 auto; width: 1.15rem; height: 1.15rem; }
.rstar svg { width: 100%; height: 100%; fill: currentColor; stroke: none; }
.rstars--sm .rstar { width: 0.95rem; height: 0.95rem; }
.rstars--xl .rstar { width: clamp(1.6rem, 1.2rem + 1.2vw, 2.1rem); height: clamp(1.6rem, 1.2rem + 1.2vw, 2.1rem); }

/* Insignia de valoración (se cuelga en cualquier [data-trust-badge]) */
.trustbadge {
  display: inline-block; padding: 0.8rem 1rem;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 12px 28px -20px color-mix(in oklch, var(--ink) 70%, transparent);
}
.trustbadge__top { display: flex; align-items: center; gap: 0.4rem; }
.trustbadge__seal { display: inline-flex; color: var(--brand); }
.trustbadge__seal svg { width: 1.15rem; height: 1.15rem; }
.trustbadge__brand { font-size: 0.95rem; color: var(--ink-strong); }
.trustbadge__score { font-weight: 800; color: var(--ink-strong); }
.trustbadge__title { margin: 0.45rem 0 0; font-weight: 800; color: var(--ink-strong); }
.trustbadge__sub { margin: 0.1rem 0 0; font-size: 0.82rem; color: var(--ink-muted); }
.footer-trust { margin-top: 1.1rem; }
