/* ============================================================================
   MODO APP — lo que cambia cuando el sitio corre instalado
   ----------------------------------------------------------------------------
   Todo acá cuelga de html[data-modo="app"], que lo pone app/shell.js. En una
   pestaña del navegador este archivo no hace absolutamente nada: es el
   invariante I-5 de docs/app/ARQUITECTURA.md, la app es aditiva y el sitio de
   siempre tiene que seguir funcionando igual para quien nunca la instaló.

   Es un archivo aparte y no un bloque dentro de style.css a propósito: así se
   puede leer de una sentada qué es "de la app" y qué es "del sitio", y borrarlo
   entero es una forma válida de revertir.
   ============================================================================ */

/* ── LA CORTINA DE DESPEGUE NO VA EN LA APP ──────────────────────────────────
   Sacada a pedido de Uriel el 2026-08-22. En la web tiene sentido —es la puesta
   en escena de la marca para alguien que llega de Google—, pero en la app es un
   paso de más entre el cliente y sus compras, cada vez que la abre.

   El trabajo real lo hace shell.js marcando la bandera que main.js ya usa. Esto
   es la RED DE SEGURIDAD para el caso de que sessionStorage esté bloqueado
   (modo privado con almacenamiento restringido): ahí la bandera no se puede
   escribir, y sin esta regla la cortina volvería a aparecer. */
html[data-modo="app"] #enter-screen {
    display: none !important;
}

/* ── LO QUE MÁS DELATA A UNA WEB DISFRAZADA DE APP ───────────────────────────
   Son tres detalles chicos que, juntos, hacen casi toda la diferencia entre
   "esto es una página" y "esto es una app". */
html[data-modo="app"] {
    /* 1. EL DESTELLO AZUL AL TOCAR. Chrome pinta un rectángulo semitransparente
          sobre cada elemento tocable. Ninguna app nativa hace eso, y es lo
          primero que delata que estás en un navegador. */
    -webkit-tap-highlight-color: transparent;

    /* 2. EL REBOTE DEL SCROLL. Al llegar al final, el navegador estira la página
          y muestra el fondo. En una app el scroll frena en seco. `contain`
          además evita el pull-to-refresh de Chrome, que en una app instalada
          es un gesto que nadie espera. */
    overscroll-behavior-y: contain;

    /* 3. El zoom por doble toque, que en una app se siente como un error. */
    touch-action: manipulation;
}

/* ── SELECCIÓN DE TEXTO: SOLO DONDE SIRVE ────────────────────────────────────
   Mantener apretado un botón y que aparezca "Copiar / Seleccionar todo" es puro
   ruido. Se apaga en los controles.

   OJO: NO se apaga en el contenido. El búnker muestra usuario y clave de PSN, y
   el cliente TIENE que poder seleccionarlos y copiarlos para pegarlos en la
   consola. Apagar la selección ahí rompería el uso principal de la app. */
html[data-modo="app"] .glass-nav,
html[data-modo="app"] .bunker-quicknav,
html[data-modo="app"] button,
html[data-modo="app"] .btn,
html[data-modo="app"] .qn-chip {
    -webkit-user-select: none;
    user-select: none;
}

/* ── ZONAS SEGURAS ───────────────────────────────────────────────────────────
   env(safe-area-inset-*) es el espacio que se come el notch arriba y la barra de
   gestos abajo. Devuelve 0 salvo que el <meta viewport> lleve viewport-fit=cover,
   que se agregó en las cinco páginas junto con este archivo.

   Por ahora solo el borde de abajo, que es el que pisa contenido. La barra de
   pestañas del Sprint 6 va a colgar de acá. */
html[data-modo="app"] body {
    padding-bottom: env(safe-area-inset-bottom, 0px);
}

/* ── RESPETAR A QUIEN PIDIÓ MENOS MOVIMIENTO ─────────────────────────────────
   El sitio tiene glitch, parpadeos y un fondo animado. A alguien con sensibilidad
   al movimiento eso le puede dar mareo, y es una preferencia que el sistema
   operativo ya expone. Se respeta en la app y en la web por igual. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ============================================================================
   EL CARTEL DE "INSTALAR APP"
   ----------------------------------------------------------------------------
   Lo dibuja app/install.js. Vive acá y no en style.css porque es de la app, no
   del sitio: borrar este archivo tiene que alcanzar para revertir toda la capa.

   OJO: esta parte NO cuelga de html[data-modo="app"], al revés que todo lo demás
   del archivo. Es a propósito — el cartel solo tiene sentido cuando la app
   TODAVÍA NO está instalada, o sea en modo web. install.js ya se encarga de no
   mostrarlo cuando corre instalada.
   ============================================================================ */

