/* ============================================================
   PALETA PROFESIONAL + RESET
   ============================================================ */
*, *::before, *::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

:root {
    /* Marca: verde de la guía, accesible */
    --primary: #27AE60;
    --primary-dark: #1A7A44;

    /* ============================================================
       EL CRISTAL, EN UN SOLO SITIO (07/10/2026)
       ============================================================
       Lo pidio el dueno: «me gusta la idea de formulario cristal aplicado a todos los
       contenedores de la aplicacion, pero iniciamos con el formulario y luego lo escalamos».
       Asi que el valor vive AQUI y lo comparten el formulario, la vitrina de las diapositivas y
       el contenedor del logo de Avero: cuando se escale al resto de contenedores, se cambia en
       un sitio y cambia en todos.

       EL 62 % NO ES UN CAPRICHO, y el verde de los precios tampoco:
         · Con el cristal al 25 % el nombre del producto mide 13,9:1 de contraste y el precio en
           bolivares 5,8:1 — los dos por encima del liston 4.5 que pide la norma.
         · El que fallaba era el VERDE del precio: #1E8E4E se quedaba en 3,66:1, y no llegaba ni
           sobre blanco casi puro. Con #1A7A44 sube a 4,71:1.
       Esta todo medido con `herramientas`-style: `medir-contraste-cristal.mjs`, que saca los
       pixeles de la pantalla ya pintada. Los numeros estan en docs/ESTADO.md, sesion 19. */
    --cristal: rgba(255, 255, 255, .62);
    --cristal-borde: rgba(255, 255, 255, .75);
    --cristal-desenfoque: blur(18px) saturate(1.4);

    /* ============================================================
       LA SOLUCIÓN SALOMÓNICA DEL CRISTAL (07/10/2026)
       ============================================================
       El dueño paró el trabajo y dijo las dos cosas exactas: «las pantallas transparentes entorpecen
       la lectura del carrito» y «la transparencia del menú lateral y el modal totalizar hace que se
       vean opacos, como sin vida». Los dos síntomas eran **el mismo error de planteamiento mío**:

         · Hice TRANSPARENTE la superficie donde se TRABAJA (el carrito, las listas) -> el texto
           quedó sobre el fondo y se lee mal.
         · Y dejé TRANSLÚCIDO lo que FLOTA encima (el modal, el menú) -> sobre un degradado suave el
           desenfoque no enseña nada, y queda una niebla plana. Sin vida.

       Es exactamente al revés. El reparto bueno es este, y son tres valores, no uno:

         · **LIENZO**: el fondo de la casa **detrás de un velo blanco fuerte**. Se ve el tono verde
           —la app sigue viva— y el texto oscuro se lee sobrado. Es la regla que el proyecto ya
           tenía escrita: «todo fondo va detrás de un velo, nunca texto directo sobre una foto».
         · **TARJETAS**: cristal MEDIO. Se despegan del lienzo sin volver a taparlo.
         · **FLOTANTES** (modal, menú lateral, calculadora): cristal CASI OPACO + desenfoque +
           sombra fuerte. Se abren encima de contenido y tienen que verse SÓLIDOS: son el primer
           plano, y un primer plano translúcido se ve muerto.

       Un solo valor para las tres cosas era el error: cada capa está a una distancia distinta del
       ojo, así que no puede llevar la misma densidad. */
    --velo-lienzo: rgba(255, 255, 255, .42);
    --cristal-tarjeta: rgba(255, 255, 255, .82);
    --cristal-flotante: rgba(255, 255, 255, .95);
    --primary-light: #D9F5E5;
    --primary-50: #EBFAF1;
    /* Carbón: estructura (tu sello) */
    --secondary: #27AE60;
    --secondary-light: #2C3A4B;
    --secondary-50: #F3F4F6;
    /* Amarillo: acento + Premium */
    --totalizar: #F1C40F;
    --totalizar-hover: #23A023;
    --accent-warn: #E67E22;
    --accent-error: #E74C3C;
    --accent-success: #27AE60;
    --accent-info: #3498DB;
    /* Neutros frescos */
    --bg-main: #F6F8F7;
    /* El gris del fondo de la app. Estaba ESCRITO A MANO en `body`, y ahora tambien lo
       usa la pantalla de acceso: el mismo color en dos sitios a mano se separa solo. */
    --bg-app: #EEF0ED;
    --bg-card: #FFFFFF;
    --bg-hover: #EEF3F0;
    --bg-elevated: #FFFFFF;
    --text-primary: #1C2422;
    --text-secondary: #52605A;
    --text-muted: #98A6A0;
    --text-inverse: #FFFFFF;
    --border: #E2E8E5;
    --border-strong: #CBD5D0;
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
    --shadow: 0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06);
    --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -1px rgba(0,0,0,0.06);
    --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05);
    --radius-sm: 4px;
    --radius: 6px;
    --radius-md: 8px;
    --radius-lg: 12px;
    --transition-fast: 120ms ease;
    --transition: 200ms ease;
    --text-xs: 0.75rem;
    --text-sm: 0.875rem;
    --text-base: 1rem;
    --text-lg: 1.125rem;
    --text-xl: 1.25rem;
    --text-2xl: 1.5rem;
}

html, body {
    width: 100%;
    height: 100%;
    min-height: 100%;
}

body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: var(--text-base);
    line-height: 1.5;
    color: var(--text-primary);
    /* ============================================================
       EL FONDO DE LA CASA, EN TODAS LAS PANTALLAS (07/10/2026)
       ============================================================
       La imagen del dueño (`fondo/fondo-app.webp`), y **aquí y no en cada pantalla**: el `body`
       es lo que se ve detrás de todo, así que una sola regla cubre la app entera.

       Y resuelve de paso LA PANTALLA DE TRANSICIÓN, que era el problema que él reportó: mientras
       la app arranca, `#app` está OCULTA (`html.arrancando`, más abajo) y lo único que se ve es
       este fondo. Antes era un gris plano —«blanco puro», dicho por él— y ahora es su imagen.

       EL ARCHIVO PESA 42 kB, y eso es una decisión medida, no una casualidad: el original son
       1.625 kB (3334x5000). Reducido a 1440 de ancho y en WebP sigue viéndose igual de suave y
       cuesta **38 veces menos**, que importa porque viaja dentro del APK.

       `cover` y anclado ABAJO: la imagen tiene el blanco arriba y las ondas verdes abajo, así que
       anclándola al pie las ondas quedan siempre en la parte baja de la pantalla, que es donde
       están bien a cualquier medida. */
    /* EL LIENZO: su fondo, DETRÁS DE UN VELO (07/10/2026, solución salomónica).
       El velo es lo que permite las dos cosas a la vez: el tono verde sigue viéndose —la app no
       queda gris— y el texto oscuro del carrito y de las listas se lee sobrado encima.
       Es la regla que este proyecto ya tenía escrita: «todo fondo va detrás de un velo, nunca texto
       directo sobre una foto». El velo va PRIMERO, así que queda por encima de la imagen. */
    background:
        linear-gradient(var(--velo-lienzo), var(--velo-lienzo)),
        #FFFFFF url('fondo/fondo-app.webp') center bottom / cover no-repeat;
    overflow: hidden;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* LOS EJEMPLOS DE LOS CAMPOS, EN GRIS (detalle de estetica del dueno, 05/10/2026).
 *
 * LO QUE PASABA: **no habia ninguna regla de `::placeholder` en todo el archivo**, asi que el
 * ejemplo («Tu usuario o email», «Repite la contrasena»…) heredaba el color del texto del campo —
 * `--text-primary`, #1C2422— y se veia **igual que lo que el usuario escribe**. El dueno lo describio
 * exacto: «parecen texto transcrito».
 *
 * EL COLOR: `--text-muted` (#98A6A0), que YA EXISTE en la paleta de la app para esto. Se eligio asi
 * por dos motivos:
 *   - El dueno pidio «#F5F5F5 o algo mas oscuro». **#F5F5F5 es casi blanco**: sobre un campo blanco
 *     (#FFFFFF) el ejemplo quedaria INVISIBLE (contraste 1,05:1). Lo que pide —que no se vea negro—
 *     se consigue con el gris de la casa, sin inventar un color nuevo.
 *   - `--text-muted` da 2,5:1 sobre blanco: se lee, y se distingue de un vistazo del texto escrito
 *     (#1C2422, 14:1). Es el registro que usan los formularios para esto.
 *
 * `opacity: 1` es necesario: Firefox baja la opacidad del ejemplo por su cuenta, y sin esto el mismo
 * color se veria distinto en cada navegador. */
input::placeholder,
textarea::placeholder {
    color: var(--text-muted);
    opacity: 1;
}

#app {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100dvh;
    min-height: 100dvh;
    max-width: 100%;
    margin: 0 auto;
    overflow: hidden;
}

/* ============================================================
   ICONOS SVG BASE
   ============================================================ */
.icon {
    width: 1.25rem;
    height: 1.25rem;
    flex-shrink: 0;
    stroke-width: 1.75;
}
.icon-sm { width: 1rem; height: 1rem; stroke-width: 2; }
.icon-lg { width: 1.5rem; height: 1.5rem; stroke-width: 1.5; }
.icon-xl { width: 1.75rem; height: 1.75rem; stroke-width: 1.5; }

/* ============================================================
   HEADER
   ============================================================ */
header {
    flex: 0 0 auto;
    width: 100%;
    background: var(--secondary);
    color: var(--text-inverse);
    padding: 10px 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    box-shadow: var(--shadow-md);
    z-index: 10;
}

.header-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}
.header-row-1 { justify-content: space-between; }
.header-row-2 { justify-content: flex-start; }

.btn-header {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border: 1px solid rgba(255,255,255,0.2);
    border-radius: var(--radius-md);
    background: rgba(255,255,255,0.08);
    color: var(--text-inverse);
    font-size: var(--text-sm);
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
    transition: background var(--transition-fast);
}
.btn-header:hover { background: rgba(255,255,255,0.15); }

.nav-menu {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    width: 100%;
    gap: 6px;
}

.nav-select {
    min-width: 240px;
    max-width: 240px;
    padding: 8px 12px;
    border: 1px solid rgba(255,255,255,0.35);
    border-radius: var(--radius-md);
    background: rgba(0,0,0,0.25);
    color: #FFFFFF;
    font-size: var(--text-sm);
    font-weight: 600;
    cursor: pointer;
    transition: all var(--transition-fast);
}
.nav-select:focus {
    outline: 2px solid #FFFFFF;
    outline-offset: 2px;
    background: rgba(0,0,0,0.35);
}
.nav-select option {
    color: #242A24;
    background: #FFFFFF;
    font-weight: 400;
}
.nav-select:disabled {
    color: rgba(255,255,255,0.55);
    background: rgba(0,0,0,0.12);
    border-color: rgba(255,255,255,0.15);
    cursor: not-allowed;
}

/* ============================================================
   TASA Y CARRITO HEADER
   ============================================================ */
.tasa-container {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border-radius: var(--radius-md);
    background: rgba(0,0,0,0.3);
    border: 1px solid rgba(255,255,255,0.15);
    font-size: var(--text-sm);
    font-weight: 600;
}
.tasa-container input {
    width: 60px;
    padding: 2px 4px;
    border: none;
    border-radius: var(--radius-sm);
    background: rgba(255,255,255,0.15);
    color: var(--text-inverse);
    font-size: var(--text-xs);
    font-weight: 600;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.tasa-container #tasa-display {
    color: #FCD34D;
    font-size: var(--text-sm);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.tasa-fuente {
    color: rgba(255,255,255,0.5);
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

#cart-summary {
    display: flex;
    gap: 12px;
    padding: 6px 12px;
    border-radius: var(--radius-md);
    background: rgba(0,0,0,0.3);
    border: 1px solid rgba(255,255,255,0.15);
    font-size: var(--text-sm);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
#cart-summary span { color: #FCD34D; }

/* ============================================================
   INDICADORES DE SINCRONIZACIÓN
   ============================================================ */
.sync-status-container {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border-radius: 999px;
    background: rgba(0,0,0,0.25);
    font-size: var(--text-xs);
}
#sync-status { font-size: 0.875rem; line-height: 1; }
#sync-badge {
    display: none;
    background: var(--accent-error);
    color: var(--text-inverse);
    border-radius: 999px;
    padding: 0 6px;
    font-size: 0.65rem;
    font-weight: 600;
    min-width: 18px;
    height: 18px;
    line-height: 18px;
    text-align: center;
    margin-left: 4px;
    font-variant-numeric: tabular-nums;
}
#network-status {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.65rem;
    font-weight: 500;
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(255,255,255,0.1);
    color: var(--text-inverse);
}
#sync-toast {
    display: none;
    position: fixed;
    bottom: 80px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--secondary);
    color: var(--text-inverse);
    padding: 12px 20px;
    border-radius: var(--radius-lg);
    font-size: var(--text-sm);
    font-weight: 500;
    z-index: 9999;
    border: 1px solid rgba(255,255,255,0.1);
    max-width: 90%;
    text-align: center;
    animation: toastIn 0.3s ease;
    box-shadow: var(--shadow-lg);
}
@keyframes toastIn {
    from { opacity: 0; transform: translateX(-50%) translateY(10px); }
    to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

/* ============================================================
   ARTÍCULOS
   ============================================================ */
.art-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 12px;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    min-width: 0;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.art-card:hover {
    border-color: var(--primary);
    box-shadow: var(--shadow);
}

/* Agrupación de presentaciones (artículo genérico con distintas
   presentaciones: cada presentación es un artículo propio). */
.art-group {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
    max-width: 100%;
    width: 100%;
    background: var(--bg-hover);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 10px;
    box-sizing: border-box;
}
.art-group-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-weight: 700;
    font-size: var(--text-sm);
    color: var(--text-primary);
    padding: 0 2px 4px;
}
.art-group-count {
    font-weight: 500;
    font-size: var(--text-xs);
    color: var(--text-muted);
}
.art-group-body {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
}
.art-image-container {
    width: 48px;
    height: 48px;
    flex-shrink: 0;
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--bg-hover);
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border);
}
.art-image { width: 100%; height: 100%; object-fit: cover; }
.art-image-container {
    transition: transform .22s ease;
}
@media (hover: hover) and (pointer: fine) {
    .art-card:hover .art-image-container {
        transform: scale(2);
        z-index: 3;
        box-shadow: 0 8px 20px rgba(0, 0, 0, .18);
    }
}
@media (hover: none) and (pointer: coarse) {
    .art-card:active .art-image-container {
        transform: scale(1.6);
        z-index: 3;
        box-shadow: 0 8px 20px rgba(0, 0, 0, .18);
    }
}
.art-image-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
}
.art-info { flex: 1 1 140px; min-width: 0; max-width: 100%; padding-right: 4px; }
.art-name {
    font-weight: 500;
    font-size: var(--text-sm);
    color: var(--text-primary);
    white-space: normal;
    overflow-wrap: break-word;
    word-break: break-word;
    line-height: 1.3;
    margin-bottom: 2px;
}
.art-promo {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 8px;
    border: 1px solid var(--accent, #6d28d9);
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    color: var(--accent, #6d28d9);
    background: color-mix(in srgb, var(--accent, #6d28d9) 10%, transparent);
    vertical-align: middle;
    white-space: nowrap;
}
/* Sellos de promoción (Fase B: destacado = PROMO) */
.badge-promo {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .4px;
    color: #fff;
    background: #d97706;
    vertical-align: middle;
    white-space: nowrap;
}
.art-card-promo {
    border-color: #d97706;
}
.art-card-promo:hover {
    border-color: #d97706;
    box-shadow: 0 0 0 1px #d97706;
}
.art-logo {
    display: inline-block;
    /* ESTA NO ES LA REGLA QUE PINTA EL LOGO DE LA TARJETA. Medido en el Redmi Note 8 el
       05/10/2026: la tarjeta da 24 px de alto, no los 32 (ni los 35) de aqui, porque
       `.art-meta .art-logo` (mas abajo) es MAS ESPECIFICA y gana. El +10% que pidio el dueno
       (punto 10) va ALLI, no aqui — y el primer intento se hizo aqui y no cambio nada.
       Esta se queda como respaldo para cualquier logo que no tenga su propia regla. */
    height: 32px;
    width: auto;
    max-width: 84px;
    margin: 0;
    border: none;
    background: none;
    object-fit: contain;
    vertical-align: middle;
}
/* Tarjeta: fila 1 imagen + datos, fila 2 precio, fila 3 Bs + controles */
.art-head {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    min-width: 0;
}
.art-head .art-image-container { flex: 0 0 auto; }
.art-meta {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 8px;
    overflow-wrap: anywhere;
}
.art-meta > span { min-width: 0; max-width: 100%; overflow-wrap: anywhere; }
.art-name {
    margin-bottom: 0;
    font-weight: 600;
    color: var(--text-primary);
}
.art-variante,
.art-presentacion,
.art-marca-txt {
    font-size: var(--text-sm);
    color: var(--text-secondary);
}
.art-meta .art-logo { height: 26.4px; max-width: 92.4px; }
.art-price { min-width: 0; }
.art-foot {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    min-width: 0;
}
.art-logo-slot {
    flex: 0 0 auto;
    margin-left: auto;
    display: inline-flex;
    align-items: center;
}
.art-foot .art-bs {
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
    font-size: var(--text-sm);
}
.art-foot .price-bs { font-size: inherit; }
.art-foot .art-controls { margin-left: auto; }
.art-price {
    color: var(--primary);
    font-weight: 600;
    font-size: var(--text-sm);
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
    font-variant-numeric: tabular-nums;
}
.art-price input.price-input {
    width: 74px;
    padding: 4px 7px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    text-align: center;
    font-weight: 500;
    font-size: 0.9rem;
    color: var(--primary);
    background: var(--bg-main);
    font-variant-numeric: tabular-nums;
}
.art-price input.price-input:focus {
    outline: 2px solid var(--primary);
    outline-offset: -1px;
    border-color: transparent;
}
.art-price .price-bs {
    font-size: var(--text-xs);
    color: var(--text-secondary);
    font-weight: 400;
    font-variant-numeric: tabular-nums;
}
.art-controls {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 1;
    flex-wrap: wrap;
    margin-left: auto;
    min-width: 0;
}
.art-controls input[type="number"] {
    width: 44px;
    padding: 4px 4px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    text-align: center;
    font-weight: 500;
    font-size: var(--text-xs);
    font-variant-numeric: tabular-nums;
}
.art-controls input[type="number"]:focus {
    outline: 2px solid var(--primary);
    outline-offset: -1px;
    border-color: transparent;
}
.art-controls select {
    padding: 4px 4px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: var(--text-xs);
    max-width: 52px;
    background: var(--bg-card);
}
.art-controls select:focus {
    outline: 2px solid var(--primary);
    outline-offset: -1px;
    border-color: transparent;
}

.btn-add {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--primary);
    color: var(--text-inverse);
    border: none;
    border-radius: var(--radius-sm);
    padding: 6px 10px;
    cursor: pointer;
    font-weight: 500;
    font-size: var(--text-xs);
    transition: background var(--transition-fast);
}
.btn-add:hover { background: var(--primary-dark); }
.btn-add.added { background: var(--accent-warn); }

.check-catalogo {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    margin: 0;
    accent-color: var(--primary);
    cursor: pointer;
}
.art-controls .check-catalogo { width: 20px; height: 20px; }

.btn-refresh {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--secondary-light);
    color: var(--text-inverse);
    border: none;
    border-radius: var(--radius-sm);
    padding: 6px 8px;
    cursor: pointer;
    font-weight: 500;
    transition: background var(--transition-fast);
}
.btn-refresh:hover { background: var(--secondary); }

/* ============================================================
   Tarjeta de producto V2.1 — 3 columnas: imagen | info | precio+acciones
   ============================================================ */
.art-card {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "img info side";
    align-items: center;
    gap: 10px;
}
.art-card > .art-image-container { grid-area: img; align-self: center; }
.art-card > .art-meta {
    grid-area: info;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    min-width: 0;
}
.art-info-main {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 8px;
    min-width: 0;
}
.art-info-brand {
    display: flex;
    align-items: center;
    min-width: 0;
}
.art-card > .art-side {
    grid-area: side;
    display: grid;
    grid-template-rows: auto auto auto;
    justify-items: end;
    gap: 4px;
    min-width: 0;
}
.art-side .art-price {
    justify-content: flex-end;
    flex-wrap: nowrap;
    white-space: nowrap;
}
.art-side .art-bs {
    font-size: var(--text-xs);
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
    min-height: 14px;
}
.art-side .art-controls {
    margin-left: 0;
    justify-content: flex-end;
    flex-wrap: nowrap;
}
.art-usd-sym { font-weight: 700; }
.art-unit-txt { color: var(--text-secondary); font-weight: 400; font-size: var(--text-xs); }
@media (max-width: 520px) {
    .art-card { gap: 8px; padding: 10px; }
    .art-side .art-controls input[type="number"] { width: 38px; }
}

/* ============================================================
   CARRITO
   ============================================================ */
#cart-sidebar h2 {
    font-size: var(--text-lg);
    font-weight: 600;
    margin-bottom: 8px;
    padding-bottom: 8px;
    flex-shrink: 0;
    color: var(--text-primary);
}
.cart-item {
    display: grid;
    grid-template-columns: auto 1fr auto;
    grid-template-areas: "check main right";
    column-gap: 8px;
    align-items: start;
    padding: 8px 0;
    border-bottom: 1px solid var(--border);
    font-size: var(--text-sm);
}
.cart-item-check {
    grid-area: check;
    display: flex;
    align-items: center;
    align-self: center;
    min-width: 20px;
}
.cart-item-check .check-item {
    width: 18px;
    height: 18px;
    margin: 0;
}
.cart-item-main {
    grid-area: main;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    min-width: 0;
}
.cart-item .qty {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--primary);
    margin-right: 4px;
    font-variant-numeric: tabular-nums;
}
.cart-item .und {
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--text-muted);
    margin-right: 6px;
}
.cart-item .item-name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: var(--text-sm);
    font-weight: 500;
    /* Permite que el nombre largo se divida y la continuación se alinee
       bajo la cantidad (después del checkbox), generando una sangría colgante. */
    white-space: normal;
    overflow-wrap: anywhere;
    word-break: normal;
    line-height: 1.35;
    cursor: pointer;
    color: var(--text-primary);
    transition: color var(--transition-fast);
}
.cart-item .item-name:hover { color: var(--primary); }
.cart-item-right {
    grid-area: right;
    display: flex;
    align-items: center;
    gap: 6px;
    align-self: center;
}
.cart-item .item-price {
    font-size: var(--text-sm);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.cart-item .btn-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    color: var(--text-muted);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    width: 24px;
    height: 24px;
    cursor: pointer;
    transition: all var(--transition-fast);
    flex-shrink: 0;
}
.cart-item .btn-remove:hover {
    background: #FEF2F2;
    color: var(--accent-error);
    border-color: #FECACA;
}

