@charset "UTF-8";
/* ============================================================================
   VISOR-BASE.CSS - Sistema de variables responsivas compartidas
   ============================================================================
   Este archivo contiene el sistema de variables responsivas + reglas
   estructurales del Visor del totem, COMPARTIDO por los 4 temas
   (light, dark, neon, curvy) y cualquier tema futuro. Es la unica fuente
   de verdad del layout: los temas solo definen tokens --theme-* y deltas
   visuales propios. Curvy es el modelo de divergencia maxima permitida
   (reescribe posiciones via --curvy-text-*-top, no las reglas base).
   Cargar este archivo ANTES de cualquier theme-specific CSS para que las
   variables esten disponibles cuando los temas las consuman.

   Contiene:
     - :root con todas las variables responsivas (default = totem grande 1920+)
     - 5 breakpoints landscape (max-width: 1899/1599/1279/1023/767)
     - 2 breakpoints portrait (900-1199 y 1200+)

   Como agregar un tema nuevo:
     1) Crear un archivo "miTheme.css" en Content/Themes/.
     2) NO redefinir el :root ni los @media (vienen de aca).
     3) Definir solo reglas theme-specific: backgrounds, gradients, shadows,
        colores, border-radius distintivos, blur, transparencias.
     4) Registrar bundle en App_Start/BundleConfig.cs incluyendo en orden:
          ~/Content/Themes/visor-base.css
          ~/Content/Themes/miTheme.css
     5) Agregar la opcion en el controlador del Visor.

   Variables principales (ver bloques abajo para descripcion completa):
     --card-w / --card-h        : tamano de la tarjeta del producto
     --card-image-h             : alto de la imagen (cuadrada, card-w - 30)
     --banda-comprar-offset     : posicion de la banda COMPRAR
     --banda-padding-y          : padding vertical de la banda COMPRAR
     --banda-font-size          : font-size de la banda COMPRAR
     --text-name-fs / desc-fs / price-fs : tamanos de los 3 textos del card
     --btn-pay-*                : boton PAGAR del footer
     --pay-slot-h / cart-icon-h : alto del slot del footer y del icono carrito
     --sig-h / sig-qty-fs / signos-fs : fila +/- y cantidad sobre la banda
     --cart-modal-*             : modal Resumen de Compra (todos los tokens)
     --footer-h                 : alto visual del footer principal
     --top-nav-mb               : margin-bottom del nav de categorias
   ========================================================================= */

/* === UX TÁCTIL: deshabilitar selección de texto en el visor =================
   Reemplaza el $("*").disableSelection() de visor-principal.js (que recorría
   TODO el DOM en JS y no cubría el contenido re-inyectado por el live-refresh).
   Declarativo: aplica a los elementos actuales y a los futuros. Se EXCLUYEN los
   campos editables para no romper la entrada de texto (datos de pago, búsqueda). */