.a51-install {
    position: fixed;
    left: 12px;
    right: 12px;
    /* Sobre la barra de gestos del iPhone. Sin viewport-fit=cover en el <meta>,
       env() devuelve 0 y el cartel queda pisado por la barra del sistema. */
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    z-index: 9999;

    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 16px;
    max-width: 520px;
    margin: 0 auto;

    background: rgba(10, 12, 10, 0.94);
    border: 1px solid var(--neon-green, #39ff14);
    border-radius: 16px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6), 0 0 24px rgba(57, 255, 20, 0.15);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);

    /* Entra desde abajo. Arranca oculto y con pointer-events apagado para que no
       robe toques durante los 300 ms de la animación. */
    transform: translateY(140%);
    opacity: 0;
    pointer-events: none;
    transition: transform 0.34s cubic-bezier(0.2, 0.9, 0.3, 1), opacity 0.34s ease;
}

.a51-install.visible {
    transform: translateY(0);
    opacity: 1;
    pointer-events: auto;
}

.a51-install-ico {
    flex: 0 0 auto;
    width: 52px;
    height: 52px;
    border-radius: 12px;
}

.a51-install-txt {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
    font-family: 'Outfit', system-ui, sans-serif;
}

.a51-install-txt strong {
    color: #fff;
    font-size: 0.95rem;
    font-weight: 800;
    line-height: 1.25;
}

.a51-install-txt span {
    color: #a8a8a8;
    font-size: 0.79rem;
    line-height: 1.4;
}