/* ============================================================
   TOTALES
   ============================================================ */
#cart-totals {
    border-top: 1px solid var(--border);
    padding-top: 10px;
    flex-shrink: 0;
}
.total-line-dual {
    display: flex;
    justify-content: space-between;
    padding: 4px 0;
    color: var(--text-secondary);
    font-size: var(--text-sm);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}
.total-line-dual .bs { color: var(--text-secondary); font-weight: 500; }
.grand-total-dual {
    display: flex;
    justify-content: space-between;
    font-size: var(--text-base);
    border-top: 2px solid var(--primary);
    color: var(--text-primary);
    font-weight: 600;
    padding-top: 8px;
    margin-top: 6px;
    font-variant-numeric: tabular-nums;
}
.grand-total-dual .bs { color: var(--text-primary); font-weight: 600; }

#btn-totalizar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: auto;
    padding: 10px 16px;
    margin-top: 10px;
    background: var(--totalizar);
    color: var(--text-inverse);
    border: none;
    border-radius: var(--radius-md);
    font-size: var(--text-sm);
    font-weight: 600;
    cursor: pointer;
    transition: background var(--transition-fast);
}
#btn-totalizar:hover { background: var(--totalizar-hover); }

/* ============================================================
   MODALES
   ============================================================ */
.modal {
    display: none;
    position: fixed;
    top: 0; left: 0;
    width: 100%; height: 100%;
    background: rgba(17,24,39,0.5);
    backdrop-filter: blur(4px);
    z-index: 1000;
    justify-content: center;
    align-items: center;
}
.modal.show { display: flex; }
.modal-content {
    background: var(--bg-card);
    border-radius: var(--radius-lg);
    max-width: 680px;
    width: 90%;
    max-height: 85vh;
    padding: 24px;
    overflow-y: auto;
    box-shadow: var(--shadow-lg);
    animation: modalSlide 0.25s ease;
}
@keyframes modalSlide {
    from { transform: translateY(-10px); opacity: 0; }
    to   { transform: translateY(0); opacity: 1; }
}
.close {
    float: right;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    font-size: var(--text-xl);
    font-weight: 400;
    cursor: pointer;
    color: var(--text-muted);
    border-radius: var(--radius);
    transition: all var(--transition-fast);
}
.close:hover { background: var(--bg-hover); color: var(--text-primary); }

/* ============================================================
   MODAL DE DOCUMENTO LEGAL (ronda 13, P4)
   ============================================================
   El texto legal son ~9.000 caracteres por documento: no cabe en la ventana del modal, así que
   **el cuerpo se desplaza** y el título se queda arriba. Eso es lo que hace falta para leer un
   documento largo sin perder de vista qué se está leyendo.

   `min-height: 0` en el cuerpo no es un detalle: sin él, un hijo de un contenedor `flex` no se
   encoge por debajo del alto de su contenido y **el desplazamiento no llega a activarse** — el
   modal crecería en lugar de desplazarse. Es la trampa clásica de `flex` + `overflow`. */
.legal-modal {
    display: flex;
    flex-direction: column;
    max-height: 85vh;
    max-width: 720px;
}
.legal-modal-cuerpo {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    margin-top: 8px;
    padding-right: 6px;
}
.legal-modal-cuerpo .legal-body {
    /* El documento trae su propio ancho para las páginas sueltas: aquí manda el modal. */
    max-width: none;
    margin: 0;
    padding: 0;
}
.legal-modal-cuerpo .legal-body h1 { font-size: 1.15rem; }
.legal-modal-cuerpo .legal-body h2 { font-size: 1rem; margin-top: 20px; }
.legal-modal-fecha {
    flex: 0 0 auto;
    margin: 10px 0 0;
    font-size: var(--text-xs);
    color: var(--text-muted);
    text-align: right;
}
#modal-body { margin-top: 12px; }
.modal-category {
    margin-bottom: 16px;
    border-bottom: 1px solid var(--border);
    padding-bottom: 12px;
}
.modal-category h3 {
    color: var(--text-primary);
    font-size: var(--text-sm);
    font-weight: 600;
    margin-bottom: 8px;
    display: flex;
    align-items: center;
    gap: 6px;
}
.modal-item {
    display: flex;
    justify-content: space-between;
    padding: 4px 0;
    font-size: var(--text-sm);
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}

/* ============================================================
   MODAL ESCÁNER
   ============================================================ */
.modal-scanner {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.95);
    z-index: 2000;
    justify-content: center;
    align-items: center;
    flex-direction: column;
}
.modal-scanner.show { display: flex; }
.modal-scanner-content {
    width: 100%; height: 100%;
    display: flex;
    flex-direction: column;
    background: #0F172A;
    position: relative;
}
.modal-scanner-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 14px 20px;
    background: rgba(0,0,0,0.6);
    color: var(--text-inverse);
    flex-shrink: 0;
    z-index: 10;
}
.modal-scanner-title {
    font-size: var(--text-base);
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 8px;
}
.modal-scanner-close {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: rgba(255,255,255,0.1);
    border: none;
    color: var(--text-inverse);
    font-size: var(--text-sm);
    font-weight: 500;
    cursor: pointer;
    padding: 6px 14px;
    border-radius: var(--radius-md);
    transition: background var(--transition-fast);
}
.modal-scanner-close:hover { background: rgba(255,255,255,0.2); }
/* EL VISOR DEL ESCANER Y SU AVISO (A5, 05/10/2026). El envoltorio existe para dar una referencia
   de posicion al aviso que NO sea la caja que tambien contiene la cabecera: colgando de
   `.modal-scanner-content`, los `top:20px` del aviso caian encima del titulo y del boton «Cerrar»
   (visto en el Redmi Note 8). Y el aviso no puede vivir dentro del contenedor porque el escaner lo
   vacia al arrancar. */
.scanner-visor {
    position: relative;
    flex: 1;
    display: flex;
    min-height: 0;
}
.scanner-container-modal {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #000;
    position: relative;
    overflow: hidden;
    min-height: 0;
}
.scanner-container-modal video { width: 100%; height: 100%; object-fit: cover; }
.scanner-beam {
    position: absolute;
    left: 10%; right: 10%;
    top: 50%;
    height: 2px;
    pointer-events: none;
    z-index: 3;
    background: linear-gradient(90deg, transparent, var(--primary) 20%, var(--primary) 50%, var(--primary) 80%, transparent);
    box-shadow: 0 0 12px 2px rgba(5,150,105,0.5);
    animation: scanner-beam 2.4s ease-in-out infinite;
    opacity: 0;
}
@keyframes scanner-beam {
    0%   { top: 25%;  opacity: 0; }
    10%  { opacity: 1; }
    50%  { top: 75%;  opacity: 1; }
    90%  { opacity: 1; }
    100% { top: 25%;  opacity: 0; }
}
.scanner-target-hint {
    position: absolute;
    top: 6%; left: 50%;
    transform: translateX(-50%);
    color: rgba(255,255,255,0.85);
    font-size: var(--text-sm);
    font-weight: 500;
    letter-spacing: 0.02em;
    text-align: center;
    width: 90%;
    pointer-events: none;
    z-index: 3;
    text-shadow: 0 1px 3px rgba(0,0,0,0.8);
}
.scanner-container-modal canvas {
    position: absolute;
    inset: 0;
    width: 100% !important;
    height: 100% !important;
    pointer-events: none;
}
.scanner-status-modal {
    position: absolute;
    /* ABAJO, NO ARRIBA (A5, 05/10/2026). El texto de ayuda del escaner
       (`.scanner-target-hint`, «Apunta el codigo al centro de la pantalla») vive ARRIBA de esta
       misma caja (`top: 6%`) y viene del codigo del escaner. Con el aviso anclado arriba, los dos
       se dibujaban uno encima del otro — visto en la captura del Redmi Note 8. Anclado abajo no
       pueden coincidir: uno arriba, otro abajo. La barra del escaner se mueve entre el 25% y el
       75%, asi que la franja de abajo queda libre. */
    bottom: 20px;
    /* CENTRADO SIN ESTRECHAR EL HUECO. Con `left: 50%` + `translateX(-50%)`, el ancho disponible
       para el texto es solo la mitad de la caja, y una frase corta —«Enfoca un codigo de barras»—
       se partia en dos lineas (visto en el Redmi Note 8). Con `left:0; right:0; margin:auto` el
       ancho disponible es TODO y el bloque se ajusta a su texto. */
    left: 0;
    right: 0;
    margin: 0 auto;
    width: fit-content;
    background: rgba(15,23,42,0.85);
    color: var(--text-inverse);
    padding: 10px 20px;
    border-radius: 999px;
    font-size: var(--text-sm);
    font-weight: 500;
    z-index: 5;
    backdrop-filter: blur(6px);
    text-align: center;
    /* SIN `nowrap`: este aviso dice cosas de largo distinto («Iniciando camara...», «Codigo
       detectado», y los errores), y con `nowrap` y `max-width:90%` un mensaje largo se sale y se
       queda sin leer. Es justo lo que A5 venia a arreglar: que el texto se lea ENTERO. */
    white-space: normal;
    border: 1px solid rgba(255,255,255,0.1);
    max-width: 90%;
}
.modal-scanner-footer {
    display: flex;
    /* EN COLUMNA, y esto era un fallo de verdad (2026-10-04): el pie tiene DOS filas —la del
       código a mano con su boton, y la de «Tomar foto» y «Linterna»— y las dos van a
       `width:100%`. Con el `flex` en fila, las dos se ponian UNA AL LADO DE LA OTRA: la primera
       quedaba a media anchura (y el texto de ayuda salia cortado, «...r no reconoce el codi...»)
       y la segunda se salia por la derecha, con el ultimo boton a medias. Medido en la captura
       del emulador a 384 px. */
    flex-direction: column;
    justify-content: center;
    padding: 14px 20px;
    background: rgba(0,0,0,0.6);
    flex-shrink: 0;
    gap: 12px;
}
.btn-flash {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: rgba(255,255,255,0.1);
    color: var(--text-inverse);
    border: 1px solid rgba(255,255,255,0.15);
    padding: 8px 16px;
    border-radius: 999px;
    font-size: var(--text-sm);
    font-weight: 500;
    cursor: pointer;
    transition: background var(--transition-fast);
}
.btn-flash:hover { background: rgba(255,255,255,0.2); }

