
/* ==========================
   EL PADDING CUENTA DENTRO DEL ANCHO
==========================

   ESTA LINEA ARREGLA LA FRANJA BLANCA DE LA DERECHA EN EL CELULAR.

   La tienda NO tenia reinicio de box-sizing. En todo el sitio publico habia
   una sola regla que lo declarara, y era para dos botones flotantes. El panel
   de administracion si lo tenia desde el principio; la tienda no, y nadie se
   dio cuenta porque el sintoma no es que algo se vea roto: es que la pagina se
   puede correr de lado unos pixeles.

   Lo que pasaba, medido en la tienda de verdad:

     .site-shell  ->  width:100% (390px) + padding 0 14px  =  418px de caja

   Con content-box el padding se SUMA al 100%, asi que el contenedor principal
   media 28px mas que la pantalla. De ahi todo lo demas: la pagina se podia
   arrastrar 28px a la derecha, y al hacerlo el encabezado —que si media 390—
   dejaba ver una franja en blanco al lado. Parecia que "el menu no ocupa toda
   la pantalla"; lo que no ocupaba toda la pantalla era la PAGINA.

   En escritorio pasaba igual y era peor: a 1265px el padding de
   clamp(16px,2vw,36px) mas los 78px de la derecha dejaban el documento en
   1369px, o sea 104px de desplazamiento lateral en todas las pantallas.

   Medido antes y despues en store.minksoft.co, en el movil y en el escritorio:
   de 28px y 104px de desborde a CERO. Y comparando elemento por elemento, lo
   unico que cambia de tamano son los descendientes del contenedor que se
   encoge, mas dos detalles de la ficha de producto que ahora miden lo que
   decian medir: las miniaturas (64px pedidos, 68px pintados por el borde) y la
   caja de cantidad.
   ========================== */

*,
*::before,
*::after {
    box-sizing: border-box;
}

/* RED DE SEGURIDAD, NO EL ARREGLO.

   El arreglo es la regla de arriba. Esto es para el dia que alguien meta un
   bloque mas ancho que la pantalla y no se de cuenta: en una tienda, que el
   visitante pueda arrastrar la pagina de lado se ve como un sitio mal hecho.

   `clip` y NO `hidden`, y la diferencia importa: `hidden` convierte al
   elemento en un contenedor de desplazamiento, y eso rompe `position:sticky`
   en todo lo que tenga dentro. `clip` recorta sin crear ese contenedor.
   Comprobado en la tienda de verdad: el desplazamiento vertical sigue
   funcionando y los botones flotantes siguen pegados donde estaban.

   En un navegador viejo que no entienda `clip` esta linea simplemente no hace
   nada, que es exactamente el comportamiento de antes. */
html {
    overflow-x: clip;
}


/* ==========================
   LOS MAPAS NO SE PINTAN ENCIMA DE LO DEMAS
==========================

   Leaflet apila sus capas con numeros propios y altos: los paneles van de 200
   a 700 y los controles de zoom estan en 1000. Las capas de la tienda son
   mucho mas bajas —el riel de redes en 45, los botones flotantes en 50, el
   panel del chat en 60—, asi que el mapa le gana a todos.

   Donde se nota: el CHECKOUT, que es la unica pagina publica con mapa y
   justo la que no puede fallar. El mapa de elegir la direccion tapaba el
   boton del carrito y el panel del chat.

   El arreglo no es subirle el numero a lo de la tienda —eso es una carrera
   que se pierde con la siguiente libreria— sino encerrar el mapa en su propio
   contexto de apilamiento. Con `isolation:isolate`, los 1000 de Leaflet se
   comparan solo entre ellos DENTRO de la caja; hacia afuera la caja vale lo
   que diga su z-index, que es 0. El mapa conserva su orden interno y deja de
   competir con la pagina.

   `.leaflet-container` es la clase que Leaflet le pone al div el solo, asi
   que esto se aplica tambien a cualquier mapa que se agregue despues sin que
   nadie tenga que acordarse. `.mapa` se escribe ademas en la vista para que
   se entienda de donde sale.
   ========================== */

.mapa,
.leaflet-container {
    position: relative;
    z-index: 0;
    isolation: isolate;
}


/* ==========================
   EL PIE SIEMPRE ABAJO
==========================

   Con poco contenido —una tienda recien creada, una categoria vacia, una
   busqueda sin resultados— el pie quedaba flotando a media pantalla y debajo
   se veia el fondo del navegador. Da la impresion de que la pagina se corto.

   La receta: el body es una columna de alto minimo la pantalla, y el bloque
   central es el unico que crece. Si el contenido es largo, todo empuja hacia
   abajo como siempre; si es corto, el hueco se lo come el centro y el pie
   aterriza justo al borde.

   Va aqui y no en cada plantilla porque las siete cargan este archivo primero
   y ninguna de ellas declara `display` sobre el body — asi que esto no le pisa
   nada a nadie.
*/