.a51-install-txt b {
    color: var(--neon-green, #39ff14);
    font-weight: 700;
}

.a51-install-btns {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

/* 44 px de alto mínimo: es el tamaño con el que un dedo le pega sin errarle. */
.a51-install-si,
.a51-install-no {
    min-height: 44px;
    padding: 0 16px;
    border-radius: 10px;
    font-family: 'Outfit', system-ui, sans-serif;
    font-size: 0.82rem;
    font-weight: 800;
    letter-spacing: 0.6px;
    cursor: pointer;
    white-space: nowrap;
    transition: transform 0.15s ease, background 0.15s ease;
}

.a51-install-si {
    background: var(--neon-green, #39ff14);
    border: none;
    color: #050505;
}

.a51-install-si:active {
    transform: scale(0.96);
}

.a51-install-no {
    background: none;
    border: 1px solid #444;
    color: #999;
    font-weight: 500;
    letter-spacing: 0;
}

.a51-install-no:active {
    background: #1a1a1a;
}

/* En pantallas angostas los botones no entran al lado del texto: se bajan. */
@media (max-width: 420px) {
    .a51-install {
        flex-wrap: wrap;
    }
    .a51-install-btns {
        flex-direction: row;
        width: 100%;
    }
    .a51-install-si,
    .a51-install-no {
        flex: 1 1 auto;
    }
}

/* ============================================================================
   LA TARJETA DE "ACTIVAR AVISOS" DEL BÚNKER
   ----------------------------------------------------------------------------
   La dibuja app/avisos-ui.js. Tampoco cuelga de html[data-modo="app"]: los avisos
   funcionan igual desde el navegador en Android, así que ofrecerlos solo dentro de
   la app instalada dejaría afuera a medio mundo.
   ============================================================================ */

.a51-avisos {
    display: flex;
    align-items: center;
    gap: 16px;
    max-width: 1000px;
    margin: 28px auto 0;
    padding: 18px 20px;

    background: rgba(0, 242, 234, 0.05);
    border: 1px solid #00F2EA;
    border-radius: 16px;
    box-shadow: 0 0 30px rgba(0, 242, 234, 0.12) inset;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);

    animation: a51-avisos-entra 0.4s cubic-bezier(0.2, 0.9, 0.3, 1);
}

@keyframes a51-avisos-entra {
    from { opacity: 0; transform: translateY(-10px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Cuando el cliente los activó, la tarjeta pasa al verde de la marca. */
.a51-avisos.a51-avisos-ok {
    background: rgba(57, 255, 20, 0.06);
    border-color: var(--neon-green, #39ff14);
    box-shadow: 0 0 30px rgba(57, 255, 20, 0.14) inset;
}

.a51-avisos-ico {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 46px;
    height: 46px;
    border-radius: 12px;
    background: rgba(0, 242, 234, 0.12);
    color: #00F2EA;
    font-size: 1.3rem;
}

.a51-avisos.a51-avisos-ok .a51-avisos-ico {
    background: rgba(57, 255, 20, 0.14);
    color: var(--neon-green, #39ff14);
}

.a51-avisos-txt {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.a51-avisos-txt strong {
    color: #fff;
    font-size: 1.02rem;
    font-weight: 800;
    line-height: 1.25;
}

.a51-avisos-txt span {
    color: #a8a8a8;
    font-size: 0.84rem;
    line-height: 1.45;
}

.a51-avisos-txt b {
    color: #00F2EA;
    font-weight: 700;
}

.a51-avisos-btns {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
}

/* 44 px de alto: el tamaño con el que un dedo le pega sin errarle. */
.a51-avisos-si,
.a51-avisos-no {
    min-height: 44px;
    padding: 0 18px;
    border-radius: 10px;
    font-family: 'Outfit', system-ui, sans-serif;
    font-size: 0.82rem;
    font-weight: 800;
    letter-spacing: 0.6px;
    cursor: pointer;
    white-space: nowrap;
    transition: transform 0.15s ease, background 0.15s ease, opacity 0.15s ease;
}

.a51-avisos-si {
    background: #00F2EA;
    border: none;
    color: #050505;
}
.a51-avisos-si:active { transform: scale(0.96); }
.a51-avisos-si:disabled { opacity: 0.6; cursor: default; }

.a51-avisos-no {
    background: none;
    border: 1px solid #444;
    color: #999;
    font-weight: 500;
    letter-spacing: 0;
}
.a51-avisos-no:active { background: #1a1a1a; }

/* En el celular los botones no entran al lado del texto: se bajan. */
@media (max-width: 640px) {
    .a51-avisos { flex-wrap: wrap; gap: 12px; }
    .a51-avisos-btns { width: 100%; }
    .a51-avisos-si, .a51-avisos-no { flex: 1 1 auto; }
}

/* ── LA VERSIÓN FINA: una línea, cuando el cliente ya decidió ────────────────
   El pedido largo se muestra una vez. Después —lo activó, o dijo "ahora no"— el
   bloque se encoge a una línea con su botón, pero NO DESAPARECE.

   Que desapareciera era el problema: el que activaba los avisos se quedaba sin
   ninguna forma de desactivarlos salvo la configuración del navegador, y el que
   los descartaba sin querer tenía que esperar 30 días para que le volvieran a
   aparecer. Una línea fina no molesta a nadie y siempre deja la puerta abierta. */
.a51-avisos-fina {
    gap: 12px;
    margin-top: 18px;
    padding: 10px 14px;
    background: rgba(255, 255, 255, 0.03);
    border-color: #2a2a2a;
    box-shadow: none;
}

.a51-avisos-fina.a51-avisos-ok {
    background: rgba(57, 255, 20, 0.04);
    border-color: rgba(57, 255, 20, 0.45);
}

.a51-avisos-fina .a51-avisos-txt span { display: none; }
.a51-avisos-fina .a51-avisos-txt strong { font-size: 0.9rem; font-weight: 700; }

.a51-avisos-fina .a51-avisos-ico {
    width: 32px;
    height: 32px;
    border-radius: 9px;
    font-size: 0.95rem;
}

.a51-avisos-fina .a51-avisos-si,
.a51-avisos-fina .a51-avisos-no {
    min-height: 38px;
    padding: 0 14px;
    font-size: 0.74rem;
}

/* Una línea es una línea: acá se revierte el "los botones se bajan" de arriba,
   que para la versión fina la convertiría en dos filas y dejaría de ser fina. */
@media (max-width: 640px) {
    .a51-avisos-fina { flex-wrap: nowrap; }
    .a51-avisos-fina .a51-avisos-btns { width: auto; }
    .a51-avisos-fina .a51-avisos-si,
    .a51-avisos-fina .a51-avisos-no { flex: 0 0 auto; }
}

/* ============================================================================
   LA BARRA DE PESTAÑAS DE ABAJO — módulo 5 de la propuesta
   ----------------------------------------------------------------------------
   La dibuja app/nav.js, y TODO cuelga de html[data-modo="app"]: en el navegador
   este bloque no existe. Quien nunca instaló la app ve el sitio de siempre, con su
   menú hamburguesa (invariante I-5).
   ============================================================================ */

html[data-modo="app"] .a51-nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 9000;

    display: grid;
    grid-template-columns: repeat(4, 1fr);
    align-items: stretch;

    /* LA LÍNEA QUE MÁS DELATA A UNA APP MAL HECHA. Sin este padding, la barra
       queda DEBAJO de la barra de gestos del iPhone y las pestañas del medio no
       se pueden tocar. env() devuelve 0 salvo que el <meta viewport> lleve
       viewport-fit=cover, que se agregó en las cinco páginas. */
    padding-bottom: env(safe-area-inset-bottom, 0px);

    background: rgba(6, 8, 6, 0.92);
    border-top: 1px solid rgba(57, 255, 20, 0.18);
    backdrop-filter: blur(16px) saturate(140%);
    -webkit-backdrop-filter: blur(16px) saturate(140%);
}

/* El contenido no puede quedar tapado por la barra. 62px + la zona segura. */
html[data-modo="app"].a51-con-nav body {
    padding-bottom: calc(62px + env(safe-area-inset-bottom, 0px)) !important;
}

html[data-modo="app"] .a51-tab {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;

    /* 56 px de alto: un dedo le pega sin errarle. La recomendación mínima son 44,
       pero en una barra de cuatro columnas el ancho ya es generoso y el alto es lo
       que decide si se toca la pestaña o el borde de la de al lado. */
    min-height: 56px;
    padding: 8px 4px;

    color: #7a7a7a;
    text-decoration: none;
    font-family: 'Outfit', system-ui, sans-serif;
    transition: color 0.18s ease;
    -webkit-tap-highlight-color: transparent;
}

html[data-modo="app"] .a51-tab-ico {
    position: relative;
    font-size: 1.22rem;
    line-height: 1;
    transition: transform 0.18s cubic-bezier(0.2, 0.9, 0.3, 1);
}

html[data-modo="app"] .a51-tab-txt {
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.2px;
}

html[data-modo="app"] .a51-tab.activa {
    color: var(--neon-green, #39ff14);
}

/* El ícono sube un poco al activarse. Es un gesto chico y es lo que hace que el
   cambio se sienta como una respuesta al dedo y no como un repintado. */
html[data-modo="app"] .a51-tab.activa .a51-tab-ico {
    transform: translateY(-2px) scale(1.08);
}

html[data-modo="app"] .a51-tab:active .a51-tab-ico {
    transform: scale(0.9);
}

/* ── EL PUNTITO ROJO ─────────────────────────────────────────────────────────
   "Con un puntito rojo cuando hay algo nuevo", dice la propuesta. Sin número: a
   esta escala un número no se lee, y lo que el cliente necesita saber es si hay
   algo, no cuánto. */
html[data-modo="app"] .a51-tab-punto {
    position: absolute;
    top: -3px;
    right: -6px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #ff3366;
    box-shadow: 0 0 0 2px rgba(6, 8, 6, 0.92);
}

html[data-modo="app"] .a51-tab-punto[hidden] {
    display: none;
}

/* ── LAS SECCIONES DEL BÚNKER ────────────────────────────────────────────────
   Las esconde nav.js al cambiar de pestaña. `!important` porque varias secciones
   del búnker traen su propio `display` en un atributo style inline. */
html[data-modo="app"] .a51-oculta {
    display: none !important;
}

/* ── LO QUE SE VA EN MODO APP ────────────────────────────────────────────────
   Con la barra abajo, el menú hamburguesa de arriba es un SEGUNDO menú que dice
   casi lo mismo — y dos menús para lo mismo es la marca registrada de una web
   disfrazada de app. En el navegador queda intacto.

   La quicknav de chips del búnker también: sus tres accesos (Taller, Solicitudes,
   Soporte) ahora son pestañas. Sus CONTADORES se siguen usando —nav.js los lee de
   ahí— así que se esconde con visibility y position, no con display:none: si se
   sacara del layout, el JS del búnker no podría escribir en ella. */
html[data-modo="app"] .hamburger {
    display: none !important;
}

/* ⚠️ .nav-links NO SE ESCONDE, Y ESTE ES EL RENGLON MAS IMPORTANTE DEL ARCHIVO.
   ---------------------------------------------------------------------------
   La primera version hacia `display: none` sobre .nav-links entera, junto con el
   hamburguesa. Adentro de esa lista viven DOS cosas que no estan en la barra de
   abajo y que no tienen otro camino:

     - EL CARRITO (#open-cart-btn), en el home, el catalogo y la ficha de producto.
       Esconderlo en una tienda significa que el cliente NO PUEDE COMPRAR. Es el
       peor error posible de toda esta capa, y estuvo puesto varias horas.
     - EL LOGOUT (#btn-logout-nav), en el bunker. Sin el, el cliente no puede
       cerrar sesion — y en un celular prestado eso deja sus credenciales de PSN a
       mano del que lo agarre.

   Lo detecto Uriel el 22/08 con una pregunta de una linea: "el carrito en la app
   donde quedo?".

   Lo que se esconde ahora es SOLO lo que la barra de abajo duplica de verdad. */
html[data-modo="app"] .nav-links {
    display: flex !important;
    align-items: center;
    gap: 6px;
    /* En el celular la lista es un menu desplegable que se abre con el hamburguesa.
       Sin hamburguesa hay que aplanarla, o queda posicionada fuera de la pantalla. */
    position: static !important;
    flex-direction: row !important;
    width: auto !important;
    height: auto !important;
    padding: 0 !important;
    margin: 0 !important;
    background: none !important;
    transform: none !important;
    box-shadow: none !important;
    backdrop-filter: none !important;
}

html[data-modo="app"] .nav-links li {
    list-style: none;
    margin: 0;
}

/* El unico que se esconde: el link a "Catalogo" del bunker, porque ES una pestaña
   de la barra de abajo. El carrito y el logout se quedan. */
html[data-modo="app"] .nav-links li:has(> a[href="catalogo.html"]) {
    display: none;
}

/* ── "AREA CLIENTES" TAMPOCO VA EN LA APP ────────────────────────────────────
   Pedido de Uriel el 22/08: la barra de abajo ya tiene "Entrar", y dos botones
   para lo mismo en la misma pantalla es ruido.

   Se comprobo antes de esconderlo —que es la leccion del carrito— que ningun JS
   lo toca: es un <a href="login.html"> FIJO. No cambia cuando el cliente entra a
   su cuenta, asi que con sesion iniciada seguia diciendo "Area Clientes" y
   llevando al login. La barra de abajo lo cubre en los dos estados: "Entrar" sin
   sesion, "Mis juegos" con sesion.

   En la web queda igual: ahi no hay barra abajo y es el unico acceso a la cuenta. */
html[data-modo="app"] .nav-clientes-btn {
    display: none !important;
}

/* En la barra de arriba, ya sin el texto: solo los iconos, que es lo que entra al
   lado del logo y el buscador. */
html[data-modo="app"] #open-cart-btn,
html[data-modo="app"] #btn-logout-nav {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    font-size: 0;          /* se va el texto "Carrito" / "ABANDONAR BASE" */
}

html[data-modo="app"] #open-cart-btn i,
html[data-modo="app"] #btn-logout-nav i {
    font-size: 1.15rem;    /* el icono vuelve a su tamaño */
}

/* El contador del carrito tiene que seguir leyendose. */
html[data-modo="app"] #cart-badge {
    font-size: 0.7rem !important;
}

html[data-modo="app"] .bunker-quicknav {
    position: absolute !important;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    pointer-events: none;
}

/* Con las pestañas abajo, la nav de arriba solo necesita el logo y el buscador. */
html[data-modo="app"] .glass-nav {
    justify-content: space-between;
}

@media (prefers-reduced-motion: reduce) {
    html[data-modo="app"] .a51-tab,
    html[data-modo="app"] .a51-tab-ico {
        transition: none;
    }
}


/* ============================================================================
   PULIDO — Sprints 6 y 7
   ============================================================================ */

/* ── EL BANNER DE ESTADO, COMPACTO EN LA APP ─────────────────────────────────
   Encontrado en las capturas que mandó Uriel el 22/08: el banner verde de
   "Servicio funcionando con normalidad" se comía una franja grande arriba del
   celular, y en modo app compite con la barra de estado del sistema.

   En la web queda igual: ahí hay lugar de sobra. En la app se achica el texto y
   el padding — la mitad del alto, la misma información. */
html[data-modo="app"] #status-banner,
html[data-modo="app"] .status-banner {
    padding-top: 6px !important;
    padding-bottom: 6px !important;
    font-size: 0.78rem !important;
    line-height: 1.3 !important;
}

/* ── SKELETONS ───────────────────────────────────────────────────────────────
   El brillo que recorre un bloque gris mientras cargan los datos. Es mejor que un
   spinner por un motivo concreto: un spinner dice "esperá" y un skeleton dice
   "va a haber algo acá y va a tener esta forma", así que la pantalla no salta
   cuando llegan los datos. */
/* ⚠️ SIN `html[data-modo="app"]` DELANTE, Y ESO ES EL CAMBIO.
   Estos estilos existian desde el Sprint 6 —anotados ahi como "listos para
   usar"— y NUNCA SE USARON: un grep de `a51-skeleton` sobre js y html daba cero.
   Ademas colgaban de modo app, asi que aunque alguien los hubiera usado, en el
   navegador no habrian hecho nada.

   La espera es igual de larga en la web que en la app, y quien entra desde una
   compu tambien merece ver que algo esta por aparecer en vez de un spinner. */
.a51-skeleton {
    position: relative;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.04);
    border-radius: 12px;
    min-height: 80px;
}

.a51-skeleton::after {
    content: '';
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgba(57, 255, 20, 0.07), transparent);
    animation: a51-brillo 1.4s infinite;
}

@keyframes a51-brillo {
    100% { transform: translateX(100%); }
}

/* ── EL FOCO SE TIENE QUE VER ────────────────────────────────────────────────
   Accesibilidad del Sprint 7. Muchos sitios matan el outline del foco porque "se
   ve feo", y con eso dejan afuera a cualquiera que navegue con teclado. Acá se
   reemplaza por uno que combina con la estética; no se saca.

   `:focus-visible` y no `:focus`, para que el anillo aparezca al tabular pero no
   al tocar con el dedo. */
html[data-modo="app"] a:focus-visible,
html[data-modo="app"] button:focus-visible,
html[data-modo="app"] .a51-tab:focus-visible {
    outline: 2px solid var(--neon-green, #39ff14);
    outline-offset: 3px;
    border-radius: 6px;
}

/* ── QUE UN DOBLE TOQUE NO DISPARE DOS VECES ─────────────────────────────────
   La clase la pone y la saca app/pulido.js. */
html[data-modo="app"] .a51-ocupado {
    opacity: 0.55;
    pointer-events: none;
    cursor: default;
}

/* ── EL AVISO DE "SE CORTÓ LA CONEXIÓN" ──────────────────────────────────────
   Va sobre la barra de pestañas, nunca debajo: si quedara tapado por la barra, el
   cliente vería medio cartel asomando y sería peor que no mostrarlo. */
html[data-modo="app"] .a51-aviso-red {
    position: fixed;
    left: 12px;
    right: 12px;
    bottom: calc(74px + env(safe-area-inset-bottom, 0px));
    z-index: 9500;
    padding: 12px 16px;
    border-radius: 12px;
    text-align: center;
    background: rgba(255, 51, 102, 0.94);
    color: #fff;
    font-family: 'Outfit', system-ui, sans-serif;
    font-size: 0.85rem;
    font-weight: 700;
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5);
    animation: a51-aviso-entra 0.3s cubic-bezier(0.2, 0.9, 0.3, 1);
}

@keyframes a51-aviso-entra {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    /* El esqueleto ya NO cuelga de modo app (ver arriba), asi que esta regla
       tampoco puede: quien pidio menos animacion en el sistema operativo veia el
       brillo igual en el navegador. El aviso de red si es solo de la app. */
    .a51-skeleton::after,
    html[data-modo="app"] .a51-aviso-red {
        animation: none;
    }
}


/* ── LA BARRA SE ADAPTA A 4 O A 5 PESTAÑAS ───────────────────────────────────
   Con sesión son cinco: entra el carrito. `grid-auto-flow: column` reparte el
   ancho solo, sin tener que declarar el número. La versión anterior tenía
   `repeat(4, 1fr)` fijo y la quinta se habría salido de la pantalla. */
html[data-modo="app"] .a51-nav {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
}

/* Con cinco pestañas el texto necesita entrar en menos ancho. */
html[data-modo="app"] .a51-nav:has(.a51-tab:nth-child(5)) .a51-tab-txt {
    font-size: 0.6rem;
    letter-spacing: 0;
}

/* ── EL CARRITO VIVE ABAJO, SIEMPRE ──────────────────────────────────────────
   Pedido de Uriel: que la barra de arriba quede con el logo, el nombre y el
   buscador, nada más.

   La primera versión de esta regla solo aplicaba `.a51-con-sesion`, porque sin
   sesión las cuatro pestañas de abajo estaban ocupadas y el visitante tenía que
   poder comprar igual. Al sacar *Ofertas* —que mostraba lo mismo que Catálogo—
   quedó lugar, el carrito bajó también para el visitante, y este selector pudo
   dejar de depender de la sesión.

   Vale la pena decirlo fuerte porque es el error más caro que tuvo esta capa:
   esconder el carrito sin darle otro lugar significa QUE EL CLIENTE NO PUEDE
   COMPRAR. Estuvo así varias horas el 22/08. Antes de tocar esta regla,
   verificar que la barra de abajo tenga su pestaña de carrito. */
html[data-modo="app"] #open-cart-btn {
    display: none !important;
}

/* ── EL CONTADOR DEL CARRITO: NÚMERO, NO PUNTITO ─────────────────────────────
   En las otras pestañas alcanza con "hay algo nuevo". En el carrito, cuántas
   cosas hay adentro es justamente lo que el cliente quiere saber antes de
   tocarlo. */
html[data-modo="app"] .a51-tab-punto-num {
    width: auto;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    top: -6px;
    right: -10px;
    border-radius: 8px;
    font-size: 0.62rem;
    font-weight: 800;
    line-height: 16px;
    text-align: center;
    color: #fff;
    font-family: 'Outfit', system-ui, sans-serif;
}

/* ── "MI BÚNKER" TAPADO POR LA BARRA DE ARRIBA ───────────────────────────────
   Reportado por Uriel el 22/08. El .bunker-header trae `padding-top: 120px`
   pensado para el escritorio, donde la nav es más baja. En el celular, con la nav
   fija MÁS el banner verde de estado encima, esos 120 px no alcanzan y el título
   queda por debajo.

   Se resuelve con la altura real de la nav —que el JS del sitio ya mide y escribe
   en --nav-h (ver mi-bunker.html)— más el aire del banner. Así sigue funcionando
   si la nav cambia de alto. */
html[data-modo="app"] .bunker-header {
    padding-top: calc(var(--nav-h, 72px) + 76px) !important;
}


/* ── LOS EASTER EGGS NO VAN EN LA APP ────────────────────────────────────────
   Pedido de Uriel el 22/08: "esos marcianos que aparecen cada unos segundos en la
   parte inferior y el interceptando senal, quitalos, porque en la app no quedan
   bien, en la web si".

   Tiene razon, y el motivo es el espacio. En una pantalla de escritorio el
   marciano que asoma y el radar de transmisiones son un guino que sobra lugar.
   En un celular de 6 pulgadas, con la barra de pestañas abajo, compiten por los
   mismos pixeles que el contenido — y el radar queda justo encima de la barra.

   EN LA WEB QUEDAN INTACTOS: son parte de la identidad del sitio. */
html[data-modo="app"] #alien-peeker,
html[data-modo="app"] #radio-interceptor {
    display: none !important;
}


/* ── EL CANDADO DE HUELLA ────────────────────────────────────────────────────
   La pantalla que tapa el búnker hasta que el cliente apoya el dedo (app/huella.js).

   NO cuelga de html[data-modo="app"], igual que la caja de avisos: el candado tiene
   que funcionar también en el navegador del celular, que es donde muchos entran sin
   haber instalado nada.

   position: fixed + inset: 0 sobre <html>, y no un display:none en el contenido: hay
   que tapar TODO el documento, incluida cualquier sección que se pinte después de que
   el overlay ya esté puesto. */
#a51-huella-overlay {
    position: fixed;
    inset: 0;
    z-index: 2147483000;          /* por encima de los modales del búnker */
    background: #05060a;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    /* Sin animación de entrada a propósito: cualquier fundido es un instante en el
       que se ve lo que hay abajo, que es justo lo que esto viene a esconder. */
}

#a51-huella-overlay .a51-huella-caja {
    max-width: 340px;
    width: 100%;
    text-align: center;
}