html, body {
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
input, textarea, select, [contenteditable], [contenteditable="true"] {
    -webkit-user-select: text;
    -moz-user-select: text;
    -ms-user-select: text;
    user-select: text;
}

:root {
    /* === CARDS DEL PRODUCTO ============================================== */
    /* Densidad: una columna mas por breakpoint vs el diseno original (todos
       los card-w/card-h bajaron un escalon para que entren mas productos por
       linea sin perder legibilidad). */
    --card-w: 300px;
    /* card-h ajustado al "fit exacto" del precio + boton. La separacion visual
       arriba/abajo del precio la aporta el line-height: 1.2 (ver .precioso),
       que mantiene 0.1em simetricos arriba y abajo del glifo dentro de su
       line-box.
       card-w(300) + 67(image-h+97) + 26.4*1.2(precio) + 72(banda) = 470.7. */
    --card-h: 475px;
    /* La imagen del producto es CUADRADA con 15px de margen a cada lado.
       Alto = card-w - 30, manteniendo aspect ratio 1:1. */
    --card-image-h: calc(var(--card-w) - 30px);
    /* Banda COMPRAR pegada al borde inferior del card (gap 0). El offset se
       reasigna en cada breakpoint que reduce --banda-padding-y /
       --banda-font-size para compensar la altura efectiva de la banda. */
    --banda-comprar-offset: calc(var(--card-h) - 69px);
    /* Padding vertical y font-size de la banda COMPRAR (.a_demo_four/static).
       Se reducen en breakpoints chicos para que la banda achique de alto y
       letra proporcional al achique de la tarjeta. */
    --banda-padding-y: 19px;
    --banda-font-size: 24px;
    /* Font-size de los botones de categoria (.a_demo_three). Independiente
       del banda-font-size: por defecto sigue el mismo valor, pero se puede
       redefinir por breakpoint para desacoplarlo del boton COMPRAR. */
    --categoria-font-size: var(--banda-font-size);

    /* Box-shadow del boton PAGAR (.payTextBig en footer + .my-cart-checkout
       en modal). Verde idéntico en los 3 temas, asi que va aqui. Una capa
       exterior + un highlight interno superior para sentir relieve sutil. */
    --btn-pay-shadow: 0 4px 12px rgba(12, 92, 45, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.3);
    --btn-pay-shadow-hover: 0 8px 20px rgba(12, 92, 45, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.4);
    --btn-pay-shadow-active: inset 0 2px 6px rgba(0, 40, 18, 0.3);
    /* Tamanos de los tres textos de la zona gris debajo de la imagen
       (nombre, descripcion, precio). Se reducen en breakpoints chicos
       para que los textos no se vean desproporcionados en tarjetas chicas. */
    --text-name-fs: 1.8em;
    --text-desc-fs: 1.3em;
    --text-price-fs: 2.2em;

    /* Posicion vertical (top) de los 3 textos bajo la imagen. Todo el bloque
       cuelga de --card-text-top (offset desde el fin de la imagen); desc y
       precio se derivan con gaps fijos. Para mover TODO el bloque arriba/
       abajo: cambiar SOLO --card-text-top (1 linea). Para separar mas la
       descripcion o el precio: ajustar los --card-text-gap-*. Mismo patron
       que Curvy (--curvy-text-*-top) — un tema "tipo Curvy" reescribe estas
       3 variables en su :root, NO redeclara las reglas .product-name/etc. */
    --card-text-top: calc(var(--card-image-h) + 30px);
    --card-text-gap-desc: 32px;
    --card-text-gap-price: 72px;
    --card-text-name-top: var(--card-text-top);
    --card-text-desc-top: calc(var(--card-text-top) + var(--card-text-gap-desc));
    --card-text-price-top: calc(var(--card-text-top) + var(--card-text-gap-price));

    /* === FOOTER PRINCIPAL (PAGAR / Agrega al carrito) =================== */
    /* Botones del footer y dimensiones del slot. Se reasignan en cada
       breakpoint para que el footer escale con la resolucion: en pantallas
       chicas el slot, el icono y la tipografia se reducen proporcional a
       la tarjeta. */
    --btn-pay-fs: 53px;
    --btn-pay-empty-fs: 58px;
    --btn-pay-padding-y: 20px;
    --btn-pay-padding-x: 30px;
    /* Alto extra del footer. Default 0 (Curvy lo mantiene → footer sin cambio).
       Light/Dark/Neon lo suben en la regla scopeada por bodyClass mas abajo,
       que TAMBIEN re-declara --pay-slot-h: --pay-slot-h se computa en :root
       (html) y la override de --footer-extra-h vive en body (descendiente),
       asi que un calc en :root no la "ve" — hay que recomputar el slot donde
       --footer-extra-h ya vale 150. Lo usa tambien .center-nav (ese sí es
       descendiente de body, hereda el valor correcto sin recomputar). */
    --footer-extra-h: 0px;
    --pay-slot-h: calc(var(--banda-padding-y) * 2 + var(--banda-font-size) * 1.2);
    --cart-icon-h: 137px;

    /* === FILA +/- y CANTIDAD SOBRE LA BANDA MORADA (.element-item .sig) === */
    /* --sig-h     : alto de la fila.
       --sig-qty-fs: tamano del numero de cantidad.
       --signos-fs : tamano de los simbolos +/-. */
    --sig-h: 76px;
    --sig-qty-fs: 28px;
    --signos-fs: 66px;

    /* === MODAL "RESUMEN DE COMPRA" (#my-cart-modal) ===================== */
    /* Variables responsivas para header, boton cerrar, boton PAGAR, +/- de
       la tabla, e imagen. Reducir --cart-modal-table-fs en breakpoints
       estrechos hace que name-fs y desc-fs (em-based) escalen automaticamente.
       --cart-modal-img-size anula el inline "max-width: 100px" del JS para
       que la imagen escale en pantallas chicas. */
    --cart-modal-title-fs: 2rem;
    --cart-modal-close-fs: 3.75rem;
    /* 1.2em sobre el .table base (28px) = 33.6px. Antes 1.6em (44.8px) se
       veia desproporcionadamente grande con nombres largos en el modal. */
    --cart-modal-name-fs: 1.2em;
    --cart-modal-desc-fs: 0.72em;
    --cart-modal-trash-fs: 3rem;
    --cart-modal-pm-w: 50px;
    --cart-modal-pm-h: 60px;
    --cart-modal-pm-fs: 28px;
    --cart-modal-table-fs: 28px;
    --cart-modal-img-size: 100px;

    /* === LAYOUT GENERAL ================================================= */
    --footer-h: 120px;
    --cart-modal-w: 880px;
    --top-nav-mb: 25px;
}

/* Footer mas alto solo en los temas estandar (Light=bg-body, Dark, Neon).
   Curvy (totem-curvy) queda fuera: --footer-extra-h sigue en 0, su footer
   bezier propio no cambia. Se RE-DECLARA --pay-slot-h aqui (no solo
   --footer-extra-h) porque --pay-slot-h se computa en :root/html y no "ve"
   esta override que vive en body; recomputarlo aqui lo resuelve con
   --footer-extra-h ya = el valor de abajo. Las --banda-* se heredan de
   :root (correctas por breakpoint), asi escala solo. Para ajustar el alto
   del footer de los 3 temas: cambiar SOLO --footer-extra-h. */
body.bg-body,
body.totem-dark,
body.totem-neon {
    --footer-extra-h: 20px;
    --pay-slot-h: calc(var(--banda-padding-y) * 2 + var(--banda-font-size) * 1.2 + var(--footer-extra-h));
}

/* ============================================================================
   BREAKPOINTS RESPONSIVOS
   ============================================================================
   Cada breakpoint redefine SOLO las variables que necesitan cambiar. Las
   variables derivadas que usan calc() (ej. --card-image-h, --banda-comprar-
   offset) se recalculan automaticamente.

   Mapeo aproximado de columnas resultantes (con margen 5px y padding 10px):
     >=1900    300x475  -> 5 cols (referencia)
     1600-1899 280x450  -> 4 cols
     1280-1599 200x360  -> 4-5 cols apretadas (forzar 4 en 1366)
     1024-1279 240x400  -> 3 cols
     <1024     220x375  -> 3 cols
     <768      180x330  -> 2 cols (mobile/tablet pequeno)
   Portrait dedicado: ver bloques al final.
   ========================================================================= */

@media (max-width: 1899.98px) {
    :root {
        --card-w: 280px;
        /* card-h: 280+67+24*1.2+72 = 447.8. */
        --card-h: 450px;
        --text-name-fs: 1.6em;
        --text-desc-fs: 1.2em;
        --text-price-fs: 2em;
        --btn-pay-fs: 46px;
        --btn-pay-empty-fs: 50px;
        --btn-pay-padding-y: 18px;
        --btn-pay-padding-x: 26px;
        --cart-icon-h: 122px;
        --sig-h: 70px;
        --sig-qty-fs: 26px;
        --signos-fs: 60px;
        --cart-modal-title-fs: 1.8rem;
        --cart-modal-close-fs: 3.4rem;
        --cart-modal-name-fs: 1.1em;
        --cart-modal-desc-fs: 0.7em;
        --cart-modal-trash-fs: 2.7rem;
        --cart-modal-pm-w: 46px;
        --cart-modal-pm-h: 56px;
        --cart-modal-pm-fs: 26px;
        --cart-modal-table-fs: 26px;
        --cart-modal-img-size: 90px;
        --footer-h: 110px;
        --cart-modal-w: 820px;
    }
}

@media (max-width: 1599.98px) {
    :root {
        /* Card-w 200 para forzar 4+ columnas en pantallas 1280-1599 sin
           depender del scrollbar/padding del container (200+10margen=210
           exterior; 1349/210=6.4 cols teoricas en 1366). */
        --card-w: 200px;
        /* card-h: 200+67+21.6*1.2+61 = 353.92. */
        --card-h: 360px;
        --banda-padding-y: 16px;
        --banda-font-size: 20px;
        /* Compensa altura efectiva de la banda (~44px con padding 11/font 20):
           offset 55 = altura banda 44 + gap fondo 11. Mantiene la banda
           visualmente en la misma posicion que en pantallas grandes. */
        --banda-comprar-offset: calc(var(--card-h) - 58px);
        --text-name-fs: 1.4em;
        --text-desc-fs: 1.1em;
        --text-price-fs: 1.8em;
        --btn-pay-fs: 40px;
        --btn-pay-empty-fs: 42px;
        --btn-pay-padding-y: 16px;
        --btn-pay-padding-x: 22px;
        --cart-icon-h: 108px;
        --sig-h: 60px;
        --sig-qty-fs: 22px;
        --signos-fs: 50px;
        /* Modal Resumen de Compra: reducido ~25% para que el contenido no
           ocupe demasiado vertical/horizontal en pantallas tipo 1366x768. */
        --cart-modal-title-fs: 1.2rem;
        --cart-modal-close-fs: 2.2rem;
        --cart-modal-name-fs: 0.85em;
        --cart-modal-desc-fs: 0.6em;
        --cart-modal-trash-fs: 1.8rem;
        --cart-modal-pm-w: 36px;
        --cart-modal-pm-h: 44px;
        --cart-modal-pm-fs: 20px;
        --cart-modal-table-fs: 22px;
        --cart-modal-img-size: 70px;
        --footer-h: 100px;
        --cart-modal-w: 620px;
        --top-nav-mb: 15px;
    }
}

@media (max-width: 1279.98px) {
    :root {
        --card-w: 240px;
        /* card-h: 240+67+21.6*1.2+61 = 393.92. */
        --card-h: 400px;
        --banda-padding-y: 16px;
        --banda-font-size: 20px;
        --banda-comprar-offset: calc(var(--card-h) - 58px);
        --text-name-fs: 1.4em;
        --text-desc-fs: 1.1em;
        --text-price-fs: 1.8em;
        --btn-pay-fs: 40px;
        --btn-pay-empty-fs: 42px;
        --btn-pay-padding-y: 16px;
        --btn-pay-padding-x: 22px;
        --cart-icon-h: 108px;
        --sig-h: 60px;
        --sig-qty-fs: 22px;
        --signos-fs: 50px;
        /* Modal Resumen de Compra: reducido ~30% en pantallas pequenas. */
        --cart-modal-title-fs: 1.15rem;
        --cart-modal-close-fs: 2rem;
        --cart-modal-name-fs: 0.8em;
        --cart-modal-desc-fs: 0.6em;
        --cart-modal-trash-fs: 1.7rem;
        --cart-modal-pm-w: 34px;
        --cart-modal-pm-h: 42px;
        --cart-modal-pm-fs: 19px;
        --cart-modal-table-fs: 20px;
        --cart-modal-img-size: 60px;
        --footer-h: 95px;
        --cart-modal-w: 580px;
    }
}

@media (max-width: 1023.98px) {
    :root {
        --card-w: 220px;
        /* card-h: 220+67+20.4*1.2+61 = 372.48. */
        --card-h: 375px;
        --banda-padding-y: 16px;
        --banda-font-size: 20px;
        --banda-comprar-offset: calc(var(--card-h) - 58px);
        --text-name-fs: 1.3em;
        --text-desc-fs: 1.05em;
        --text-price-fs: 1.7em;
        --btn-pay-fs: 37px;
        --btn-pay-empty-fs: 38px;
        --btn-pay-padding-y: 14px;
        --btn-pay-padding-x: 20px;
        --cart-icon-h: 99px;
        --sig-h: 55px;
        --sig-qty-fs: 20px;
        --signos-fs: 46px;
        /* Modal Resumen de Compra: reducido ~30% en pantallas pequenas. */
        --cart-modal-title-fs: 1rem;
        --cart-modal-close-fs: 1.8rem;
        --cart-modal-name-fs: 0.75em;
        --cart-modal-desc-fs: 0.55em;
        --cart-modal-trash-fs: 1.5rem;
        --cart-modal-pm-w: 32px;
        --cart-modal-pm-h: 40px;
        --cart-modal-pm-fs: 18px;
        --cart-modal-table-fs: 18px;
        --cart-modal-img-size: 55px;
        --footer-h: 90px;
        --cart-modal-w: 540px;
        --top-nav-mb: 11px;
    }
}

@media (max-width: 767.98px) {
    :root {
        --card-w: 180px;
        /* card-h: 180+67+18*1.2+55 = 323.6. */
        --card-h: 330px;
        --banda-padding-y: 14px;
        --banda-font-size: 18px;
        /* Banda con padding 14/font 18: altura ~50, offset 55 = pad-top(5) + 50. */
        --banda-comprar-offset: calc(var(--card-h) - 52px);
        --text-name-fs: 1.15em;
        --text-desc-fs: 0.95em;
        --text-price-fs: 1.5em;
        --btn-pay-fs: 30px;
        --btn-pay-empty-fs: 30px;
        --btn-pay-padding-y: 12px;
        --btn-pay-padding-x: 16px;
        --cart-icon-h: 90px;
        --sig-h: 48px;
        --sig-qty-fs: 18px;
        --signos-fs: 38px;
        /* Modal Resumen de Compra: reducido para mobile/tablet pequeno. */
        --cart-modal-title-fs: 0.95rem;
        --cart-modal-close-fs: 1.6rem;
        --cart-modal-name-fs: 0.7em;
        --cart-modal-desc-fs: 0.55em;
        --cart-modal-trash-fs: 1.3rem;
        --cart-modal-pm-w: 30px;
        --cart-modal-pm-h: 36px;
        --cart-modal-pm-fs: 17px;
        --cart-modal-table-fs: 16px;
        --cart-modal-img-size: 50px;
        --footer-h: 85px;
        /* --cart-modal-w no aplica aca: el modal queda fluido al 96vw via
           regla del view (#my-cart-modal .modal-dialog max-width: 96vw). */
    }
}

/* === PORTRAIT DEDICADO ====================================================
   Totems verticales (orientation: portrait) tienen un alto de viewport mucho
   mayor al ancho. Eso permite tarjetas mas altas (mas espacio para imagen y
   precio) y un footer mas generoso sin recortar el catalogo. Se separa en
   dos rangos:
     - 900-1199 px de ancho  : totem vertical estandar (1080x1920 tipico).
     - 1200+ px de ancho     : totem vertical grande (1200x1920, 1440x2560).
   Por debajo de 900 px en portrait dejamos los breakpoints normales de
   width (767/1023) que ya cubren mobile/tablet pequenos.
   ======================================================================= */

@media (orientation: portrait) and (min-width: 900px) {
    :root {
        /* Card-w 250 para garantizar 4 columnas en totems portrait 1080x1920
           tipicos (viewport efectivo ~1085 con barras de Chrome). 250+10margen
           = 260 exterior; 1085/260 = 4.17 cols. Estos valores se aplican a
           cualquier portrait desde 900px en adelante (no escalamos en pantallas
           portrait mayores: el totem objetivo es 1080x1920 y no queremos que
           los elementos crezcan si en el futuro hubiera un monitor mas grande). */
        --card-w: 250px;
        /* card-h: 250+67+21.6*1.2+61 = 403.92. */
        --card-h: 410px;
        --banda-padding-y: 16px;
        --banda-font-size: 20px;
        --banda-comprar-offset: calc(var(--card-h) - 58px);
        --text-name-fs: 1.4em;
        --text-desc-fs: 1.1em;
        --text-price-fs: 1.8em;
        --btn-pay-fs: 43px;
        --btn-pay-empty-fs: 46px;
        --btn-pay-padding-y: 18px;
        --btn-pay-padding-x: 24px;
        --cart-icon-h: 115px;
        --sig-h: 60px;
        --sig-qty-fs: 22px;
        --signos-fs: 50px;
        /* Modal Resumen de Compra: reducido ~25% en portrait 900-1199. */
        --cart-modal-title-fs: 1.2rem;
        --cart-modal-close-fs: 2.2rem;
        --cart-modal-name-fs: 0.85em;
        --cart-modal-desc-fs: 0.6em;
        --cart-modal-trash-fs: 1.8rem;
        --cart-modal-pm-w: 36px;
        --cart-modal-pm-h: 44px;
        --cart-modal-pm-fs: 20px;
        --cart-modal-table-fs: 22px;
        --cart-modal-img-size: 70px;
        --footer-h: 130px;
        --top-nav-mb: 35px;
    }

    /* En pantallas portrait mayores al objetivo (1080x1920) topamos el catalogo
       de productos y la barra de categorias a 1080px y los centramos. Asi en
       monitores portrait mas grandes (ej. 1440x2425) entran las mismas 4 cards
       por fila que en el totem estandar — los elementos NO crecen, solo quedan
       centrados con espacio vacio a los lados. */
    .top-nav,
    .center-nav {
        max-width: 1080px;
        margin-left: auto;
        margin-right: auto;
    }
}

/* === REGLAS COMPARTIDAS (independientes del tema) =======================
   Reglas que tienen el MISMO body en los 3 temas (light, neon, dark) y por
   tanto NO dependen del tema visual. Centralizadas aqui para evitar duplicacion.
   Cuidado al modificar: cualquier cambio aqui aplica a TODOS los temas.
   Si una regla diverge entre temas, sacarla de aqui y especializarla por tema.
   ======================================================================= */

* {
    box-sizing: border-box;
}

.element-item .product-description:empty::before {
        content: "\25C6";
        font-size: 1.1em;
        line-height: 1;
    }

::-webkit-scrollbar {
    display: none;
}

.swal2-popup {
    font-size: 1.6rem !important;
}

.btn {
    font-size: 25px;
    border-radius: 6px;
}

/* Boton "Refrescar" del modal de info (#totemInfoModal). Mas chico que el
   .btn base (25px) y violeta de marca, anulando el azul de .btn-primary.
   Specificity de 2 IDs gana sin !important. Modal compartido = 1 sola regla
   para los 4 temas. */
#totemInfoModal #totemInfoRefreshBtn {
    font-size: 1.05rem;
    padding: 0.4rem 1.2rem;
    border-radius: 6px;
    background-color: rgb(105, 33, 124);
    border: 1px solid rgb(105, 33, 124);
    color: #fff;
    /* Separacion extra respecto a la linea "Agent:" de arriba. */
    margin-top: 1rem;
}