body {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

/* ==========================
   CINTA DE PROMOCIONES
==========================

   La franja de arriba con mensajes cortos que se desplazan hacia la izquierda.
   La pinta _CintaPromos.cshtml desde _Header, así que queda como hijo directo
   del body: ancho completo sin tocar ninguno de los siete layouts. */

.cinta {
    /* `0 0 auto`: el body es una columna flex y .site-shell es el único que
       puede crecer (de eso depende que el pie quede abajo). Sin esto, la cinta
       se estiraría o se encogería según el contenido de la página. */
    flex: 0 0 auto;

    overflow: hidden;

    /* Gris medio y color heredado: es lo ÚNICO que se lee igual en las siete
       plantillas, claras y oscuras. Una franja negra con letra blanca se ve muy
       bien en Moderno y desaparece en Zafiro. */
    background: rgba(128,128,128,.14);
    border-bottom: 1px solid rgba(128,128,128,.25);
    color: inherit;

    font-size: .78rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    padding: 7px 0;
}

.cinta-pista {
    display: flex;
    /* `max-content` para que la pista mida lo que miden sus mensajes y no el
       ancho de la pantalla. Si se encogiera, el -50% de la animación dejaría de
       coincidir con una copia exacta y el bucle daría un salto visible. */
    width: max-content;
    animation-name: cinta-correr;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
    /* La duración la pone la vista, con los segundos que configuró la tienda. */
}

    /* Se detiene al pasar el mouse, para alcanzar a leer un mensaje.
       En táctil no hay hover y no pasa nada: la cinta sigue andando, que es el
       comportamiento correcto en un celular. */
    .cinta:hover .cinta-pista {
        animation-play-state: paused;
    }

.cinta-grupo {
    display: flex;
    flex: none;
}

.cinta-item {
    padding: 0 28px;
    white-space: nowrap;
}

    /* El separador entre mensajes. Va como pseudo-elemento y no como carácter
       dentro del texto: así un lector de pantalla no lee "punto" entre frases. */
    .cinta-item::after {
        content: "";
        display: inline-block;
        width: 4px;
        height: 4px;
        border-radius: 50%;
        background: currentColor;
        opacity: .45;
        margin-left: 28px;
        vertical-align: middle;
    }

@keyframes cinta-correr {
    from { transform: translateX(0); }
    /* -50% = exactamente una de las dos copias de los mensajes. */
    to   { transform: translateX(-50%); }
}

/* Hay quien marca en su sistema que no quiere animaciones, y no es un capricho:
   a alguien con vértigo o migraña vestibular, un texto cruzando la pantalla sin
   parar le produce malestar físico.

   No se esconde la cinta —la información sigue sirviendo—: se detiene y los
   mensajes se acomodan centrados, envolviéndose si no caben. */
@media (prefers-reduced-motion: reduce) {
    .cinta-pista {
        animation: none;
        width: 100%;
        flex-wrap: wrap;
        justify-content: center;
    }

    /* La segunda copia sobra cuando no hay movimiento: repetiría todo. */
    .cinta-grupo[aria-hidden="true"] {
        display: none;
    }

    .cinta-grupo {
        flex-wrap: wrap;
        justify-content: center;
    }
}

@media (max-width: 780px) {
    .cinta {
        font-size: .72rem;
    }

    .cinta-item {
        padding: 0 16px;
    }

        .cinta-item::after {
            margin-left: 16px;
        }
}

/* ==========================
   CONTENEDOR PRINCIPAL
========================== */

.site-shell {
    /* FLEX Y NO GRID, PARA QUE LA COLUMNA QUE NO ESTÁ NO OCUPE SITIO.

       Con `grid-template-columns: 250px 1fr` la primera columna existe aunque
       nadie la llene: la tarjeta de la izquierda la apaga el dueño de la
       tienda desde Configuración, y al apagarla quedaban 250px en blanco a la
       izquierda con todo el catálogo corrido hacia la derecha. Una rejilla
       reserva sus columnas; un flex solo reparte lo que hay.

       Ahora el <aside> lo pinta _SidebarIzquierda, y cuando no hay tarjeta no
       emite nada: el catálogo se queda con la fila entera, sin hueco y sin
       regla aparte que mantener. */
    display: flex;
    gap: 28px;
    align-items: flex-start;

    /* EL ANCHO.

       Era 1320px centrado: en un monitor de 1600 dejaba 140px muertos a cada
       lado y la barra izquierda arrancaba despegada del borde. Con 1680 la
       página llena la pantalla de un portátil normal —la izquierda queda
       pegada— y en un monitor muy ancho sigue centrada, que es lo correcto:
       una línea de texto de 2000px no se lee.

       El padding en clamp acompaña: 16px en una tableta, 36px en grande. */
    max-width: 1680px;
    margin: 28px auto;
    padding: 0 clamp(16px, 2vw, 36px);

    /* Lo que empuja el pie hasta abajo. `1 0 auto`: crece para llenar el
       sobrante, no se encoge por debajo de su contenido. */
    flex: 1 0 auto;

    /* En una columna flex el ancho es el eje transversal y el item se estira
       por defecto; sin esto el max-width de arriba deja de centrar. */
    width: 100%;
}

/* El hueco de la barra de redes.

   La barra flota pegada al borde derecho y a media altura. Sin reservarle el
   ancho, en una pantalla justa se pone encima de la última columna de
   productos — y lo que tapa es el botón de agregar al carrito.

   Solo en escritorio: en un teléfono, 50px de los 390 que hay es demasiado
   para dejarlos en blanco, y ahí la barra pasa a flotar por encima (es más
   angosta y traslúcida, ver .redes-rail). */
@media (min-width: 1025px) {
    .site-shell {
        padding-right: 78px;
    }
}

.col-izq {
    /* Ni crece ni se encoge: es una tarjeta de ancho fijo al lado de un
       catálogo elástico. */
    flex: 0 0 250px;
    position: sticky;
    top: 20px;
}

.col-centro {
    /* min-width:0 es lo que le permite encogerse por debajo del ancho de su
       contenido. Sin esto, una tira de destacados con tarjetas de 240px fijos
       se niega a bajar de ahí y empuja la página fuera de la pantalla. */
    flex: 1 1 auto;
    min-width: 0;
}

/* ==========================
   SECCIONES
========================== */

.seccion {
    margin-bottom: 48px;
}

.seccion-head {
    display: flex;
    justify-content: space-between;
    align-items: center;

    /* gap y wrap: el enlace se iba contra el borde y, en un título largo en
       pantalla chica, "Ver todo" se partía letra a letra o se salía de la
       pantalla. Pasando de línea se lee entero y se puede tocar. */
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

    .seccion-head h2 {
        margin: 0;
        min-width: 0;
    }

/* EL "VER TODO" ES UN BOTÓN, NO UN ENLACE SUELTO.

   Era `text-decoration:none; opacity:.7` y nada más. Ninguna de las siete
   plantillas le da color, así que se quedaba con el azul subrayado del
   navegador —en una plantilla oscura, azul marino sobre azul marino— y en la
   práctica no se veía. Con marco propio y currentColor se ve igual en las
   siete y se nota que se puede pulsar. */
.seccion-head a,
.seccion-ver {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
    padding: 7px 15px;
    border: 1px solid rgba(128,128,128,.4);
    border-radius: 999px;
    color: inherit;
    text-decoration: none;
    font-size: .82rem;
    font-weight: 600;
    opacity: .85;
    white-space: nowrap;
    transition: border-color .15s ease, opacity .15s ease;
}

    .seccion-head a:hover,
    .seccion-ver:hover {
        border-color: currentColor;
        opacity: 1;
    }

/* ==========================
   BADGE OFERTA
========================== */

/* El ancla del badge.
   .badge-oferta es position:absolute y se posiciona contra el ancestro
   posicionado mas cercano. Ninguna de las seis plantillas le daba uno, asi
   que se anclaba al bloque contenedor inicial —la pagina— y aparecia
   flotando sobre el logo, arriba a la izquierda. */
.producto-card,
.producto-img {
    position: relative;
}

.badge-oferta {
    position: absolute;
    top: 10px;
    left: 10px;
    z-index: 2;
    background: #dc2626;
    color: #fff;
    font-size: .7rem;
    padding: 4px 10px;
    border-radius: 20px;
    text-transform: uppercase;
    letter-spacing: .05em;
}

.precio-anterior {
    text-decoration: line-through;
    opacity: .45;
    font-size: .8em;
    margin-right: 6px;
}

/* ==========================
   MENÚ DESPLEGABLE
========================== */

.menu-item {
    position: relative;
    display: inline-block;
}

    .menu-item .submenu {
        display: none;
        position: absolute;
        top: 100%;
        left: 0;
        background: #fff;
        min-width: 170px;
        box-shadow: 0 8px 28px rgba(0,0,0,.18);
        border-radius: 8px;
        padding: 8px 0;
        z-index: 50;
    }

    /* QUIEN ABRE EL SUBMENU ES LA CLASE, NO EL HOVER.

       Aqui habia `:hover, :focus-within` y "cero JavaScript". Estaba mal en el
       celular, que es donde mas se usa: en tactil no hay hover, y el
       :focus-within tampoco salvaba nada porque el disparador era un <a href>
       — al tocarlo el navegador NAVEGA en vez de darle el foco. Las
       subcategorias eran inalcanzables desde un telefono.

       Ahora cada categoria con hijas lleva su propia flechita, que es un
       <button>, y el script del encabezado le pone .abierto al item. El mismo
       gesto funciona en telefono y en escritorio. */
    .menu-item.abierto .submenu {
        display: block;
    }

/* El hover se conserva SOLO donde existe de verdad.

   `hover: hover` y `pointer: fine` son los dos que separan un raton de un
   dedo. Sin esta guarda, un navegador tactil simula un hover pegajoso al
   tocar: el submenu se abre y se queda abierto hasta que se toque otra cosa,
   peleandose con el .abierto del script. */
@media (hover: hover) and (pointer: fine) {
    .menu-item:hover .submenu {
        display: block;
    }
}

/* La flechita que despliega. Hereda el color del menu de cada plantilla. */
.submenu-btn {
    background: none;
    border: none;
    padding: 2px 4px;
    margin-left: 2px;
    cursor: pointer;
    color: inherit;
    font: inherit;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    opacity: .75;
    vertical-align: middle;
}

    .submenu-btn:hover { opacity: 1; }

/* El boton de las tres lineas. En escritorio no existe. */
.menu-boton {
    display: none;
    background: none;
    border: none;
    padding: 6px;
    cursor: pointer;
    color: inherit;
    line-height: 0;
    /* 44px es el minimo para que un dedo acierte sin pelear. */
    min-width: 44px;
    min-height: 44px;
    align-items: center;
    justify-content: center;
}

    .menu-item .submenu a {
        display: block;
        padding: 9px 18px;
        color: #333 !important;
        opacity: 1 !important;
        margin: 0 !important;
        font-size: .9rem;
        white-space: nowrap;
        text-transform: none;
        letter-spacing: normal;
    }

        .menu-item .submenu a:hover {
            background: #f4f4f8;
        }

.producto-link {
    text-decoration: none;
    color: inherit;
    display: block;
}

/* ==========================
   REDES
========================== */

.red-wa {
    background: #25D366 !important;
}

.red-ig {
    background: radial-gradient(circle at 30% 110%, #fdf497 0%, #fd5949 45%, #d6249f 60%, #285AEB 90%) !important;
}

.red-fb {
    background: #1877F2 !important;
}

/* TikTok es negro sobre blanco, sin degradado. En las plantillas oscuras un
   circulo negro desaparece contra el panel, asi que lleva un borde tenue que
   solo se nota cuando el fondo tambien es oscuro. */
.red-tk {
    background: #000 !important;
    box-shadow: inset 0 0 0 1px rgba(255,255,255,.25);
}

/* ==========================
   RESPONSIVE
========================== */

@media (max-width:1024px) {

    /* En movil se oculta la IZQUIERDA.
       Es contenido de relleno —la tarjeta que escribe el dueño de la tienda—
       y en una columna sola queda empujando el catalogo hacia abajo. Lo que
       un comprador en el celular sí necesita a la mano —carrito y chat— ya no
       vive en ninguna columna: flota.

       El .site-shell es flex, así que escondiendo el <aside> el catálogo se
       queda con la fila entera sin tocar nada más. */
    .col-izq {
        display: none;
    }
}

/* Los dos grupos del menú.

   Solo los emite _MenuTienda en la disposición "partido". En TODO lo demás
   —las otras tres disposiciones, y cualquier ancho por debajo de 1025px
   incluida la partida— desaparecen de la caja con `display:contents`: las
   entradas se maquetan como si fueran hijas directas de la navegación y el
   encabezado se comporta exactamente igual que antes de que existieran.

   Ojo: `display:contents` quita la CAJA, no el nodo. Los selectores de hijo
   directo `.site-nav > a` siguen sin alcanzar lo que está dentro del grupo,
   por eso las reglas del menú en pantalla chica traen su versión con
   `> .nav-grupo >`. */
.nav-grupo {
    display: contents;
}

/* ==========================
   DISPOSICIÓN DE LA BARRA SUPERIOR

   Tres acomodos del encabezado que elige el dueño de la tienda desde
   Admin › Configuración. Lo único que cambia es DÓNDE VA EL LOGO; el orden
   de las categorías no se toca, ese lo manda Categorías.

   POR QUÉ ESTÁ AQUÍ Y NO EN LAS SIETE HOJAS DE PLANTILLA

   Cada plantilla declara su propio `.site-header { display:flex; ... }` y su
   `.site-actions { margin-left:auto }`, y su hoja se carga DESPUÉS de esta.
   Con la misma especificidad gana la última, así que una regla
   `.site-header { ... }` suelta aquí no haría nada. Dos clases en el mismo
   elemento —`.site-header.nav-partido`— le ganan a una sin depender del orden
   de carga, y así las siete plantillas quedaron sin tocar: una disposición
   nueva es CSS aquí y nada más.

   POR QUÉ TODO VA DENTRO DE min-width:1025px

   Es la garantía de que esto NO PUEDE romper el responsive. Por debajo de
   1025px no existe ninguna de estas reglas: el encabezado se comporta
   exactamente igual que antes de que las disposiciones existieran —logo,
   botón de tres líneas, y la navegación como acordeón— sin importar cuál
   eligió el dueño. Un logo centrado en 390px no cabe con el menú al lado, y
   la salida no es apretarlo: es que en el celular las tres disposiciones se
   vean igual, que es lo que un celular necesita.

   El corte en 1025 y no en 781 es a propósito: entre 781 y 1024 el
   encabezado ya está en su versión de escritorio pero con poco ancho, y ahí
   un logo en el medio queda demasiado apretado. En esa franja también manda
   la disposición clásica.
========================== */

@media (min-width:1025px) {

    /* -----------------------------------------------------------------
       1. nav-izquierda — LA DE SIEMPRE

       No tiene reglas, y eso es la idea: es el comportamiento que ya traía
       cada plantilla. Una tienda que nunca toque esta opción no recibe ni un
       byte de CSS distinto del que recibía ayer.
       ----------------------------------------------------------------- */

    /* -----------------------------------------------------------------
       2. nav-apilado — LOGO ARRIBA, MENÚ CENTRADO DEBAJO

       Dos filas. Es la que mejor aguanta un logo grande y un menú largo,
       porque no compiten por el mismo ancho.
       ----------------------------------------------------------------- */

    .site-header.nav-apilado {
        flex-wrap: wrap;
        justify-content: center;
        row-gap: 12px;
        /* Las acciones van en la primera fila, a la derecha del logo. Con
           `position:relative` + absoluto se sacan del reparto y el logo
           queda centrado de verdad, no desplazado por el ancho del icono de
           la cuenta. */
        position: relative;
    }

        .site-header.nav-apilado .site-brand {
            flex: 0 0 100%;
            text-align: center;
        }

            /* `margin:auto` y no `text-align` a secas: el <a> de la marca es
               un bloque con la imagen dentro, y centrar el texto no centra la
               imagen. */
            .site-header.nav-apilado .site-brand img {
                margin-left: auto;
                margin-right: auto;
            }

        .site-header.nav-apilado .site-nav {
            flex: 0 0 100%;
            justify-content: center;
            flex-wrap: wrap;
        }

        .site-header.nav-apilado .site-actions {
            position: absolute;
            right: clamp(16px, 2vw, 32px);
            top: 16px;
            margin-left: 0;
        }

        /* Los submenús de la fila de abajo se abren hacia abajo y, en la
           última categoría de la derecha, se salían por el borde. Centrado el
           menú, el riesgo está en los dos extremos: se anclan al lado que les
           quede espacio. */
        .site-header.nav-apilado .site-nav > .menu-item:last-child .submenu {
            left: auto;
            right: 0;
        }
}

/* ==========================
   nav-partido — LOGO EN EL MEDIO CON EL MENÚ A LADO Y LADO

   La de la referencia. El menú viene en dos `<span class="nav-grupo">`
   que pone _MenuTienda (y SOLO en esta disposición); aquí la navegación
   ocupa todo el ancho y los separa a los extremos, con el logo encima,
   en el centro.

   El logo NO va absoluto. Fue la primera versión, porque centrarlo sobre
   la barra lo deja en el centro exacto de la pantalla; se midió y se cayó
   sola (el porqué está abajo, en la regla de .site-nav). Ahora es un
   hermano más de la fila, entre los dos grupos.

   Hubo una cuarta disposición, "logo centrado con el menú entero a la
   izquierda". Se quitó: por debajo de unos 1300px el menú no cabe en la
   mitad izquierda, se parte en dos líneas y la mitad derecha queda
   vacía. Esta hace lo mismo y mejor, usando el ancho completo.

   POR QUÉ ESTA EMPIEZA EN 1200 Y NO EN 1025 COMO LAS OTRAS DOS

   Porque necesita más ancho por construcción: el menú va PARTIDO, con el
   logo en medio, así que el mismo número de entradas ocupa más fila que
   puestas en bloque. Medido con cuatro categorías más "Quiénes somos": a
   1200 y para arriba cabe en una línea; a 1025 se parte en dos y tres
   filas. No se rompe nada —los grupos son hermanos del logo y no pueden
   solaparse con él— pero una barra de tres pisos se ve peor que la
   clásica, y entre 1025 y 1199 la clásica es mejor opción.

   Entre 1025 y 1199, entonces, una tienda con el logo partido se ve con la
   disposición de siempre. Debajo de 1025, como todas.
========================== */

@media (min-width:1200px) {


.site-header.nav-partido {
    flex-wrap: nowrap;
}

    /* LA NAVEGACIÓN DEJA DE PINTAR CAJA.

       Sus dos grupos pasan a ser hijos directos del encabezado y se
       reparten la fila con el logo EN MEDIO, como hermanos.

       Esto empezó con el logo en `position:absolute` centrado sobre la
       barra, porque así queda exactamente en el centro de la pantalla.
       Se midió y no sirve: el grupo de la derecha se coloca desde el
       borde derecho hacia adentro, así que en cuanto el menú crece —una
       categoría más, nombres largos— su borde izquierdo se mete por
       debajo del logo. Pasaba a 1200px con cuatro categorías y a 1440 con
       nombres largos. Un `gap` no lo arregla: con `space-between` el gap
       es un mínimo, no una reserva.

       Siendo hermanos de la misma fila, solaparse es IMPOSIBLE. Si el
       menú no cabe, el grupo se parte dentro de su propia mitad y la
       barra crece — feo, pero legible, y nunca encima del logo.

       El precio: el logo queda centrado entre los dos grupos, no en el
       centro exacto de la pantalla (las acciones de la derecha lo corren
       unos 50px). Vale ese precio. */
    .site-header.nav-partido .site-nav {
        display: contents;
    }

    .site-header.nav-partido .site-nav > .nav-grupo {
        display: flex;
        align-items: center;
        flex-wrap: wrap;

        /* 18px es el valor de las plantillas; se conserva donde hay sitio
           y se aprieta un poco donde escasea.

           BAJADO DE clamp(12,1.3vw,18) A clamp(10,1.1vw,15) AL METER LA LUPA.

           La lupa le suma unos 40px a este grupo, y medido con cuatro nombres
           de categoria largos eso bastaba para partir el menu en dos filas a
           1440px, donde antes cabia en una. Tres pixeles menos de separacion
           entre entradas no se ven; una segunda fila si.

           Como hay cinco o seis separaciones por grupo y son dos grupos, el
           apretón devuelve mas de lo que cuesta la lupa — y de paso baja un
           poco el encabezado en el tramo de 1200 a 1366px, que ya salia en dos
           filas antes de todo esto. */
        gap: clamp(10px, 1.1vw, 15px);

        /* `0 1 auto`: cada grupo ocupa lo que mide su contenido y puede
           encogerse si falta sitio, pero no se estira.

           Se probó `1 1 0` —los dos grupos exactamente del mismo ancho—
           y dejaba el logo en el centro matemático a costa de partir el
           menú en dos y tres filas desde 1200px, porque ningún grupo
           podía pasar de la mitad aunque sobrara espacio al otro lado.
           Entre un logo en el centro exacto y un menú en una sola línea,
           manda la línea. */
        flex: 0 1 auto;
        min-width: 0;
    }

        .site-header.nav-partido .site-nav > .nav-grupo:first-child {
            order: -1;
            justify-content: flex-start;
        }

        .site-header.nav-partido .site-nav > .nav-grupo:last-child {
            order: 1;
            justify-content: flex-end;
        }

    .site-header.nav-partido .site-brand {
        order: 0;
        flex: 0 0 auto;

        /* `margin: 0 auto` es lo que centra el logo, y es un truco de
           flex que vale la pena entender: un margen `auto` en un hijo
           flex se come el espacio libre de la fila. Con uno a cada lado,
           el sobrante se reparte por igual y el logo queda justo en medio
           de lo que quede entre los dos grupos — sin sacarlo del flujo,
           así que seguir siendo hermano de los grupos (y no poder
           solaparse con ellos) sigue siendo cierto.

           El padding de abajo es el aire mínimo para que el logo no
           toque el menú cuando la barra va justa y los márgenes `auto`
           se quedan en cero. */
        margin: 0 auto;
        padding: 0 clamp(14px, 2vw, 34px);
    }

        /* El logo vuelve a estar en el flujo, así que sostiene el alto de
           la barra solo: ya no hace falta el min-height que compensaba su
           ausencia. El tope sigue, para que una plantilla con un logo
           enorme no estire el encabezado. */
        .site-header.nav-partido .site-brand img {
            max-height: 44px;
            width: auto;
        }

    .site-header.nav-partido .site-actions {
        order: 2;
        margin-left: 0;
        flex: 0 0 auto;
    }
}

/* ==========================
   EL BUSCADOR DE LA BARRA

   Una lupa que, al tocarla, despliega el campo hacia la izquierda. En el
   celular no es una lupa: es el campo entero arriba del cajon del menu (eso
   esta mas abajo, en la media query de 780px).

   TODOS LOS COLORES SON HEREDADOS O GRISES TRANSPARENTES.

   Esta hoja la comparten las siete plantillas, claras y oscuras, y cada una
   trae su propia paleta. Un #fff de fondo desaparece en la plantilla clara y
   un #111 en la oscura. `color:inherit` toma el del texto de la barra —que la
   plantilla ya eligio para que contraste— y `rgba(128,128,128,.12)` se ve como
   un gris suave sobre cualquiera de los dos, porque el gris medio es el unico
   color que no se parece ni al blanco ni al negro. Es el mismo criterio del
   riel de redes sociales.
   ========================== */

.nav-buscar {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    margin: 0;
    /* min-width:0 es lo que deja que el flex lo encoja cuando la barra va
       justa, en vez de empujar el resto del menu fuera de la pantalla. */
    min-width: 0;
}

.nav-buscar-boton {
    background: none;
    border: 0;
    /* 3px arriba y abajo, no 6. Con 6 el boton medía 29px de alto contra los
       ~20 de un enlace de texto, y como el grupo esta centrado verticalmente
       eso estiraba el encabezado entero 9px en la disposicion partida. Medido:
       con 3px la diferencia baja a 3px y deja de notarse. */
    padding: 3px 4px;
    margin: 0;
    cursor: pointer;
    color: inherit;
    display: inline-flex;
    align-items: center;
    /* line-height:0 quita el renglon fantasma que deja el <button> debajo del
       SVG y que desalineaba la lupa con el texto de al lado. */
    line-height: 0;
    border-radius: 999px;
    flex: 0 0 auto;
}

    .nav-buscar-boton:hover { opacity: .65; }

    .nav-buscar-boton:focus-visible {
        outline: 2px solid currentColor;
        outline-offset: 1px;
    }

/* Cerrado: ancho cero y, sobre todo, visibility:hidden.

   Con `opacity:0` a secas el campo seguiria estando ahi: lo alcanzaria el
   tabulador y un lector de pantalla lo leeria. `visibility:hidden` lo saca de
   las dos cosas y aun asi permite la transicion, que `display:none` no. */
.nav-buscar-campo {
    width: 0;
    min-width: 0;
    padding: 0;
    border: 0;
    opacity: 0;
    visibility: hidden;
    font: inherit;
    font-size: .88rem;
    color: inherit;
    background: rgba(128,128,128,.12);
    box-shadow: inset 0 0 0 1px rgba(128,128,128,.3);
    border-radius: 999px;
    outline: none;
    transition: width .18s ease, opacity .18s ease, padding .18s ease;
    /* Safari le pinta al type="search" un borde redondeado propio y le mete
       un alto fijo que no respeta el padding. */
    -webkit-appearance: none;
    appearance: none;
}

    .nav-buscar-campo::placeholder {
        color: inherit;
        opacity: .5;
    }

.nav-buscar.abierto .nav-buscar-campo {
    padding: 7px 12px;
    opacity: 1;
    visibility: visible;
}

    .nav-buscar.abierto .nav-buscar-campo:focus {
        box-shadow: inset 0 0 0 1px rgba(128,128,128,.6);
    }

/* ==========================
   AL ABRIR, EL CAMPO OCUPA EL SITIO DEL MENU. NO SE LO AÑADE.

   ESTO SE MIDIO Y LA PRIMERA VERSION ESTABA MAL.

   El primer intento fue lo evidente: el campo crece y empuja. Medido en 84
   combinaciones (tres disposiciones x nombres de categoria cortos y largos x
   siete anchos), fallaba en tres:

     · 1024px con categorias largas -> el documento se iba a 1114px. O sea
       barra de desplazamiento horizontal en TODA la pagina, que es el bug que
       ya se habia arreglado una vez en este mismo encabezado.
     · 1280 y 1440 en la disposicion partida -> el campo se bajaba a una
       segunda fila, debajo de "Quienes somos".

   La causa es estructural y no se arregla con un ancho mas chico: las siete
   plantillas declaran `.site-header { display:flex }` SIN wrap y con 32px de
   padding; entre el logo, el menu y la cuenta no sobra nada. Cualquier cosa
   que se le sume al menu tiene que salir de alguna parte.

   LO QUE SE HACE AHORA: al abrir, las entradas del menu se esconden y el
   campo se queda con exactamente el espacio que dejaron. El ancho total de la
   navegacion no cambia, asi que NO PUEDE desbordar ni partirse en dos filas,
   pase lo que pase con los nombres de las categorias.

   Y de paso se lee mejor: mientras se busca, el menu no es lo que se esta
   mirando.

   LO QUE SE DESCARTO Y POR QUE:

     · Flotar el campo encima del menu (position:absolute). Es lo que hacen
       las tiendas grandes y aqui no se puede: haria falta un fondo opaco, y
       el fondo lo pone cada plantilla en SU hoja —una de ellas con un
       degradado—. Desde esta hoja no hay forma de saber cual es, y un fondo
       traslucido deja los enlaces del menu leyendose por debajo del texto
       que uno escribe.

     · Dejar que el encabezado se parta en dos filas (flex-wrap). Quita el
       desborde pero mueve la pagina entera hacia abajo al tocar una lupa.

   La clase la pone el guion del encabezado, no un `:has()`: funciona igual en
   navegadores viejos, y es el mismo mecanismo de clases que ya usan el cajon
   del celular y los submenus.
   ========================== */

@media (min-width: 781px) {

    .site-nav.buscando > a,
    .site-nav.buscando > .menu-item,
    .site-nav.buscando > .nav-grupo > a,
    .site-nav.buscando > .nav-grupo > .menu-item {
        display: none;
    }

    /* El formulario se queda con el hueco. En la disposicion partida ademas
       hay que soltarle el grupo que lo contiene, que es `flex:0 1 auto` y por
       si solo no crece. */
    .site-nav.buscando .nav-buscar {
        flex: 1 1 auto;
    }

    .site-nav.buscando > .nav-grupo {
        flex: 1 1 auto;
    }

    .site-nav.buscando .nav-buscar-campo {
        width: 100%;
        min-width: 0;
        flex: 1 1 auto;
    }
}

/* ==========================
   ENCABEZADO EN PANTALLAS CHICAS

   El bug: .site-header es un flex SIN wrap, con padding lateral de 32px y
   una navegacion de cinco enlaces. Su ancho minimo ronda los 600px. En un
   celular de 390px eso desborda, el navegador hace shrink-to-fit y TODA la
   pagina se ve encogida contra el borde izquierdo con una franja negra al
   lado. No era un problema del ancho de la grilla: era el encabezado
   arrastrando el resto.

   Ninguna de las seis plantillas tenia media query para el encabezado, asi
   que esto estaba roto en todas.
========================== */

@media (max-width:780px) {

    .site-header {
        flex-wrap: wrap;
        gap: 10px 16px;
        padding: 12px 16px;
    }

    .site-brand {
        font-size: 1.05rem;
    }

        .site-brand img {
            height: 32px;
        }

    /* LA NAVEGACION SE ESCONDE DETRAS DEL BOTON DE LAS TRES LINEAS.

       Antes se envolvia en dos y tres filas de categorias que empujaban el
       catalogo fuera de la primera pantalla: quien entraba desde el celular
       veia un indice antes que un producto.

       Sigue ocupando su fila propia cuando se abre —no flota encima— porque
       los submenus son position:absolute y un contenedor flotante con
       overflow los recortaria. Abierta, empuja hacia abajo y siempre cabe. */
    .menu-boton {
        display: inline-flex;
    }

    /* `.site-header .site-nav` Y NO `.site-nav` A SECAS.

       Las siete plantillas declaran `.site-nav { display: flex }` en SU hoja,
       que se carga DESPUES de esta. Con la misma especificidad gana la ultima,
       asi que un `display:none` suelto aqui no hacia nada: la navegacion se
       quedaba visible en el celular con el boton al lado. Dos clases le ganan
       a una sin depender del orden de carga. */
    .site-header .site-nav {
        display: none;
        order: 3;
        flex-basis: 100%;
        flex-direction: column;
        align-items: flex-start;
        gap: 2px;
        overflow: visible;
        padding-top: 6px;
        border-top: 1px solid rgba(128,128,128,.25);
        margin-top: 4px;
    }

        .site-header .site-nav.abierto {
            display: flex;
        }

        /* Cada entrada, una linea alta. Un menu de telefono se toca, y 42px es
           lo que necesita un dedo para no fallar. */
        /* Las dos ultimas alcanzan el caso de la disposicion "partido", que
           mete las entradas dentro de un <span class="nav-grupo">: el grupo
           no pinta caja, pero el selector de hijo directo si lo ve. Sin
           estas dos, el menu del celular de una tienda con el logo centrado
           se quedaria sin el alto de 42px que necesita un dedo. */
        .site-nav > a,
        .site-nav > .menu-item,
        .site-nav > .nav-grupo > a,
        .site-nav > .nav-grupo > .menu-item {
            display: flex;
            align-items: center;
            width: 100%;
            min-height: 42px;
        }

        .site-nav a {
            white-space: nowrap;
        }

        /* EL BUSCADOR EN EL CELULAR: PRIMERO Y YA ABIERTO.

           Aqui la navegacion es un cajon detras del boton de las tres lineas.
           Una lupa dentro de un cajon son dos toques antes de poder escribir,
           y buscar es lo que mas se hace desde un telefono.

           `order:-1` lo sube al principio del cajon sin tocar el marcado: en
           el HTML sigue al lado de "Quienes somos", que es donde va en
           escritorio. Los dos selectores cubren las cuatro disposiciones —en
           la partida el formulario cuelga de un <span class="nav-grupo">, que
           es display:contents y por eso el hijo directo sigue siendo un item
           del flex, pero el SELECTOR si necesita el paso de en medio. */
        .site-nav > .nav-buscar,
        .site-nav > .nav-grupo > .nav-buscar {
            order: -1;
            width: 100%;
            margin-bottom: 6px;
        }

        /* Cuatro clases: le gana a `.nav-buscar.abierto .nav-buscar-campo`
           (tres) sin depender de cual hoja se cargue despues. El proyecto ya
           se tropezo con esto: las siete plantillas se cargan DESPUES de esta
           y con la misma especificidad ganaba la ultima. */
        .site-header .site-nav .nav-buscar .nav-buscar-campo {
            /* flex:1 1 auto con min-width:0 y no solo width:100%: son
               hermanos del boton dentro de un flex, y un item al 100% de
               ancho empuja al hermano fuera de la caja si no se le permite
               encogerse. */
            flex: 1 1 auto;
            width: 100%;
            min-width: 0;
            padding: 10px 14px;
            opacity: 1;
            visibility: visible;
            /* 16px exactos. Por debajo de eso, iOS hace zoom sobre el campo al
               tocarlo y deja la pagina descuadrada, y el usuario tiene que
               pellizcar para volver. */
            font-size: 16px;
        }

        /* La lupa pasa a ser el boton de enviar, a la derecha del campo. */
        .site-header .site-nav .nav-buscar {
            display: flex;
            gap: 6px;
        }

            .site-header .site-nav .nav-buscar .nav-buscar-boton {
                padding: 8px;
                min-height: 42px;
            }

    /* El submenu, en flujo y no flotando.
       Absoluto en un telefono se sale por el borde derecho, y con el
       overflow-x:hidden del body queda inaccesible. Asi se comporta como un
       acordeon: empuja el contenido hacia abajo y siempre cabe. */
    .menu-item {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
    }

        /* En flujo y no flotando: absoluto en un telefono se sale por el borde
           derecho. Asi se comporta como un acordeon, empuja hacia abajo y
           siempre cabe. */
        .menu-item.abierto .submenu {
            position: static;
            flex-basis: 100%;
            min-width: 0;
            box-shadow: none;
            border-radius: 6px;
            margin: 4px 0 6px 14px;
        }

        /* La flechita, mas grande y separada del nombre: son dos destinos
           distintos y con el dedo hay que poder elegir sin acertar por suerte. */
        .menu-item .submenu-btn {
            margin-left: 8px;
            min-width: 40px;
            min-height: 40px;
            justify-content: center;
        }

    .site-actions {
        gap: 14px;
    }

    .site-shell {
        gap: 18px;
        margin: 18px auto;
        padding: 0 14px;
    }
}

/* NO poner overflow-x:hidden en html/body.
   Se intento como "red de seguridad" y fue peor: no arregla el desborde,
   lo ESCONDE. El contenido que se sale deja de ser alcanzable — ni
   siquiera con scroll — y el sintoma pasa de "la pagina se ve corrida" a
   "faltan cosas", que es mucho mas dificil de diagnosticar.
   Si algo desborda, hay que encontrar que lo hace. */

img {
    max-width: 100%;
}

/* ==========================
   MENU DE LA CUENTA (encabezado)
==========================

   El desplegable del icono de usuario: Mi cuenta, Mis pedidos, Cerrar sesion.

   El panel es una tarjeta BLANCA fija, igual que el submenu de categorias, y
   no un color heredado. Las siete plantillas tienen encabezados de colores
   distintos —unas claras, otras casi negras— y un panel que herede el color
   de alguna de ellas es ilegible en el resto. Una tarjeta flotante blanca se
   lee sobre cualquier fondo, que es justo lo que hace todo el mundo.
*/

.cuenta-menu {
    position: relative;
}

/* El disparador es un <button>: hay que quitarle la pinta de boton para que se
   vea igual que el resto del encabezado. */
.cuenta-menu .cuenta-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    color: inherit;
    font: inherit;
    cursor: pointer;
}

/* ABRE Y CIERRA POR CLIC, no por :hover.
   Estaba con hover y estaba mal donde mas se usa: en un telefono no existe el
   hover, asi que "Cerrar sesion" era inalcanzable desde el encabezado. Ahora
   lo controla el atributo `hidden` que pone el JavaScript del encabezado, y el
   mismo gesto sirve en pantalla tactil y con raton. */
.cuenta-menu .cuenta-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;              /* pegado a la derecha: el icono vive en esa esquina */
    background: #fff;
    min-width: 200px;
    box-shadow: 0 8px 28px rgba(0,0,0,.22);
    border-radius: 8px;
    padding: 6px 0;
    z-index: 60;
}

    /* Con !important por si alguna plantilla declara `display` sobre este
       selector: sin el, ese display le gana al hidden y el panel se queda
       abierto para siempre. */
    .cuenta-menu .cuenta-panel[hidden] {
        display: none !important;
    }

/* El !important repite el del submenu de categorias y por lo mismo: varias
   plantillas pintan `.site-header a` con su propio color y opacidad, y sin
   esto el texto del panel sale blanco sobre blanco. */
.cuenta-menu .cuenta-panel a,
.cuenta-menu .cuenta-panel button {
    display: block;
    width: 100%;
    text-align: left;
    padding: 9px 18px;
    color: #333 !important;
    opacity: 1 !important;
    margin: 0 !important;
    font-size: .9rem;
    font-family: inherit;
    white-space: nowrap;
    text-transform: none;
    letter-spacing: normal;
    text-decoration: none;
    background: none;
    border: none;
    cursor: pointer;
}

    .cuenta-menu .cuenta-panel a:hover,
    .cuenta-menu .cuenta-panel button:hover {
        background: #f3f4f6;
    }

/* Cerrar sesion, separado del resto: es la accion que no se deshace de las
   tres, y pegada a las otras se pulsa por error. */
.cuenta-menu .cuenta-panel form {
    border-top: 1px solid #e5e7eb;
    margin-top: 6px;
    padding-top: 6px;
}

/* ==========================
   PÁGINA CARRITO
========================== */
.carrito-fila {
    display: grid;
    grid-template-columns: 70px 1fr auto auto auto;
    gap: 16px;
    align-items: center;
    padding: 14px 0;
    border-bottom: 1px solid #eee;
}

.carrito-img {
    width: 70px;
    height: 70px;
    object-fit: cover;
    border-radius: 8px;
    background: #f2f2f4;
}

.carrito-datos {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.carrito-var {
    font-size: .8rem;
    opacity: .6;
}

.carrito-precio {
    font-size: .85rem;
    opacity: .7;
}

.carrito-cant {
    display: flex;
    gap: 6px;
    align-items: center;
}

    .carrito-cant input {
        width: 56px;
        padding: 6px;
        border: 1px solid #ccc;
        border-radius: 6px;
    }

.carrito-subtotal {
    font-weight: 700;
    min-width: 90px;
    text-align: right;
}

.btn-mini {
    padding: 6px 10px;
    border: 1px solid #ccc;
    background: #fff;
    border-radius: 6px;
    cursor: pointer;
    font-size: .8rem;
}

.btn-eliminar {
    border: none;
    background: none;
    color: #dc2626;
    cursor: pointer;
    font-size: 1rem;
}

.carrito-resumen {
    display: flex;
    justify-content: flex-end;
    gap: 20px;
    align-items: center;
    padding: 20px 0;
    font-size: 1.2rem;
}

.carrito-acciones {
    display: flex;
    gap: 12px;
    justify-content: flex-end;
    flex-wrap: wrap;
}

.btn-secundario {
    padding: 12px 18px;
    border: 1px solid #ccc;
    background: #fff;
    border-radius: 8px;
    text-decoration: none;
    color: #333;
    cursor: pointer;
}

.btn-pagar {
    padding: 12px 22px;
    background: #16a34a;
    color: #fff;
    border-radius: 8px;
    text-decoration: none;
    font-weight: 600;
}

/* ==========================
   CARRUSEL
========================== */
.carrusel {
    position: relative;
    overflow: hidden;
    border-radius: 12px;
    margin-bottom: 40px;
}

/* EL BANNER A TODO EL ANCHO.

   Cuando está activado, el carrusel NO se pinta dentro de la columna central:
   lo pinta _Header, que es hijo directo del <body>. Así queda al ancho de la
   pantalla sin `100vw`, sin márgenes negativos y sin tener que recortar el
   desbordamiento de la página entera.

   SE INTENTÓ PRIMERO CON PURO CSS Y ESTABA MAL. Dejándolo en su columna y
   sacándolo con `width:100vw` más un margen negativo, el banner se montaba
   encima de las dos barras laterales: la izquierda desaparecía debajo y la
   derecha se pintaba encima del banner. Las tres columnas comparten fila, así
   que cualquier cosa que se ensanche las invade. No era un problema de
   cuentas: el banner estaba en el sitio equivocado del documento. */
.carrusel.ancho-completo {
    /* El body es una columna flex y solo .site-shell puede crecer, que es de lo
       que depende que el pie quede abajo. */
    flex: 0 0 auto;

    /* Pegado a los bordes de la pantalla, las esquinas redondeadas se leen como
       un error de recorte. */
    border-radius: 0;

    /* El aire de abajo lo pone el margen superior de .site-shell; sumar los dos
       deja un hueco del doble. */
    margin-bottom: 0;
}

.carrusel-track {
    display: flex;
    transition: transform .5s ease;
}

.carrusel-slide {
    flex: 0 0 100%;
    position: relative;
    text-decoration: none;
}

    .carrusel-slide img {
        width: 100%;

        /* 340px era casi un tercio de la pantalla de un portátil solo en la
           miniatura de la columna. El catálogo —que es a lo que se viene—
           empezaba por debajo del pliegue. 250px sigue siendo un banner que
           se lee y deja ver productos sin bajar. */
        height: 250px;
        object-fit: cover;
        display: block;
    }

    /* CAJA DE ALTO FIJO, IMAGEN COMPLETA Y SIN FRANJAS. LAS TRES.

       Esto se intentó tres veces y las dos primeras estaban mal:

       1. `height:460px` con object-fit:cover. Alto firme y sin franjas, pero
          RECORTABA: se perdió el "30% DTO." de la esquina del banner.
       2. `height:auto`. Nada recortado y de borde a borde, pero el alto salía
          de la proporción de cada imagen, así que el banner CAMBIABA DE TAMAÑO
          al pasar de un slide a otro. Se ve peor que el recorte.

       El problema de fondo es geométrico: con una caja de proporción fija y
       una imagen de otra proporción, o se recorta o sobra espacio. No hay una
       tercera opción... salvo LLENAR ESE ESPACIO CON ALGO.

       Eso es lo que se hace aquí, y es lo mismo que hacen YouTube o Netflix
       con las portadas que no les calzan: la foto va entera y centrada
       (`contain`, nada recortado), y detrás va una copia de ella misma
       ampliada y desenfocada que tapa el sobrante. El resultado es una caja
       que no cambia nunca de alto, llena de borde a borde, con la imagen
       completa y sin deformar.

       Y cuando la imagen SÍ tiene la proporción de la caja, el desenfoque no
       se ve: `contain` y `cover` coinciden y la foto tapa el fondo entero. O
       sea que subiendo los banners a 1600x500 esto es invisible. */
    .carrusel.ancho-completo .carrusel-slide {
        /* LO QUE FIJA EL ALTO. Es la misma proporción en TODOS los slides, así
           que el banner mide siempre igual y no da el brinco al cambiar.

           La proporción la pone el script, leyéndola del PRIMER banner: quien
           administra la tienda decide el alto simplemente poniendo de primero
           el banner con la forma que quiere. Así una imagen hecha a medida
           llena la caja exacta, sin recorte y sin relleno.

           El 1600/500 de aquí es solo el respaldo para cuando el script todavía
           no ha medido —o está deshabilitado—: sin un valor la caja no tendría
           alto y el banner desaparecería. */
        aspect-ratio: var(--ratio-banner, 1600 / 500);
        overflow: hidden;

        /* EL TECHO DEL BANNER.

           La proporción sola no alcanza: un banner de 1600x500 en un monitor
           de 1600 mide 500px de alto, y con el encabezado encima la portada
           entera era banner. No se veía ni el primer producto sin bajar.

           El techo recorta ese alto en torno a un tercio sin tocar la imagen:
           la caja se vuelve más apaisada que la foto, así que el script deja
           de marcarla como "calza" y la foto pasa a `contain` —entera,
           centrada, nada recortado— con su propia copia desenfocada tapando
           el sobrante de los lados. Es el mismo mecanismo que ya existía para
           las imágenes de otra medida.

           En vh y no en píxeles: lo que estorba no es un número de píxeles,
           es cuánta pantalla se come. En un portátil bajo, el banner baja con
           él. Los dos extremos del clamp son para que no se vuelva una tirita
           en una pantalla pequeña ni una pared en un monitor 4K. */
        max-height: clamp(240px, 50vh, 460px);
    }

    /* CUANDO LA IMAGEN CALZA CON LA CAJA, LLENA Y YA. SIN DIFUMINADO.

       Esta clase la pone el script después de comparar la proporción real de
       la foto con la de la caja. Si coinciden —que es lo que pasa con el banner
       que definió el alto, y con cualquier otro hecho de la misma medida— se
       pasa a `cover`: la imagen toca los cuatro bordes y el relleno de atrás
       sobra, así que se esconde.

       El difuminado queda entonces para lo que de verdad es: la red que salva
       a una imagen de otra medida, no el comportamiento de todos los días. */
    .carrusel.ancho-completo .carrusel-slide.calza .carrusel-foto {
        object-fit: cover;
    }

    .carrusel.ancho-completo .carrusel-slide.calza .carrusel-fondo {
        display: none;
    }

    /* El relleno del sobrante: la misma imagen, ampliada y desenfocada.

       Es el MISMO src que la foto de adelante, así que el navegador la
       descarga una sola vez — no cuesta una petición más.

       El `scale(1.2)` no es decorativo: un desenfoque grande difumina también
       los bordes del elemento y dejaría un halo claro contra el borde de la
       caja. Ampliando, ese halo queda fuera del recorte. */
    .carrusel.ancho-completo .carrusel-fondo {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
        filter: blur(30px) brightness(.5) saturate(1.15);
        transform: scale(1.2);
        z-index: 0;
    }

    /* La foto de verdad: entera, centrada y sin deformar. */
    .carrusel.ancho-completo .carrusel-foto {
        position: relative;
        z-index: 1;
        width: 100%;
        height: 100%;
        object-fit: contain;
        max-height: none;
    }

/* Fuera del modo ancho completo el carrusel sigue siendo una miniatura dentro
   de su columna: ahí lo que importa es que todas midan igual, así que se
   recorta con `cover` como siempre y el fondo desenfocado no pinta nada. */
.carrusel:not(.ancho-completo) .carrusel-fondo {
    display: none;
}

/* En un celular, 340px de alto contra ~350px de ancho deja el banner casi
   cuadrado y empuja el resto de la portada fuera de la primera pantalla. */
@media (max-width: 780px) {
    /* El de la columna sí se recorta: es una miniatura y lo que importa es que
       todas midan igual. */
    .carrusel-slide img {
        height: 175px;
    }

    /* En el celular la caja se hace más alta. Con la proporción del
       escritorio, 3.2, un banner en una pantalla de 390px mediría 122px de
       alto: una tirita donde no se lee nada.

       2/1 da unos 195px en un teléfono de 390. Era 16/9 (220px) y se comía la
       primera pantalla entera junto con el encabezado y la cinta. La foto
       ancha sigue saliendo entera y centrada, y el sobrante de arriba y abajo
       lo tapa el fondo desenfocado. */
    .carrusel.ancho-completo .carrusel-slide {
        aspect-ratio: 1.8 / 1;

        /* Y un techo también aquí: en una tableta en horizontal, 1.8/1 sobre
           1000px de ancho son 550px de alto otra vez. */
        max-height: 44vh;
    }

    .carrusel.ancho-completo .carrusel-foto {
        height: 100%;
        max-height: none;
    }
}

.carrusel-titulo {
    /* z-index por encima del fondo desenfocado y de la foto del banner. */
    z-index: 2;
    position: absolute;
    bottom: 24px;
    left: 28px;
    background: rgba(0,0,0,.55);
    color: #fff;
    padding: 10px 20px;
    border-radius: 8px;
    font-size: 1.4rem;
    font-weight: 700;
}

.carrusel-btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background: rgba(0,0,0,.4);
    color: #fff;
    border: none;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    font-size: 1.6rem;
    cursor: pointer;
}

    .carrusel-btn.prev {
        left: 16px;
    }

    .carrusel-btn.next {
        right: 16px;
    }

    .carrusel-btn:hover {
        background: rgba(0,0,0,.7);
    }

/* ==========================
   DESTACADOS — carrusel horizontal

   Misma tarjeta que la grilla normal de productos (mismo ancho, misma foto),
   solo que arriba lleva la descripción. Va en una sola fila con scroll a la
   derecha: antes era grilla y con 3+ productos la segunda fila empujaba las
   demás secciones fuera de la pantalla.

   Alturas fijas: es lo que mantiene todas las tarjetas parejas por más que una
   descripción sea larga y otra corta.

   Colores en rgba/inherit a propósito: este archivo lo comparten las 5
   plantillas, así que sirve en el fondo oscuro de Luxury y en los claros.
========================== */
.destacados-wrap {
    position: relative;
}

.destacados-track {
    display: flex;
    gap: 28px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    padding: 4px 2px 10px;
    /* Sin barra de scroll: se navega con las flechas o arrastrando. */
    scrollbar-width: none;
    -ms-overflow-style: none;
}

    .destacados-track::-webkit-scrollbar {
        display: none;
    }

.destacado-card {
    /* Ancho fijo igual al de las tarjetas de la grilla de productos. */
    flex: 0 0 240px;
    max-width: 100%;
    scroll-snap-align: start;
    display: flex;
    flex-direction: column;
    border-radius: 10px;
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    background: rgba(128,128,128,.07);
    border: 1px solid rgba(128,128,128,.2);
    transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}

    .destacado-card:hover {
        transform: translateY(-3px);
        box-shadow: 0 12px 26px rgba(0,0,0,.18);
        border-color: rgba(128,128,128,.42);
    }

/* Alto fijo: aquí es donde se emparejan todas las tarjetas. */
.destacado-texto {
    height: 118px;
    padding: 16px 16px 10px;
    overflow: hidden;
}

    .destacado-texto h3 {
        margin: 0 0 7px;
        font-size: .95rem;
        line-height: 1.3;
        /* Un nombre largo no puede empujar la descripción fuera de la caja. */
        display: -webkit-box;
        -webkit-line-clamp: 1;
        line-clamp: 1;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }

.destacado-desc {
    margin: 0;
    font-size: .78rem;
    line-height: 1.5;
    opacity: .7;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* LA FOTO LLENA LA TARJETA DE BORDE A BORDE. LEER ESTO ANTES DE TOCARLO.

   Esto ya se cambio dos veces y las dos primeras estaban mal, por dos razones
   distintas:

   1. `background:#fff` + `padding:10px` sobre la imagen. El marco pintaba
      blanco donde la foto no llegaba: dos franjas blancas encuadrando el
      producto dentro de una tarjeta oscura.
   2. Quitar el fondo pero dejar `object-fit: contain`. Se fue el color
      inventado, pero la foto seguia sin llenar la tarjeta — y como las fotos
      de catalogo YA TRAEN su propio fondo blanco, quedaba un rectangulo
      blanco flotando en medio de una tarjeta oscura. Mismo defecto visual,
      otro culpable.

   La solucion de verdad es que no sobre espacio: `cover` escala la foto hasta
   tapar toda la caja. El fondo blanco de la foto pasa a SER la baldosa, no un
   bloque suelto dentro de ella, y no queda ni un pixel de marco.

   El precio de `cover` es que recorta un poco por el lado largo. Se acepta a
   proposito: la ficha del producto sigue en `contain` y ahi se ve completo.
   Si alguien vuelve a poner `contain` aqui, vuelve el rectangulo blanco. */
.destacado-media {
    position: relative;
    height: 220px;
    background: transparent;
    overflow: hidden;
}

    .destacado-media img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        /* El producto suele estar centrado en la foto; recortar por los bordes
           es lo que menos se lleva por delante. */
        object-position: center;
        display: block;
    }

.destacado-precio {
    position: absolute;
    left: 12px;
    bottom: 12px;
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    background: #fff;
    color: #111;
    padding: 6px 12px;
    border-radius: 8px;
    font-weight: 700;
    font-size: .88rem;
    box-shadow: 0 5px 15px rgba(0,0,0,.2);
}

.destacado-antes {
    opacity: .45;
    font-weight: 400;
    font-size: .74rem;
}

.destacado-oferta {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 1;
    background: #dc2626;
    color: #fff;
    padding: 4px 9px;
    border-radius: 999px;
    font-size: .65rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
}

/* ---- Flechas ---- */
.destacados-btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    width: 40px;
    height: 40px;
    border: none;
    border-radius: 50%;
    background: rgba(0,0,0,.62);
    color: #fff;
    font-size: 1.35rem;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 14px rgba(0,0,0,.28);
    transition: background .18s ease;
}

    .destacados-btn:hover {
        background: rgba(0,0,0,.82);
    }

    .destacados-btn.prev { left: -10px; }
    .destacados-btn.next { right: -10px; }

    /* Se ocultan cuando no hay a dónde desplazarse. */
    .destacados-btn[hidden] {
        display: none;
    }