#a51-huella-overlay .fa-fingerprint {
    font-size: 3.4rem;
    color: var(--neon-green, #39FF14);
    margin-bottom: 18px;
    filter: drop-shadow(0 0 18px rgba(57, 255, 20, 0.45));
}

#a51-huella-overlay h2 {
    color: #fff;
    font-size: 1.15rem;
    letter-spacing: 2px;
    margin: 0 0 10px;
}

#a51-huella-overlay p {
    color: #9aa;
    font-size: 0.92rem;
    line-height: 1.5;
    margin: 0 0 22px;
}

#a51-huella-overlay .neon-btn {
    width: 100%;
    margin: 0 0 14px;
    padding: 13px;
}

#a51-huella-overlay #a51-huella-salir {
    background: none;
    border: none;
    color: #667;
    font-family: inherit;
    font-size: 0.85rem;
    text-decoration: underline;
    cursor: pointer;
    padding: 6px;
}


/* ── LO QUE LA BARRA DE ABAJO YA RESUELVE ────────────────────────────────────
   El link "Catálogo" del encabezado viene del sitio original, de antes de que
   existiera la barra de pestañas. En la web sigue siendo la única forma de volver
   al catálogo desde el búnker, así que ahí se queda.

   En la app no: la barra de abajo tiene su propia pestaña Catálogo, y dos puertas
   a lo mismo a diez centímetros una de otra es ruido — encima en la parte de la
   pantalla que menos lugar tiene. Pedido de Uriel el 23/08.

   Se esconde por CSS y no borrando el <li>, porque el mismo HTML sirve a los dos
   modos: es el invariante I-5 (el sitio funciona completo sin nada de la app). */