#totemInfoModal #totemInfoRefreshBtn:hover,
#totemInfoModal #totemInfoRefreshBtn:focus {
    background-color: rgb(124, 45, 145);
    border-color: rgb(124, 45, 145);
    color: #fff;
}

#totemInfoModal #totemInfoRefreshBtn:active {
    background-color: rgb(85, 25, 100);
    border-color: rgb(85, 25, 100);
    color: #fff;
}

/* Override la base font-size global de .table SOLO dentro del modal Resumen
   de Compra. Asi name-fs y desc-fs (em-based) y los totales/qty inputs de
   la tabla del carrito escalan en breakpoints estrechos via la variable
   --cart-modal-table-fs (ver :root y media queries). Especificidad
   #my-cart-modal #my-cart-table = (0,2,0) > .table = (0,1,0), asi que esta
   regla gana sobre la generica sin necesidad de !important. */
#my-cart-modal #my-cart-table {
    font-size: var(--cart-modal-table-fs, 28px);
}

/* Imagen del producto dentro de la tabla del modal: !important para anular
   los inline "max-width: 100px; max-height: 100px; width: ..." que jquery.
   mycart.js inyecta al renderizar cada fila. Con width/height auto y los
   max-* responsivos via --cart-modal-img-size, la imagen se reduce
   proporcionalmente en breakpoints estrechos manteniendo aspect ratio. */
#my-cart-modal #my-cart-table img {
    max-width: var(--cart-modal-img-size, 100px) !important;
    max-height: var(--cart-modal-img-size, 100px) !important;
    width: auto !important;
    height: auto !important;
}

.close {
    font-size: 40px;
    color: var(--theme-modal-close-color);
    opacity: var(--theme-modal-close-opacity);
}

.h4, h4 {
    font-size: 30px;
}

/* === FOOTER (.footer + .bill) ===========================================
   Estructura compartida entre los 3 temas. Cada tema define los tokens
   --theme-bill-bg, --theme-bill-color y --theme-footer-border-top en su :root.
   Neon agrega backdrop-filter en su archivo (transparency theme-only).
   ======================================================================= */
.footer {
    position: fixed;
    left: 0;
    bottom: 0;
    width: 100%;
    text-align: center;
    border-top: var(--theme-footer-border-top);
    /* Por encima de los controles +/- de productos (.element-item .sig usa z-index:9
       y .signos:active usa z-index:10): 100 deja margen sobrado para que el footer
       siempre tape la banda morada con cantidad cuando una tarjeta se superpone. */
    z-index: 100;
}

.bill {
    margin: 0;
    padding: 0 22px;
    font-size: var(--banda-font-size);
    line-height: 1.2;
    background: var(--theme-bill-bg);
    color: var(--theme-bill-color);
    width: 100%;
}

/* Toda la barra del footer es clickeable (abre/paga el carrito, ver handler .footer .bill
   en visor-mycart.js): cursor pointer en toda el area y sus hijos (incluidos los <img> de
   los iconos, que por defecto no heredarian el pointer). */
.footer .bill,
.footer .bill * {
    cursor: pointer;
}

.bill .total {
        font-weight: bold;
        font-size: 1.6em;
    }

.bill .total .pay-merged--solo {
            width: 100%;
            box-sizing: border-box;
            vertical-align: middle;
        }

.bill .total .qrcode:hover {
                color: lightgray;
            }

.bill .total .canje {
            float: left;
            margin-left: -129px;
            margin-top: 95px;
            font-size: 17px;
            line-height: 6px;
            text-shadow: -1px 0px 13px #000000;
        }

.bill .total .pais {
            width: 100%;
            text-align: center;
            align-content: center;
            align-items: center;
            padding-left: 15px;
            width: 5%;
            cursor: default;
        }

.bill .total .paisd {
            width: 100%;
            float: left;
            margin-top: 12px;
            font-size: 17px;
            line-height: 6px;
            text-shadow: -1px 0px 13px #000000;
            cursor: default;
        }

.bill .total .pagar {
            text-align: right;
            padding-right: 25px;
            width: 5%;
        }

.bill tr td {
        padding: 0.50em 20px;
    }

/* +/- y cantidad sobre la banda morada (.a_demo_four). Para que +/- y qty
   queden VERTICALMENTE CENTRADOS sobre el boton, el top de .sig se calcula
   con dos compensaciones:
     1) +5px: el .element-item tiene padding: 5px. .sig es absolute (mide
        desde padding-edge = card top), pero el boton .a_demo_four esta en
        el flujo (mide desde content-edge = card top + 5px). Sin este +5
        .sig queda 5px arriba del boton.
     2) -(sig-h - boton-h)/2: como .sig (--sig-h) suele ser MAS ALTO que el
        boton (padding-y*2 + font-size*1.2), centramos .sig sobre el boton
        restando la mitad de la diferencia. Asi el centro vertical de los
        +/- y la qty coincide con el centro del boton COMPRAR.
     boton_h = padding-y * 2 + font-size * 1.2
     offset  = banda-comprar-offset + 5 - (sig-h - boton_h) / 2 */
.element-item .sig {
    position: absolute;
    left: -5px;
    right: -5px;
    top: calc(var(--banda-comprar-offset) + 5px - (var(--sig-h) - (var(--banda-padding-y) * 2 + var(--banda-font-size) * 1.2)) / 2);
    bottom: auto;
    height: var(--sig-h);
    box-sizing: border-box;
    display: none;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    padding: 0 10px;
    z-index: 9;
    /* pointer-events: auto para que la zona del .sig capture clicks y NO los
       deje pasar al .a_demo_four (banda COMPRAR) que esta debajo. Antes
       estaba en 'none' y causaba que clicks en la esquina del boton "-"
       (fuera del input exacto) cayeran en COMPRAR sumando al carrito. */
    pointer-events: auto;
}

.element-item .sig .totem-cart-qty {
    font-size: var(--sig-qty-fs);
    font-weight: 700;
    color: #fff;
    min-width: 1.4em;
    text-align: center;
    line-height: 1;
    /* Click en el numero = click en "+" (handler en visor-principal.js). flex: 1 hace
       que el span absorba TODO el espacio entre "−" y "+", asi cualquier
       toque en esa zona dispara el incremento (no solo el numero exacto). */
    flex: 1;
    cursor: pointer;
    user-select: none;
}

/* Fila −/+ visible: cantidad solo en .totem-cart-qty (#id value sigue para +/− en JS; ::before duplicaba) */
.element-item.totem-sig-open .a_demo_four::before {
    content: none !important;
}

/* Sin ::before el bloque colapsaba a su min-height base (~48px). Para que
   conserve la misma altura que cuando muestra "COMPRAR", igualamos al alto
   natural del boton: padding vertical * 2 + font-size con leading.
   Las variables --banda-padding-y y --banda-font-size son responsivas, asi
   que la altura escala correctamente en cada breakpoint. */
.element-item.totem-sig-open .a_demo_four {
    min-height: calc(var(--banda-padding-y) * 2 + var(--banda-font-size) * 1.2);
}

.element-item .sig input.signos {
    pointer-events: auto;
    float: none;
    position: relative;
    top: auto;
    width: auto;
    min-width: 0;
    height: auto;
    margin: 0;
    padding: 8px 12px;
    border: none;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    font-size: var(--signos-fs);
    font-weight: 900;
    line-height: 1;
    cursor: pointer;
    user-select: none;
    text-shadow: none;
    transform: none;
    transform-origin: center center;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: opacity 0.12s ease;
    -webkit-appearance: none;
    appearance: none;
}

.element-item .sig .signos.menos {
    color: #e74c3c;
    margin-left: 10px;
    /* Sube 2px solo los signos +/- del card del producto (no la cantidad)
       para corregir desalineamiento optico de los glifos de la fuente. */
    position: relative;
    top: -2px;
    /* Click area extendido +2px a cada lado horizontal (override del padding
       8px 12px del .signos generico). Asi es mas comodo apuntarle al "-"
       sin acercarse a otras zonas clickeables del card. */
    padding-left: 14px;
    padding-right: 14px;
}

.element-item .sig .signos.mas {
    color: #27ae60;
    margin-right: 10px;
    position: relative;
    top: -2px;
}

.element-item .sig .signos.menos:active,
.element-item .sig .signos.mas:active {
    opacity: 0.65;
    font-size: var(--signos-fs);
    line-height: 1;
    z-index: 10;
}

.interaccion {
}

.under {
    margin-top: 17%;
}

.datos {
    position: absolute;
    bottom: -5px;
    width: 100%;
    font-size: 35px;
    margin-left: -40px;
}

.descript {
    position: absolute;
    bottom: -30px;
    width: 100%;
    font-size: 28px;
    margin-left: -40px;
}

.precio {
    position: absolute;
    bottom: -70px;
    width: 100%;
    font-size: 35px;
    margin-left: -40px;
}

/* Hide Radio Buttons */
[type=radio] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

/* .a_demo_three (categorias), .a_demo_four / .a_demo_static (banda COMPRAR)
   y sus pseudo-estados (:active, :focus, ::before) viven en visor-structure.css
   y usan los tokens definidos arriba en :root. */

.unselectable {
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    -o-user-select: none;
    user-select: none;
}

ul li {
    list-style-type: none;
}

/*Cart Modal*/
.modal {
    text-align: center;
    padding: 0 !important;
}