@media (max-width: 620px) {
    /* La tarjeta ocupa el 78% para que ASOME la siguiente: es la pista
       visual de que hay mas y se puede arrastrar. */
    .destacado-card {
        flex: 0 0 78%;
    }

    /* Las flechas se ocultan (en tactil se arrastra), pero entonces hay que
       devolver la barra de desplazamiento: sin flechas Y sin barra, nada
       indica que la fila continua. */
    .destacados-btn {
        display: none;
    }

    .destacados-track {
        scrollbar-width: thin;
        -ms-overflow-style: auto;
    }

        .destacados-track::-webkit-scrollbar {
            display: block;
            height: 4px;
        }

        .destacados-track::-webkit-scrollbar-thumb {
            background: rgba(128,128,128,.45);
            border-radius: 4px;
        }
}


/* ==========================
   CHAT DEL ASISTENTE

   Base para las cinco plantillas. layout-luxury.css ya trae su propia
   versión de .chat-widget y se carga después, así que la suya manda; lo
   de abajo es lo que ven las otras cuatro, más las piezas nuevas
   (tarjetas de producto y puntos de "escribiendo") que ninguna tenía.

   Los colores van en grises translúcidos a propósito: así el bloque se
   ve bien tanto sobre el fondo claro de Moderno como sobre el oscuro de
   Industrial, sin tener que escribirlo cinco veces.
========================== */