/* ============================================================
   FORMULARIO
   ============================================================ */
.form-group { margin-bottom: 14px; }
.form-group label {
    display: block;
    font-weight: 500;
    font-size: var(--text-sm);
    margin-bottom: 6px;
    color: var(--text-secondary);
}
.form-group input,
.form-group select {
    width: 100%;
    padding: 8px 12px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    font-size: var(--text-sm);
    font-family: inherit;
    transition: all var(--transition-fast);
    background: var(--bg-card);
}
.form-group input:focus,
.form-group select:focus {
    outline: 2px solid var(--primary);
    outline-offset: -1px;
    border-color: var(--primary);
}
.btn-primary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    background: var(--primary);
    color: var(--text-inverse);
    border: none;
    padding: 10px 16px;
    border-radius: var(--radius-md);
    font-size: var(--text-sm);
    font-weight: 600;
    cursor: pointer;
    transition: background var(--transition-fast);
    width: 100%;
}
.btn-primary:hover { background: var(--primary-dark); }

/* ============================================================
   SCROLLBAR
   ============================================================ */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 768px) {
    html, body { width: 100%; height: 100%; min-height: 100%; overflow: hidden; }
    #app { width: 100%; height: 100dvh; min-height: 100dvh; display: flex; flex-direction: column; overflow: hidden; }
    header { flex: 0 0 auto; width: 100%; padding: 8px 12px; gap: 6px; }
    .header-row { gap: 6px; }
    main {
        flex: 1 1 auto;
        display: flex;
        flex-direction: column;
        width: 100%;
        height: auto;
        min-height: 0;
        overflow: hidden;
        padding: 0;
        padding-bottom: 140px;
    }
    #content {
        flex: 0 0 35%;
        width: 100%;
        padding: 8px 12px;
        overflow-y: auto;
        background: var(--bg-main);
        min-height: 0;
        max-height: 35vh;
    }
    #article-list {
        display: grid;
        grid-template-columns: 1fr !important;
        gap: 8px;
        width: 100%;
    }
    #breadcrumb { font-size: var(--text-xs); margin-bottom: 6px; padding: 4px 10px; }
    .art-card { padding: 10px; gap: 8px; flex-wrap: wrap; }
    .art-image-container { width: 40px; height: 40px; }
    .art-name { font-size: var(--text-sm); }
    .art-price input.price-input { width: 65px; font-size: 0.9rem; }
    .art-controls input[type="number"] { width: 40px; font-size: var(--text-xs); }
    .art-controls select { max-width: 48px; font-size: 0.7rem; }
    .btn-add { padding: 6px 8px; font-size: var(--text-xs); }
    .btn-refresh { padding: 5px 7px; font-size: var(--text-xs); }
    #cart-sidebar {
        flex: 0 0 65%;
        width: 100%;
        min-width: unset;
        background: var(--bg-card);
        border-top: 1px solid var(--border);
        padding: 8px 12px 0 12px;
        display: flex;
        flex-direction: column;
        overflow: hidden;
        max-height: 65vh;
        position: relative;
    }
    #cart-sidebar h2 { font-size: var(--text-lg); margin-bottom: 6px; padding-bottom: 6px; flex-shrink: 0; border-bottom: 1px solid var(--border); }
    #cart-items { flex: 1; overflow-y: auto; margin-bottom: 0; min-height: 0; max-height: calc(65vh - 60px); padding-bottom: 4px; }
    .cart-item { font-size: var(--text-sm); padding: 6px 0; }
    .cart-item .btn-remove { width: 22px; height: 22px; }
    #cart-totals {
        position: fixed !important;
        bottom: 0 !important;
        left: 0 !important;
        right: 0 !important;
        z-index: 999 !important;
        /* ESTA BARRA ES UN FLOTANTE, no una tarjeta (07/10/2026): va `position: fixed` al pie, con
           z-index 999, o sea ENCIMA del carrito. Le toca el cristal de flotante, no el de tarjeta.
           El `!important` se conserva porque esta regla existe precisamente para pisar la base. */
        background: var(--cristal-flotante) !important;
        border-top: 1px solid var(--border) !important;
        padding: 10px 16px !important;
        box-shadow: 0 -4px 12px rgba(0,0,0,0.08) !important;
        margin: 0 !important;
        width: 100% !important;
        max-width: 100% !important;
        border-radius: 0 !important;
    }
    .total-line-dual { font-size: var(--text-sm); padding: 2px 0; }
    .grand-total-dual { font-size: var(--text-base); padding-top: 6px; margin-top: 4px; }
    #btn-totalizar { padding: 10px; font-size: var(--text-sm); margin-top: 6px; }
    .nav-select { min-width: 140px; max-width: 140px; font-size: var(--text-xs); padding: 6px 8px; }
    #cart-summary { font-size: var(--text-sm); padding: 4px 10px; gap: 8px; }
    .tasa-container { font-size: var(--text-xs); padding: 4px 8px; }
    .tasa-container input { width: 48px; font-size: var(--text-xs); }
    .btn-header { font-size: var(--text-xs); padding: 4px 10px; }
    .sync-status-container { font-size: var(--text-xs); padding: 3px 8px; }
    #sync-status { font-size: var(--text-sm); }
    #network-status { font-size: 0.65rem; }
    #sync-badge { font-size: 0.6rem; min-width: 16px; height: 16px; line-height: 16px; }
    #sync-toast { font-size: var(--text-sm); padding: 10px 18px; bottom: 70px; }
    .modal-content { padding: 18px; width: 95%; max-height: 90vh; }
}

@media (min-width: 769px) {
    main { display: flex; flex: 1; overflow: hidden; gap: 0; min-height: 0; }
    #content { flex: 0 0 65%; width: 65%; padding: 10px 14px; overflow-y: auto; background: var(--bg-main); height: 100%; min-height: 0; }
    #article-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; }
    #cart-sidebar {
        flex: 0 0 35%;
        width: 35%;
        background: var(--bg-card);
        border-left: 1px solid var(--border);
        padding: 12px 16px;
        display: flex;
        flex-direction: column;
        height: 100%;
        overflow: hidden;
        min-width: 250px;
    }
    #cart-items { flex: 1; overflow-y: auto; margin-bottom: 8px; min-height: 0; max-height: calc(100vh - 320px); }
    #breadcrumb {
        font-size: var(--text-sm);
        color: var(--text-secondary);
        margin-bottom: 10px;
        padding: 6px 12px;
        background: var(--bg-card);
        border-radius: var(--radius);
        border: 1px solid var(--border);
        flex-shrink: 0;
    }
    #cart-totals { border-top: 1px solid var(--border); padding-top: 8px; flex-shrink: 0; position: relative; bottom: auto; box-shadow: none; }
}

@media (max-width: 480px) {
    header { padding: 6px 10px; gap: 4px; }
    .header-row { gap: 4px; }
    .tasa-container { font-size: var(--text-xs); padding: 4px 8px; }
    .tasa-container input { width: 46px; font-size: 0.7rem; }
    .tasa-container #tasa-display { font-size: var(--text-sm); font-weight: 600; }
    .tasa-fuente { color: rgba(255,255,255,0.5); font-size: 0.55rem; }
    #cart-summary { font-size: var(--text-xs); padding: 4px 8px; gap: 6px; }
    .nav-select { min-width: 100px; max-width: 100px; font-size: 0.7rem; }
    #breadcrumb { font-size: var(--text-xs); margin-bottom: 6px; padding: 4px 8px; }
    .art-price .price-bs { font-size: 0.7rem; }
    .art-price input.price-input { width: 60px; font-size: 0.84rem; }
    .art-controls input[type="number"] { width: 36px; padding: 3px 2px; border: 1px solid var(--border); border-radius: var(--radius-sm); text-align: center; font-weight: 500; font-size: 0.7rem; }
    .art-controls select { padding: 3px 3px; border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 0.7rem; max-width: 48px; }
    .btn-add { padding: 5px 7px; font-size: 0.7rem; }
    .btn-refresh { padding: 4px 6px; font-size: 0.7rem; }
    #content { flex: 0 0 35%; max-height: 35vh; }
    #cart-sidebar h2 { font-size: var(--text-base); margin-bottom: 6px; padding-bottom: 6px; flex-shrink: 0; border-bottom: 1px solid var(--border); }
    #cart-sidebar { flex: 0 0 65%; max-height: 65vh; }
    #cart-items { flex: 1 1 auto; min-height: 0; padding-bottom: 150px; overflow-y: auto; max-height: calc(70vh - 60px); }
    .cart-item { font-size: var(--text-sm); padding: 5px 0; }
    .cart-item .item-price { font-size: var(--text-sm); }
    .cart-item .btn-remove { width: 22px; height: 22px; }
    .total-line-dual { font-size: var(--text-sm); flex-wrap: wrap; }
    .grand-total-dual { font-size: var(--text-sm); flex-wrap: wrap; }
    #cart-totals { min-height: 120px; padding: 8px 12px !important; }
    #btn-totalizar { padding: 10px; font-size: var(--text-sm); }
    .modal-scanner-header { padding: 10px 14px; }
    .modal-scanner-title { font-size: var(--text-sm); }
    .scanner-status-modal { bottom: 14px; font-size: 0.75rem; padding: 6px 14px; max-width: 95%; }
    .btn-flash { font-size: 0.75rem; padding: 6px 14px; }
}

/* ============================================================
   MODAL TOTALIZAR BOTONES
   ============================================================ */
#modal-totalizar .modal-content > div:last-child {
    display: flex;
    gap: 10px;
    margin-top: 20px;
    flex-wrap: wrap;
    justify-content: flex-end;
    border-top: 1px solid var(--border);
    padding-top: 16px;
}
#modal-totalizar .modal-content > div:last-child button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 10px 20px;
    border: none;
    border-radius: var(--radius-md);
    font-size: var(--text-sm);
    font-weight: 600;
    cursor: pointer;
    transition: background var(--transition-fast);
    flex: 1;
    min-width: 120px;
}
#modal-totalizar .modal-content > div:last-child button:first-child { background: var(--primary); color: var(--text-inverse); }
#modal-totalizar .modal-content > div:last-child button:first-child:hover { background: var(--primary-dark); }
#modal-totalizar .modal-content > div:last-child button:last-child { background: #0F9D58; color: var(--text-inverse); }
#modal-totalizar .modal-content > div:last-child button:last-child:hover { background: #0B7A44; }
@media (max-width: 480px) {
    #modal-totalizar .modal-content > div:last-child button { font-size: var(--text-sm); padding: 10px 14px; min-width: 110px; }
}

/* ============================================================
   MODO SUPERMERCADO (checklist)
   ============================================================ */
.cart-categoria-header {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--primary);
    padding: 12px 4px 6px;
    border-bottom: 1px solid var(--border);
    margin-top: 10px;
    display: flex;
    align-items: center;
    gap: 6px;
}
.cart-categoria-header.cart-categoria-completados {
    color: var(--text-muted);
    border-bottom-color: var(--border);
}
.check-item {
    width: 18px;
    height: 18px;
    margin-right: 8px;
    cursor: pointer;
    accent-color: var(--primary);
    flex-shrink: 0;
}
.cart-item.item-completado { opacity: 0.55; }
.cart-item.item-completado .item-name { text-decoration: line-through; }

/* ============================================================
   LAYOUT NATIVO (v2)
   ============================================================ */
body { overflow: hidden; display: flex; flex-direction: column; }
/* EL MARCO DE LA APP, TRANSPARENTE (07/10/2026, al escalar el cristal a las pantallas interiores).
 *
 * Aquí había `background: var(--bg-main)` — un gris claro OPACO (#F6F8F7) —, y tapaba el fondo de
 * la casa: el contenido quedaba sobre gris y **el cristal de las tarjetas no se veía**, porque
 * detrás no había nada que traslucir. Medido en staging: `#app` pintaba rgb(246,248,247) y el
 * fondo del `body` no asomaba por ningún sitio.
 *
 * Transparente, el degradado verde llega hasta el contenido, y las tarjetas de cristal tienen algo
 * que enseñar a través. Y el texto NO queda sobre el fondo directamente: cada bloque se apoya en su
 * tarjeta de cristal, que es lo que sostiene la legibilidad.
 *
 * OJO PARA EL QUE VENGA: si algún día se ve «el fondo no llega a las pantallas», el sospechoso
 * número uno es un `background` opaco en un contenedor de este tamaño. Se mide subiendo desde un
 * elemento de dentro hacia el `body` y apuntando quién pinta — que es como se encontró este. */
#app { display: flex; flex-direction: column; height: 100dvh; min-height: 100dvh; overflow: hidden; overflow-x: hidden; background: transparent; min-width: 0; max-width: 100%; }
@media (min-width: 481px) {
    body { align-items: center; }
    #app { width: 100%; max-width: 480px; border-left: 1px solid var(--border); border-right: 1px solid var(--border); box-shadow: 0 0 20px rgba(0,0,0,0.08); }
}

/* ---------- HEADER MÍNIMO ---------- */
#app-header {
    flex: 0 0 auto;
    width: 100%;
    background: var(--secondary);
    color: var(--text-inverse);
    box-shadow: var(--shadow-md);
    z-index: 20;
    flex-direction: column;
    gap: 0;
    padding: 0;
}
.header-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 10px 14px;
    min-height: 56px;
}
.hdr-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border: none;
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--text-inverse);
    cursor: pointer;
    position: relative;
    transition: background var(--transition-fast);
    flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
}
.hdr-icon:hover { background: rgba(255,255,255,0.12); }
.hdr-icon:focus-visible { outline: 2px solid var(--text-inverse); outline-offset: 1px; }
.hdr-icon:hover { background: rgba(255,255,255,0.16); }
.hdr-icon .icon { width: 1.25rem; height: 1.25rem; }
.app-title {
    font-size: var(--text-lg);
    font-weight: 600;
    letter-spacing: -0.01em;
    white-space: nowrap;
    flex: 1 1 auto;
    min-width: 0 !important;
    max-width: 100% !important;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 0 8px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 8px;
}
.app-title .icon { width: 1.5rem; height: 1.5rem; stroke-width: 1.75; }
.header-actions { display: flex; align-items: center; gap: 6px; }
.cart-badge {
    position: absolute;
    top: -2px;
    right: -2px;
    min-width: 18px;
    height: 18px;
    line-height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--accent-error);
    color: var(--text-inverse);
    font-size: 0.65rem;
    font-weight: 600;
    text-align: center;
    border: 2px solid var(--secondary);
    font-variant-numeric: tabular-nums;
}

/* ---------- Nav catálogo ---------- */
#catalogo-nav {
    display: none;
    flex-wrap: nowrap !important;
    flex-direction: row !important;
    gap: 6px;
    padding: 0 14px 10px;
}
#app-header.show-nav #catalogo-nav { display: flex !important; }
#catalogo-nav .nav-select {
    min-width: 0 !important;
    max-width: none !important;
    width: auto !important;
    flex: 1 1 0 !important;
    font-size: var(--text-sm);
    padding: 8px 8px;
    box-sizing: border-box;
}

/* ---------- Breadcrumb contextual ---------- */
#breadcrumb-bar {
    flex: 0 0 auto;
    background: var(--bg-card);
    color: var(--text-secondary);
    font-size: var(--text-sm);
    font-weight: 500;
    padding: 10px 14px;
    border-bottom: 1px solid var(--border);
    z-index: 15;
    display: flex;
    align-items: center;
    gap: 6px;
}
#breadcrumb-bar .icon { width: 1rem; height: 1rem; color: var(--text-muted); }
#breadcrumb-bar.hidden { display: none; }