.modal:before {
        content: '';
        display: inline-block;
        height: 100%;
        vertical-align: middle;
        margin-right: -4px;
    }

.modal-body {
    padding: 0;
}

#my-cart-modal #my-cart-table > tbody > tr > td:nth-child(2) {
    vertical-align: middle !important;
    text-align: start !important;
    padding-left: 0.5rem !important;
    padding-right: 0.75rem !important;
}

#my-cart-modal #my-cart-table .my-cart-product-name {
    display: block;
    font-weight: normal;
    line-height: 1.15;
    margin: 0;
    padding: 0;
    text-align: inherit;
}

*:focus {
    outline: none;
}

.bill .total .my-cart-grand-total {
    text-shadow: var(--theme-text-shadow-emboss);
}

.alert {
    margin-bottom: 0;
}

/* new spinner*/

.spinner {
    animation: spinner .6s linear infinite;
}

/*  for modal loader — alineado con #pageNavLoader (_Layout): velo suave + blur */
#fade {
    display: none;
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 1001;
    background: rgba(0, 0, 0, 0.5);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    pointer-events: auto;
}

/* === REGLAS COMPARTIDAS (extraidas de los <style> inline de las vistas) ====
   Reglas que tenian el MISMO body en Light.cshtml, Neon.cshtml y Dark.cshtml.
   Antes vivian duplicadas en cada vista (~38 reglas x 3 = 114 bloques duplicados).
   Centralizadas aqui para que todas las vistas las hereden por bundle visor-base.
   ======================================================================= */

input[type="search"]::-webkit-search-cancel-button {
            -webkit-appearance: searchfield-cancel-button;
        }

.footer td.cog .fa,
        .footer td.cog .totem {
            opacity: 0 !important; /* invisible */
            visibility: hidden !important;
        }

.footer td.cog {
            cursor: pointer;
            position: absolute;
        }

/* === .payTextBig (boton "Pagar" en footer) - estructural y verde ========== */
.payTextBig {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 20px;
    height: 100%;
    position: relative;
    padding: var(--btn-pay-padding-y) var(--btn-pay-padding-x);
    color: #fff !important;
    user-select: none;
    width: auto;
    margin: 0 auto;
    max-width: calc(100% - 100px);
    background-color: var(--theme-pay-bg) !important;
    background-image: none !important;
    border: 2px solid var(--theme-pay-border) !important;
    border-radius: 16px;
    box-sizing: border-box;
    transition: background-color .15s ease-in-out, border-color .15s ease-in-out, transform .15s ease, box-shadow .15s ease;
    cursor: pointer;
    box-shadow: var(--btn-pay-shadow);
}

.footer .pay-footer-slot > .payTextBig:not(.pay-btn-empty) {
    align-self: stretch;
}

.payTextBig:hover {
    background-color: var(--theme-pay-bg-hover) !important;
    border-color: var(--theme-pay-border-hover) !important;
    /* Sin transform en hover: el boton solo cambia de color (bg + border)
       y el box-shadow. El translateY estaba haciendo "saltar" el boton al
       pasar el mouse, lo cual molestaba. El :active si conserva translate. */
    box-shadow: var(--btn-pay-shadow-hover);
}

.payTextBig:active {
    background-color: var(--theme-pay-bg-active) !important;
    border-color: var(--theme-pay-border-active) !important;
    transform: translateY(-1px);
    box-shadow: var(--btn-pay-shadow-active);
}

.payTextBig.pay-btn-empty .payLabelBig {
                white-space: nowrap;

                font-size: var(--btn-pay-empty-fs);
                font-weight: 600 !important;
                letter-spacing: normal !important;
            }

.payTextBig .my-badge-style {
                position: absolute !important;
                top: -20px; /* ajusta fino */
                right: -30px; /* ajusta fino */
                z-index: 9999;
                transform: translate(0, 0);
                line-height: 1.1;
                padding: 6px 16px;
            }

.payTextBig .payLabelBig,
        .payTextBig .payAmountWrap,
        .payTextBig .payAmountWrap .moneda,
        .payTextBig .payAmountWrap .my-cart-grand-total {
            text-shadow: none !important;
        }

.payLabelBig {
            color: #fff !important;
            font-family: 'Viga', sans-serif;
            font-weight: 900;
            font-size: var(--btn-pay-fs);
            line-height: 1;
            text-transform: uppercase;
            letter-spacing: normal;
        }

.payAmountWrap {
            color: #fff !important;
            font-family: 'Viga', sans-serif;
            font-weight: 900;
            font-size: var(--btn-pay-fs);
            line-height: 1;
            letter-spacing: normal;
            white-space: nowrap;
            display: inline-flex;
            align-items: baseline;
            gap: 8px;
        }

.payAmountWrap .moneda,
            .payAmountWrap .my-cart-grand-total {
                font-size: inherit !important;
                line-height: inherit !important;
                vertical-align: baseline;
            }

.pay-merged {
            vertical-align: middle;
        }

/* Altura mínima del pie: igual con carrito vacío (botón morado más chico) o con Pagar (verde llena la ranura).
           Layout: flex con spacers simétricos a cada lado del botón.
             • Spacer izquierdo (flex:1) — vacío, solo ocupa espacio.
             • Botón (sin flex-grow) — mantiene su ancho natural, NO se estira.
             • Spacer derecho (flex:1) — contiene el ícono del carrito centrado en él.
           Como ambos spacers tienen el mismo flex:1, el espacio sobrante se reparte
           simétricamente: el botón queda centrado en el slot, y el ícono queda
           matemáticamente centrado en el espacio entre el botón y el borde derecho.
           No depende del ancho del botón ni del slot. */
        .footer .pay-footer-slot {
            display: flex;
            align-items: center;
            /* Altura FIJA (no min-height): el slot no crece aunque el icono del carrito
               sea mas alto. El icono asoma fuera del slot por arriba/abajo (overflow
               visible), pero el boton PAGAR/Agrega al carrito mantiene su altura
               original. */
            height: var(--pay-slot-h);
            box-sizing: border-box;
            /* Anclaje para los iconos absolute (cart-footer-icon real y
               placeholder): la posicion del icono del carrito ya NO depende
               del ancho del spacer, sino del slot completo. Asi el icono
               queda fijo en su lugar al cambiar el ancho del boton. */
            position: relative;
        }

.footer .pay-footer-slot > .pay-footer-spacer {
            flex: 1;
            display: flex;
            justify-content: center;
            align-items: center;
            /* Sin position: relative ni min-width: el icono y el badge ahora
               se posicionan absolute relativos al slot, no al spacer. Los
               spacers son simplemente flex-fillers que dejan al boton
               centrado entre ellos. */
        }

/* Iconos del carrito posicionados ABSOLUTE relativos al slot. Centro
           del icono al 15% del borde correspondiente del slot. Como es
           absolute, NO se mueve cuando el boton crece con precios largos.
           La formula:
              right: 15% + transform: translate(50%, -50%)
           hace que el CENTRO del icono quede exactamente a 15% del borde. */
        .footer .pay-footer-slot .cart-footer-icon--placeholder {
            position: absolute;
            left: 15%;
            top: 50%;
            transform: translate(-50%, -50%);
        }

.footer .pay-footer-slot .cart-footer-icon:not(.cart-footer-icon--placeholder) {
            position: absolute;
            right: 15%;
            top: 50%;
            transform: translate(50%, -50%);
        }

/* Badge de cantidad de items, anclado al borde superior del ícono del carrito.
           Antes vivía dentro del botón "PAGAR" (esquina superior derecha del botón);
           ahora se reubica sobre la imagen para que la información (cantidad) quede
           visualmente asociada al carrito, no al botón. El JS sigue actualizando este
           mismo span por la clase .my-cart-badge — no requiere cambios. */
        .footer .pay-footer-slot .pay-footer-spacer .my-cart-badge {
            position: absolute;
            /* -25px de ajuste fino para subir el badge despues del cambio
               de reference point (antes era el spacer, ahora el slot). */
            top: calc((var(--pay-slot-h) - var(--cart-icon-h)) / 2 + var(--cart-icon-h) * 0.37 - 20px);
            /* Badge absolute relativo al SLOT, alineado al icono real cuyo
               centro esta a 15% del borde derecho. El badge va sobre la
               mitad superior derecha del icono: offset 0.275*icon-h hacia el
               borde derecho del slot. Combinado con translateX(50%), el
               centro del badge queda en (15% - 0.275*icon-h) del borde
               derecho del slot. */
            right: calc(15% - var(--cart-icon-h) * 0.275);
            left: auto;
            transform: translateX(50%);
            z-index: 10;
            border-radius: 10px;
            padding: 4px 10px;
            /* font-size 1.5rem aplica a Light/Neon/Dark; Curvy lo override
               en curvy.css con --curvy-qty-fs sobre el wrapper .cart-badge-count. */
            font-size: 1.5rem;
            font-weight: 700;
            line-height: 1.1;
            min-width: 1.7em;
            display: inline-flex;
            align-items: center;
            justify-content: center;
        }

/* Placeholder invisible que ocupa el mismo espacio que el ícono real, en el
           spacer izquierdo del slot. Garantiza simetría: el botón queda centrado en el
           slot tanto en "Agrega al carrito" (chico) como en "PAGAR" (ancho), porque
           ambos spacers tienen el mismo ancho mínimo. visibility:hidden conserva el
           layout sin renderizar la imagen. pointer-events:none asegura que aunque
           visibility:hidden ya bloquee el hit-testing, no hay riesgo de capturar clicks
           accidentales (por encima del clic en .totem-footer-info-hit, etc.). */
        .footer .pay-footer-slot .cart-footer-icon--placeholder {
            visibility: hidden;
            cursor: default;
            pointer-events: none;
        }

.footer .pay-footer-slot > .payTextBig.pay-btn-empty ~ .pay-footer-spacer .my-cart-badge {
            visibility: hidden;
        }

.footer .pay-footer-slot > .payTextBig[style*="visibility: hidden"] ~ .pay-footer-spacer {
            visibility: hidden;
        }

/* Zona oculta banda izquierda del footer (~100px × alto completo): doble clic → modal información */
        .totem-footer-info-hit {
            position: absolute;
            left: 0;
            top: 0;
            bottom: 0;
            width: 100px;
            height: auto;
            padding: 0;
            margin: 0;
            border: 0;
            background: transparent;
            opacity: 0;
            cursor: default;
            z-index: 10;
            pointer-events: auto;
        }