html[data-modo="app"] .nav-links .nav-solo-web {
    display: none;
}

/* ============================================================================
   QUÉ AVISOS QUIERO RECIBIR — el panel de preferencias
   ----------------------------------------------------------------------------
   Se despliega debajo de la caja de avisos cuando el cliente ya los activó. Vive
   acá y no en style.css porque es parte de la capa de app: el invariante I-5 dice
   que todo esto se saca borrando archivos, y este panel también.

   Las seis banderas existían en la base desde el Sprint 3 y `enviar-push` las
   respetaba — pero no había NINGUNA pantalla para tocarlas. Con 23 avisos, al que
   le sobre uno apaga los 23, y ahí se pierde el que importa.
   ============================================================================ */

.a51-prefs {
    max-width: 1000px;
    margin: 10px auto 0;
    padding: 6px 20px 14px;
    border: 1px solid rgba(0, 242, 234, 0.35);
    border-radius: 16px;
    background: rgba(0, 242, 234, 0.03);
}

.a51-prefs[hidden] { display: none; }

.a51-prefs-intro {
    margin: 12px 0 6px;
    color: #9ad9d6;
    font-size: 0.82rem;
    line-height: 1.5;
}

/* 48 px de alto y el label entero clickeable: en un celular el objetivo tiene que
   ser la fila, no el cuadradito de 16 px. */