/* ---------- Área principal ---------- */
#main-layout {
    flex: 1 1 auto;
    min-height: 0;
    min-width: 0;
    display: flex;
    overflow: hidden;
    overflow-x: hidden;
    padding: 0 !important;
    height: auto;
}
.view {
    display: none;
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    flex-direction: column;
    overflow: hidden;
    overflow-x: hidden;
}
.view.view-active { display: flex; }
.view-header {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 14px;
    border-bottom: 1px solid var(--border);
    background: var(--bg-card);
}
.view-title {
    font-size: var(--text-lg);
    font-weight: 600;
    margin: 0;
    display: flex;
    align-items: center;
    gap: 8px;
}
.view-actions { display: flex; align-items: center; gap: 8px; }
.net-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.7rem;
    font-weight: 500;
    padding: 3px 10px;
    border-radius: 999px;
    background: var(--bg-hover);
    color: var(--text-secondary);
    border: 1px solid var(--border);
}
.sync-badge {
    background: var(--accent-error);
    color: var(--text-inverse);
    border-radius: 999px;
    padding: 0 6px;
    font-size: 0.65rem;
    font-weight: 600;
    min-width: 18px;
    height: 18px;
    line-height: 18px;
    text-align: center;
}

/* ---------- Vistas internas ---------- */
/* padding-bottom despeja el mini-cart sticky fijo para que no tape el último artículo */
#view-catalogo { background: var(--bg-main); padding: 10px 12px 150px; overflow-y: auto; }
#article-list { display: grid; grid-template-columns: 1fr; gap: 8px; }

/* EL INSTRUCTIVO DE LA PANTALLA DE INICIO DEL CATÁLOGO (06/10/2026).
   Antes el mensaje de «no hay nada elegido» era un <p> con estilos EN LÍNEA
   (`color:#999; text-align:center`) y sin ninguna regla aquí. Ahora lleva los pasos, así que
   necesita ser legible: alineado a la izquierda, con aire entre pasos y los sub-pasos en
   letra. Se aplica a TODOS los mensajes de la lista (el instructivo y los avisos cortos de
   categoría y subcategoría), para que la pantalla no cambie de estilo según el estado. */
.empty-article-message {
    grid-column: 1 / -1;
    margin: 0;
    padding: 4px 2px 10px;
    color: var(--text-secondary);
    font-size: 0.9rem;
    line-height: 1.5;
}
.empty-article-message__intro { margin: 0 0 10px; color: var(--text-main); font-weight: 600; }
.empty-article-message__lista { margin: 0; padding-left: 22px; }
.empty-article-message__lista > li { margin-bottom: 9px; }
.empty-article-message__lista ol { margin: 6px 0 0; padding-left: 20px; list-style: lower-alpha; }
.empty-article-message__lista ol li { margin-bottom: 4px; }
.empty-article-message__paso { margin: 6px 0 0; }
.empty-article-message__pista {
    margin: 8px 0 0;
    padding-top: 8px;
    border-top: 1px dashed var(--border);
    color: var(--text-muted);
    font-size: 0.85rem;
}
#view-carrito { background: var(--bg-card); overflow: hidden; }
#view-carrito #cart-items { flex: 1 1 auto; overflow-y: auto; padding: 10px 14px; min-height: 0; }
#view-buscar { background: var(--bg-main); overflow-y: auto; padding: 14px 14px 150px; }
.buscador-box { display: flex; flex-direction: column; gap: 12px; padding: 10px 0; }
.buscador-row { display: flex; align-items: center; gap: 8px; }
.buscador-input {
    flex: 1;
    min-width: 0;
    width: 100%;
    padding: 12px 16px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    font-size: var(--text-base);
    font-family: inherit;
    background: var(--bg-card);
    box-shadow: var(--shadow-sm);
    transition: all var(--transition-fast);
}
.buscador-input:focus {
    outline: 2px solid var(--primary);
    outline-offset: -1px;
    border-color: var(--primary);
}
.btn-dictado {
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    background: var(--bg-card);
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    color: var(--text-secondary);
    transition: all var(--transition-fast);
}
.btn-dictado:hover { border-color: var(--primary); color: var(--primary); }
.btn-dictado.escuchando {
    background: var(--accent-error);
    border-color: var(--accent-error);
    color: var(--text-inverse);
    animation: dictadoPulso 1.2s ease-in-out infinite;
}
@keyframes dictadoPulso {
    0%, 100% { box-shadow: 0 0 0 0 rgba(220,38,38,0.4); }
    50% { box-shadow: 0 0 0 10px rgba(220,38,38,0); }
}
.buscador-aviso {
    color: var(--text-secondary);
    font-size: var(--text-sm);
    background: var(--bg-card);
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius-lg);
    padding: 20px;
    text-align: center;
}
#view-listas { background: var(--bg-main); overflow-y: auto; padding: 14px 14px 150px; }

/* ---------- Totales del carrito ---------- */
#cart-totals.cart-totals-panel {
    position: static !important;
    bottom: auto !important;
    left: auto !important;
    right: auto !important;
    z-index: auto !important;
    border-top: 1px solid var(--border);
    padding: 12px 14px 14px;
    flex-shrink: 0;
    box-shadow: none !important;
    margin: 0 !important;
    width: 100% !important;
    max-width: 100% !important;
    min-height: auto !important;
    border-radius: 0 !important;
}
#view-carrito #cart-items {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0;
    margin-bottom: 0;
    padding-bottom: 8px !important;
    max-height: none !important;
}
#cart-totals .cart-actions {
    display: flex;
    gap: 8px;
    margin-top: 12px;
    flex-wrap: wrap;
}
#cart-totals .cart-actions .btn-accion {
    flex: 1 1 0;
    min-width: 0;
}
#cart-totals .cart-actions #btn-totalizar {
    margin-top: 0;
}
.btn-accion {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    border: none;
    border-radius: var(--radius-md);
    padding: 10px 16px;
    font-size: var(--text-sm);
    font-weight: 600;
    cursor: pointer;
    transition: background var(--transition-fast);
    white-space: nowrap;
    font-family: inherit;
}
.btn-guardar { background: var(--primary); color: var(--text-inverse); }
.btn-guardar:hover { background: var(--primary-dark); }
.btn-limpiar { background: var(--bg-hover); color: var(--accent-error); border: 1px solid var(--border); }
.btn-limpiar:hover { background: #FEF2F2; border-color: #FECACA; }

/* ---------- MINI-CARRITO STICKY ---------- */
#mini-cart {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    width: min(calc(100% - 24px), 360px);
    bottom: 120px;
    z-index: 90;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    background: var(--primary);
    color: var(--text-inverse);
    padding: 12px 16px;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    cursor: pointer;
    font-size: var(--text-sm);
    font-weight: 600;
    transition: background var(--transition-fast);
}
#mini-cart:hover { background: var(--primary-dark); }
#mini-cart.hidden { display: none; }
.mini-cart-arrow { font-size: var(--text-base); opacity: 0.8; }

/* ---------- BARRA DE TABS INFERIOR ---------- */
#bottom-tabs {
    flex: 0 0 auto;
    display: flex;
    background: var(--bg-card);
    border-top: 1px solid var(--border);
    z-index: 100;
    padding-bottom: env(safe-area-inset-bottom);
}
.tab-btn {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 10px 4px 8px;
    border: none;
    background: none;
    color: var(--text-muted);
    font-size: 0.7rem;
    font-weight: 500;
    cursor: pointer;
    transition: color var(--transition-fast);
    font-family: inherit;
}
.tab-ico {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    line-height: 1;
}
.tab-ico .icon { width: 22px; height: 22px; stroke-width: 1.5; }
.tab-btn.tab-active { color: var(--primary); font-weight: 600; }
.tab-btn:hover:not(.tab-active) { color: var(--text-secondary); }

/* ============================================================
   DISPOSICIONES
   ============================================================ */
body.layout-split #view-catalogo.view-active,
body.layout-split #view-carrito.view-active,
body.layout-responsive #view-catalogo.view-active,
body.layout-responsive #view-carrito.view-active { display: flex; }
body.layout-split #mini-cart,
body.layout-responsive #mini-cart { display: none; }
@media (min-width: 769px) {
    body.layout-split #view-catalogo.view-active,
    body.layout-responsive #view-catalogo.view-active { flex: 1 1 62%; border-right: 1px solid var(--border); }
    body.layout-split #view-carrito.view-active,
    body.layout-responsive #view-carrito.view-active { flex: 1 1 38%; border-left: 1px solid var(--border); }
}
@media (max-width: 768px) {
    body.layout-split #main-layout,
    body.layout-responsive #main-layout { flex-direction: column; }
    body.layout-split #view-catalogo.view-active,
    body.layout-responsive #view-catalogo.view-active { flex: 0 0 40%; max-height: 40%; border-bottom: 1px solid var(--border); border-right: none; }
    body.layout-split #view-carrito.view-active,
    body.layout-responsive #view-carrito.view-active { flex: 1 1 60%; border-left: none; }
}

/* ============================================================
   MENÚ LATERAL
   ============================================================ */
#menu-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(17,24,39,0.5);
    z-index: 300;
    backdrop-filter: blur(2px);
}
#menu-overlay.active { display: block; }
#menu-lateral {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    width: 85%;
    max-width: 320px;
    background: var(--bg-card);
    box-shadow: var(--shadow-lg);
    transform: translateX(-105%);
    transition: transform 0.28s ease;
    z-index: 400;
    display: flex;
    flex-direction: column;
}
#menu-lateral.open { transform: translateX(0); }
.menu-header {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 20px 18px;
    background: var(--primary);
    color: var(--text-inverse);
    flex-shrink: 0;
}
.menu-username {
    font-size: var(--text-base);
    font-weight: 600;
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* `.menu-plan` SE QUITO el 08/10/2026 junto con la etiqueta del encabezado (lo pidio el dueno: se
   veia blanco sobre claro porque la regla del cristal le ponia un fondo claro debajo del texto
   blanco). El plan se enseña en la seccion Estado. Lo vigila `scripts/menu-test.mjs`. */
.menu-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    background: rgba(255,255,255,0.15);
    border: none;
    color: var(--text-inverse);
    border-radius: var(--radius);
    cursor: pointer;
    transition: background var(--transition-fast);
}
.menu-close:hover { background: rgba(255,255,255,0.25); }
.menu-body { flex: 1; overflow-y: auto; padding: 8px 0; }
.menu-section { padding: 14px 18px; border-bottom: 1px solid var(--border); }
.menu-section-title {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
    margin-bottom: 10px;
}
.menu-link {
    display: flex;
    align-items: center;
    gap: 12px;
    /* EL INTERLINEADO DEL MENU (detalle de estetica del dueno, 05/10/2026).
       El dueno lo describio como «de 2 a 1» y pedia «1,5 a 1, para que la barra se vea mas compacta».
       MEDIDO: con `padding: 10px 0`, cada linea ocupaba 10 + 21 (el texto) + 10 = **41 px**, y
       41 / 21 = **1,95 ≈ 2 a 1** — su numero era exacto. Con **5 px** queda 5 + 21 + 5 = **31 px**,
       y 31 / 21 = **1,48 ≈ 1,5 a 1**, que es lo que pide.
       Es relleno y no `line-height` a proposito: el interlineado que se ve entre dos opciones del
       menu es el HUECO entre ellas, y ese hueco lo hace el relleno. Tocar `line-height` habria
       apretado el texto dentro de cada opcion, que no es lo mismo. */
    padding: 5px 0;
    color: var(--text-primary);
    text-decoration: none;
    font-size: var(--text-sm);
    font-weight: 500;
    cursor: pointer;
    background: none;
    border: none;
    width: 100%;
    text-align: left;
    font-family: inherit;
    transition: color var(--transition-fast);
}
.menu-link:hover { color: var(--primary); }
.menu-link .icon { width: 1.125rem; height: 1.125rem; stroke-width: 1.75; color: var(--text-secondary); }
.menu-link:hover .icon { color: var(--primary); }
.menu-btn { border: none; background: none; }
.menu-status-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    /* LA SECCION «ESTADO», AL MISMO RITMO QUE LAS OPCIONES (05/10/2026).
       Aqui estaba el fallo: el interlineado del menu se arreglo en `.menu-link` (las opciones que se
       pulsan) y esta seccion —Conexion, Plan, Pendientes— usa OTRA regla, que se quedo en 8 px.
       Medido: 8 + 21 + 8 = 37 px, y 37 / 21 = **1,76 a 1**, que es el «2 a 1» que el dueno seguia
       viendo. Con 5 px queda 1,48, igual que el resto del menu.
       Y por eso la guarda (`menu-test.mjs`) ahora mira LAS DOS clases: antes solo miraba `.menu-link`,
       y por eso dio el visto bueno con la mitad del menu sin arreglar. */
    padding: 5px 0;
    /* Y LA MISMA ALTURA DE LINEA QUE LAS OPCIONES. Medido EN EL TELEFONO el 05/10/2026, con el mismo
       relleno de 5 px: las opciones quedaban en **31,5 px** de alto y estas filas en **36,3 px**,
       porque heredaban el `line-height: 1.5` del cuerpo mientras las opciones usan `normal`. Cinco
       pixeles mas por fila, tres filas — y la seccion se veia mas aireada que el resto del menu, que
       es lo que el dueno seguia notando como «2 a 1». Con `normal`, las dos clases miden lo mismo. */
    line-height: normal;
    font-size: var(--text-sm);
    color: var(--text-secondary);
}
.menu-status-val { font-weight: 500; color: var(--text-primary); }
.menu-lab {
    display: block;
    font-size: var(--text-sm);
    font-weight: 500;
    margin-bottom: 6px;
    color: var(--text-secondary);
}
.menu-select {
    width: 100%;
    padding: 8px 12px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    font-size: var(--text-sm);
    background: var(--bg-card);
    font-family: inherit;
}
.menu-hint {
    font-size: var(--text-xs);
    color: var(--text-muted);
    margin-top: 8px;
    font-style: italic;
}

@media (max-width: 768px) {
    .header-inner { min-height: 52px; padding: 8px 12px; }
    .app-title { font-size: var(--text-base); }
    .hdr-icon { width: 38px; height: 38px; }
    #view-catalogo { padding: 8px 10px 150px; }
    #article-list { grid-template-columns: 1fr; gap: 6px; }
    #view-listas { padding: 10px 10px 150px; }
    #menu-lateral { width: 90%; }
}
@media (max-width: 480px) {
    #catalogo-nav .nav-select { min-width: 0 !important; max-width: none !important; width: auto !important; flex: 1 1 0 !important; font-size: 0.75rem; padding: 7px 6px; }
    .tab-lbl { font-size: 0.65rem; }
    .tab-ico { width: 20px; height: 20px; }
    .tab-ico .icon { width: 20px; height: 20px; }
}

.art-controls { gap: 4px; flex-wrap: nowrap; }

/* ============================================================
   BUSCADOR INTELIGENTE
   ============================================================ */
.buscar-resultados { display: flex; flex-direction: column; gap: 10px; padding-top: 8px; }
.buscar-aviso {
    color: var(--text-secondary);
    font-size: var(--text-sm);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 18px;
    text-align: center;
}
.buscar-grupo-titulo {
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin: 12px 0 6px;
    padding-bottom: 4px;
    display: flex;
    align-items: center;
    gap: 6px;
}
.buscar-grupo-titulo .icon { width: 0.9rem; height: 0.9rem; }
.buscar-grupo-titulo .art-logo { height: 20px; max-width: 50px; margin: 0 2px 0 0; }
.marcas-grid {
    display: grid;
    /* PUNTO 9 DEL DUENO (05/10/2026): +10% de logo y -15% de separacion, para que se vean mejor.
       Antes: minmax(84px, 1fr) y gap 10px. */
    grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
    gap: 8.5px;
    padding: 6px 2px 2px;
}
/* LA AYUDA DE LAS MARCAS (punto 13, 05/10/2026). Un parrafo suelto debajo del titulo se rechazo:
   «fue una salida facil, sin estilo alguno, sin estetica alguna». Esto es el cuadro que se despliega
   al pasar el dedo o el raton por el titulo. */