/* === BOTON "VOLVER ARRIBA" (.totem-scrolltop) ===========================
   Boton flotante que EMERGE desde dentro del footer y asoma por encima de el
   (esquina inferior derecha) cuando la pagina tiene scroll. Al tocarlo sube el
   scroll al inicio (logica en visor-scrolltop.js); cuando la pagina vuelve al
   tope, el boton se esconde LENTAMENTE "por donde vino" metiendose otra vez
   dentro del footer.

   Mecanica de aparecer/ocultar SIN animar z-index (z-index no es animable):
   - Es hijo de .footer (position: fixed) y se ancla al borde SUPERIOR del
     footer con bottom: 100%.
   - z-index: -1 CONSTANTE: dentro del stacking context del footer pinta DETRAS
     del fondo del .bill. Asi, "metido" (translateY hacia abajo, solapando el
     area del footer) queda oculto detras del bill; y "asomando" por encima del
     footer (translateY negativo) no solapa nada y se ve completo. El descenso
     lento se lee como el boton metiendose dentro del footer.
   - El color lo hereda del footer del tema via tokens --theme-bill-* /
     --theme-footer-border-top, asi combina con cada tema (incluido Curvy) sin
     reglas por-tema.

   La clase .is-visible la togglea visor-scrolltop.js segun la posicion de
   scroll. Cargado por el bundle "totem-catalog" en las 4 vistas del visor.
   ======================================================================= */
:root {
    --scrolltop-size: 64px;            /* tamaño original FIJO; solo se reduce en movil (ver @media 767.98px abajo) */
    --scrolltop-gap: 14px;            /* margen entre el boton y el borde del footer */
    --scrolltop-right: clamp(18px, 2.4vw, 32px);
}

.totem-scrolltop {
    position: absolute;
    right: var(--scrolltop-right);
    bottom: 100%;                     /* ancla: borde superior del footer */
    z-index: -1;                      /* detras del .bill cuando esta metido */
    width: var(--scrolltop-size);
    height: var(--scrolltop-size);
    margin: 0;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: var(--theme-footer-border-top, none);
    border-radius: 50%;
    background: var(--theme-bill-bg);
    color: var(--theme-bill-color);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.28);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    -webkit-tap-highlight-color: transparent;
    user-select: none;
    /* Oculto: metido dentro del footer (slide hacia abajo) + transparente.
       Transicion LENTA por defecto = ocultamiento "lento" al volver al tope. */
    transform: translateY(100%);
    opacity: 0;
    pointer-events: none;
    transition: transform 0.9s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.9s ease;
}

.totem-scrolltop svg {
    width: 52%;
    height: 52%;
    display: block;
    pointer-events: none;
}

/* Visible: asoma por encima del footer con --scrolltop-gap de margen.
   Transicion mas RAPIDA al aparecer (el ocultar usa la base, lento). */
.totem-scrolltop.is-visible {
    transform: translateY(calc(-1 * var(--scrolltop-gap)));
    opacity: 1;
    pointer-events: auto;
    transition: transform 0.34s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.28s ease;
}

.totem-scrolltop:active {
    transform: translateY(calc(-1 * var(--scrolltop-gap))) scale(0.92);
}

/* Solo en modo MOVIL (≤767.98px) el boton se reduce; fuera de movil conserva el
   tamaño original (64px) sin encoger con el ancho del viewport (antes usaba
   clamp(...4.6vw...) y se achicaba en pantallas medianas). */
@media (max-width: 767.98px) {
    :root {
        --scrolltop-size: clamp(46px, 4.6vw, 64px);
    }
}

/* Centrar en viewport: el tema usa .modal:before + .modal-dialog inline-block para el carrito; aquí restauramos flex de BS */
        #totemInfoModal.modal::before {
            display: none;
            content: none;
        }

#totemInfoModal .modal-dialog.modal-dialog-centered {
            display: flex !important;
            align-items: center;
            min-height: calc(100% - 2rem);
            min-width: 0;
            width: auto;
            max-width: min(420px, 92vw);
            margin-left: auto;
            margin-right: auto;
        }

#my-cart-modal .modal-dialog {
            width: min(880px, 96vw) !important;
            max-width: 880px !important;
        }

#my-cart-modal .modal-header .close.cierre span,
            #totemInfoModal .modal-header .close.cierre span,
            #paymentModal .modal-header .close.cierre span {
                line-height: 0.85;
                display: block;
            }

#paymentModal .payment-method-list {
            display: flex;
            flex-direction: column;
            gap: 14px;
        }

#paymentModal .payment-method-item:active {
            transform: translateY(0);
        }

#paymentModal .payment-method-item__logo img {
            width: 100%;
            height: 100%;
            object-fit: contain;
            object-position: center;
            display: block;
        }

#my-cart-modal .modal-footer.cart-footer {
            padding-top: 0 !important;
            /* 2rem - 10px: se reduce 10px el espacio inferior del footer
               (entre el boton PAGAR y el borde del modal). */
            padding-bottom: calc(2rem - 10px) !important;
            padding-left: 4.25rem !important;
            padding-right: 4.25rem !important;
        }

#my-cart-modal .table-striped > tbody > tr:nth-of-type(odd) > * {
            --bs-table-accent-bg: transparent;
        }

/* Margins reducidos de 20px a 8px para que [- 1 +] quepa en
               la columna qty fija sin que la layout fuerce vertical stack
               en breakpoints estrechos. 8px da separacion visual suficiente
               sin hinchar el ancho total del grupo. */
            #my-cart-modal .btnm {
                margin: 0 8px 0 0 !important;
            }

#my-cart-modal .btnp {
                margin: 0 0 0 8px !important;
            }

#my-cart-modal .my-cart-checkout-paylike.cart-checkout-hidden,
        #my-cart-modal .btn-success.my-cart-checkout.cart-checkout-hidden {
            display: none !important;
        }

#my-cart-modal .my-cart-checkout-paylike {
            display: inline-flex !important;
            align-items: center;
            justify-content: center;
            flex-wrap: nowrap;
            gap: 20px;
            font-family: 'Viga', sans-serif !important;
        }

#my-cart-modal .my-cart-checkout-paylike .cart-checkout-label {
                text-transform: uppercase;
                white-space: nowrap;
                font-family: 'Viga', sans-serif !important;
                font-size: 1em !important;
                line-height: 1 !important;
                font-weight: 900 !important;
                letter-spacing: normal !important;
            }

#my-cart-modal .my-cart-checkout-paylike .payAmountWrap {
                display: inline-flex !important;
                align-items: baseline;
                gap: 7px;
                font-family: 'Viga', sans-serif !important;
                font-weight: 900 !important;
                white-space: nowrap;
                font-size: 1em !important;
                line-height: 1 !important;
                letter-spacing: normal !important;
            }

/* Modo "imprimir": cuando el carrito tiene solo productos gratis, el boton
   PAGAR cambia a IMPRIMIR y el monto se oculta. Selector con mayor
   especificidad que la regla anterior para ganar al display:inline-flex
   !important. La clase la agrega visor-principal.js en togglePayAmountIfZero. */
#my-cart-modal .my-cart-checkout-paylike.cart-checkout-print .payAmountWrap {
    display: none !important;
}

#my-cart-modal .my-cart-checkout-paylike .payAmountWrap .moneda,
            #my-cart-modal .my-cart-checkout-paylike .payAmountWrap .my-cart-grand-total {
                font-family: 'Viga', sans-serif !important;
                font-size: inherit !important;
                line-height: inherit !important;
                vertical-align: baseline;
            }

#my-cart-modal .my-cart-checkout-paylike .cart-checkout-label,
            #my-cart-modal .my-cart-checkout-paylike .payAmountWrap,
            #my-cart-modal .my-cart-checkout-paylike .payAmountWrap .moneda,
            #my-cart-modal .my-cart-checkout-paylike .payAmountWrap .my-cart-grand-total {
                text-shadow: none !important;
            }

/* === REGLAS LIGHT=DARK (Neon redefine) ==================================
   Reglas que tienen el MISMO body en Light y Dark pero Neon redefine
   completamente. Centralizadas aqui para evitar duplicacion entre Light y
   Dark. Neon mantiene su override en neon.css que se carga al final del
   bundle visor-neon (gana por cascada).
   ======================================================================= */

/* Posiciones absolutas dentro de la tarjeta: ancladas a --card-image-h vía
   las variables --card-text-*-top (ver :root, seccion CARDS). Si la tarjeta
   achica en breakpoint chico, los textos siguen al final de la imagen sin
   invadirla. Bloque AUTOCONTENIDO (position/overflow/clamp incluidos): UNICA
   fuente de verdad del layout de texto para Light/Dark/Neon. Curvy lo
   reescribe con sus variables --curvy-text-*-top; no reintroducir copias
   por-tema. Margen lateral 15px con !important descarta el width:94%/left:0
   heredados de isotope-docs.css. */
.element-item .product-name {
    position: absolute;
    top: var(--card-text-name-top);
    left: 15px !important;
    right: 15px !important;
    width: auto !important;
    text-align: center;
    font-size: var(--text-name-fs);
    /* Nombre = 1 sola linea con elipsis. */
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
}

.element-item .product-description {
    position: absolute;
    top: var(--card-text-desc-top);
    left: 15px !important;
    right: 15px !important;
    width: auto !important;
    text-align: center;
    /* Descripcion responsiva via --text-desc-fs (default 1.2em, baja en
       breakpoints chicos). */
    font-size: var(--text-desc-fs);
    /* Regla del card producto: MAXIMO 2 lineas. Si el texto excede, se
       trunca con elipsis (...) y no se muestra el resto. line-height fijo
       para que la altura sea predecible.
       !important + height: auto necesarios para anular el "height: 50px"
       de isotope-docs.css (que dejaba entrar una 3a linea = 50/17.28 = ~2.9).
       max-height = 2 lineas * line-height 1.2 = 2.4em (= font-size * 2.4). */
    line-height: 1.2 !important;
    height: auto !important;
    max-height: 2.4em !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    display: -webkit-box !important;
    -webkit-line-clamp: 2 !important;
    -webkit-box-orient: vertical !important;
}

/* Cuando la descripcion viene vacia, mostramos un separador sutil:
   solo el rombo (glifo del ::before, ver mas arriba). Sin lineas.
   min-height equivalente a 2 lineas de descripcion (line-height 1.2) para
   que el espacio reservado del separador iguale al de una descripcion con
   2 lineas, manteniendo layout consistente entre cards con y sin texto.
   !important en display:flex y align/justify para ganar a las reglas con
   !important del padre (display:-webkit-box, line-clamp, etc), que de otra
   forma dejarian el rombo arriba a la izquierda y descentrado. */
.element-item .product-description:empty {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    text-align: center;
    min-height: 2.4em;
    /* max-height heredado del padre (2.4em !important) limita el alto, asi
       que aqui min == max y el separador siempre mide exactamente 2.4em. */
    opacity: 0.3;
}

.element-item .precioso {
    position: absolute;
    top: var(--card-text-price-top);
    left: 0;
    width: 100%;
    text-align: center;
    font-size: var(--text-price-fs);
    /* Line-height fijo para que la altura visual del precio sea predecible
       en cada breakpoint (necesario para garantizar el gap de 10px entre
       precio y boton COMPRAR). */
    line-height: 1.2;
}

