/* =============================================================================
   Vault Solutions — 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); }
.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 0 ); border: 1px solid var(--border);
  transition: border-color var(--t), background-color var(--t), box-shadow var(--t); }
.hsearch:focus-within { background: #fff; border-color: oklch(0.6 0.14 91 / 0.55); box-shadow: 0 0 0 3px oklch(0.6 0.14 91 / 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 91); }
.hsearch.is-busy > svg { color: oklch(0.5 0.14 91); 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 91); }
.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; }
}

/* 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(154,108,0, 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(154,108,0, 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 91 / 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 91 / 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 91); 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; }
}

/* 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; } }
/* ===================== EL PIE EN EL MÓVIL — rehecho el 13-ago-2026 =========
   Antes: los tres grupos apilados y cada lista en UNA columna (se pidió así el
   17-jul-2026). Visto en un teléfono de verdad no funcionaba, y el dueño lo
   dijo: «el pie de página se ve mal, no está cuadrado».

   El problema medido en un iPhone de 390 px: cada enlace ocupaba una fila
   entera, así que la lista se comía la mitad izquierda de la pantalla y la
   MITAD DERECHA QUEDABA VACÍA de arriba abajo. Y el pie entero medía 1471 px
   —más de una pantalla y media sólo de pie— por 17 filas de enlaces sueltos.

   Ahora los enlaces van en DOS COLUMNAS dentro de cada grupo. El título sigue
   cruzando entero, que es lo que separa las secciones, pero las 17 filas se
   quedan en 10 y el ancho se usa completo. El pie baja a ~950 px.

   La letra baja a 0.88rem A PROPÓSITO: es lo que hace que «Términos y
   condiciones» y «Libro de Reclamaciones» —los dos más largos— quepan en una
   sola línea en una columna de 165 px. Con 0.95rem partían en dos y la rejilla
   quedaba desigual. El área de toque NO se toca: los 44 px de alto mínimo se
   mantienen con `min-height`, que es lo que importa para el dedo. */
@media (max-width: 520px) {
  .site-footer { padding-block: 2.5rem 1.5rem; }
  .footer-top { grid-template-columns: 1fr; gap: 1.9rem; }
  .footer-col h5 { margin-bottom: 0.55rem; }

  .footer-col ul {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 1rem;
  }

  .footer-col a {
    font-size: 0.88rem;
    display: flex;
    align-items: center;
    min-height: 44px;          /* el mínimo cómodo para un dedo */
  }

  .footer-pay { margin-top: 2rem; padding-top: 1.25rem; justify-content: center; text-align: center; }
  .footer-pay__marks { justify-content: center; }
  /* La barrita separadora sobra en cuanto la franja se centra y se parte en dos
     líneas: se queda colgando sola detrás de Diners, separando nada. */
  .footer-pay__sep { display: none; }
  .footer-bottom { margin-top: 1.25rem; padding-top: 1.25rem; }
}

/* Por debajo de 360 px (un iPhone SE) dos columnas ya aprietan demasiado: los
   enlaces largos partirían igual. Ahí se vuelve a una sola, que es lo correcto
   cuando de verdad no hay ancho. */
@media (max-width: 359px) {
  .footer-col ul { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------ 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; }