.marcas-titulo {
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    border-radius: var(--radius-sm);
    transition: color var(--transition-fast);
}
.marcas-titulo:hover,
.marcas-titulo:focus-visible { color: var(--primary); }
/* La senal de que el titulo se puede tocar: no se le ocurre a nadie pasar el dedo por un titulo. */
.marcas-titulo__ayuda {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 15px;
    height: 15px;
    margin-left: 2px;
    border-radius: 50%;
    background: var(--border);
    color: var(--text-secondary);
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0;
    transition: background var(--transition-fast), color var(--transition-fast);
}
.marcas-titulo:hover .marcas-titulo__ayuda,
.marcas-titulo:focus-visible .marcas-titulo__ayuda {
    background: var(--primary);
    color: #fff;
}
.marcas-ayuda {
    position: relative;
    /* EN REJILLA, NO EN FILA: con el boton «Entendido» al lado, el texto se quedaba en un carril
       estrecho y partia en cinco lineas (visto en el Note 8). Asi el texto ocupa todo el ancho y el
       boton baja a su propia fila, a la derecha. */
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 8px 10px;
    align-items: start;
    margin: 2px 0 12px;
    padding: 12px 14px;
    background: var(--bg-card, #fff);
    border: 1px solid var(--border);
    border-left: 3px solid var(--primary);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow);
    font-size: 0.84rem;
    line-height: 1.45;
    color: var(--text-primary);
    animation: marcas-ayuda-entra 180ms ease-out;
}
.marcas-ayuda[hidden] { display: none; }
/* La flechita que apunta al titulo: el cuadro va DEBAJO de el, y asi se entiende de donde sale. */
.marcas-ayuda__flecha {
    position: absolute;
    top: -7px;
    left: 22px;
    width: 12px;
    height: 12px;
    background: var(--bg-card, #fff);
    border-left: 1px solid var(--border);
    border-top: 1px solid var(--border);
    transform: rotate(45deg);
}
.marcas-ayuda__icono {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--primary-light, #dcfce7);
    color: var(--primary);
}
.marcas-ayuda__texto { grid-column: 2; min-width: 0; }
.marcas-ayuda__texto strong { color: var(--primary); }
.marcas-ayuda__cerrar {
    /* Fila propia, en la columna del texto y pegada a la derecha. */
    grid-column: 2;
    justify-self: end;
    padding: 6px 12px;
    border: 1px solid var(--primary);
    border-radius: 999px;
    background: none;
    color: var(--primary);
    font-family: inherit;
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
}
.marcas-ayuda__cerrar:hover { background: var(--primary); color: #fff; }
@keyframes marcas-ayuda-entra {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
    .marcas-ayuda { animation: none; }
}
/* Chip = solo el logo, sin caja ni texto: el logo es la marca. */
.marca-chip {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 8px;
    background: none;
    border: none;
    cursor: pointer;
    font-family: inherit;
    text-align: center;
    -webkit-tap-highlight-color: transparent;
}
.marca-chip .art-logo {
    /* PUNTO 9: +10% sobre los 40 px que tenia. */
    height: 44px;
    max-width: 100%;
    margin: 0;
    transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}
.marca-chip:hover .art-logo,
.marca-chip:focus-visible .art-logo {
    transform: scale(1.15);
    filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.18));
}
.marca-chip:focus-visible {
    outline: 2px solid var(--primary-light);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}
.marca-back {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    align-self: flex-start;
    background: none;
    border: none;
    padding: 0;
    margin: 2px 0 4px;
    color: var(--primary);
    font-weight: 600;
    font-size: var(--text-sm);
    font-family: inherit;
    cursor: pointer;
}
.marca-back:hover { color: var(--primary-dark); }
.buscar-resultados .art-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 10px;
    min-width: 0;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
}
.buscar-accion {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    background: var(--primary-50);
    border: 1px solid var(--primary-light);
    border-radius: var(--radius-md);
    padding: 14px;
    font-size: var(--text-sm);
    color: var(--primary-dark);
}
.buscar-accion button {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--primary);
    color: var(--text-inverse);
    border: none;
    border-radius: var(--radius-md);
    padding: 8px 16px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    font-size: var(--text-sm);
    font-family: inherit;
    transition: background var(--transition-fast);
}
.buscar-accion button:hover { background: var(--primary-dark); }

/* ============================================================
   NOTIFICACIONES (campanita)
   ============================================================ */