.chat-widget {
    display: flex;
    flex-direction: column;
    height: 440px;
    overflow: hidden;
    border: 1px solid rgba(128,128,128,.28);
    border-radius: 10px;
    background: rgba(127,127,127,.05);
}

.chat-header {
    padding: 12px 16px;
    font-weight: 600;
    border-bottom: 1px solid rgba(128,128,128,.28);
}

.chat-body {
    flex: 1;
    overflow-y: auto;
    padding: 14px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.chat-msg {
    padding: 8px 12px;
    border-radius: 10px;
    font-size: .85rem;
    line-height: 1.5;
    max-width: 88%;
    white-space: pre-wrap;
    word-break: break-word;
}

    .chat-msg.bot {
        background: rgba(127,127,127,.16);
        align-self: flex-start;
    }

    .chat-msg.user {
        background: rgba(127,127,127,.32);
        align-self: flex-end;
    }

.chat-input {
    display: flex;
    border-top: 1px solid rgba(128,128,128,.28);
}

    .chat-input input {
        flex: 1;
        min-width: 0;
        border: none;
        padding: 12px;
        background: transparent;
        color: inherit;
        outline: none;
        font: inherit;
        font-size: .88rem;
    }

    .chat-input button {
        border: none;
        background: rgba(127,127,127,.24);
        color: inherit;
        padding: 0 16px;
        cursor: pointer;
        font-size: 1rem;
    }

    .chat-input button:disabled,
    .chat-input input:disabled {
        opacity: .5;
        cursor: default;
    }

/* ---- "Escribiendo..." ----
   Tres puntos en vez de un texto fijo: ocupa poco y no hay que traducirlo. */
.chat-pensando {
    display: flex;
    gap: 5px;
    align-items: center;
    padding: 12px;
}

    /* El primer hijo es el texto ("Consultando"); los puntos son los que van
       después. Sin el :not, el texto se convertiría en un cuarto punto. */
    .chat-pensando-txt {
        font-size: .8rem;
        opacity: .7;
        margin-right: 3px;
    }

    .chat-pensando span:not(.chat-pensando-txt) {
        width: 6px;
        height: 6px;
        border-radius: 50%;
        background: currentColor;
        opacity: .35;
        animation: chatPunto 1.1s infinite ease-in-out;
    }

    .chat-pensando span:not(.chat-pensando-txt):nth-child(3) { animation-delay: .18s; }
    .chat-pensando span:not(.chat-pensando-txt):nth-child(4) { animation-delay: .36s; }

@keyframes chatPunto {
    0%, 80%, 100% { opacity: .25; transform: translateY(0); }
    40%           { opacity: .9;  transform: translateY(-3px); }
}

/* ---- Tarjetas de producto dentro del chat ----
   Las dibuja el navegador con los datos que devuelve NUESTRO servidor
   (precio, imagen y enlace reales), no con lo que haya dicho la IA. */
.chat-productos {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.chat-producto {
    display: flex;
    gap: 10px;
    align-items: center;
    padding: 8px;
    border: 1px solid rgba(128,128,128,.28);
    border-radius: 10px;
    background: rgba(127,127,127,.07);
}

    .chat-producto img {
        width: 54px;
        height: 54px;
        object-fit: cover;
        border-radius: 8px;
        flex: 0 0 auto;
    }

.chat-producto-datos {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
    flex: 1;
}

.chat-producto-nombre {
    font-size: .82rem;
    font-weight: 600;
    text-decoration: none;
    color: inherit;
    line-height: 1.3;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

    .chat-producto-nombre:hover {
        text-decoration: underline;
    }

.chat-producto-precio {
    font-size: .82rem;
    opacity: .8;
}

.chat-producto-btn,
.chat-agregar-todos {
    border: 1px solid rgba(128,128,128,.45);
    background: transparent;
    color: inherit;
    border-radius: 999px;
    padding: 4px 12px;
    font-size: .75rem;
    cursor: pointer;
    align-self: flex-start;
    font-family: inherit;
}

    .chat-producto-btn:hover,
    .chat-agregar-todos:hover {
        background: rgba(127,127,127,.22);
    }

    .chat-producto-btn:disabled,
    .chat-agregar-todos:disabled {
        opacity: .6;
        cursor: default;
    }

.chat-agregar-todos {
    align-self: stretch;
    text-align: center;
    padding: 7px 12px;
    font-size: .78rem;
}

/* ==========================================================================
   LO QUE FLOTA SOBRE LA TIENDA

   Antes esto era una tercera columna de .site-shell: 270px fijos con el chat,
   las redes y el carrito dentro, en todas las páginas. Tres cosas que no son
   contenido ocupando una columna de contenido. Ahora flotan y la rejilla se
   quedó con dos columnas.

   Las tres reglas que se respetan aquí:

   1. No tapan nada que haga falta. La barra de redes va a media altura y el
      .site-shell le reserva el ancho; la pila de abajo se queda en la esquina.
   2. Tamaño de dedo. Nada de lo que se toca baja de 44px.
   3. Los colores los sigue poniendo la plantilla. Estas reglas colocan y
      dimensionan; el fondo y el texto salen de .redes, .carrito-btn y
      .chat-widget, que cada plantilla define a su manera. Por eso el marcado
      conserva esas clases en vez de estrenar unas nuevas.
   ========================================================================== */

/* --------------------------------------------------------------------------
   LA BARRA DE REDES, PEGADA AL BORDE DERECHO
   -------------------------------------------------------------------------- */
.redes-rail {
    position: fixed;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    z-index: 45;

    /* Redondeada solo por la izquierda: el lado derecho muere contra el borde
       de la pantalla y una esquina redonda ahí se lee como un error de
       recorte. */
    border-radius: 14px 0 0 14px;
    padding: 10px 7px;

    /* EL RIEL SALE DE LA PLANTILLA, NO DE UN GRIS FIJO.

       Era `#f1f4f7`: un recuadro gris claro pegado al borde derecho, igual en
       las siete plantillas. En las claras pasaba desapercibido y en las
       oscuras —luxury, zafiro— se veía como un parche de otra página.

       Un gris translúcido sobre lo que haya detrás funciona en las dos: sobre
       blanco se lee como un panel apenas más oscuro, sobre negro como uno
       apenas más claro. Y el borde en `currentColor` hereda el color del
       texto de la plantilla, así que el contorno siempre pertenece. */
    background: rgba(128,128,128,.14);
    box-shadow: 0 6px 24px rgba(0,0,0,.16), inset 0 0 0 1px rgba(128,128,128,.22);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    color: inherit;
}

    /* .redes es horizontal en las siete plantillas. Aquí va en vertical, y la
       regla gana por especificidad (0,2,0) sin importar el orden de carga de
       las hojas. */
    .redes-rail .redes {
        display: flex;
        flex-direction: column;
        gap: 10px;
        justify-content: center;
    }

        /* CADA RED CON SU COLOR, EL CÍRCULO CON EL DE LA PLANTILLA.

           Antes cada enlace era un círculo RELLENO del color de la marca:
           verde, degradado rosa, azul y negro, los cuatro a la vez, pegados
           al borde de la pantalla. En una tienda sobria eso es lo más
           llamativo de la página, y compite con los productos.

           Ahora el círculo es transparente con un aro del color del texto de
           la plantilla —así pertenece a la tienda— y lo que lleva el color de
           la marca es EL ICONO. Se siguen distinguiendo los cuatro de un
           vistazo, que es para lo que sirve el color, pero dejan de gritar.
           Al pasar el cursor sí se rellenan: ahí sí es la acción que se está
           a punto de hacer.

           El `!important` no es pereza: las siete plantillas declaran
           `.redes a { background:#fff }` y sus hojas se cargan DESPUÉS de
           esta. Sin él, los cuatro círculos salen blancos. */
        .redes-rail .redes a {
            width: 38px;
            height: 38px;
            background: transparent !important;
            box-shadow: inset 0 0 0 1px rgba(128,128,128,.4);
            transition: background .15s ease, color .15s ease, transform .15s ease;
        }

            .redes-rail .redes a:hover {
                transform: translateY(-1px);
            }

                /* Relleno de marca y glifo blanco. Se escribe red por red y
                   no con `background: currentColor`: el icono tendría el
                   mismo color que el relleno y desaparecería. */
                .redes-rail .redes a:hover i {
                    color: #fff;
                }

        /* Los colores de marca, en el ICONO. Los tres son los oficiales con
           un ajuste: el azul de Facebook se aclaró un punto para que también
           se lea sobre el negro de las plantillas oscuras. */
        .redes-rail .red-wa { color: #25D366 !important; }
        .redes-rail .red-ig { color: #E1306C !important; }
        .redes-rail .red-fb { color: #3B82F6 !important; }

        .redes-rail .red-wa:hover { background: #25D366 !important; }
        .redes-rail .red-ig:hover { background: #E1306C !important; }
        .redes-rail .red-fb:hover { background: #3B82F6 !important; }

        /* TikTok es blanco y negro: no tiene un color que ponerle, así que
           hereda el del texto de la plantilla. En una tienda clara sale
           oscuro y en una oscura sale claro — que es exactamente lo que es la
           marca.

           Por lo mismo no se rellena al pasar el cursor: el relleno sería del
           color del texto y el glifo blanco encima se perdería en la mitad de
           las plantillas. Se marca el aro y basta. */
        .redes-rail .red-tk {
            color: inherit !important;
        }

            .redes-rail .red-tk:hover {
                background: rgba(128,128,128,.26) !important;
            }

                .redes-rail .red-tk:hover i {
                    color: inherit;
                }

/* --------------------------------------------------------------------------
   LA PILA DE ABAJO A LA DERECHA: CARRITO Y CHAT

   En columna y no uno al lado del otro: en un teléfono de 360px dos pastillas
   en fila no caben, y la que se sale es siempre la misma.

   LOS DOS MIDEN EXACTAMENTE LO MISMO.

   Cada uno venía de un sitio: el carrito es un <a> con los estilos de la
   plantilla, el chat un <button> nuevo. Uno quedaba más alto y más ancho que
   el otro y la esquina parecía mal armada. Dos botones que hacen lo mismo
   —esperar a que los pulses— tienen que leerse como un par, así que el alto,
   el ancho mínimo, el redondeo y la tipografía se fijan AQUÍ para los dos a
   la vez; lo único que cada uno conserva es su color.
   -------------------------------------------------------------------------- */
.flotantes {
    position: fixed;
    right: 16px;
    bottom: 16px;
    z-index: 50;
    display: flex;
    flex-direction: column;

    /* stretch y no flex-end: es lo que iguala el ancho de los dos al del más
       ancho, sin tener que adivinar un número que se rompa al traducir
       "Mi carrito". */
    align-items: stretch;
    gap: 10px;
}

    .flotantes .carrito-btn,
    .flotantes .chat-fab {
        /* El mismo molde para los dos. */
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: 9px;
        box-sizing: border-box;
        height: 48px;
        min-width: 172px;
        padding: 0 20px;
        border: none;
        border-radius: 999px;
        font: inherit;
        font-size: .9rem;
        font-weight: 600;
        line-height: 1;
        text-decoration: none;
        white-space: nowrap;
        cursor: pointer;
        box-shadow: 0 8px 24px rgba(0, 0, 0, .3);
    }

    /* El carrito ya era flotante por debajo de 1024px. Ahora lo es siempre,
       que es lo que deja de necesitar una columna para él. */
    .flotantes .carrito-btn {
        position: relative;
    }

        /* El contador se reubica: con el botón redondo, el "left: 26px" de las
           plantillas lo dejaba encima del texto. */
        .flotantes .carrito-btn .carrito-badge {
            left: auto;
            right: -4px;
            top: -4px;
        }

/* --------------------------------------------------------------------------
   EL BOTÓN DEL CHAT

   El molde (alto, ancho, redondeo, tipografía) lo pone .flotantes, arriba,
   para que sea idéntico al del carrito. Aquí va solo lo suyo: el color y el
   punto verde.
   -------------------------------------------------------------------------- */
.chat-fab {
    background: #111827;
    color: #fff;
}

    .chat-fab:hover {
        filter: brightness(1.12);
    }

    /* Con el panel abierto el botón sobra y además queda debajo. Se va. */
    .chat-fab.oculto {
        display: none;
    }

    .chat-fab-ico {
        font-size: 1.05rem;
        line-height: 1;
    }

    /* El punto verde. Dice "hay alguien" sin escribirlo, que es lo que hace
       que a un chat se le hable. */
    .chat-fab-punto {
        width: 8px;
        height: 8px;
        border-radius: 50%;
        background: #22c55e;
        flex: 0 0 auto;
    }

/* --------------------------------------------------------------------------
   EL PANEL DEL CHAT
   -------------------------------------------------------------------------- */
.chat-panel {
    position: fixed;
    right: 16px;
    bottom: 16px;
    z-index: 60;
    width: min(380px, calc(100vw - 32px));
    display: flex;
}

    /* `hidden` es un atributo del HTML, pero su regla del navegador
       (display:none) tiene menos peso que el display:flex de arriba: sin esto
       el panel nace abierto y tapa la tienda. */
    .chat-panel[hidden] {
        display: none;
    }

    /* Las siete plantillas le dan al chat `height: 440px` porque vivía dentro
       de una columna. Aquí el alto lo pone el panel, y el widget lo llena. La
       regla gana por especificidad, no por orden. */
    .chat-panel .chat-widget {
        width: 100%;
        height: min(560px, calc(100vh - 110px));
        box-shadow: 0 18px 50px rgba(0, 0, 0, .35);
    }

    /* El encabezado pasa a llevar el botón de cerrar a la derecha. */
    .chat-panel .chat-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 10px;
    }

.chat-cerrar {
    border: none;
    background: transparent;
    color: inherit;
    font-size: 1.35rem;
    line-height: 1;
    cursor: pointer;

    /* 34px es lo mínimo que un pulgar acierta. Un × de 14px en la esquina de
       un panel es el botón que se falla tres veces antes de darle. */
    width: 34px;
    height: 34px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: .85;
}

    .chat-cerrar:hover {
        opacity: 1;
        background: rgba(255, 255, 255, .15);
    }

/* --------------------------------------------------------------------------
   EN PANTALLA CHICA

   El panel ocupa el ancho entero y la barra de redes se encoge. Las dos cosas
   por la misma razón: en 360px de ancho no sobra ni un píxel.
   -------------------------------------------------------------------------- */
@media (max-width: 560px) {
    .chat-panel {
        right: 10px;
        left: 10px;
        bottom: 10px;
        width: auto;
    }

        .chat-panel .chat-widget {
            height: min(72vh, calc(100vh - 90px));
        }

    .flotantes {
        right: 12px;
        bottom: 12px;
        gap: 8px;
    }

        /* Solo el icono: dos pastillas con texto en una pantalla de 360px se
           comen la esquina entera y tapan el último producto de la lista.
           Siguen midiendo igual entre sí, que es lo que importa. */
        .flotantes .carrito-btn .carrito-txt,
        .flotantes .chat-fab .chat-fab-txt,
        .flotantes .chat-fab .chat-fab-punto {
            display: none;
        }

        .flotantes .carrito-btn,
        .flotantes .chat-fab {
            padding: 0;
            width: 52px;
            min-width: 0;
            height: 52px;
        }

    .redes-rail {
        padding: 7px 5px;
        border-radius: 12px 0 0 12px;
    }

        .redes-rail .redes {
            gap: 7px;
        }

            .redes-rail .redes a {
                width: 34px;
                height: 34px;
                font-size: .95rem;
            }
}

/* LA BARRA DE REDES EN PANTALLA CHICA.

   No se esconde: es la única puerta a WhatsApp, y en un teléfono WhatsApp es
   la mitad de las ventas de una tienda colombiana. Antes había una copia en
   el pie para cubrirla y se veía mal, así que la copia se quitó y la barra se
   queda.

   Lo que sí cambia es que deja de reservarse su ancho —50px de 390 en blanco
   es demasiado— y pasa a flotar POR ENCIMA del contenido. Para que se lea
   como algo que flota y no como una columna rota: más angosta, traslúcida y
   con el borde apenas marcado. Lo que tapa es el canto derecho de la foto de
   un producto; el nombre y el precio van abajo a la izquierda. */
@media (max-width: 1024px) {
    /* El fondo translúcido y el desenfoque ya vienen de la regla general: lo
       único que cambia aquí es que se marca un poco más, porque en el celular
       la barra flota ENCIMA de las fotos de los productos y necesita
       separarse de lo que tapa. */
    .redes-rail {
        background: rgba(128,128,128,.2);
    }
}

/* Pantalla baja (un celular en horizontal): la barra de redes a media altura
   se cruza con la pila de la esquina. Ahí sí se va — entre las redes y el
   carrito, el carrito. */
@media (max-height: 520px) {
    .redes-rail {
        display: none;
    }
}

/* --------------------------------------------------------------------------
   LA TARJETA DE LA BARRA IZQUIERDA

   Una sola, y la escribe el dueño de la tienda. Los colores siguen saliendo
   de .side-card, que cada plantilla define; aquí van solo las piezas nuevas
   y los topes que impiden que la tarjeta crezca sin control.
   -------------------------------------------------------------------------- */
.side-card-foto {
    /* Caja de alto fijo con la foto recortada dentro. Puesta suelta, una
       imagen vertical estiraba la tarjeta hasta quedar más alta que el
       catálogo que acompaña. */
    height: 130px;
    margin: -4px 0 12px;
    border-radius: 10px;
    overflow: hidden;
}

    .side-card-foto img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        display: block;
    }

.side-card-texto {
    /* El servicio ya recorta a 500 caracteres al guardar. Esto es lo otro:
       500 caracteres en una columna angosta son unas quince líneas, y la
       tarjeta quedaría más alta que la primera fila de productos. Se muestran
       nueve y el resto se corta con puntos suspensivos. */
    display: -webkit-box;
    -webkit-line-clamp: 9;
    line-clamp: 9;
    -webkit-box-orient: vertical;
    overflow: hidden;

    /* Los saltos de línea que escribió el dueño se respetan; una palabra
       larguísima parte en vez de ensanchar la tarjeta. */
    white-space: pre-line;
    overflow-wrap: anywhere;
}

.side-card-btn {
    display: inline-block;
    margin-top: 4px;
    font-weight: 600;
}

/* ==========================================================================
   EL PIE, EN COLUMNAS

   El color de fondo y el del texto los sigue poniendo cada plantilla en
   .site-footer; aquí va solo la estructura. Las seis plantillas le ponen
   `text-align:center`, que servía cuando el pie era una línea de enlaces y
   estorba ahora que son columnas de datos: se corrige dentro de .footer-grid,
   que gana por especificidad sin tocar las siete hojas.

   `auto-fit` con `minmax` y no un número de columnas: una tienda que no llenó
   sus datos de contacto pinta dos columnas, y las dos se reparten el ancho
   solas. Y en un teléfono se apilan sin una sola media query.
   ========================================================================== */
.footer-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 30px 40px;
    max-width: 1680px;
    margin: 0 auto 26px;
    text-align: left;
}

.footer-col h4 {
    margin: 0 0 10px;
    font-size: 1.05rem;
    font-weight: 700;
    color: inherit;
}

.footer-col h5 {
    margin: 0 0 14px;
    font-size: .82rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .09em;
}

.footer-lema {
    margin: 0 0 18px;
    font-size: .88rem;
    line-height: 1.6;

    /* Es la descripción de la tienda, que no tiene tope de longitud: tres
       líneas bastan para presentarse y evitan que una columna del pie mida
       media pantalla. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* El rótulo chiquito en versalita sobre cada dato: es lo que deja leer el pie
   de un vistazo en vez de tener que adivinar qué es cada línea. */
.footer-rotulo {
    margin: 0 0 4px;
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .12em;
    opacity: .55;
}

.footer-dato {
    margin: 0 0 16px;
    font-size: .9rem;
    font-weight: 600;
    line-height: 1.5;

    /* Un correo largo parte en vez de ensanchar la columna. */
    overflow-wrap: anywhere;
}

    .footer-dato a {
        color: inherit;
        text-decoration: none;
    }

        .footer-dato a:hover {
            text-decoration: underline;
        }

/* Los enlaces, uno debajo del otro: en columna son una lista de secciones, no
   una fila de migas. En el pie viejo iban en fila y centrados. */
.site-footer .footer-links {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
    margin: 0;
}

    .site-footer .footer-links a {
        font-size: .9rem;
    }

/* La franja de abajo: razón social, NIT y el copyright. Separada por una
   línea, porque es letra chica legal y no parte del menú. */
.footer-base {
    max-width: 1680px;
    margin: 0 auto;
    padding-top: 20px;
    border-top: 1px solid rgba(128,128,128,.22);
    text-align: center;
}

    .footer-base .footer-copy {
        margin: 0 0 4px;
        font-size: .8rem;
        opacity: .65;
    }

        /* Sin esto, "MinkSoft" se queda con el azul subrayado del navegador:
           ninguna plantilla estiliza un <a> dentro del copyright. */
        .footer-base .footer-copy a {
            color: inherit;
            text-decoration: none;
        }

            .footer-base .footer-copy a:hover {
                text-decoration: underline;
            }

        .footer-base .footer-copy:last-child {
            margin-bottom: 0;
        }

@media (max-width: 560px) {
    .footer-grid {
        gap: 24px;
        margin-bottom: 20px;
    }
}

/* ==========================
   PÁGINAS ARMADAS POR SECCIONES  (Quiénes somos)

   Las ocho formas de sección que puede poner el dueño de la tienda desde
   Admin › Quiénes somos. El catálogo está cerrado a propósito: cada una está
   maquetada y probada en celular, y no hay forma de combinar cosas que nadie
   haya visto nunca.

   NADA DE COLORES AQUÍ DENTRO.

   Las secciones NO traen color propio. `fondo-suave` y `fondo-oscuro` usan
   `currentColor` y transparencias sobre lo que ya puso la plantilla, así que
   la página se ve de la tienda —no de MinkSoft— en las siete plantillas, y el
   contraste del texto nunca puede quedar mal: es el mismo texto de siempre.

   LAS REJILLAS BAJAN SOLAS.

   `--pg-cols` es lo que eligió el dueño (2, 3 o 4) y solo manda en pantalla
   grande. En tablet son 2 y en celular 1, siempre, sin que nadie pueda
   cambiarlo. Es la misma garantía que las disposiciones de la barra: lo que
   se configura no puede romper el teléfono.
========================== */

.pg-seccion {
    padding: clamp(28px, 4vw, 56px) 0;
}

    /* El ancho de LECTURA, que no es el ancho de la columna. Una línea de 140
       caracteres se lee mal por mucho espacio que haya. */
    .pg-seccion .pg-ancho {
        max-width: 1080px;
        margin: 0 auto;
    }

/* Los dos fondos con color son bloques redondeados dentro de la columna, no
   franjas de borde a borde: ver el comentario de QuienesSomos.cshtml. */
.pg-seccion.fondo-suave,
.pg-seccion.fondo-oscuro {
    border-radius: 18px;
    padding-left: clamp(16px, 3vw, 40px);
    padding-right: clamp(16px, 3vw, 40px);
    margin: 10px 0;
}

.pg-seccion.fondo-suave {
    background: rgba(128,128,128,.09);
}

.pg-seccion.fondo-oscuro {
    background: #10131a;
    color: #f3f4f6;
}

    .pg-seccion.fondo-oscuro a {
        color: inherit;
    }

.pg-titulo {
    font-size: clamp(1.45rem, 3.2vw, 2.4rem);
    line-height: 1.18;
    margin: 0 0 14px;
}

.pg-sub {
    font-size: clamp(.98rem, 1.3vw, 1.1rem);
    line-height: 1.7;
    opacity: .78;
    max-width: 64ch;
    margin: 0 0 18px;
}

.pg-texto p {
    line-height: 1.85;
    margin: 0 0 1.05em;
    max-width: 68ch;
}

    .pg-texto p:last-child {
        margin-bottom: 0;
    }

/* El botón. Hereda el color del texto en vez de traer uno: en una plantilla
   clara sale oscuro y en una oscura sale claro, sin una regla por plantilla. */
.pg-boton {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 20px;
    padding: 11px 24px;
    border: 1px solid currentColor;
    border-radius: 999px;
    color: inherit;
    text-decoration: none;
    font-size: .86rem;
    font-weight: 600;
    letter-spacing: .04em;
    opacity: .9;
    transition: opacity .15s ease, background .15s ease;
}

    .pg-boton:hover {
        opacity: 1;
        background: rgba(128,128,128,.12);
    }

/* ---------- Portada ---------- */

.pg-portada {
    text-align: center;
    padding: clamp(10px, 2vw, 26px) 0;
}

    .pg-portada .pg-sub {
        margin-left: auto;
        margin-right: auto;
    }

/* La portada CON foto.

   El texto va sobre la imagen, y eso obliga a lo único de toda la página que
   fuerza un color: debajo hay una foto que puede ser de cualquier color, así
   que el color de la plantilla deja de ser predecible. El velo oscuro del
   ::after es lo que garantiza que el título se lea sobre CUALQUIER imagen —
   sin él, una foto clara deja el texto blanco invisible y una oscura deja el
   negro invisible, y quien sube la foto no tiene por qué pensar en eso. */
.pg-portada.con-foto {
    position: relative;
    display: grid;
    place-items: center;
    min-height: clamp(220px, 30vw, 380px);
    padding: clamp(28px, 5vw, 60px) clamp(18px, 4vw, 48px);
    border-radius: 18px;
    overflow: hidden;
    color: #fff;
}

    .pg-portada-fondo {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        /* cover y no contain: la foto la sube el dueño y va a venir de
           cualquier proporción. Con contain quedarían franjas vacías a los
           lados; con cover se recorta, que es lo que espera cualquiera. */
        object-fit: cover;
        object-position: center;
    }

    .pg-portada.con-foto::after {
        content: "";
        position: absolute;
        inset: 0;
        background: rgba(0,0,0,.48);
    }

    .pg-portada-texto {
        position: relative;
        /* Encima del velo. 2 y no 1 porque el velo ya ocupa el 1. */
        z-index: 2;
    }

    /* Dentro de la portada con foto el texto es blanco entero: el .pg-sub
       traía opacidad .78, que sobre una foto se vuelve ilegible. */
    .pg-portada.con-foto .pg-sub {
        opacity: .92;
        color: #fff;
    }

    .pg-portada.con-foto .pg-boton {
        border-color: rgba(255,255,255,.85);
        color: #fff;
    }

        .pg-portada.con-foto .pg-boton:hover {
            background: rgba(255,255,255,.18);
        }

/* Con foto, el fondo y el relleno de la sección sobran: los tapa la imagen, y
   dejarlos pone un marco gris alrededor de la foto que parece un error.

   `:has()` no lo entienden los navegadores viejos, y está bien: ahí
   simplemente no se aplica y queda el marco, que se ve raro pero no rompe
   nada. Es degradación, no fallo. */
.pg-seccion.tipo-portada:has(.pg-portada.con-foto) {
    padding: 0;
    background: none;
}

/* ---------- Texto con imagen ---------- */

.pg-dos {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(22px, 4vw, 54px);
    align-items: center;
}

    /* El ORDEN y no un `direction:rtl` ni dos maquetas: en celular la rejilla
       pasa a una columna y el texto tiene que quedar PRIMERO siempre, elija lo
       que elija el dueño. Con `order` eso sale solo, porque la media query
       simplemente deja de aplicar el cambio de orden. */
    .pg-dos.imagen-izquierda .pg-dos-media {
        order: -1;
    }

    /* Sin foto no hay dos columnas que repartir: el texto se queda con la
       página entera en vez de con media y un hueco al lado. */
    .pg-dos.sin-foto {
        grid-template-columns: 1fr;
    }

.pg-dos-media img {
    width: 100%;
    height: auto;
    display: block;
    border-radius: 14px;
}

/* ---------- Columnas ---------- */

.pg-cols {
    display: grid;
    grid-template-columns: repeat(var(--pg-cols, 3), minmax(0, 1fr));
    gap: clamp(20px, 3vw, 40px);
    margin-top: 26px;
}

.pg-col h3 {
    font-size: .95rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    margin: 0 0 10px;
    line-height: 1.35;
}

.pg-col p {
    margin: 0;
    line-height: 1.75;
    font-size: .93rem;
    opacity: .82;
}

/* ---------- Cifras ---------- */

.pg-cifras {
    display: grid;
    grid-template-columns: repeat(var(--pg-cols, 3), minmax(0, 1fr));
    gap: clamp(18px, 3vw, 36px);
    margin-top: 22px;
    text-align: center;
}

.pg-cifra-n {
    font-size: clamp(1.8rem, 4vw, 2.9rem);
    font-weight: 700;
    line-height: 1.05;
}

.pg-cifra-t {
    font-size: .76rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    opacity: .68;
    margin-top: 7px;
    line-height: 1.5;
}

/* ---------- Galería ---------- */

.pg-galeria {
    display: grid;
    grid-template-columns: repeat(var(--pg-cols, 3), minmax(0, 1fr));
    gap: 14px;
    margin-top: 22px;
}

.pg-foto {
    margin: 0;
}

    /* aspect-ratio y object-fit: las fotos las sube el dueño y van a venir de
       todos los tamaños. Sin esto, una vertical entre dos horizontales estira
       la fila entera y la rejilla se ve rota. */
    .pg-foto img {
        width: 100%;
        aspect-ratio: 4/3;
        object-fit: cover;
        display: block;
        border-radius: 12px;
    }

    .pg-foto figcaption {
        font-size: .82rem;
        opacity: .7;
        margin-top: 7px;
    }

/* ---------- Video ---------- */

.pg-video {
    position: relative;
    aspect-ratio: 16/9;
    border-radius: 14px;
    overflow: hidden;
    background: #000;
    margin: 22px auto 0;

    /* Sin tope, en un monitor ancho el video mide 1080x607 y se come la
       pantalla entera. 880 es lo que se ve bien sin volverse el protagonista
       de una página que es de texto. */
    max-width: 880px;
}

    .pg-video iframe {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        border: 0;
    }

/* ---------- Llamado ---------- */

.pg-llamado {
    text-align: center;
}

    .pg-llamado .pg-sub {
        margin-left: auto;
        margin-right: auto;
    }

/* ---------- Pantallas chicas ----------

   Lo que elige el dueño (2, 3 o 4 columnas) manda SOLO en pantalla grande.
   De aquí para abajo no hay configuración que valga: dos columnas en tablet,
   una en celular, y la imagen siempre debajo del texto. Es la misma garantía
   que las disposiciones de la barra superior — lo que se configura no puede
   romper el teléfono, porque en el teléfono no se aplica. */

@media (max-width:900px) {

    .pg-cols,
    .pg-cifras,
    .pg-galeria {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .pg-dos {
        grid-template-columns: 1fr;
    }

        /* El texto primero, siempre. Una foto de 300px de alto antes del
           primer párrafo es media pantalla de teléfono gastada en algo que no
           dice nada. */
        .pg-dos.imagen-izquierda .pg-dos-media {
            order: 0;
        }
}

@media (max-width:560px) {

    .pg-cols,
    .pg-cifras {
        grid-template-columns: 1fr;
    }

    /* La galería se queda en dos: una foto por fila en un celular vuelve la
       galería un rollo infinito de scroll. */
    .pg-galeria {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 10px;
    }

    .pg-seccion.fondo-suave,
    .pg-seccion.fondo-oscuro {
        border-radius: 14px;
    }
}