.a51-pref {
    display: flex;
    align-items: center;
    gap: 14px;
    min-height: 48px;
    padding: 6px 0;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
    cursor: pointer;
}
.a51-pref:first-of-type { border-top: none; }

.a51-pref-txt { flex: 1 1 auto; min-width: 0; }

.a51-pref-txt strong {
    display: block;
    color: #fff;
    font-size: 0.9rem;
    font-weight: 600;
}

.a51-pref-txt span {
    display: block;
    color: #8a8a8a;
    font-size: 0.78rem;
    line-height: 1.4;
    margin-top: 2px;
}

/* El interruptor. Es un <input type="checkbox"> de verdad debajo, para que el
   teclado y los lectores de pantalla lo encuentren solos. */
.a51-pref input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.a51-pref-sw {
    flex: 0 0 auto;
    position: relative;
    width: 48px;
    height: 28px;
    border-radius: 999px;
    background: #2a2a2a;
    border: 1px solid #444;
    transition: background 0.18s ease, border-color 0.18s ease;
}

.a51-pref-sw::after {
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #888;
    transition: transform 0.18s ease, background 0.18s ease;
}

.a51-pref input:checked + .a51-pref-sw {
    background: rgba(57, 255, 20, 0.18);
    border-color: #39FF14;
}
.a51-pref input:checked + .a51-pref-sw::after {
    transform: translateX(20px);
    background: #39FF14;
}