#btn-notificaciones { position: relative; }
.notif-panel {
    position: fixed;
    top: 64px;
    right: max(12px, calc((100vw - 480px) / 2 + 12px));
    width: min(340px, calc(100% - 24px));
    max-height: 70vh;
    background: var(--bg-card);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    z-index: 500;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: 1px solid var(--border);
}
.notif-panel.hidden { display: none; }
.notif-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 16px;
    background: var(--bg-card);
    color: var(--text-primary);
    font-weight: 600;
    font-size: var(--text-sm);
    flex-shrink: 0;
    border-bottom: 1px solid var(--border);
}
.notif-cerrar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    background: transparent;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 0;
    border-radius: var(--radius-sm);
    transition: all var(--transition-fast);
}
.notif-cerrar:hover { background: var(--bg-hover); color: var(--text-primary); }
.notif-lista { overflow-y: auto; padding: 6px 0; }
.notif-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border);
    font-size: var(--text-sm);
    color: var(--text-primary);
    cursor: pointer;
    transition: background var(--transition-fast);
}
.notif-item:last-child { border-bottom: none; }
.notif-item:hover { background: var(--bg-hover); }
.notif-item:active { background: var(--secondary-50); }
.notif-item .notif-icon-wrap {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border-radius: 999px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--primary-50);
    color: var(--primary);
}
.notif-item.tipo-success .notif-icon-wrap { background: var(--primary-50); color: var(--primary); }
.notif-item.tipo-warn    .notif-icon-wrap { background: #FEF3C7; color: var(--accent-warn); }
.notif-item.tipo-error   .notif-icon-wrap { background: #FEE2E2; color: var(--accent-error); }
.notif-item.tipo-info    .notif-icon-wrap { background: #DBEAFE; color: var(--accent-info); }
.notif-item .notif-msg { flex: 1; line-height: 1.4; }
.notif-empty {
    padding: 28px 16px;
    text-align: center;
    color: var(--text-muted);
    font-size: var(--text-sm);
}

/* ============================================================
   NOTIFICACIONES TOAST (sistema nuevo)
   ============================================================ */
.notif-toast-container {
    position: fixed;
    top: 70px;
    right: 16px;
    z-index: 9998;
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-width: 360px;
    pointer-events: none;
}
.notif-toast {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 16px;
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    border-left: 3px solid var(--primary);
    font-size: var(--text-sm);
    color: var(--text-primary);
    animation: toastSlide 0.25s ease;
    pointer-events: auto;
}
.notif-toast.toast-success { border-left-color: var(--primary); }
.notif-toast.toast-warn    { border-left-color: var(--accent-warn); }
.notif-toast.toast-error   { border-left-color: var(--accent-error); }
.notif-toast.toast-info    { border-left-color: var(--accent-info); }
.notif-toast .toast-icon {
    flex-shrink: 0;
    width: 20px;
    height: 20px;
}
.notif-toast.toast-success .toast-icon { color: var(--primary); }
.notif-toast.toast-warn    .toast-icon { color: var(--accent-warn); }
.notif-toast.toast-error   .toast-icon { color: var(--accent-error); }
.notif-toast.toast-info    .toast-icon { color: var(--accent-info); }
.notif-toast .toast-msg { flex: 1; line-height: 1.4; }
@keyframes toastSlide {
    from { opacity: 0; transform: translateX(10px); }
    to   { opacity: 1; transform: translateX(0); }
}
@media (max-width: 480px) {
    .notif-toast-container { left: 12px; right: 12px; max-width: none; }
}

/* ============================================================
   CALCULADORA CAMBIARIA
   ============================================================ */
.calculadora-panel {
    position: fixed;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 100%;
    max-width: 480px;
    max-height: 78vh;
    overflow-y: auto;
    background: var(--bg-card);
    box-shadow: var(--shadow-lg);
    z-index: 600;
    border-bottom-left-radius: var(--radius-lg);
    border-bottom-right-radius: var(--radius-lg);
    border: 1px solid var(--border);
    border-top: none;
}
.calculadora-panel.hidden { display: none; }
.calc-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 18px;
    background: var(--bg-card);
    color: var(--text-primary);
    font-weight: 600;
    position: sticky;
    top: 0;
    z-index: 1;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 8px;
}
.calc-panel-body {
    padding: 18px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.calc-tasa-dia {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 14px;
    background: var(--primary-50);
    border: 1px solid var(--primary-light);
    border-radius: var(--radius-md);
    font-size: var(--text-sm);
    color: var(--text-secondary);
}
.calc-tasa-dia strong {
    color: var(--primary-dark);
    font-size: var(--text-base);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.form-group input.calc-input {
    width: 100%;
    padding: 12px 14px;
    font-size: var(--text-xl);
    font-weight: 600;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--bg-card);
    font-variant-numeric: tabular-nums;
    font-family: inherit;
}
.form-group input.calc-input:focus,
.form-group input.calc-input.calc-input-activo {
    outline: 2px solid var(--primary);
    outline-offset: -1px;
    border-color: var(--primary);
}
/* Teclado numérico de la calculadora */
.calc-teclado {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
    margin-top: 2px;
}
.calc-key {
    appearance: none;
    -webkit-appearance: none;
    border: 1px solid var(--border);
    background: var(--bg-main);
    color: var(--text-primary);
    font-family: inherit;
    font-size: var(--text-lg);
    font-weight: 600;
    line-height: 1;
    padding: 14px 0;
    border-radius: var(--radius-md);
    cursor: pointer;
    font-variant-numeric: tabular-nums;
    transition: background var(--transition-fast), transform var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
    user-select: none;
}
.calc-key:hover { background: var(--bg-card); }
.calc-key:active { transform: scale(0.96); background: var(--primary-50); }
.calc-key:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.calc-key-fn { color: var(--primary-dark); background: var(--primary-50); }
.calc-key-fn:hover { background: var(--primary-light); }
.calc-key-span2 { grid-column: span 2; }
@media (max-height: 520px) {
    .calculadora-panel { max-height: 100vh; }
}
/* Logo en header y login */
/* El logo TIENE que poder encogerse. Medido a 324 px de ancho (el emulador: una
   ventana de 720 con `window.scale=0.45`), `.app-title` mide 128 px y el logo pedia
   138,45: desbordaba 10,45 px por debajo del grupo de acciones, que van despues en el
   flex, y el boton de agregar lo tapaba. Con `max-width: 100%` y `object-fit` el logo
   se encoge en vez de desbordar, y a 360 px o mas no cambia NADA (cabe entero).
   Ojo: tiene que ser `max-width`, no `width`; con un ancho fijo el logo se deformaria. */
.app-logo {
    height: 44px;
    width: auto;
    max-width: 100%;
    object-fit: contain;
    display: block;
    /* Resplandor claro para que el logo destaque sobre el verde de la cabecera: la
       sombra sigue la silueta (el PNG tiene transparencia) y no dibuja un cajon. */
    filter: drop-shadow(0 0 3px rgba(255, 255, 255, 0.85)) drop-shadow(0 0 7px rgba(255, 255, 255, 0.55));
}
/* EL HUECO DEL LOGO AL ARRANCAR, que se veia en el emulador durante el primer segundo.
   `ui/logo.js` oculta el `<img>` con el atributo `hidden`, pero eso NO basta: la regla
   de autor de arriba (`display: block`) pesa mas que la del navegador
   (`[hidden] { display: none }` en su hoja por defecto), asi que la imagen se pintaba
   igual y salia su hueco. Aqui se le da al atributo la fuerza que le faltaba. */
.app-logo[hidden] { display: none; }
.app-title-text { font-size: var(--text-base); font-weight: 700; color: var(--text-inverse); }
.auth-head { background: #1F2937; color: #fff; }
.auth-head p { color: rgba(255,255,255,0.7); }
.auth-logo { width: 36px; height: auto; max-width: 100%; margin: 0 auto 8px; display: block; }

/* ---------- 2. ICONOS MÁS GRANDES ---------- */
.hdr-icon { width: 36px; height: 36px; font-size: 1.2rem; }
.hdr-icon .icon, .hdr-icon svg { width: 22px; height: 22px; }

.tab-ico { font-size: 1.5rem; line-height: 1; }
.tab-ico .icon, .tab-ico svg { width: 28px; height: 28px; }

.icon    { width: 1.375rem; height: 1.375rem; }
.icon-sm { width: 1.125rem; height: 1.125rem; }
.icon-lg { width: 1.75rem;  height: 1.75rem; }

.tab-btn { min-height: 60px; padding: 10px 4px 8px; }

/* ============================================================
   ACTUALIZAR PLAN (tarjetas de planes + métodos de pago)
   ============================================================ */
/* ============================================================
   LOS PLANES, UNA COLUMNA POR PLAN (ronda 13, P3)
   ============================================================
   EL DEFECTO, MEDIDO Y REPORTADO POR EL DUEÑO: «modificar la exposición del modal planes para que
   muestre 1 columna por fila (una columna un plan)».

   Estaba con `repeat(auto-fit, minmax(150px, 1fr))`, que **se acomoda solo** y da resultados
   distintos según el ancho: con el modal a 300 px de contenido cabía **una** columna (y parecía
   estar bien), pero en cuanto hay 384 px —el ancho de la app en un móvil normal— caben **DOS** y
   los planes salen **apretados de lado**, a 155 px cada uno y 645 px de alto.

   POR QUÉ ESTE DEFECTO ESTUVO ESCONDIDO: se medía en un emulador de 360 px CSS de ancho, donde
   solo cabía una columna. En el **Redmi Note 8 (393 px)** y en el emulador corregido (384 px) el
   `auto-fit` sí parte en dos. **El instrumento hacía invisible el fallo.** Por eso ahora la
   columna es explícita: no depende del ancho de quien mire.

   Y el número que lo justifica: apilados, los planes miden 372 y 458 px en una columna de 323, y
   solo hay que desplazar **73 px** — frente a los 645 px de alto y 155 de ancho que tenían de lado. */
.planes-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 12px;
}
.plan-card {
    position: relative;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    text-align: left;
    box-shadow: var(--shadow-sm);
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast);
}
.plan-card:hover { box-shadow: var(--shadow-md); }
.plan-card.plan-actual { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary), var(--shadow-md); }

.plan-card .plan-cab { padding: 16px 16px 13px; border-bottom: 1px solid var(--border); }
.plan-card.plan-freemium .plan-cab { background: var(--secondary-50); }
.plan-card.plan-premium_plus .plan-cab { background: linear-gradient(135deg, #ffffff, var(--primary-50)); }

.plan-card .plan-tag { display: inline-flex; align-items: center; gap: 5px; font-size: 0.62rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: .4px; color: var(--secondary); background: #fff;
    border: 1px solid var(--border); border-radius: 999px; padding: 3px 9px; margin-bottom: 9px; }
.plan-card.plan-premium_plus .plan-tag { color: var(--primary-dark); background: var(--primary-50); border-color: var(--primary-light); }
.plan-card.plan-actual .plan-tag { color: var(--primary-dark); background: var(--primary-light); border-color: transparent; }

.plan-card .plan-nombre { font-size: var(--text-base); font-weight: 700; color: var(--text-primary); }
.plan-card .plan-desc { font-size: var(--text-xs); color: var(--text-secondary); line-height: 1.4; margin-top: 4px; }
.plan-card .plan-precio { display: flex; align-items: baseline; gap: 5px; margin-top: 10px; }
.plan-card .plan-precio .monto { font-size: 1.5rem; font-weight: 800; color: var(--text-primary); letter-spacing: -.4px; }
.plan-card .plan-precio .per { font-size: var(--text-xs); color: var(--text-muted); }
.plan-card .plan-precio-bs { font-size: var(--text-xs); color: var(--text-secondary); font-weight: 600; margin-top: 2px; }

.plan-features { list-style: none; margin: 0; padding: 14px 16px 4px; display: flex; flex-direction: column; gap: 8px; }
.plan-features li { display: flex; gap: 9px; align-items: flex-start; font-size: var(--text-xs); color: var(--text-primary); line-height: 1.4; }
.plan-features li .feat-ic { width: 18px; height: 18px; border-radius: 50%; background: var(--primary-50); color: var(--primary);
    display: flex; align-items: center; justify-content: center; flex: 0 0 auto; margin-top: 1px; }
.plan-features li .feat-ic svg { width: 11px; height: 11px; }
.plan-features li.off { color: var(--text-muted); }
.plan-features li.off .feat-ic { background: var(--secondary-50); color: var(--text-muted); }

.plan-card .plan-pie { padding: 12px 16px 16px; margin-top: auto; }
.plan-card .plan-btn { width: 100%; padding: 11px 12px; border: 0; border-radius: var(--radius-md);
    background: var(--primary); color: #fff; font-weight: 700; font-size: var(--text-sm); cursor: pointer;
    box-shadow: 0 2px 6px rgba(39,174,96,.28); transition: background var(--transition-fast), transform var(--transition-fast); }
.plan-card .plan-btn:hover { background: var(--primary-dark); transform: translateY(-1px); }
.plan-card.plan-actual .plan-btn { background: var(--secondary-50); color: var(--text-secondary); box-shadow: none; cursor: default; transform: none; }

.plan-note { display: flex; gap: 8px; align-items: flex-start; font-size: var(--text-xs); color: var(--text-secondary);
    background: var(--primary-50); border: 1px solid var(--primary-light); border-radius: var(--radius-md); padding: 10px 12px; line-height: 1.45; }
.plan-note svg { width: 14px; height: 14px; color: var(--primary); flex: 0 0 auto; margin-top: 1px; }

/* Selección de beneficios + lanzamiento */
.plan-vigencia {
    grid-column: 1 / -1;
    text-align: center;
    font-size: var(--text-xs);
    color: var(--text-secondary);
    background: var(--secondary-50);
    border-radius: var(--radius-md);
    padding: 10px 14px;
    margin: 4px 0 0;
}
.plan-beneficios {
    grid-column: 1 / -1;
    margin-top: 12px;
    border-top: 1px solid var(--border);
    padding-top: 14px;
    text-align: left;
}
.plan-beneficios h3 {
    font-size: var(--text-sm);
    color: var(--text-primary);
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    gap: 8px;
}
.plan-beneficio {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    background: var(--secondary-50);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 10px 14px;
    margin-bottom: 8px;
}
.plan-beneficio > span { font-size: 1.05rem; width: 26px; height: 26px; border-radius: 8px; background: #fff;
    display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.plan-beneficio strong { font-size: var(--text-sm); }
.plan-beneficio p { font-size: var(--text-xs); color: var(--text-secondary); margin-top: 2px; line-height: 1.4; }

/* Métodos de pago */
.pago-metodos { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.pago-metodo {
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--bg-card);
    cursor: pointer;
    transition: border-color var(--transition-fast), background var(--transition-fast), box-shadow var(--transition-fast);
}
.pago-metodo:hover { border-color: var(--border-strong); background: var(--secondary-50); }
.pago-metodo.metodo-activo { border-color: var(--primary); background: var(--primary-50); box-shadow: 0 0 0 1px var(--primary); }
.pago-metodo .metodo-icono { width: 38px; height: 38px; border-radius: 10px; background: var(--secondary-50); color: var(--text-secondary);
    display: flex; align-items: center; justify-content: center; flex: 0 0 auto; transition: background var(--transition-fast), color var(--transition-fast); }
.pago-metodo.metodo-activo .metodo-icono { background: var(--primary); color: #fff; }
.pago-metodo .metodo-icono svg { width: 20px; height: 20px; }
.pago-metodo .metodo-info { flex: 1; min-width: 0; }
.pago-metodo .metodo-nombre { display: block; font-weight: 700; font-size: var(--text-sm); color: var(--text-primary); }
.pago-metodo .metodo-desc { display: block; font-size: var(--text-xs); color: var(--text-secondary); margin-top: 1px; }
.pago-metodo .metodo-check { width: 20px; height: 20px; border-radius: 50%; border: 2px solid var(--border-strong);
    display: flex; align-items: center; justify-content: center; color: transparent; flex: 0 0 auto; transition: all var(--transition-fast); }
.pago-metodo.metodo-activo .metodo-check { border-color: var(--primary); background: var(--primary); color: #fff; }
.pago-metodo .metodo-check svg { width: 12px; height: 12px; }
.pago-metodo .metodo-radio { position: absolute; opacity: 0; pointer-events: none; }

/* Orden de compra (cabecera del modal de pago) */
.pago-orden { display: flex; align-items: center; gap: 12px; background: var(--secondary-50); border: 1px solid var(--border);
    border-radius: var(--radius-md); padding: 10px 14px; margin-bottom: 14px; }
.pago-orden .po-icon { width: 34px; height: 34px; border-radius: 9px; background: var(--primary); color: #fff;
    display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.pago-orden .po-icon svg { width: 18px; height: 18px; }
.pago-orden .po-prod { flex: 1; min-width: 0; }
.pago-orden .po-prod strong { display: block; font-size: var(--text-sm); color: var(--text-primary); }
.pago-orden .po-prod span { font-size: var(--text-xs); color: var(--text-secondary); }
.pago-orden .po-total { text-align: right; }
.pago-orden .po-total strong { display: block; font-size: 1.1rem; font-weight: 800; color: var(--primary-dark); }
.pago-orden .po-total span { font-size: var(--text-xs); color: var(--text-secondary); }

/* Detalle del método (datos + formulario) */
.pago-detalle { border-top: 1px solid var(--border); padding-top: 14px; }
.pago-detalle .pay-intro { font-size: var(--text-sm); color: var(--text-secondary); margin: 0 0 10px; }
.pago-detalle .pay-intro strong { color: var(--text-primary); }
.pay-datos { border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden; margin-bottom: 4px; }
.pay-datos .pd-fila { display: flex; justify-content: space-between; gap: 12px; padding: 8px 12px; font-size: var(--text-sm); }
.pay-datos .pd-fila + .pd-fila { border-top: 1px solid var(--border); }
.pay-datos .pd-sep { padding: 6px 12px; background: var(--secondary-50); border-top: 1px solid var(--border); font-size: var(--text-xs);
    font-weight: 700; text-transform: uppercase; letter-spacing: .4px; color: var(--text-muted); }
.pay-datos .pd-sep:first-child { border-top: 0; }
.pay-datos .pd-lbl { color: var(--text-muted); }
.pay-datos .pd-val { text-align: right; font-weight: 600; color: var(--text-primary); word-break: break-word; }
.pay-datos .pd-val .bs { display: block; font-weight: 400; font-size: var(--text-xs); color: var(--text-muted); }
.pay-datos .pd-total { background: var(--primary-50); }
.pay-datos .pd-total .pd-val { font-size: 1rem; font-weight: 800; color: var(--primary-dark); }
.pay-campo { display: block; margin-top: 12px; }
.pay-campo > span { display: block; font-size: var(--text-xs); font-weight: 700; color: var(--text-primary); margin-bottom: 4px; }
.pay-campo input, .pay-campo select { width: 100%; padding: 10px 12px; border: 1px solid var(--border-strong); border-radius: var(--radius);
    font-family: inherit; font-size: var(--text-sm); color: var(--text-primary); background: var(--bg-card);
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast); }
.pay-campo input:focus, .pay-campo select:focus { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-50); outline: none; }
.pay-campo small { display: block; font-size: var(--text-xs); color: var(--text-muted); margin-top: 3px; }
.pay-enlace { display: flex; gap: 8px; align-items: center; background: var(--secondary-50); border: 1px solid var(--border);
    border-radius: var(--radius-md); padding: 10px 12px; margin: 12px 0 4px; }
.pay-enlace svg { width: 16px; height: 16px; color: var(--text-secondary); flex: 0 0 auto; }
.pay-enlace a { font-size: var(--text-xs); font-weight: 600; color: var(--primary-dark); }
.pago-accion {
    margin-top: 16px; width: 100%; padding: 13px 12px; border: 0; border-radius: var(--radius-md);
    background: var(--primary); color: #fff; font-weight: 700; font-size: var(--text-sm); cursor: pointer;
    box-shadow: 0 2px 8px rgba(39,174,96,.3); transition: background var(--transition-fast), transform var(--transition-fast);
}
.pago-accion:hover { background: var(--primary-dark); transform: translateY(-1px); }
.pago-accion:disabled { background: var(--text-muted); box-shadow: none; cursor: not-allowed; transform: none; }
.pago-volver { text-align: center; margin-top: 8px; }
.pago-volver a { font-size: var(--text-xs); color: var(--text-muted); text-decoration: none; }
.pago-volver a:hover { color: var(--text-secondary); }
.pago-aviso { display: flex; gap: 7px; align-items: flex-start; font-size: var(--text-xs); color: var(--text-secondary); margin-top: 10px; line-height: 1.4; }
.pago-aviso svg { width: 14px; height: 14px; color: var(--totalizar); flex: 0 0 auto; margin-top: 1px; }

/* Confirmación */
#confirmacion-body .conf-ok { width: 64px; height: 64px; border-radius: 50%; background: var(--primary-50); color: var(--primary);
    display: flex; align-items: center; justify-content: center; margin: 0 auto 12px; }
#confirmacion-body .conf-ok svg { width: 32px; height: 32px; }
#confirmacion-body h3 { margin-bottom: 6px; }
#confirmacion-body p { color: var(--text-secondary); font-size: var(--text-sm); line-height: 1.5; margin-bottom: 8px; }
.conf-pasos { display: flex; flex-direction: column; gap: 8px; text-align: left; margin: 12px 0; }
.conf-pasos .paso { display: flex; gap: 10px; align-items: flex-start; font-size: var(--text-xs); color: var(--text-secondary); }
.conf-pasos .paso b { width: 22px; height: 22px; border-radius: 50%; background: var(--secondary-50); flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center; font-size: 0.7rem; color: var(--text-secondary); }
.conf-pasos .paso.actual b { background: var(--primary); color: #fff; }
#confirmacion-body .conf-btn {
    margin-top: 14px; padding: 11px 26px; border: 0; border-radius: var(--radius-md);
    background: var(--primary); color: #fff; font-weight: 700; font-size: var(--text-sm); cursor: pointer;
    box-shadow: 0 2px 8px rgba(39,174,96,.3);
}
#confirmacion-body .conf-btn:hover { background: var(--primary-dark); }

/* MIENTRAS SE DECIDE SI HAY QUE PEDIR LA ENTRADA (ver el principio de `interfaz.html`),
   el marco de la app no se enseña. MEDIDO en el emulador el 01/10/2026: sin esto quedaban
   ~0,4 s de "Inicio" vacío —cabecera y menú de abajo, sin nada dentro— antes de la pantalla
   de acceso, que es exactamente lo que el dueño reportó como «se ve la app vacía antes del
   acceso». El marco se suelta en cuanto se sabe, y si hay que entrar ya lo tapa la capa. */
html.arrancando #app { visibility: hidden; }

/* ============================================================
   ACCESO DEL CLIENTE NATIVO (core/acceso.js)
   Solo se ve DENTRO del paquete nativo: en la web el shell inyecta los valores y
   esta capa no se muestra nunca. Los estilos van aquí y no en línea para que el
   HTML de la app no dependa de nada del entorno.
   ============================================================ */
.acceso-nativo {
    position: fixed;
    inset: 0;
    z-index: 9999;
    overflow-y: auto;
    padding: 34px 20px 24px;
    /* LOS BLOQUES, REPARTIDOS POR LA PANTALLA (07/10/2026, pedido del dueno).
       Antes la columna se quedaba pegada arriba y sobraba un hueco al final. Ahora la capa es una
       columna flexible y el hueco se reparte ENTRE los bloques en vez de quedarse muerto al pie.
       ERAN TRES y ahora son DOS (07/10/2026): se quitó el contenedor del ecosistema Avero, porque
       **en los teléfonos quedaba fuera de pantalla**. La vitrina arriba y el formulario debajo.
       Si el contenido no cabe en un movil pequeno, la capa ya tiene `overflow-y: auto` y se
       desplaza: repartir nunca puede esconder nada. */
    display: flex;
    flex-direction: column;
    /* EL FONDO DE LA CASA, CON EL ENCUADRE NATURAL (corregido el 07/10/2026).
     *
     * Aquí había `auto 200%` —un acercamiento al doble de alto—, y fue un ERROR DE ENCUADRE que el
     * dueño cazó: «las ondas se desplazaron hacia arriba y entorpecen todo el texto desde 1/3
     * hacia abajo». Con el alto al doble y anclado abajo, lo que se ve es la MITAD INFERIOR de la
     * imagen, o sea las ondas suben hasta un tercio de la pantalla.
     *
     * Estaba puesto para que el verde quedara detrás del formulario. Pero la razón por la que hacía
     * falta era otra —las ondas oscuras— y se arregla en el MATERIAL, no en el encuadre: el fondo
     * nuevo tiene el verde menta ACLARADO un 50 %, así que se lee en todo el alto (medido: el peor
     * punto pasa de 8,6:1 a 11,3:1) y no hace falta empujar nada.
     *
     * Con `cover` y anclado abajo, las ondas se quedan en la franja de abajo —donde él quería— en
     * cualquier pantalla, y el resto queda claro. */
    background: #FFFFFF url('fondo/fondo-app.webp') center bottom / cover no-repeat;
    color: var(--text-primary);
}
/* EL `@media (min-aspect-ratio: 4/3)` QUE HABÍA AQUÍ YA NO HACE FALTA, y se quita.
 *
 * Existía para tapar las «dos ventanas blancas» de un monitor: el encuadre `auto 200%` dejaba la
 * imagen en una franja central. Con `cover` en todas partes, el fondo llena el ancho SIEMPRE, así
 * que la excepción sobra. Y una regla que ya no hace nada es una trampa para el que venga: parece
 * que protege de algo y no protege de nada. */
.acceso-nativo[hidden] { display: none; }
/* La marca, del tamaño que ya generó la biblioteca de WordPress (768x471): no se
   reescala en CSS; se pinta a 196 px de ancho y el navegador usa el resto. */
.acceso-nativo__logo { width: 196px; height: auto; display: block; margin: 0 auto 4px; }
.acceso-nativo__lema {
    margin: 0;
    text-align: center;
    font-size: .88rem;
    color: var(--text-secondary);
}
/* LA COLUMNA DEL ACCESO (punto 6 del dueno, 05/10/2026).
   `.acceso-nativo` es la capa a pantalla completa: su FONDO tiene que cubrir todo, pero su
   CONTENIDO no. Las pestanas «Iniciar Sesion» / «Registrarme» colgaban de la capa, asi que en
   pantalla ancha se estiraban a todo el ancho mientras el formulario si estaba limitado: se veian
   desbordando por encima. MEDIDO en el emulador a 1600x720: las pestanas ocupaban 1600 px y la caja
   del formulario quedaba centrada y estrecha.
   El tope es el MISMO que el de la caja (480 px, el ancho del contenedor de la app), para que todo
   el acceso se vea alineado; en un movil normal (392 px) este tope no llega a actuar y no cambia
   nada de lo que ya se veia bien. */
.acceso-nativo__centro {
    width: 100%;
    max-width: 480px;
    margin: 0 auto;
    /* La columna de los DOS bloques: la vitrina y el formulario (con sus pestanas y el pie legal).
       `space-between` reparte el alto que sobra ENTRE ellos, asi que el hueco de abajo se lo queda
       el formulario en vez de quedarse vacio. */
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}
/* El contenedor que rellena `core/auth-form.js` tiene que poder crecer: sin esto, el `flex: 1`
   de la columna de dentro no tiene de donde tomar el alto y el reparto no ocurre. */
#acceso-nativo-formulario {
    flex: 1;
    display: flex;
    flex-direction: column;
}

/* El bloque del formulario: pestanas + los tres paneles + el pie legal, como UNA pieza.
   Ver el comentario del marcado en `core/auth-form.js`: sin agruparlos, el reparto del alto
   metia un hueco entre las pestanas y los campos, que van pegados. */
.acceso-nativo__bloque {
    display: flex;
    flex-direction: column;
}

/* ============================================================
   LA VITRINA DE LA ENTRADA (diseno aprobado el 07/10/2026)
   ============================================================
   Tres diapositivas que se DESVANECEN solas. NO es un carrusel: no hay puntitos, ni miniaturas,
   ni nada que se arrastre — el dueno lo descarto expresamente. Solo fundido cruzado.

   Y SOLO se anima `opacity` con un `transform` casi imperceptible: las dos cosas que pinta la
   GPU. El caso duro de este proyecto es el Redmi Note 8 (2019), y una animacion que obligue al
   navegador a repintar la capa entera da tirones ahi. */
.entrada-vitrina {
    padding: 8px;
    margin: 0 0 0;
    border-radius: 22px;
    background: var(--cristal);
    border: 1px solid var(--cristal-borde);
    -webkit-backdrop-filter: var(--cristal-desenfoque);
    backdrop-filter: var(--cristal-desenfoque);
    box-shadow: 0 18px 44px rgba(6, 60, 30, .20);
}
.entrada-vitrina__marco {
    position: relative;
    height: 232px;
    border-radius: 16px;
    overflow: hidden;
}
/* EL RITMO: 36 SEGUNDOS PARA LAS TRES, o sea 12 por diapositiva (pedido del dueno, 07/10/2026:
   «la transicion es muy rapida, duplicale el tiempo»). Antes eran 18 y 6.
   Los tiempos viven SOLO aqui: los keyframes van en porcentaje, asi que cambiar esta duracion
   reajusta el fundido entero sin tocar nada mas. Los dos retrasos tienen que ser un TERCIO de la
   duracion cada uno (36 / 3 = 12) para que las tres se turnen sin solaparse. */
.entrada-dia {
    position: absolute;
    inset: 0;
    opacity: 0;
    animation: entradaFundido 36s infinite;
}
.entrada-dia:nth-child(2) { animation-delay: 12s; }
.entrada-dia:nth-child(3) { animation-delay: 24s; }
.entrada-dia > img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* AQUÍ ESTABA EL VELO, Y SE QUITÓ (07/10/2026, pedido del dueño).
 *
 * Era un degradado oscuro de arriba abajo que cubría TODA la diapositiva, para que el texto blanco
 * contrastara. El dueño lo cazó con un refrán criollo: **«lo que es bueno para el pavo no lo es
 * para la pava»** — el texto ganaba legibilidad y **la foto perdía su luz**, que es justo lo que se
 * quiere enseñar.
 *
 * El efecto está INVERTIDO: la imagen va limpia, y el resplandor oscuro lo lleva **el texto**
 * (ver `.entrada-dia__pie`, más abajo). Es la misma técnica del logo —un halo alrededor de las
 * letras— pero al revés: oscuro en vez de claro, y solo donde hay letras.
 *
 * Y no se deja la clase muerta: si alguien la vuelve a usar, que sea a conciencia. */
.entrada-dia__logo {
    position: absolute;
    top: 12px;
    left: 0;
    right: 0;
    z-index: 2;
    display: flex;
    justify-content: center;
    padding: 0 14px;
}
/* EL RESPLANDOR DEL LOGO: BLANCO, SIN HALO VERDE (corregido el 07/10/2026, pedido del dueno:
   «el resplandor verde del logo mata las imagenes de la presentacion, con la capa blanca seria
   suficiente»).

   Tenia razon y era un exceso mio: el halo verde competia con el verde de las fotos —que ya son
   verdes— y las apagaba. Ahora son tres capas BLANCAS (el filo, el cuerpo y el halo) mas una
   oscura por debajo, que es la que despega el logo de la foto sin colorearlo.

   El PNG tiene el fondo TRANSPARENTE de verdad (alfa 0 en todo el borde, medido), asi que el
   resplandor sigue la SILUETA del carro y las letras, no un rectangulo. */
.entrada-dia__logo img {
    display: block;
    width: 79%;
    height: auto;
    filter:
        drop-shadow(0 0 2px rgba(255, 255, 255, 1))
        drop-shadow(0 0 8px rgba(255, 255, 255, .95))
        drop-shadow(0 0 18px rgba(255, 255, 255, .75))
        drop-shadow(0 3px 9px rgba(4, 32, 16, .55));
}
.entrada-dia__pie {
    position: absolute;
    left: 14px;
    right: 14px;
    bottom: 12px;
    z-index: 2;
    color: #fff;
    /* EL TEXTO SE DESVANECE APARTE DE LA IMAGEN (07/10/2026).
     *
     * LO QUE PASABA, con los tiempos medidos: `entradaFundido` dura 36 s y cada diapositiva ocupa
     * 12 s. La que sale se apaga del 33 % al 40 % (11,88 s a 14,4 s) y la que entra se enciende del
     * 0 % al 7 % de SU ciclo (12 s a 14,52 s). O sea: **2,4 segundos con las dos capas a la vez**, y
     * como el texto iba DENTRO de la diapositiva, se desvanecia con ella — **los dos titulares
     * encima, los dos a medio gas, ilegibles justo en el cambio**. Lo cazo una captura de pantalla.
     *
     * LA SOLUCION: el texto lleva su propio ciclo (`entradaPie`) que **se apaga ANTES de que empiece
     * el de la que entra**. Queda asi: el texto se va, las imagenes se cruzan solas, y el texto nuevo
     * aparece cuando su imagen ya manda. **En el cruce no hay ningun texto**, en vez de dos.
     *
     * El LOGO no lo necesita, y es a proposito: es **la misma imagen en las tres diapositivas**, asi
     * que dos logos al 50 % se ven igual que uno. Si algun dia una diapositiva lleva un logo
     * distinto, hay que darle este mismo tratamiento. */
    animation: entradaPie 36s infinite;
}
.entrada-dia:nth-child(2) .entrada-dia__pie { animation-delay: 12s; }
.entrada-dia:nth-child(3) .entrada-dia__pie { animation-delay: 24s; }
/* EL RESPLANDOR OSCURO VA EN EL TEXTO, NO EN LA DIAPOSITIVA (07/10/2026).
   Cuatro capas oscuras alrededor de las letras —la misma idea del resplandor del logo, pero al
   revés—. Así el pie se lee sobre cualquier foto sin apagar la foto. */
.entrada-dia__pie b {
    display: block;
    font-size: .98rem;
    font-weight: 700;
    text-shadow:
        0 0 3px rgba(4, 22, 12, .95),
        0 0 8px rgba(4, 22, 12, .88),
        0 0 16px rgba(4, 22, 12, .68),
        0 2px 10px rgba(0, 0, 0, .75);
}
.entrada-dia__pie small {
    display: block;
    margin-top: 3px;
    font-size: .78rem;
    /* Sin transparencia: un blanco al 95 % sobre una foto clara pierde lo que se gana con el halo. */
    text-shadow:
        0 0 3px rgba(4, 22, 12, .95),
        0 0 8px rgba(4, 22, 12, .82),
        0 1px 8px rgba(0, 0, 0, .72);
}

@keyframes entradaFundido {
    0%   { opacity: 0; transform: scale(1.035); }
    7%   { opacity: 1; transform: scale(1); }
    33%  { opacity: 1; transform: scale(1); }
    40%  { opacity: 0; transform: scale(1.015); }
    100% { opacity: 0; transform: scale(1.035); }
}
/* EL CICLO DEL TEXTO. Los numeros no son decorativos: son los que hacen que NO se pisen.
 *
 *   · del 0 % al 9 %  : el texto entra (la imagen ya esta entrando desde el 0 %; el texto llega un
 *                       poco despues, para que no aparezca letra sobre una foto a medio pintar),
 *   · del 9 % al 30 % : se lee entero,
 *   · del 30 % al 33% : SE APAGA, y termina en el 33 % — **justo antes** de que la diapositiva
 *                       siguiente empiece su ciclo (12 s). Ahi esta el arreglo,
 *   · del 33 % al 100%: nada. El texto de esta diapositiva no vuelve a salir.
 *
 * Y con el relevo de 12 s, el texto que entra no empieza hasta 1,08 s despues del cambio (9 % de
 * 12 s), que es cuando la imagen nueva ya manda.
 *
 * SI ALGUIEN TOCA ESTOS PORCENTAJES, hay una prueba que lo vigila sin mirar el archivo: calcula los
 * intervalos y exige que **en ningun instante haya dos textos visibles a la vez**
 * (`scripts/entrada-desvanecido-test.mjs`). Y esa prueba tambien comprueba lo contrario —que las
 * IMAGENES si se cruzan—, para que nadie "arregle" el solapamiento apagando la presentacion. */
@keyframes entradaPie {
    0%   { opacity: 0; }
    6%   { opacity: 0; }
    9%   { opacity: 1; }
    30%  { opacity: 1; }
    33%  { opacity: 0; }
    100% { opacity: 0; }
}
/* QUIEN PIDE MENOS MOVIMIENTO, VE LA PRIMERA DIAPOSITIVA QUIETA. No es un detalle: hay gente a
   la que el movimiento le marea, y el sistema ya lo dice por ellos. */
@media (prefers-reduced-motion: reduce) {
    .entrada-dia { animation: none; }
    .entrada-dia__pie { animation: none; }
    .entrada-dia:first-child { opacity: 1; }
    .entrada-dia:first-child .entrada-dia__pie { opacity: 1; }
}

/* AQUÍ ESTABA EL CONTENEDOR DEL LOGO DE AVERO, Y SE QUITÓ (07/10/2026).
 *
 * Estaba reservado y vacío, a la espera del archivo del logo del ecosistema. El dueño lo ha mandado
 * quitar con una razón que se mide: **«en los teléfonos queda fuera de pantalla»**. Y es verdad — en
 * un móvil el contenido de la entrada ya llega al borde, así que un bloque más al pie no se ve: se
 * pierde sitio en la caja del formulario, que es lo que de verdad hay que enseñar ahí.
 *
 * Se van con él la caja, el cristal y el texto «Ecosistema Avero Global».
 *
 * OJO, QUE NO SE CONFUNDA: los CAMPOS del registro con el mismo nombre (`avero_acepto_eco` y
 * `avero_acepto_marketing`) NO se tocan — son aceptaciones que el usuario marca al crear la cuenta y
 * tienen sus pruebas. Esto que se quita era solo el recuadro decorativo del pie de la entrada. */
.acceso-nativo__caja {
    display: flex;
    flex-direction: column;
    width: 100%;
    /* El MISMO tope que la columna: si la caja fuera mas estrecha que las pestanas, volveria a
       verse desalineado — que es lo que se arregla aqui. */
    max-width: 480px;
    margin: 8px auto 0;
    padding: 18px 18px 20px;
    /* EL FORMULARIO, EN CRISTAL (07/10/2026), pedido por el dueno.
       Y DEBAJO DEL CONTENEDOR DE IMAGENES, CERCA PERO SIN MONTARSE: por eso el margen de arriba
       es 8 px y no un solape. Se probo con solape (-20 px y -10 px) y lo corrigio el: «debe quedar
       debajo del contenedor de imagenes (cerca pero no montado)». */
    background: var(--cristal);
    border: 1px solid var(--cristal-borde);
    -webkit-backdrop-filter: var(--cristal-desenfoque);
    backdrop-filter: var(--cristal-desenfoque);
    border-radius: var(--radius-lg);
    box-shadow: 0 18px 44px rgba(6, 60, 30, .20);
}
/* `display: flex` PISA el atributo `hidden` (solo apaga lo que no tiene display propio):
   la pestaña inactiva se seguía viendo. La regla explícita lo apaga de verdad — es la
   MISMA trampa que ya sufrió el logo (`.app-logo[hidden]`). */
.acceso-nativo__caja[hidden] { display: none; }
/* Y EL BLOQUE DE UBICACIÓN, POR LO MISMO (B2bis, 05/10/2026). Es la TERCERA vez que esta trampa
   aparece en este archivo —el logo, la caja y ahora este bloque—: cuando un país no tiene
   subdivisiones cargadas el bloque se oculta entero, y si alguna regla le diera un `display`
   propio, el usuario vería campos vacíos que no llevan a ninguna parte. La guarda lo comprueba. */
.acceso-nativo__ubicacion[hidden] { display: none; }
.acceso-nativo__etiqueta { font-size: .8rem; font-weight: 600; margin: 14px 0 6px; }
.acceso-nativo__etiqueta:first-child { margin-top: 0; }
.acceso-nativo__campo {
    width: 100%;
    padding: 12px;
    font-size: .95rem;
    border: 1.5px solid var(--cristal-borde);
    border-radius: var(--radius-md);
    /* Los campos, un poco mas claros que la tarjeta: sobre el cristal, un campo blanco OPACO
       partiria la tarjeta en trozos y se perderia el efecto. */
    background: rgba(255, 255, 255, .82);
    color: inherit;
}
.acceso-nativo__campo:focus { outline: none; border-color: var(--primary); }
.acceso-nativo__recordar {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 14px;
    font-size: .82rem;
    font-weight: 400;
    color: var(--text-secondary);
}
.acceso-nativo__recordar input { width: auto; }
.acceso-nativo__error { margin: 8px 0 0; font-size: .85rem; color: var(--accent-error); }
/* RECUPERACIÓN DE CONTRASEÑA (Camino B, 06/10/2026).
   «¿Olvidaste tu contraseña?» y «Volver a iniciar sesión» son BOTONES, no enlaces: el
   formulario vive dentro de la app nativa y un enlace sacaría al usuario del paquete. Se
   pintan como un enlace (sin fondo ni borde) para que se lean como lo que son. */
.acceso-nativo__olvide {
    display: block;
    width: 100%;
    margin: 10px 0 0;
    padding: 6px 0;
    background: none;
    border: 0;
    color: var(--primary-dark);
    font: inherit;
    font-size: .9rem;
    text-align: center;
    text-decoration: underline;
    cursor: pointer;
}
.acceso-nativo__olvide:hover { color: var(--primary); }
/* El aviso de «revisa tu correo»: no es un error, así que NO va en rojo. */
.acceso-nativo__hecho {
    margin: 8px 0 0;
    font-size: .88rem;
    color: var(--primary-dark);
    background: var(--primary-50);
    border: 1px solid var(--primary-light);
    border-radius: 8px;
    padding: 8px 10px;
}
.acceso-nativo__boton {
    width: 100%;
    margin-top: 18px;
    padding: 13px;
    font-size: 1rem;
    font-weight: 600;
    border: 0;
    border-radius: var(--radius-md);
    background: var(--primary);
    color: #fff;
    font-family: inherit;
}
.acceso-nativo__boton[disabled] { opacity: .6; }
.acceso-nativo__pie {
    margin: 18px 0 0;
    text-align: center;
    font-size: .78rem;
    /* EL PIE LEGAL VA SOBRE EL FONDO, NO SOBRE UNA TARJETA (corregido el 07/10/2026, reportado por
       el dueno: «el texto con los enlaces a los documentos legales no contrastan»).

       Y EL BLANCO, SOLO, NO LO ARREGLA — esta MEDIDO: sobre el verde del fondo (mediana #8ACD8A)
       el texto blanco da un contraste de **1,88:1**, y en el punto mas claro del fondo **1,06:1**,
       cuando la norma pide 4.5. Es PEOR que el gris oscuro que habia. El problema no era el color
       del texto: es que **el fondo es demasiado claro para texto blanco**.

       Asi que se le da al pie su propia PLACA verde oscura (el mismo recurso que la tarjeta del
       formulario, pero oscura). Con el blanco encima, el contraste pasa de 4.5 y el texto se lee
       en cualquier zona del fondo. La placa va pegada al texto (`align-self`), no de lado a lado:
       una banda oscura de borde a borde pesaria demasiado y competiria con el bloque de abajo. */
    align-self: center;
    padding: 6px 13px;
    border-radius: 11px;
    background: rgba(6, 40, 22, .5);
    color: rgba(255, 255, 255, .92);
}
/* Y LOS DOS ENLACES, EN NEGRITA Y BLANCOS.
   EL AMBITO ES SOLO EL PIE, y es importante: estos mismos botones se usan DENTRO del formulario de
   registro, sobre la tarjeta clara, y alli tienen que seguir siendo verdes. Un cambio global los
   habria dejado blancos sobre blanco — invisibles. */
.acceso-nativo__pie .acceso-nativo__legal {
    color: #fff;
    font-weight: 700;
    /* El aire se reserva SIEMPRE y no solo al pasar por encima: si se anadiera en el `hover`, el
       texto se moveria al apuntarlo con el raton. */
    padding: 2px 5px;
    border-radius: 5px;
}
/* Al pasar por encima: fondo verde de la casa y texto blanco, que es lo que pidio el dueno
   («hover verde/blanco»). */
.acceso-nativo__pie .acceso-nativo__legal:hover,
.acceso-nativo__pie .acceso-nativo__legal:focus-visible {
    background: var(--primary-dark);
    color: #fff;
    text-decoration: none;
}
/* Los enlaces a los documentos legales, que aquí son BOTONES (los abre el modal de la
   app, no una página del servidor: eso sacaría al usuario del paquete). Se ven como un
   enlace, pero es un botón con `data-legal`, igual que los del menú. */
.acceso-nativo__legal {
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-weight: 600;
    color: var(--primary-dark);
    text-decoration: underline;
    cursor: pointer;
}

/* Pestañas «Iniciar Sesión / Registrarme». */
.acceso-nativo__pestanas {
    display: flex;
    gap: 4px;
    /* Cerquita de la vitrina (9 px) y pegada a su formulario (8 px): las tres piezas —vitrina,
       pestanas y formulario— se leen como una sola columna. */
    margin: 9px 0 8px;
    padding: 4px;
    border-radius: 13px;
    background: rgba(255, 255, 255, .55);
    border: 1px solid rgba(255, 255, 255, .62);
}
.acceso-nativo__pestana {
    flex: 1;
    padding: 9px;
    font-size: .88rem;
    font-weight: 600;
    /* Sin borde: la pildora lo lleva el contenedor, y la activa se marca con blanco. Con dos
       botones con borde dentro de otra caja con borde se veia un marco dentro de otro marco. */
    border: 0;
    border-radius: 10px;
    background: transparent;
    color: var(--text-secondary);
    font-family: inherit;
    cursor: pointer;
}
.acceso-nativo__pestana--activa {
    background: #fff;
    color: var(--primary-dark);
    box-shadow: 0 1px 5px rgba(0, 0, 0, .12);
}

/* Nota pequeña junto a una etiqueta (lo mismo que el `span.auth-note` de la web). */
.acceso-nativo__nota { font-weight: 400; color: var(--text-secondary); }

/* El campo de contraseña con el ojo para verla/ocultarla. */
.acceso-nativo__clave { position: relative; }
.acceso-nativo__clave .acceso-nativo__campo { padding-right: 56px; }
.acceso-nativo__ojo {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    padding: 6px 10px;
    border: 0;
    background: none;
    color: var(--primary-dark);
    font-size: .78rem;
    font-weight: 600;
    cursor: pointer;
}

/* Las casillas de consentimiento del registro. */
.acceso-nativo__consentimiento { margin: 14px 0 0; font-size: .82rem; color: var(--text-secondary); line-height: 1.5; }
.acceso-nativo__check { display: flex; gap: 8px; align-items: flex-start; }
.acceso-nativo__check input { width: auto; margin-top: 2px; }


/* ============================================================
   EL MODAL LEGAL TIENE QUE QUEDAR POR ENCIMA DE LA CAPA DE ACCESO

   EL FALLO QUE ARREGLA (reportado por el dueño): «los enlaces a documentos legales
   desde el formulario [...] no responden al click».

   No era el clic: el manejador escucha en el documento entero y el modal SE ABRÍA
   (`ui/legal-view.js` le añade `show`, y `.modal.show` es `display: flex`). Lo que
   pasaba es que el modal quedaba **por debajo**: la capa de acceso es `z-index: 9999`
   y `.modal` es `z-index: 1000`. El documento se abría detrás de una capa opaca, así
   que desde fuera se veía exactamente igual que un enlace muerto.

   POR QUÉ UNA REGLA SOLO PARA EL LEGAL, y no subir `.modal`:
   ese `1000` lo comparten los demás modales, y el orden de capas de este proyecto es
   una cadena MEDIDA (999 el del cliente nativo, 1000 los modales, 2000 el escáner,
   9998 el aviso de sesión caducada, 9999 el acceso). Mover la base para arreglar un
   caso es como se rompen los otros cuatro.

   Y NO SE PUDO CAZAR ANTES porque la guarda que había (`scripts/acceso-test.mjs`)
   comprobaba que los botones `data-legal` estuvieran EN EL MARCADO, y estaban: lo que
   fallaba era que quedaran visibles. Ahora hay una guarda que lee el ORDEN DE CAPAS.
   ============================================================ */
#modal-legal { z-index: 10001; }

/* ============================================================
   LA AYUDA: EL MANUAL DENTRO DE LA APP, SIN CONEXION (04/10/2026)
   El manual es una pagina entera —con sus estilos y sus anclas— y se abre en un MARCO, asi que
   aqui solo hay que darle el hueco: casi toda la pantalla, con su propio desplazamiento.
   Va por ENCIMA del modal legal (10002 > 10001) porque la ayuda puede abrirse desde cualquier
   sitio y no debe quedar detras de nada.
   ============================================================ */
#modal-ayuda { z-index: 10002; }
.ayuda-modal {
    max-width: none;
    width: 100%;
    height: 100%;
    max-height: none;
    border-radius: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.ayuda-cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 10px 14px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
    background: #fff;
}
.ayuda-cabecera h2 { margin: 0; font-size: 1.05rem; }
.ayuda-cabecera .close { position: static; padding: 0 6px; font-size: 1.7rem; line-height: 1; }
.ayuda-marco { flex: 1; width: 100%; border: 0; background: #fff; }

/* LA VERSION Y LA FECHA, bajo la ayuda (04/10/2026). Discretas a proposito: informan, no llaman.
   Es el dato que se mira para saber QUE se estaba viendo cuando algo falla. */
.menu-version {
    font-size: 0.72rem;
    color: var(--text-secondary, #666);
    /* CENTRADA Y EN DOS LINEAS (04/10/2026): el dueño lo pidio asi —«una sobre otra centrada»—
       porque en una sola linea parecia «un texto añadido sin mas». */
    text-align: center;
    padding: 6px 12px 0;
    line-height: 1.6;
}
.menu-version span { display: block; }

/* LA LISTA DE REQUISITOS DE LA CONTRASEÑA (B3, 04/10/2026). Discreta y clara: gris mientras falta,
   verde cuando se cumple, con el visto delante. Es informacion, no un error. */
.acceso-nativo__requisitos {
    list-style: none;
    margin: 6px 0 2px;
    padding: 0 0 0 2px;
    font-size: 0.74rem;
    line-height: 1.6;
    color: var(--text-secondary, #6b7280);
}
.acceso-nativo__requisitos li { display: flex; align-items: center; gap: 6px; }
.acceso-nativo__requisitos li::before {
    content: '○';
    font-size: 0.8rem;
    color: #cbd5e1;
}
.acceso-nativo__requisitos li.cumplido { color: #16a34a; }
.acceso-nativo__requisitos li.cumplido::before { content: '✓'; color: #16a34a; font-weight: 700; }

/* LA CONFIRMACIÓN QUE NO COINCIDE (04/10/2026): el campo se marca, para que se vea sin leer el
   aviso. El aviso en sí usa el mismo hueco de error que el envío. */
.contrasena-no-coincide { border-color: #dc2626 !important; box-shadow: 0 0 0 3px rgba(220,38,38,0.12); }

/* EL WHATSAPP: EL PAIS Y EL NUMERO EN UNA FILA (B1, 04/10/2026). El pais es corto (bandera + codigo)
   y el numero se lleva el resto; asi se lee de un vistazo «+58 414-1234567». */
.acceso-nativo__whatsapp { display: flex; gap: 8px; align-items: stretch; }
.acceso-nativo__whatsapp .acceso-nativo__pais { flex: 0 0 auto; width: auto; min-width: 92px; max-width: 40%; }
.acceso-nativo__whatsapp input { flex: 1 1 auto; min-width: 0; }

/* LOS CAMPOS QUE ESPERAN A OTRO (B2, 04/10/2026): se ven apagados, para que se entienda que no es
   que esten rotos, es que falta elegir antes. */
.acceso-nativo__campo:disabled { background: #f3f4f6; color: #9ca3af; cursor: not-allowed; }
/* ============================================================
   LA BIENVENIDA DE INICIO (B + D del bloque F5, 05/10/2026)
   ============================================================
   LO QUE PIDIO EL DUENO: «el inicio se despliega sobre un fondo plano; quiero un fondo vivo [...] o
   una presentacion agradable de la aplicacion con una secuencia de uso», y despues: «fondo cuando la
   lista o contenedor esten vacios pero de manera sutil, casi imperceptible, una transparencia 80 a
   85%».

   EL SUELO (D): un degradado de la casa moviendose muy despacio, SIEMPRE detras. No depende de
   ninguna imagen —si algo falla, la pantalla nunca se ve rota— y solo se pinta cuando la lista esta
   vacia. Al 15-20% de visibilidad, que es su «casi imperceptible».

   LA SECUENCIA (B): cinco tarjetas que se deslizan con el dedo. Sin librerias: `scroll-snap` es del
   navegador. Y respeta `prefers-reduced-motion`, que es lo que hace que un fondo «vivo» no moleste a
   quien le molesta el movimiento. */
.inicio-bienvenida {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius-lg);
    padding: 22px 0 6px;
}
.inicio-bienvenida__capa {
    position: absolute;
    inset: -20%;
    z-index: 0;
    opacity: 0.18;
    background:
        radial-gradient(circle at 20% 25%, var(--primary-light, #dcfce7) 0%, transparent 45%),
        radial-gradient(circle at 80% 70%, var(--primary, #16a34a) 0%, transparent 50%),
        radial-gradient(circle at 55% 15%, #bbf7d0 0%, transparent 40%);
    background-size: 200% 200%;
    animation: inicio-suelo 48s ease-in-out infinite alternate;
}
@keyframes inicio-suelo {
    from { background-position: 0% 0%; }
    to   { background-position: 100% 100%; }
}
.inicio-bienvenida__contenido { position: relative; z-index: 1; }
.inicio-bienvenida__icono {
    display: flex;
    justify-content: center;
    margin-bottom: 8px;
    color: var(--text-muted);
}
.inicio-bienvenida__titulo { text-align: center; color: var(--text-primary); font-weight: 600; }
.inicio-bienvenida__texto {
    text-align: center;
    font-size: 0.9rem;
    margin-top: 8px;
    color: var(--text-secondary);
}
.inicio-secuencia {
    display: flex;
    gap: 12px;
    margin-top: 22px;
    padding: 0 16px 8px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.inicio-secuencia::-webkit-scrollbar { display: none; }
.inicio-tarjeta {
    flex: 0 0 auto;
    width: 198px;
    scroll-snap-align: center;
    background: var(--bg-card, #fff);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow);
    padding: 10px 10px 12px;
}
.inicio-tarjeta__marco {
    position: relative;
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--bg-app);
    aspect-ratio: 4 / 3;
}
.inicio-tarjeta__imagen { width: 100%; height: 100%; object-fit: cover; display: block; }
.inicio-tarjeta__numero {
    position: absolute;
    top: 6px; left: 6px;
    width: 22px; height: 22px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: var(--primary);
    color: #fff;
    font-size: 0.75rem;
    font-weight: 700;
}
.inicio-tarjeta__titulo { margin: 8px 0 2px; font-size: 0.9rem; font-weight: 600; }
.inicio-tarjeta__texto { margin: 0; font-size: 0.78rem; line-height: 1.35; color: var(--text-secondary); }
@media (prefers-reduced-motion: reduce) {
    .inicio-bienvenida__capa { animation: none; }
}

/* ============================================================
   EL CRISTAL, ESCALADO A LOS CONTENEDORES DE LAS PANTALLAS INTERIORES (07/10/2026)
   ============================================================
   El dueño lo pidió así: «me gusta la idea de formulario cristal aplicado a TODOS los contenedores
   de la aplicación, pero iniciamos con el formulario y luego lo ESCALAMOS». El formulario de la
   entrada se hizo primero (sesión 20) y esto es la escalada.

   LO QUE NO SE TOCA, y son decisiones suyas ya tomadas:
     - **La cabecera de título, EN VERDE**: «el verde es inamovible de la cabecera de título».
     - **El pie de los 5 iconos, EN BLANCO**, en la versión al 100 % que eligió.
     - **Los campos, los botones y las pestañas**: no son contenedores. Un campo de cristal sobre
       una tarjeta de cristal deja el texto flotando y no se sabe dónde se escribe.

   EL VALOR SALE DE `--cristal`, en un solo sitio (`:root`): si mañana se quiere más o menos
   transparencia, se cambia una línea y cambia en todas.

   Y AQUÍ VA LA DECISIÓN DE RENDIMIENTO, que importa más de lo que parece:
   -------------------------------------------------------------------
   `backdrop-filter` (el desenfoque) es CARO, y se paga por área y por número de elementos. En una
   pantalla de catálogo puede haber decenas de tarjetas a la vez, y **el caso duro de este proyecto
   es el Redmi Note 8, de 2019**.

   Por eso el desenfoque se reparte en DOS grupos, y no es un capricho:
     · **Tarjetas repetidas (SIN desenfoque).** Detrás de ellas solo hay el degradado del fondo,
       que es SUAVE: un blanco translúcido encima se ve prácticamente igual que si se desenfocara.
       Se paga lo mismo y no se gana nada — así que no se paga.
     · **Superficies que SÍ tapan contenido (CON desenfoque).** Un modal, el menú lateral o el
       panel del carrito se abren ENCIMA de la app: detrás hay texto y fotos, y ahí el desenfoque
       es lo que hace que el contenido de debajo no compita con el de encima.
   Si algún día se quiere el desenfoque en las tarjetas, se añade a la primera lista; pero conviene
   medirlo antes en el Note 8, no después.
   ============================================================================ */

/* ── GRUPO 1: contenedores repetidos, sin desenfoque ─────────────────────────────────────── */
/*
 * TODAS LAS REGLAS DE ESTE BLOQUE VAN ANCLADAS A `#app`, Y NO ES UN CAPRICHO.
 *
 * Se descubrió MIDIENDO (censo-superficies.mjs, que recorre la app y pregunta al navegador el color
 * calculado de cada elemento): con el selector a secas, `.art-card` seguía BLANCA en los resultados
 * de búsqueda. La causa es la ESPECIFICIDAD: `.buscar-resultados .art-card` son dos clases y gana a
 * una, **aunque la regla del cristal vaya después en el archivo**. Leyendo el CSS eso no se ve;
 * preguntándole al navegador, salta a la primera.
 *
 * Anclar a `#app` (un id) sube la especificidad por encima de cualquier combinación de clases, y
 * así no hace falta `!important` — que además rompería los estados `:hover` que repintan el fondo.
 *
 * Los dos últimos selectores salieron del censo, no de leer el archivo: `.lista-card` y
 * `#copias-bloque` pintaban blanco y no estaban en ninguna lista.
 */
#app .art-card,
#app .inicio-tarjeta,
#app .plan-card,
#app .pago-metodo,
#app .marcas-ayuda,
#app .marcas-ayuda__flecha,
#app .buscador-aviso,
#app .buscar-aviso,
#app #breadcrumb,
#app #breadcrumb-bar,
#app .view-header,
#app .notif-toast,
#app .plan-beneficio > span,
#app .plan-card .plan-tag,
#app #network-status,
#app .lista-card,
#app #copias-bloque {
    background: var(--cristal-tarjeta);
    border: 1px solid var(--cristal-borde);
}

/* ── GRUPO 2: superficies que se abren ENCIMA de contenido, con desenfoque ───────────────── */
/*
 * ESTE GRUPO SE ANCLA A `body`, NO A `#app`, y la diferencia se descubrió midiendo: el menú
 * lateral (#menu-lateral) **NO vive dentro de #app** — su padre es el BODY, porque se mueve ahí
 * para poder taparlo todo. Con el anclaje a #app no lo alcanzaba ninguna regla, y seguía blanco.
 * `body` es antepasado de TODO (dentro y fuera de #app), así que sirve para los dos casos.
 *
 * El modal SÍ está dentro de #app; con `body` también queda cubierto.
 */
body .modal-content,
body #cart-sidebar,
body #cart-totals,
body #menu-lateral,
body .notif-panel,
body .notif-panel-header,
body .calculadora-panel,
body .calc-panel-header,
body .menu-select,
body .ayuda-marco,
body .ayuda-cabecera {
    background: var(--cristal-flotante);
    border: 1px solid var(--cristal-borde);
    -webkit-backdrop-filter: var(--cristal-desenfoque);
    backdrop-filter: var(--cristal-desenfoque);
    /* Y UNA SOMBRA DE VERDAD, que es la otra mitad de que un flotante no se vea muerto: lo que
       dice que algo está ENCIMA no es que sea translúcido, es que proyecta sombra. */
    box-shadow: 0 18px 44px rgba(6, 60, 30, .22);
}


/* ── EL FONDO TIENE QUE LLEGAR AL CONTENIDO (07/10/2026) ────────────────────────────────────
   Para que el cristal se VEA, detrás tiene que haber algo. Y no lo había: estos contenedores
   pintaban un gris claro OPACO (#F6F8F7) que tapaba el fondo de la casa.

   Se encontró MIDIENDO, no leyendo: con elementFromPoint() en un punto del área blanca y
   subiendo por la cadena de padres apuntando quién pinta. El primero que salió fue #app; al
   arreglarlo apareció el siguiente — section#view-catalogo.view —, y de ahí salieron los demás.
   UN CONTENEDOR OPACO TAPA A LOS QUE VIENEN DETRÁS, así que hay que ir subiendo hasta que no
   quede ninguno.

   NO se les pone cristal, y es a propósito: son superficies GRANDES y de fondo. Apilar cristal
   sobre cristal deja las tarjetas sin contraste entre ellas — el cristal es para las TARJETAS,
   no para el lienzo. */
#content,
#view-catalogo,
#view-buscar,
#view-listas,
#view-carrito,
.view,
.inicio-tarjeta__marco {
    background: transparent;
}