/* Card de producto (estructura comun, valores via tokens). Las propiedades
   estructurales adicionales (position, display, vertical-align, float) las
   define isotope-docs.css. */
.element-item {
    width: var(--card-w);
    height: var(--card-h);
    padding: 5px;
    border-radius: 10px;
    overflow: hidden;
    background: var(--theme-card-bg);
    color: var(--theme-card-color);
    border: var(--theme-card-border);
    /* Toda la zona "gris" de la card es clickeable (nombre, descripcion,
       precio, espacios) y suma al carrito via el handler en Light/Neon/
       Dark.cshtml. cursor: pointer da feedback visual. */
    cursor: pointer;
}

/* Imagen del producto: borde uniforme de 5px en los 4 lados. Se usan top/
   left/right explicitos en 5px (no width) para garantizar el calculo
   exacto del browser, ya que con position:absolute + box-sizing:border-box
   el "padding-edge" del containing block se interpreta como el border-edge
   y no como el content-edge esperado. height = card-w - 10 mantiene la
   imagen cuadrada (igual al ancho disponible). */
.element-item img {
    position: absolute !important;
    top: 15px !important;
    left: 15px !important;
    right: 15px !important;
    /* width:auto !important descarta el width:94% heredado de
       isotope-docs.css para que el browser respete "right". */
    width: auto !important;
    margin: 0 !important;
    height: var(--card-image-h);
    object-fit: contain;
    box-sizing: border-box;
}

/* === "IMAGE ZOOM" (opcional POR TOTEM) =====================================
   La imagen llena TODA la card (cover) en vez de flotar arriba. Nacio fijo en Prisma
   y ahora es un interruptor por totem (dbo.UserMac.VisorImageZoom): el Layout emite
   body.img-zoom al bootear y SignalR la conmuta en vivo. Vale para los 5 temas.
   Especificidad (0,2,2) + !important: gana a la regla base de arriba y a la de Curvy
   (ambas (0,1,1)) sin depender del orden de carga de las hojas.
   Los insets van si o si: sin ellos sobreviven los top/left/right:15px de arriba y la
   imagen queda corrida y desbordando la card. */
body.img-zoom .element-item img {
    position: absolute !important;
    inset: 0 !important;
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
    margin: 0 !important;
    box-sizing: border-box !important;
    border-radius: inherit !important;
    filter: none !important;   /* mata el drop-shadow global de Neon */
}
/* Cadena de redondeo card -> .sombra -> img, para que la imagen a sangre siga la curva
   del marco (en Curvy la card NO recorta: overflow visible). Prisma pisa esta regla con
   su radio interior propio (misma especificidad, su hoja carga despues). */
body.img-zoom .element-item .sombra {
    border-radius: inherit !important;
}
/* Placeholder "sin imagen": mostrarlo entero, nunca recortado. Prisma queda EXCLUIDO: ahi el
   zoom siempre recorto tambien el placeholder y hay que conservar ese look tal cual estaba. */
body.img-zoom:not(.totem-prisma) .element-item.no-image img {
    object-fit: contain !important;
}
/* PENDIENTE DE DISENO (no improvisar aca): con el zoom ENCENDIDO fuera de Prisma, los textos de la
   card quedan sobre la foto sin velo. Prisma lo resuelve con velo propio + textos en z-index 2;
   light/dark no tienen velo, el panel de Neon queda debajo de la foto y la onda de Curvy la tapa
   por encima. Subir solo el velo NO alcanza: sin dar capa explicita a los textos, el velo termina
   tapandolos. Requiere una pasada de capas por tema (velo + z-index de textos). */

html, body {
    font: 12px "Viga";
    width: 100%;
    height: 100%;
    /* overflow-y: auto en body para que el scroll de las cards y categorias
       lo maneje el body (no .center-nav). Asi al hacer scroll, todo el
       contenido (categorias + cards) se mueve junto y termina en el top
       real de la pantalla. */
    overflow-y: auto;
    overflow-x: hidden;
    background-color: var(--theme-body-bg);
    color: var(--theme-body-color);
}

.table {
    font-size: 28px;
    color: var(--theme-modal-text);
    margin-bottom: 0;
}

.table > tbody > tr > td, .table > tbody > tr > th, .table > tfoot > tr > td, .table > tfoot > tr > th, .table > thead > tr > td, .table > thead > tr > th {
    border-top: none;
    vertical-align: middle !important;
}

button.close {
    font-size: 45px;
    color: var(--theme-modal-text);
    opacity: 1;
    margin-top: -10px !important;
}

/* Botones +/- de cantidad en cards (compartidos entre temas via tokens). */
.btnm, .btnp {
    width: 44px;
    height: 52px;
    font-size: 24px;
    font-weight: 700;
    line-height: 1;
    background-color: var(--theme-btn-pm-bg);
    color: var(--theme-btn-pm-color);
    border-radius: 6px;
    border: none;
    cursor: pointer;
}

.btnm { content: "-"; }
.btnp { content: "+"; margin-left: -10px; }

.pagar .btn-default {
    box-shadow: var(--theme-pagar-btn-shadow);
}

button.bill .total .qrcode {
            padding-left: 25px;
            width: 5%;
            cursor: pointer;
        }

.bill .total .milabel {
            font-size: 1.2em;
            width: 20%;
            cursor: default;
            text-shadow: var(--theme-text-shadow-emboss);
        }

.bill .total .my-cart-grand-total {
        text-align: left;
        /* Unificado con Neon a tamano relativo (1.2em del .total que ya tiene
           font-size: 1.6em, sobre .bill 2.4em). El footer moderno usa
           .payAmountWrap con clamp() y !important via .payAmountWrap
           .my-cart-grand-total { font-size: inherit !important }, asi que esta
           regla queda como default heredado para usos legacy del .bill. */
        font-size: 1.2em;
        cursor: default;
    }

.top-nav {
    width: 100%;
    overflow-x: unset;
    overflow-y: unset;
    text-align: center;
    display: block;
    /* Separacion superior con respecto al borde de la pantalla / banner.
       Compartido entre los 4 temas (light/neon/dark/curvy). */
    margin-top: 10px;
    /* margin-bottom hardcoded con !important para forzar el valor en los
       4 temas (Light/Neon/Dark/Curvy) sin depender de --top-nav-mb. */
    margin-bottom: 30px !important;
}

/* Tope de columnas en landscape: maximo 5 cards por linea. Calculamos el
   max-width como 5 * (card-w + margen 10px) para que se ajuste al --card-w
   activo en cada breakpoint. En pantallas mayores el catalogo queda centrado
   con franjas vacias a los lados (mismo criterio que portrait, donde topamos
   a 1080px = 4 cards). */
@media (orientation: landscape) {
    .top-nav,
    .center-nav {
        max-width: calc(5 * (var(--card-w) + 10px));
        margin-left: auto;
        margin-right: auto;
    }
}

.center-nav {
    width: 100%;
    /* height auto + overflow visible: deja que el body sea el scroll
       container. Asi cuando el usuario hace scroll, las cards Y las
       categorias se mueven juntas, todo termina en el top de la pantalla. */
    height: auto;
    overflow: visible !important;
    /* El footer es position:fixed; bottom:0 y mide ~--footer-h reales (carrito asoma del
       slot + padding del .bill + border-top). El padding-bottom debe superar esa altura
       visual para que la última fila de productos quede arriba del footer al hacer scroll
       completo. Lo derivamos de (--footer-h + --footer-extra-h) × 2.4 para que escale
       automáticamente con cada breakpoint y compense el +50px de los temas estandar
       (Curvy: --footer-extra-h=0, sin cambio). */
    padding-bottom: calc((var(--footer-h) + var(--footer-extra-h)) * 2.4);
    /* Sin min-height: 100% — combinado con height:90vh hacía que el contenedor creciera a
       100% del padre (=100vh del body) y se desbordara debajo del viewport, "robando"
       píxeles del scroll efectivo. Forzando solo height:90vh el scroll termina justo
       donde el viewport del browser puede mostrarlo. */
    overflow-y: scroll;
    overflow-x: hidden;
    text-align: center;
    margin-bottom: 20px;
}

/*Category Buttons. Tipografia y padding escalan con clamp para que las
  categorias se vean grandes en totems 1920+ y se compriman en pantallas
  chicas sin romper el wrap horizontal. */

    
.modal-dialog {
    display: inline-block;
    text-align: left;
    vertical-align: middle;
    width: auto;
    /* min-width responsivo: 500px en pantallas grandes pero NUNCA mas que el 92% del
       viewport para que no aparezca scroll horizontal en tabletas (1024 y menos). */
    min-width: min(500px, 92vw);
    width: 95%;
}

input {
    /*text-shadow: 0 0 0 black;*/
    background-color: transparent;
    border: none;
}

/* Footer PAGAR: mismo volumen verde que Neon (contraste claro vs. vidrio) */
        .payTextBig {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 20px;
            height: 100%;
            position: relative;
            padding: var(--btn-pay-padding-y) var(--btn-pay-padding-x);
            color: #fff !important;
            user-select: none;
            width: auto;
            margin: 0 auto;
            max-width: calc(100% - 100px);
            background-color: var(--theme-pay-bg) !important;
            background-image: none !important;
            border: 2px solid var(--theme-pay-border) !important;
            border-radius: 16px;
            box-sizing: border-box;
            cursor: pointer;
            transition: background-color .15s ease-in-out, border-color .15s ease-in-out, transform .15s ease, box-shadow .15s ease;
            box-shadow: var(--btn-pay-shadow);
        }

.payTextBig .my-cart-badge {
                border-radius: 10px;
                font-size: 1.75rem;
                font-weight: 700;
                display: inline-flex;
                align-items: center;
                justify-content: center;
                min-width: 1.95em;
            }

/* Ícono del carrito (Content/Images/carrito.png) dentro del spacer derecho —
           queda centrado en el espacio entre el botón y el margen derecho. Altura más
           grande que el slot (180 px > 122 px), el ícono asoma fuera del slot. Ahora
           es CLIQUEABLE: con click se abre el modal "Resumen de Compra" (delegado en
           visor-mycart.js → click.mycartFooterIcon → trigger sobre .my-cart-icon),
           así el cliente puede ver el resumen tocando el carrito directo, sin tener
           que apuntar al botón centrado. user-select:none evita que un long-press
           seleccione la imagen en touch. */
        .footer .pay-footer-slot .cart-footer-icon {
            width: auto;
            height: var(--cart-icon-h);
            max-width: 100%;
            object-fit: contain;
            cursor: pointer;
            user-select: none;
        }

#my-cart-modal .modal-body,
        #totemInfoModal .modal-body,
        #paymentModal .modal-body {
            /* Padding reducido de 2.5rem (40px) horizontal a 0.75rem (12px)
               para que la tabla del carrito disponga de 56px extra de ancho
               util. En el modal de 540px (breakpoint pequeno) esto pasa de
               460px utiles a 516px, un +12 por ciento de espacio para
               nombre, qty y total. */
            padding: 1rem 0.75rem 1.25rem;
        }