/* Foco visible: se navega con teclado en escritorio. */
.a51-pref input:focus-visible + .a51-pref-sw {
    outline: 2px solid #00F2EA;
    outline-offset: 2px;
}

/* Mientras se guarda. No se bloquea el toggle —el cambio ya se ve— pero se avisa
   que hay algo en vuelo. */
.a51-prefs.a51-prefs-guardando { opacity: 0.7; }

.a51-prefs-estado {
    margin: 10px 0 0;
    min-height: 18px;
    font-size: 0.78rem;
    color: #39FF14;
}
.a51-prefs-estado.a51-prefs-error { color: #ff6b81; }

@media (max-width: 640px) {
    .a51-prefs { border-radius: 14px; padding: 6px 14px 12px; }
}
/* ============================================================================
   EL LUGAR FIJO PARA INSTALAR LA APP — app/instalar-boton.js
   ----------------------------------------------------------------------------
   Dos puntos de entrada, un mismo camino: la tarjeta de la pestaña Ayuda del
   búnker y el renglón del pie de todas las páginas. Ver el encabezado largo de
   `app/instalar-boton.js` para el porqué de que exista.

   ⚠️ ESTA REGLA ES LA QUE APAGA TODO CON LA APP INSTALADA. No hay ni una línea
   de JS decidiendo si se ve: cuelga de `data-modo`, que shell.js resuelve una
   sola vez para las tres plataformas. Es el mismo mecanismo que el resto del
   modo app, y es lo que hace que la web de escritorio no se entere de nada.
   ============================================================================ */

html[data-modo="app"] .a51-instalar-zona {
    display: none !important;
}

/* La tarjeta del búnker reusa `.a51-avisos` entero: mismo borde cian, mismo
   ícono, mismos botones de 44px. No hace falta nada más que el margen, porque
   acá arriba no hay una caja de avisos de la que separarse. */
#a51-instalar-section {
    margin-top: 0;
    margin-bottom: 22px;
}