#paymentModal .payment-methods-body {
            padding: 0.75rem 1rem 1.35rem;
        }

#my-cart-modal .cart-empty-msg {
            margin-left: auto;
            margin-right: auto;
            max-width: 100%;
            /* El footer tiene padding-top:0 y padding-bottom:2rem. Esa
               asimetria deja el texto pegado al top. 21px (1rem + 5px de
               ajuste fino) lo lleva al centro vertical visual del footer
               sin cambiar dimensiones ni layout. */
            margin-top: 21px;
        }

#my-cart-modal .table > :not(caption) > * > * {
            background-color: transparent !important;
            box-shadow: none !important;
        }

#my-cart-modal a.my-cart-remove-btn {
            display: inline-flex !important;
            align-items: center;
            justify-content: center;
            text-decoration: none !important;
            background: transparent !important;
            border: none !important;
            padding: 0;
            /* Sin min-width/min-height: el boton se ajusta exactamente al
               tamano visual del icono. Antes tenia min 3.2rem (51px) que
               agregaba espacio vacio alrededor del trash incluso con la
               celda compactada. */
            min-width: 0;
            min-height: 0;
            margin: 0 auto;
        }

#my-cart-modal .btn-success.my-cart-checkout {
            color: #fff !important;
            background-color: var(--theme-pay-bg) !important;
            background-image: none !important;
            font-family: 'Viga', sans-serif !important;
            font-size: var(--btn-pay-fs) !important;
            font-weight: 900 !important;
            letter-spacing: normal !important;
            line-height: 1 !important;
            padding: var(--btn-pay-padding-y) var(--btn-pay-padding-x) !important;
            text-shadow: none !important;
            border: 2px solid var(--theme-pay-border) !important;
            transition: background-color .15s ease-in-out, border-color .15s ease-in-out, transform .15s ease, box-shadow .15s ease;
            border-radius: 14px !important;
            box-shadow: var(--btn-pay-shadow);
        }

#my-cart-modal .btn-success.my-cart-checkout:hover,
#my-cart-modal .btn-success.my-cart-checkout:focus {
    color: #fff !important;
    background-color: var(--theme-pay-bg-hover) !important;
    /* Sin transform en hover: solo cambia color + box-shadow. */
    text-shadow: none !important;
    border-color: var(--theme-pay-border-hover) !important;
    box-shadow: var(--btn-pay-shadow-hover);
}

#my-cart-modal .btn-success.my-cart-checkout:active {
    color: #fff !important;
    background-color: var(--theme-pay-bg-active) !important;
    transform: translateY(-1px);
    text-shadow: none !important;
    border-color: var(--theme-pay-border-active) !important;
    box-shadow: var(--btn-pay-shadow-active);
}

/* === REGLAS PARIDAD (estaban en Light y Dark, ahora compartidas) ========
   Reglas que Light y Dark tenian con el mismo body. Centralizadas aqui para
   que todos los temas (incluido Neon y futuros) las hereden por defecto.
   ======================================================================= */

.moneda {
    font-size: 78px;
    cursor: default;
    text-shadow: var(--theme-text-shadow-emboss);
}

.totalmedio {
    padding-top: 18px;
    color: var(--theme-modal-text);
    font-size: 2em !important;
}

.product-qty {
    padding-top: 18px;
    color: var(--theme-modal-text);
    font-size: 2em;
}

/* Breakpoints responsivos (5 landscape + 2 portrait) viven en visor-base.css
   Si necesitas un override SOLO de Light en algun breakpoint, agregalo aqui
   con su propio @media. */

::placeholder {
    color: var(--theme-input-placeholder) !important;
}

.conexion-nav {
    background-color: orangered;
    /* fixed: queda por encima de #fade (apilamiento respecto al viewport) */
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    color: white;
    z-index: 99999;
    padding: 20px;
    display: none;
    box-sizing: border-box;
}

.conexion-nav span {
        display: block;
        color: white;
        text-align: center;
        font-size: 15px;
    }

.selection {
    background-color: lightgray !important;
}

#clickZone {
            position: fixed;
            bottom: 20px; /* Espaciado desde la parte inferior */
            left: 50%; /* Centra el elemento respecto al ancho */
            transform: translateX(-50%); /* Ajusta la posición para centrar */
            width: 100px; /* Tamaño ajustable */
            height: 100px; /* Tamaño ajustable */
            z-index: 1000; /* Asegura que esté encima */
            cursor: pointer;
        }

/* Ambos estados del botón ("Agrega al carrito" empty y "PAGAR" lleno) comparten la
           misma altura: la natural por padding + contenido. Antes el estado "PAGAR" usaba
           align-self:stretch + height:100% (heredado de .payTextBig) y se estiraba al alto
           del slot (122 px), quedando notablemente más alto que el botón empty. Forzar
           height:auto + align-self:center los iguala visualmente. */
        .footer .pay-footer-slot > .payTextBig:not(.pay-btn-empty),
        .footer .pay-footer-slot > .payTextBig.pay-btn-empty {
            height: auto;
            align-self: center;
        }

#invoiceModal .modal-header,
        #dataUserModal .modal-header {
            position: relative;
        }

#invoiceModal .modal-header .modal-title,
        #dataUserModal .modal-header .modal-title {
            width: 100%;
            text-align: center;
            margin-bottom: 0;
        }

#invoiceModal .modal-header .close,
        #dataUserModal .modal-header .close {
            position: absolute !important;
            top: 50% !important;
            right: 0.65rem !important;
            left: auto !important;
            transform: translateY(-50%) !important;
            margin: 0 !important;
            padding: 0.25rem 0.45rem !important;
            font-size: 2.25rem;
            font-weight: 200;
            line-height: 1;
            z-index: 2;
        }

#invoiceModal .modal-header .close:hover,
        #invoiceModal .modal-header .close:focus,
        #dataUserModal .modal-header .close:hover,
        #dataUserModal .modal-header .close:focus {
            transform: translateY(-50%) !important;
        }

#paymentModal .modal-footer {
            border-top: none;
        }

@keyframes spinner {
    to {
        transform: rotate(360deg);
    }
}

/* === REGLAS TOKENIZADAS (botones accion + cart empty) ====================
   Consumen tokens --theme-btn-action-* y --theme-cart-empty-*. Cada tema
   (light, neon, dark) define los valores en su :root.
   ======================================================================= */

#my-cart-modal #my-cart-table input.btnm,
#my-cart-modal #my-cart-table input.btnp,
#my-cart-modal .btnm,
#my-cart-modal .btnp {
    background-color: var(--theme-btn-action-bg) !important;
}

    #my-cart-modal #my-cart-table input.btnm:hover,
    #my-cart-modal #my-cart-table input.btnp:hover,
    #my-cart-modal .btnm:hover,
    #my-cart-modal .btnp:hover {
        background-color: var(--theme-btn-action-bg-hover) !important;
    }

    #my-cart-modal #my-cart-table input.btnm:active,
    #my-cart-modal #my-cart-table input.btnp:active,
    #my-cart-modal .btnm:active,
    #my-cart-modal .btnp:active {
        background-color: var(--theme-btn-action-bg-active) !important;
    }

#my-cart-modal .cart-empty-msg {
    color: var(--theme-cart-empty-color);
}

.swal2-popup.totem-idle-swal .swal2-cancel {
    background-color: var(--theme-btn-action-bg) !important;
    border-color: var(--theme-btn-action-border) !important;
}

    .swal2-popup.totem-idle-swal .swal2-cancel:hover {
        background-color: var(--theme-btn-action-bg-hover) !important;
        border-color: var(--theme-btn-action-bg-hover) !important;
    }

    .swal2-popup.totem-idle-swal .swal2-cancel:active {
        background-color: var(--theme-btn-action-bg-active) !important;
        border-color: var(--theme-btn-action-border-active) !important;
    }

    .swal2-popup.totem-idle-swal .swal2-cancel:focus {
        box-shadow: var(--theme-btn-action-focus-ring) !important;
    }

/* === COLOR DE TEXTO EN CARDS (tokenizado) ================================
   Color principal y secundario del texto dentro de las tarjetas de producto.
   Cada tema define los valores en su :root via --theme-card-text-primary y
   --theme-card-text-secondary. Light usa "inherit" (mantiene look antiguo),
   Neon "beige", Dark grises AMOLED.
   ======================================================================= */

.element-item .product-name,
.element-item .precioso {
    color: var(--theme-card-text-primary);
}

.element-item .product-description {
    color: var(--theme-card-text-secondary);
}

/* === FIX BOOTSTRAP 5 TABLE COLOR DENTRO DEL MODAL CARRITO ===============
   Bootstrap 5 setea --bs-table-color (~#212529) en .table que se aplica a
   td/th. En Dark eso hace que el texto del producto se vea casi negro sobre
   fondo AMOLED. Forzamos el color del modal-text aqui.
   ======================================================================= */

#my-cart-modal #my-cart-table,
#my-cart-modal #my-cart-table > :not(caption) > * > * {
    --bs-table-color: var(--theme-modal-text);
    color: var(--theme-modal-text);
}

/* === MODAL CARRITO: botones +/- y cantidad uniforme ======================
   visor-mycart.js renderiza 3 inputs dentro de .my-cart-qty-controls:
     <input type="button" value="-" class="btnm product-quantity">
     <input type="text" value="N" style="width:50px;...">     <- inline style
     <input type="button" value="+" class="btnp product-quantity">
   Las 3 secciones deben tener el MISMO TAMAÑO visual. !important para
   sobrescribir el style="width:50px" inline del input central.
   El color del simbolo (+ y -) es BLANCO en los 3 temas. El bg viene
   de --theme-btn-action-* (tokenizado mas arriba).
   ======================================================================= */

#my-cart-modal .my-cart-qty-controls input {
    /* Sizing tokenizado y responsivo (--cart-modal-pm-w/h/fs) compartido por
       los 3 inputs (- texto +). Antes estaba hardcoded a 50px, lo que entraba
       en conflicto con la regla de visor-modal.css que usa los tokens en el
       input[type="text"] (especificidad mayor). Resultado: el input central
       quedaba mas chico que los botones +/-. Centralizamos aqui los 3 con
       los mismos tokens => tamano IDENTICO en cada breakpoint. */
    width: var(--cart-modal-pm-w) !important;
    height: var(--cart-modal-pm-h) !important;
    font-size: var(--cart-modal-pm-fs) !important;
    line-height: 1 !important;
    padding: 0 !important;
    text-align: center !important;
    vertical-align: middle !important;
    box-sizing: border-box !important;
    border-radius: 6px !important;
    border: none !important;
    /* Mismo background que los botones +/- (token del tema). El input text
       central por default es transparent (regla global "input"), aqui lo
       igualamos a los botones para que las 3 secciones se vean homogeneas. */
    background-color: var(--theme-btn-action-bg) !important;
    color: #fff !important;
}

/* Color y tamano de los simbolos +/- en el modal "Resumen de compra": rojo
   para "−" y verde para "+", a 1.5x del font-size base del modal-pm para que
   se vean mas prominentes. El boton mantiene su tamano (width/height por el
   token --cart-modal-pm-w/h) y el input central de cantidad mantiene su
   font-size original. */
#my-cart-modal .btnm,
#my-cart-modal #my-cart-table input.btnm {
    color: #ff5252 !important;
    font-size: calc(var(--cart-modal-pm-fs) * 1.5) !important;
}

#my-cart-modal .btnp,
#my-cart-modal #my-cart-table input.btnp {
    color: #4caf50 !important;
    font-size: calc(var(--cart-modal-pm-fs) * 1.5) !important;
}

/* ============================================================================
   REGLAS TOKENIZADAS COMPARTIDAS
   ============================================================================
   Bloque consolidado de reglas con la MISMA estructura entre temas pero
   valores distintos. Consumen tokens --theme-* que cada tema define en su
   :root (light.css / neon.css / dark.css). Para crear un tema nuevo, definir
   los tokens — el comportamiento se hereda solo.
   ========================================================================= */

/* === FORM CONTROL FOCUS (compartido) ====================================== */
.form-control:focus {
    border-color: var(--theme-input-focus-border);
    box-shadow: var(--theme-input-focus-shadow);
}

/* === "Agrega al carrito" en estado vacio (call-to-action de solo texto) === */
.payTextBig.pay-btn-empty {
    background: transparent !important;
    background-image: none !important;
    border: none !important;
    border-radius: 0;
    padding: 0;
    gap: 16px;
    box-shadow: none !important;
}

.payTextBig.pay-btn-empty:hover,
.payTextBig.pay-btn-empty:active {
    background: transparent !important;
    border: none !important;
    transform: none;
    box-shadow: none !important;
}

/* === SwAl2 icon "info" + spinner del confirm en loading =================== */
.swal2-popup .swal2-icon.swal2-info {
    border-color: var(--theme-swal-info-border) !important;
    color: var(--theme-swal-info-color) !important;
}

.swal2-popup .swal2-actions.swal2-loading .swal2-styled.swal2-confirm {
    border-color: var(--theme-swal-spinner-border) !important;
    border-left-color: var(--theme-swal-spinner-border-left) !important;
}

/* === SwAl2 SKELETON (Dark + Neon) ========================================
   Estructura comun de los popups swal2 para los temas oscuros/translucidos.
   Light y Curvy NO entran (usan el look default de swal2): el :is() solo
   matchea body.totem-dark / body.totem-neon. Cada tema define los colores
   en su :root via tokens --theme-swal-*. El icono "info" y el spinner de
   loading ya estan tokenizados arriba (compartidos por todos los temas).
   Curvy es el modelo de divergencia: si un tema futuro tipo Curvy quiere
   este look, agrega su bodyClass al :is() y define los tokens.
   border (confirm/cancel) en props separadas (NO shorthand) para que el
   override del spinner de loading siga aplicando border-*-color. */
:is(body.totem-dark, body.totem-neon) .swal2-popup {
    background: var(--theme-swal-popup-bg) !important;
    border: 1px solid var(--theme-swal-popup-border) !important;
    color: var(--theme-swal-text) !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-title,
:is(body.totem-dark, body.totem-neon) .swal2-popup #swal2-title {
    color: var(--theme-swal-text) !important;
    font-weight: normal !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-content,
:is(body.totem-dark, body.totem-neon) .swal2-popup #swal2-content,
:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-html-container {
    color: var(--theme-swal-muted) !important;
    font-weight: normal !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-icon.swal2-warning,
:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-icon.swal2-error {
    border-color: var(--theme-swal-icon-border) !important;
    color: var(--theme-swal-text) !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-icon.swal2-error .swal2-x-mark-line-left,
:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-icon.swal2-error .swal2-x-mark-line-right {
    background-color: var(--theme-swal-text) !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-icon.swal2-success {
    border-color: var(--theme-swal-icon-border) !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-icon.swal2-success .swal2-success-line-long,
:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-icon.swal2-success .swal2-success-line-tip {
    background-color: var(--theme-swal-text) !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-icon.swal2-success .swal2-success-ring {
    border-color: var(--theme-swal-icon-ring) !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-styled.swal2-confirm,
:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-styled.swal2-cancel {
    background-color: var(--theme-swal-btn-bg) !important;
    border-width: 1px !important;
    border-style: solid !important;
    border-color: var(--theme-swal-btn-border) !important;
    color: var(--theme-swal-text) !important;
    border-radius: 10px !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-actions.swal2-loading .swal2-styled.swal2-confirm {
    border-width: .25em !important;
    border-style: solid !important;
    border-radius: 50% !important;
    background-color: transparent !important;
    color: transparent !important;
    width: 2.5em !important;
    height: 2.5em !important;
    box-shadow: none !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-actions.swal2-loading .swal2-styled.swal2-cancel {
    display: none !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-input {
    background: var(--theme-swal-input-bg) !important;
    border: 1px solid var(--theme-swal-input-border) !important;
    color: var(--theme-swal-text) !important;
    border-radius: 10px !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-input::placeholder {
    color: var(--theme-swal-input-placeholder) !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-validation-message {
    background: var(--theme-swal-validation-bg) !important;
    color: var(--theme-swal-text) !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-close {
    color: var(--theme-swal-muted) !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .swal2-close:hover {
    color: var(--theme-swal-close-hover) !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .qr-modal-title,
:is(body.totem-dark, body.totem-neon) .swal2-popup .qr-modal-text {
    color: var(--theme-swal-text) !important;
}

:is(body.totem-dark, body.totem-neon) .swal2-popup .qr-modal-hr {
    border-color: var(--theme-swal-qr-hr);
}

/* === MODAL HEADER (carrito + totemInfo + payment) =========================
   Padding lateral reducido de 4.25rem (68px) -> 1rem (16px). El boton de
   cierre (X) sigue posicionado con position:absolute + right: 0.65rem, asi
   que no choca con el titulo. */
#my-cart-modal .modal-header,
#totemInfoModal .modal-header,
#paymentModal .modal-header {
    background-color: var(--theme-modal-header-bg);
    color: var(--theme-modal-header-color);
    border-bottom: none;
    border-radius: var(--theme-modal-header-radius);
    position: relative;
    padding-top: 1rem;
    padding-bottom: 1rem;
    padding-left: 1rem;
    padding-right: 1rem;
}

#my-cart-modal .modal-header .modal-title,
#totemInfoModal .modal-header .modal-title,
#paymentModal .modal-header .modal-title {
    color: var(--theme-modal-title-color);
}

/* === BOTON DE CIERRE (.close.cierre) del modal header ===================== */
#my-cart-modal .modal-header .close.cierre,
#totemInfoModal .modal-header .close.cierre,
#paymentModal .modal-header .close.cierre {
    color: var(--theme-modal-header-close-color) !important;
    opacity: 1 !important;
    text-shadow: var(--theme-modal-header-close-text-shadow);
    background: transparent !important;
    background-color: transparent !important;
    border: none !important;
    box-shadow: none !important;
    font-size: 3.75rem;
    font-weight: 200;
    line-height: 1;
    min-width: 3.5rem;
    min-height: 3.5rem;
    position: absolute !important;
    top: 50% !important;
    right: 0.65rem !important;
    left: auto !important;
    transform: translateY(-50%) !important;
    margin: 0 !important;
    padding: 0.25rem 0.45rem !important;
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
}

#my-cart-modal .modal-header .close.cierre:hover,
#my-cart-modal .modal-header .close.cierre:focus,
#totemInfoModal .modal-header .close.cierre:hover,
#totemInfoModal .modal-header .close.cierre:focus,
#paymentModal .modal-header .close.cierre:hover,
#paymentModal .modal-header .close.cierre:focus {
    color: var(--theme-modal-header-close-color-hover) !important;
    opacity: 1 !important;
    background: transparent !important;
    transform: translateY(-50%) !important;
}

/* === PAYMENT METHOD ITEM (#paymentModal) ================================== */
#paymentModal .payment-method-item {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    width: 100%;
    text-align: left;
    padding: 1rem 1.2rem;
    margin: 0;
    border: none;
    border-radius: 14px;
    background: var(--theme-payment-item-bg);
    color: var(--theme-payment-item-color);
    box-shadow: var(--theme-payment-item-shadow);
    cursor: pointer;
    transition: background .15s ease, transform .12s ease, box-shadow .15s ease;
    -webkit-tap-highlight-color: transparent;
    font-size: 28px;
}

#paymentModal .payment-method-item:hover,
#paymentModal .payment-method-item:focus-visible {
    background: var(--theme-payment-item-bg-hover);
    box-shadow: var(--theme-payment-item-shadow-hover);
    transform: translateY(-2px);
    outline: none;
}

#paymentModal .payment-method-item__logo {
    flex: 0 0 92px;
    width: 92px;
    height: 92px;
    border-radius: 12px;
    background: var(--theme-payment-item-logo-bg);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    border: 1px solid var(--theme-payment-item-logo-border-color);
}

#paymentModal .payment-method-item__name {
    flex: 1;
    font-size: inherit;
    font-weight: normal;
    color: var(--theme-payment-item-name-color);
    line-height: 1.15;
}
#my-cart-modal .table {
    --bs-table-bg: transparent;
    --bs-table-striped-bg: transparent;
    --bs-table-accent-bg: transparent;
    --bs-table-border-color: var(--theme-cart-table-border-color);
}

#my-cart-modal a.my-cart-remove-btn .fa {
    font-family: FontAwesome !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    width: auto;
    height: auto;
    border-radius: 0;
    border: none !important;
    background: transparent !important;
    box-shadow: none !important;
    color: #e74c3c !important;
    font-size: var(--cart-modal-trash-fs);
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    filter: drop-shadow(0 0 3px rgba(231, 76, 60, 0.22));
}

#my-cart-modal a.my-cart-remove-btn:hover .fa,
#my-cart-modal a.my-cart-remove-btn:focus .fa {
    color: #c0392b !important;
    filter: drop-shadow(0 0 5px rgba(231, 76, 60, 0.38));
}

#my-cart-modal #my-cart-table .my-cart-product-desc {
    color: var(--theme-cart-desc-color) !important;
}

#my-cart-modal #my-cart-table input[type="text"] {
    background-color: var(--theme-cart-qty-input-bg) !important;
    color: var(--theme-cart-qty-input-color) !important;
    font-weight: var(--theme-cart-qty-input-font-weight) !important;
}