/* ── EL RENGLÓN DEL PIE ──────────────────────────────────────────────────────
   Es un <button>, no un <a>: no navega a ningún lado, abre un diálogo. Un <a
   href="#"> ahí ensucia el historial y le miente al lector de pantalla. Pero
   tiene que LEERSE como los demás enlaces del pie, así que se le saca todo lo
   que el navegador le pone por ser un botón. */
button.footer-link {
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font-family: inherit;
    font-size: 0.95rem;
    text-align: center;
    cursor: pointer;
    /* El pie es una columna flex: sin un align-self propio el botón se estira a
       todo el ancho y el área clickeable ocupa media pantalla.
       ⚠️ Pero `flex-start` lo pegaba a la izquierda mientras los <a> vecinos
       —que sí se estiran— quedaban centrados, así que este renglón se veía
       corrido respecto de los otros cinco del pie. `center` resuelve las dos
       cosas: lo centra Y lo deja del ancho de su texto. */
    align-self: center;
}

/* ── EL MODAL DE INSTRUCCIONES ───────────────────────────────────────────────
   Para iPhone —donde Apple no deja instalar por código— y para el navegador que
   todavía no ofreció el diálogo nativo. El botón nunca se queda sin hacer nada. */
.a51-inst-modal {
    position: fixed;
    inset: 0;
    z-index: 100002;               /* arriba de los modales del búnker (100000-100001) */
    display: grid;
    place-items: center;
    padding: 20px;
    background: rgba(0, 0, 0, 0.78);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    animation: a51-inst-fade 0.2s ease;
}
.a51-inst-modal[hidden] { display: none; }

@keyframes a51-inst-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.a51-inst-caja {
    position: relative;
    width: min(460px, 100%);
    /* Tope de alto y scroll adentro: en un iPhone chico, en horizontal, los tres
       pasos no entran y sin esto el botón de cerrar queda fuera de la pantalla. */
    max-height: calc(100vh - 40px);
    max-height: calc(100dvh - 40px);
    overflow-y: auto;
    padding: 26px 22px 22px;
    background: #0b0f14;
    border: 1px solid #00F2EA;
    border-radius: 18px;
    box-shadow: 0 0 40px rgba(0, 242, 234, 0.18);
    text-align: center;
}

.a51-inst-x {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 40px;
    height: 40px;
    background: none;
    border: none;
    color: #888;
    font-size: 1rem;
    cursor: pointer;
    border-radius: 10px;
}
.a51-inst-x:hover { color: #fff; background: rgba(255, 255, 255, 0.06); }

.a51-inst-ico {
    display: grid;
    place-items: center;
    width: 56px;
    height: 56px;
    margin: 0 auto 14px;
    border-radius: 16px;
    background: rgba(0, 242, 234, 0.12);
    color: #00F2EA;
    font-size: 1.5rem;
}

.a51-inst-caja h3 {
    margin: 0 0 10px;
    color: #00F2EA;
    font-size: 1.15rem;
    line-height: 1.3;
}

.a51-inst-intro {
    margin: 0 0 16px;
    color: #cfd6dd;
    font-size: 0.92rem;
    line-height: 1.5;
}

/* Los pasos van numerados y alineados a la izquierda aunque la caja esté
   centrada: una lista de pasos centrada se lee mucho peor. */
.a51-inst-pasos {
    margin: 0;
    padding: 0 0 0 22px;
    text-align: left;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.a51-inst-pasos li {
    color: #ddd;
    font-size: 0.92rem;
    line-height: 1.55;
}
.a51-inst-pasos b { color: #fff; }

.a51-inst-pie {
    margin: 16px 0 0;
    padding-top: 14px;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    color: #8b949e;
    font-size: 0.82rem;
    line-height: 1.45;
}

@media (max-width: 480px) {
    .a51-inst-caja { padding: 24px 16px 18px; border-radius: 14px; }
    .a51-inst-caja h3 { font-size: 1.05rem; }
}
