/* ===========================================================================
   Tienda en línea — hoja de la vista `tienda.php`
   ===========================================================================

   Reescrita el 2026-09-02. La versión anterior tenía 1 120 líneas y **cerca del
   40% no pintaba nada**: quedaban enteras las secciones `.product-details-*`
   (313 líneas) y `.checkout-steps` / `.payment-methods` / `.cost-row` /
   `.purchase-*` de una ficha de detalle y un checkout por pasos que se
   retiraron del marcado el 2026-09-01. Se borraron; si vuelven, vuelven con su
   CSS.

   Qué cambió de verdad, en tres puntos:

   1. **La foto se ve entera.** Las 50 imágenes del catálogo son tomas de
      estudio en vertical sobre fondo blanco (276x500 la más estrecha). La
      tarjeta las metía en 180 px de alto con `object-fit: cover`: recortaba la
      lata por arriba y por abajo y dejaba a la vista un trozo de etiqueta.
      Ahora van con `contain` en un panel cuadrado.

   2. **Un solo azul.** Había tres compitiendo en la misma pantalla: `#1976d2`
      en el botón de agregar, `#14507a` en los filtros y `#2c5aa0`
      —`--primary-color`, el de la marca— en todo el resto del sitio. Los dos
      primeros no salían de ningún sitio.

   3. **Contraste de los controles.** Los bordes eran `#e9ecef` sobre blanco:
      **1.19:1**, o sea prácticamente invisibles, cuando el borde es lo único
      que dibuja un campo o un botón de cantidad. WCAG 1.4.11 pide 3:1.
   =========================================================================== */

/* ---------------------------------------------------------------------------
   Los tokens de la tienda
   ---------------------------------------------------------------------------
   Van en `:root` y **no** en `.store-container`, que es donde estuvieron hasta
   que rompieron el carrito.

   El razonamiento de entonces era que ponerlos en la raiz los ofreceria a las
   otras once vistas como si fueran del sistema. **Es falso**: esta hoja solo la
   carga `tienda.php`, asi que su `:root` no existe en ninguna otra pagina. Lo
   que si era cierto y no se vio es que **el carrito lateral vive fuera de
   `.store-container`** — `NavbarHelper::getStandardCartSidebarHTML()` lo imprime
   como hermano de `<main>`, hijo directo de `<body>`—, y sus renglones los
   estiliza esta misma hoja.

   Con los tokens ahi dentro, cada `var(--t-*)` del carrito resolvia a vacio.
   Y una variable vacia no es "el valor por defecto": invalida **toda la
   declaracion**, asi que `border: 1.5px solid var(--t-borde-control)` dejaba los
   botones `+`/`−` sin borde, sin fondo y sin radio — dos glifos sueltos en vez
   de dos controles. Medido en produccion el 2026-09-02: los seis tokens vacios
   dentro de `#cartSidebar` y con valor dentro de `.store-container`.
   --------------------------------------------------------------------------- */
:root {
  --t-fondo: #eef2f7;
  --t-superficie: #ffffff;
  --t-panel: #f2f6fa;
  --t-borde: #dae2ec;
  /* 3.08:1 sobre blanco. El anterior, #e9ecef, daba 1.19:1. */
  --t-borde-control: #8494ab;
  --t-tinta: #17233a;
  /* 5.50:1 sobre blanco */
  --t-tinta-suave: #5a6a80;
  --t-marca: var(--primary-color);
  --t-marca-oscura: #204378;
  --t-marino: var(--secondary-color);
  /* El rojo de la etiqueta de la lata. 5.78:1 sobre blanco. */
  --t-acento: #c1272d;
  --t-ml: #ffe600;

  --t-radio: 14px;
  --t-radio-chico: 8px;
}

.store-container {
  background: var(--t-fondo);
  /* El navbar es `position: fixed` y no empuja el contenido; cada página se
     despeja sola. 80 px es su alto real (15+15 de padding + 50 del logo). */
  padding: calc(80px + 2.5rem) 1rem 4rem;
  color: var(--t-tinta);
}

/* ---------------------------------------------------------------------------
   Cabecera
   --------------------------------------------------------------------------- */
.store-header {
  max-width: 46rem;
  margin: 0 auto 2.5rem;
  text-align: center;
}

.store-header__eyebrow {
  margin: 0 0 0.75rem;
  font-size: var(--texto-xs);
  font-weight: var(--peso-semi);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--t-tinta-suave);
}

.store-header__title {
  margin: 0 0 0.75rem;
  font-size: var(--titulo-2);
  font-weight: var(--peso-fuerte);
  line-height: var(--interlineado-titulo);
  color: var(--t-marino);
}

.store-header__subtitle {
  margin: 0;
  font-size: var(--texto-md);
  font-weight: var(--peso-normal);
  line-height: var(--interlineado-base);
  color: var(--t-tinta-suave);
}

/* ---------------------------------------------------------------------------
   Filtros por categoría
   ---------------------------------------------------------------------------
   **No van pegajosos.** Lo estuvieron —`position: sticky; top: 80px`— y hacia
   dos destrozos a la vez, los dos medidos en produccion el 2026-09-02:

   1. Con fondo opaco, la barra **guillotinaba la escalera de presentaciones** de
      la tarjeta que pasaba por debajo: 17 px de recorte a 1440 y 35 de 45 a
      820 px, donde la barra se parte en dos renglones y mide 120 px de alto. Se
      veian los "latas" sin sus numeros.
   2. El `top: 80px` reservaba sitio para el navbar, pero
      `modern-enhancements.js` **esconde el navbar al desplazar hacia abajo**
      (`translateY(-100%)` pasados 200 px). Al esconderse quedaba una banda de
      80 px por la que el contenido pasaba desnudo POR ENCIMA de la barra.

   Coordinar una barra pegajosa con un navbar que se auto-esconde es fragil, y
   la reja son once tarjetas, no doscientas. Se queda arriba, quieta.
   --------------------------------------------------------------------------- */
.filtros-categoria {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
  max-width: 1200px;
  margin: 0 auto 2rem;
  padding: 0.25rem;
}

.filtro-categoria {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  /* 44 px de alto tocable. Antes eran 34, y es el control que más se pulsa en
     móvil después de los botones de cantidad. */
  min-height: 44px;
  padding: 0.5rem 1rem;
  border: 1.5px solid var(--t-borde-control);
  border-radius: 999px;
  background: var(--t-superficie);
  color: var(--t-tinta);
  font-family: var(--fuente-base);
  font-size: var(--texto-sm);
  font-weight: var(--peso-medio);
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.filtro-categoria:hover {
  border-color: var(--t-marca);
  color: var(--t-marca-oscura);
}

.filtro-categoria.is-activa {
  background: var(--t-marino);
  border-color: var(--t-marino);
  color: #fff;
  font-weight: var(--peso-semi);
}

.filtro-categoria__conteo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.5rem;
  height: 1.5rem;
  padding: 0 0.35rem;
  border-radius: 999px;
  background: var(--t-panel);
  color: var(--t-tinta-suave);
  font-size: var(--texto-xs);
  font-weight: var(--peso-semi);
}

.filtro-categoria.is-activa .filtro-categoria__conteo {
  background: rgba(255, 255, 255, 0.22);
  color: #fff;
}

/* ---------------------------------------------------------------------------
   La reja
   --------------------------------------------------------------------------- */
.store-products {
  max-width: 1200px;
  margin: 0 auto;
}

.products-grid {
  display: grid;
  /* `min(100%, 17.5rem)` y no `17.5rem` a secas: en un contenedor más estrecho
     que la pista mínima, `minmax(17.5rem, 1fr)` desborda. */
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17.5rem), 1fr));
  gap: 1.25rem;
  /* responsive-modern.css:474 declara `margin-bottom: 40px` sobre esta misma
     clase para la reja de la portada. Se anula aquí. */
  margin-bottom: 0;
}

.store-vacio {
  margin: 3rem 0 0;
  text-align: center;
  color: var(--t-tinta-suave);
  font-size: var(--texto-md);
}

/* ---------------------------------------------------------------------------
   La tarjeta
   --------------------------------------------------------------------------- */
.product-card {
  display: flex;
  flex-direction: column;
  background: var(--t-superficie);
  border: 1px solid var(--t-borde);
  border-radius: var(--t-radio);
  /* `visible` a propósito, y no es un descuido: responsive-modern.css:466
     declara `overflow: hidden` sobre `.product-card`, y eso **recortaba el
     anillo de foco** de los controles pegados al borde de la tarjeta. El
     redondeo que hacía falta lo pone ahora el propio panel de la foto. */
  overflow: visible;
  /* responsive-modern.css:469 pone `text-align: center` para la reja de la
     portada. Aquí el contenido es una ficha, no un pie de foto. */
  text-align: left;
  box-shadow: 0 1px 2px rgba(23, 35, 58, 0.06), 0 6px 16px rgba(23, 35, 58, 0.06);
  transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}

/* El filtro por categoría oculta tarjetas con el atributo `hidden`, y la regla
   `[hidden] { display: none }` es del navegador: cualquier `display` declarado
   aquí por el autor le gana. Antes funcionaba de casualidad, porque
   `.product-card` no declaraba ninguno; en cuánto se le puso `display: flex`,
   el filtro dejo de ocultar nada. Misma trampa que el botón de Mercado Libre. */
.product-card[hidden] {
  display: none;
}

.product-card:hover {
  transform: translateY(-4px);
  border-color: #c3d0e0;
  box-shadow: 0 2px 4px rgba(23, 35, 58, 0.07), 0 14px 32px rgba(23, 35, 58, 0.13);
}

/* ---------------------------------------------------------------------------
   La foto
   ---------------------------------------------------------------------------
   El panel resuelve las dos cosas que estropeaban las imágenes:

   * `contain` sobre un panel de proporción fija. Las latas son verticales y
     `cover` en 180 px de alto las decapitaba. La proporción la fija el CSS, así
     que tampoco hace falta `width`/`height` en el `<img>` para evitar el salto
     de maquetación.

   * `mix-blend-mode: multiply`. Las 50 fotos son recortes de estudio sobre
     **blanco puro**, y un rectangulo blanco sobre una tarjeta blanca no se lee
     como producto: se lee como un hueco. Multiplicar por el panel convierte ese
     blanco en el color del panel —blanco x color = color— y deja la lata
     recortada, sin tener que editar 50 archivos. De paso, la sombra del `::before`
     se ve **a traves** del fondo de la foto por la misma razón, y es lo que
     asienta la lata en vez de dejarla flotando.
   --------------------------------------------------------------------------- */
.product-card__foto {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--t-radio) var(--t-radio) 0 0;
  overflow: hidden;
  background: linear-gradient(180deg, #f7fafd 0%, var(--t-panel) 100%);
}

.product-card__foto::before {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 11%;
  width: 55%;
  height: 14px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(23, 35, 58, 0.26), rgba(23, 35, 58, 0));
}

/* Dos trampas, las dos costaron una vuelta:
 *
 * 1. Con el panel en `display: grid` y la imagen centrada, `max-height: 100%`
 *    se resolvía contra la altura del **area de la reja**, que a su vez la fija
 *    el contenido: porcentaje contra `auto`, o sea contra nada. La lata se
 *    pintaba a tamaño natural y el panel la recortaba igual que antes.
 *
 * 2. Con la imagen en absoluto e `inset` por los cuatro lados **pero `width` y
 *    `height` en `auto`**, tampoco. En un elemento reemplazado —y un `<img>` lo
 *    es— `auto` se resuelve al tamaño intrinseco, no al hueco: la especificación
 *    manda ignorar `right` y `bottom` cuando el sistema queda sobredeterminado.
 *    Salía una lata de 500 px anclada arriba a la izquierda, más recortada aún.
 *
 * Con `width`/`height` explicitos los porcentajes se resuelven contra la caja
 * del panel, que si tiene altura definida por `aspect-ratio`, y `contain` centra
 * la foto dentro sin deformarla.
 */
.product-card__lata {
  position: absolute;
  top: 1.25rem;
  left: 1.25rem;
  width: calc(100% - 2.5rem);
  height: calc(100% - 3rem);
  object-fit: contain;
  mix-blend-mode: multiply;
  transition: transform 0.35s ease;
}

.product-card:hover .product-card__lata {
  transform: scale(1.04);
}

/* Hueco cuando un producto no tiene foto, para que la tarjeta no se descuadre */
.product-card__sin-foto {
  width: 100%;
  height: 100%;
  border-radius: var(--t-radio-chico);
  background:
    repeating-linear-gradient(45deg, #e7edf5 0 10px, #eef3f8 10px 20px);
}

/* Arriba a la derecha y no abajo a la izquierda: la lata esta centrada y ocupa
   el tercio central, así que la esquina inferior izquierda la tapaba. */
.product-card__peso {
  position: absolute;
  right: 0.75rem;
  top: 0.75rem;
  padding: 0.3rem 0.6rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid var(--t-borde);
  color: var(--t-tinta-suave);
  font-size: var(--texto-xs);
  font-weight: var(--peso-semi);
}

/* ---------------------------------------------------------------------------
   Cuerpo de la tarjeta
   --------------------------------------------------------------------------- */
.product-card__content {
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
  /* Crece para llenar la tarjeta, que en una reja se estira a la altura de la
     más alta de su fila. Sin esto el `margin-top: auto` de las acciones no tenía
     contra que empujar y los botones quedaban a media tarjeta, desalineados de
     los de al lado. */
  flex: 1;
  padding: 1.125rem 1.125rem 1.25rem;
}

.product-card__categoria {
  margin: 0;
  font-size: var(--texto-xs);
  font-weight: var(--peso-semi);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--t-tinta-suave);
}

.product-card__title {
  margin: -0.5rem 0 0;
  font-size: var(--texto-lg);
  font-weight: var(--peso-semi);
  line-height: var(--interlineado-medio);
  color: var(--t-tinta);
}

/* ---------------------------------------------------------------------------
   La escalera de presentaciones
   ---------------------------------------------------------------------------
   Sustituye al `<select>`. Los cinco precios de un producto estaban escondidos
   dentro del desplegable, y nada decía que la caja de 24 sale más barata **por
   lata** que la de 3 — que es la única razón de comprarla. Ahora las
   presentaciones estan a la vista, con su ahorro, y el precio por lata debajo.

   Son `input[type=radio]` de verdad: las flechas del teclado recorren el grupo,
   el estado seleccionado lo anuncia el navegador y un `Tab` salta al siguiente
   control en vez de recorrer las cinco opciones. El input no se oculta con
   `display: none` —eso lo sacaria del orden de foco—, sino reducido a 1 px.
   --------------------------------------------------------------------------- */
.presentaciones {
  margin: 0;
  padding: 0;
  border: 0;
  /* Un `fieldset` trae `min-width: min-content` de la hoja del navegador, y con
     ella el contenido no se encoge y desborda la tarjeta. */
  min-width: 0;
}

.presentaciones__titulo {
  display: block;
  margin: 0 0 0.5rem;
  padding: 0;
  font-size: var(--texto-xs);
  font-weight: var(--peso-semi);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--t-tinta-suave);
}

/* Flex y no `grid-template-columns: repeat(auto-fit, minmax(...))`: con pistas
   de ancho mínimo fijo, la quinta presentación caia sola a un segundo renglón
   en cuánto la tarjeta se estrechaba —a 820 px, con tres columnas, sobraban
   4 px—. Con `flex: 1 1 0` y `min-width: 0` las cinco se reparten el ancho que
   haya, sean tres o sean cinco, y la escalera nunca se parte. */
.presentaciones__escalera {
  display: flex;
  gap: 0.375rem;
  /* Hueco para la insignia de la mejor presentación, que sobresale por arriba */
  margin-top: 0.5rem;
}

.presentacion {
  position: relative;
  display: block;
  flex: 1 1 0;
  min-width: 0;
  cursor: pointer;
}

.presentacion input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
}

.presentacion__cara {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.05rem;
  min-height: 44px;
  padding: 0.4rem 0.15rem;
  border: 1.5px solid var(--t-borde-control);
  border-radius: var(--t-radio-chico);
  background: var(--t-superficie);
  transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease;
}

.presentacion__cara > span {
  /* Con las pistas repartiendose un ancho estrecho, "latas" no debe empujar la
     caja más allá de su parte: se recorta antes de romper la fila. */
  max-width: 100%;
  overflow: hidden;
}

.presentacion__n {
  font-size: var(--texto-base);
  font-weight: var(--peso-fuerte);
  line-height: 1.1;
  color: var(--t-tinta);
}

.presentacion__u {
  font-size: 0.6875rem;
  color: var(--t-tinta-suave);
  line-height: 1.1;
}

/* Una sola por tarjeta: la presentación que sale más barata por lata. */
.presentacion__ahorro {
  position: absolute;
  top: -0.55rem;
  left: 50%;
  transform: translateX(-50%);
  padding: 0.05rem 0.35rem;
  border-radius: 999px;
  background: var(--t-acento);
  color: #fff;
  font-size: 0.625rem;
  font-weight: var(--peso-fuerte);
  line-height: 1.6;
  white-space: nowrap;
}

.presentacion.es-mejor .presentacion__cara {
  border-color: var(--t-acento);
}

.presentacion:hover .presentacion__cara {
  border-color: var(--t-marca);
}

.presentacion input:checked + .presentacion__cara {
  border-color: var(--t-marca);
  background: #eaf1fa;
  box-shadow: inset 0 0 0 1px var(--t-marca);
}

.presentacion input:checked + .presentacion__cara .presentacion__n {
  color: var(--t-marca-oscura);
}

/* El anillo de foco global es `*:focus-visible`, y el input mide 1 px: no se
   veria. Se traslada a la cara, que es lo que se ve. Mismos valores que
   responsive-modern.css:1385, incluido el aro oscuro exterior. */
.presentacion input:focus-visible + .presentacion__cara {
  outline: 3px solid #F28123;
  outline-offset: 2px;
  box-shadow: 0 0 0 6px rgba(23, 35, 58, 0.9);
}

/* ---------------------------------------------------------------------------
   Precio
   --------------------------------------------------------------------------- */
.product-card__precio {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.5rem;
  padding-top: 0.125rem;
}

.precio {
  font-size: var(--titulo-4);
  font-weight: var(--peso-fuerte);
  line-height: 1.1;
  color: var(--t-tinta);
  /* Los precios van de $260 a $25,500 y cambian al elegir presentación: con
     cifras de ancho variable la línea entera se movía en cada cambio. */
  font-variant-numeric: tabular-nums;
}

.precio__unidad {
  font-size: var(--texto-sm);
  color: var(--t-tinta-suave);
}

.precio__lata {
  flex-basis: 100%;
  font-size: var(--texto-sm);
  font-weight: var(--peso-medio);
  color: var(--t-marca-oscura);
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
   Cantidad y acciones
   --------------------------------------------------------------------------- */
.product-card__acciones {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  margin-top: auto;
}

.cantidad {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.cantidad > label {
  font-size: var(--texto-sm);
  font-weight: var(--peso-medio);
  color: var(--t-tinta-suave);
}

.cantidad__controles {
  display: flex;
  align-items: center;
  gap: 0.375rem;
}

.quantity-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: 1.5px solid var(--t-borde-control);
  border-radius: var(--t-radio-chico);
  background: var(--t-superficie);
  color: var(--t-tinta);
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease, color 0.15s ease;
}

.quantity-btn:hover:not(:disabled) {
  border-color: var(--t-marca);
  background: #eaf1fa;
  color: var(--t-marca-oscura);
}

.quantity-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.quantity-input {
  width: 3.25rem;
  height: 40px;
  padding: 0 0.25rem;
  border: 1.5px solid var(--t-borde-control);
  border-radius: var(--t-radio-chico);
  background: var(--t-superficie);
  color: var(--t-tinta);
  font-family: var(--fuente-base);
  font-size: var(--texto-base);
  font-weight: var(--peso-semi);
  text-align: center;
}

/* Las flechas nativas del `number` caben mal en 52 px y duplican los botones
   que ya hay al lado */
.quantity-input::-webkit-outer-spin-button,
.quantity-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.quantity-input {
  -moz-appearance: textfield;
  appearance: textfield;
}

.btn-add-to-cart,
.btn-mercadolibre {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  min-height: 44px;
  padding: 0.625rem 1rem;
  border: 1.5px solid transparent;
  border-radius: var(--t-radio-chico);
  font-family: var(--fuente-base);
  font-size: var(--texto-sm);
  font-weight: var(--peso-semi);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease, transform 0.1s ease;
}

.btn-add-to-cart:active,
.btn-mercadolibre:active {
  transform: translateY(1px);
}

.btn-add-to-cart {
  /* Blanco sobre #2c5aa0 = 6.80:1. El #1976d2 anterior daba 4.60:1, que pasaba
     el mínimo por una centesima. */
  background: var(--t-marca);
  color: #fff;
}

.btn-add-to-cart:hover {
  background: var(--t-marca-oscura);
}

.btn-mercadolibre {
  /* El amarillo de la marca de Mercado Libre. En la hoja había dos distintos,
     #fff159 aquí y #ffe600 en ml.css; este es el bueno. Con #111 da 16.6:1. */
  background: var(--t-ml);
  border-color: #e6cf00;
  color: #111;
  /* "Comprar en Mercado Libre" no cabe a 14 px en una tarjeta de tres columnas
     (213 px de contenido contra 215 que mide la línea): partia en dos renglones
     y desalineaba el pie de todas las tarjetas de su fila. Un paso menos de
     cuerpo lo resuelve sin recortar la etiqueta, que tiene que decir a donde
     lleva el botón. */
  white-space: nowrap;
  font-size: 0.8125rem;
  padding-inline: 0.5rem;
}

.btn-mercadolibre:hover {
  background: #ffd900;
  color: #111;
}

/* `hidden` sobre un elemento con `display` declarado por el autor no oculta
   nada: la regla del navegador tiene menos peso. Sin esto, elegir una
   presentación sin publicación dejaba el botón amarillo a la vista **con el
   enlace de la presentación anterior**. */
.btn-add-to-cart[hidden],
.btn-mercadolibre[hidden] {
  display: none;
}

.ml-logo {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

/* ---------------------------------------------------------------------------
   Aparicion de las tarjetas
   ---------------------------------------------------------------------------
   `modern-enhancements.js:19` añade `animate-fadeInUp` a cada `.product-card`
   cuando entra en pantalla, y **esa clase no estaba definida en ninguna hoja
   del repositorio**: animate.css define `.fadeInUp`, sin prefijo. Eran 67 KB
   cargados para una animación que nunca ocurria. Aquí son cinco líneas.

   El estado inicial no se declara: si el JS no llega, las tarjetas ya estan
   visibles y no pasa nada.
   --------------------------------------------------------------------------- */
@keyframes tiendaFadeInUp {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

.product-card.animate-fadeInUp {
  animation: tiendaFadeInUp 0.45s ease-out both;
}

@media (prefers-reduced-motion: reduce) {
  .product-card.animate-fadeInUp { animation: none; }

  .product-card,
  .product-card__lata,
  .btn-add-to-cart,
  .btn-mercadolibre {
    transition: none;
  }

  .product-card:hover { transform: none; }
  .product-card:hover .product-card__lata { transform: none; }
}

/* ---------------------------------------------------------------------------
   Carrito lateral: los renglones
   --------------------------------------------------------------------------- */
.cart-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.875rem 0;
  border-bottom: 1px solid #e7edf5;
}

.cart-item__image {
  width: 56px;
  height: 56px;
  object-fit: contain;
  border-radius: var(--t-radio-chico);
  background: #f2f6fa;
  flex-shrink: 0;
}

.cart-item__details {
  flex: 1;
  min-width: 0;
  text-align: left;
}

.cart-item__details h4 {
  margin: 0 0 0.2rem;
  font-size: var(--texto-sm);
  font-weight: var(--peso-semi);
  color: #17233a;
}

.cart-item__price {
  margin: 0.15rem 0;
  color: #204378;
  font-weight: var(--peso-fuerte);
  font-size: var(--texto-sm);
}

.cart-item__cans {
  margin: 0.15rem 0;
  color: #5a6a80;
  font-size: var(--texto-xs);
}

.cart-item__quantity {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.4rem;
  font-size: var(--texto-sm);
  color: #5a6a80;
}

.cart-item__quantity .quantity-btn {
  width: 32px;
  height: 32px;
}

.cart-item__remove {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border: none;
  border-radius: 50%;
  /* #fff sobre #f44336 daba 3.68:1, por debajo del mínimo. Este da 5.78:1. */
  background: #c1272d;
  color: #fff;
  font-size: var(--texto-lg);
  line-height: 1;
  cursor: pointer;
}

.cart-item__remove:hover {
  background: #9d1f24;
}

.cart-empty {
  padding: 2rem 1rem;
  text-align: center;
  color: #5a6a80;
}

/* `store-cart.js` deshabilita "Proceder al Pago" con el carrito vacio; antes
   ese clic abria un `alert()` del navegador. */
.checkout-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ---------------------------------------------------------------------------
   Modal de finalizar compra
   --------------------------------------------------------------------------- */
.checkout-modal {
  position: fixed;
  inset: 0;
  z-index: 2100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: rgba(23, 35, 58, 0.6);
}

/* Sin esta regla el modal se pinta a pantalla completa desde la primera carga.
   `.hidden { display: none }` vive en responsive-modern.css, que se carga
   **antes** que esta hoja: misma especificidad, gana la última, o sea
   `display: flex`. Hasta el 2026-09-02 lo único que lo tapaba era un `<style>`
   con `!important` que `store-cart.js` inyectaba al ejecutarse — así que el
   velo negro se veía mientras cargaba el JS, y se quedaba para siempre si el
   JS fallaba. Dos clases: gana siempre, sin `!important` y sin depender de
   ningún script. */
.checkout-modal.hidden {
  display: none;
}

.checkout-modal__content {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 620px;
  max-height: 90vh;
  background: #fff;
  border-radius: var(--t-radio);
  box-shadow: 0 24px 60px rgba(23, 35, 58, 0.35);
}

.checkout-modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.25rem 1.25rem 0.875rem;
  border-bottom: 1px solid #e7edf5;
}

.checkout-modal__header h2 {
  margin: 0;
  font-size: var(--titulo-4);
  font-weight: var(--peso-fuerte);
  color: #17233a;
}

.checkout-modal__close {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Medido en 24x33 antes: por debajo de cualquier mínimo táctil. */
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border: none;
  border-radius: var(--t-radio-chico);
  background: none;
  color: #5a6a80;
  cursor: pointer;
}

.checkout-modal__close:hover {
  background: #f2f6fa;
  color: #17233a;
}

.checkout-modal__body {
  /* `flex: 1` con `min-height: 0`: sin el `min-height`, un hijo flexible no se
     encoge por debajo de su contenido y el area desplazable empuja el pie fuera
     del dialogo, que es justo lo que se quiere evitar. */
  flex: 1;
  min-height: 0;
  padding: 1.25rem;
  overflow-y: auto;
}

/* El pie queda fuera del area desplazable: el total es el dato que se viene a
   mirar y no puede depender de que alguien descubra que ese bloque se desplaza. */
.checkout-modal__pie {
  flex-shrink: 0;
  padding: 0 1.25rem 1.25rem;
}

.checkout-modal__pie:empty {
  display: none;
}

/* Renglones del checkout — los pinta store-cart.js */
.checkout-note {
  margin: 0 0 1rem;
  padding: 0.75rem 0.875rem;
  border-radius: var(--t-radio-chico);
  background: #eaf1fa;
  color: #204378;
  font-size: var(--texto-sm);
}

.checkout-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin: 0;
  padding-top: 0.875rem;
  border-top: 1px solid #dae2ec;
  font-size: var(--texto-base);
  color: #5a6a80;
}

.checkout-total strong {
  font-size: var(--titulo-4);
  font-weight: var(--peso-fuerte);
  color: #17233a;
  font-variant-numeric: tabular-nums;
}

.ml-checkout-items {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.ml-checkout-item {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem;
  border: 1px solid #dae2ec;
  border-radius: var(--t-radio-chico);
}

.ml-checkout-item__image {
  width: 56px;
  height: 56px;
  flex-shrink: 0;
  object-fit: contain;
  border-radius: 6px;
  background: #f2f6fa;
}

.ml-checkout-item__details {
  flex: 1;
  min-width: 0;
  text-align: left;
}

.ml-checkout-item__details h4 {
  margin: 0 0 0.25rem;
  font-size: var(--texto-base);
  font-weight: var(--peso-semi);
  color: #17233a;
}

.ml-checkout-item__equivalencia {
  margin: 0;
  font-size: var(--texto-sm);
  color: #5a6a80;
}

.btn-mercadolibre-details {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.625rem 1rem;
  border: 1.5px solid #e6cf00;
  border-radius: var(--t-radio-chico);
  background: #ffe600;
  color: #111;
  font-size: var(--texto-sm);
  font-weight: var(--peso-semi);
  text-decoration: none;
  white-space: nowrap;
}

.btn-mercadolibre-details:hover {
  background: #ffd900;
  color: #111;
}

.ml-checkout-item__contacto {
  background: #eef2f7;
  border-color: #8494ab;
}

.ml-checkout-item__contacto:hover {
  background: #dfe7f0;
}

/* ---------------------------------------------------------------------------
   Aviso de catálogo no disponible
   --------------------------------------------------------------------------- */
.store-aviso {
  max-width: 40rem;
  margin: 0 auto;
  padding: 1.25rem 1.5rem;
  border: 1px solid #f0d9a8;
  border-left: 4px solid #b8860b;
  border-radius: var(--t-radio-chico);
  background: #fff6e6;
  color: #4a2a04;
  text-align: left;
}

.store-aviso p { margin: 0 0 0.5rem; }
.store-aviso p:last-child { margin-bottom: 0; }

/* ---------------------------------------------------------------------------
   Responsive
   ---------------------------------------------------------------------------
   Los breakpoints son los del sistema: 1024 / 768 / 480. Las cuatro reglas que
   había antes apuntaban a `.store-products`, que no es un grid —el grid es
   `.products-grid`—, así que no hacian nada.
   --------------------------------------------------------------------------- */
@media (max-width: 1024px) {
  .products-grid {
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr));
  }
}

@media (max-width: 768px) {
  .store-container {
    padding: calc(80px + 1.5rem) 0.875rem 3rem;
  }

  .store-header {
    margin-bottom: 1.75rem;
  }

  .products-grid {
    /* 16rem = 256 px, que es el `min-content` real de la tarjeta: lo fijan la
       fila de cantidad (etiqueta + 40+52+40) y el boton de Mercado Libre, que va
       en `nowrap`. Con pistas mas estrechas —estuvo en 14rem— el item de reja no
       se encoge por debajo de su minimo, empuja la reja fuera del contenedor y
       aparece scroll horizontal. Medido: 18 px de desborde entre 732-768 px y
       entre 492-524 px de ancho de ventana. */
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr));
    gap: 1rem;
  }

  /* responsive-modern.css:1003 limita `.product-card` a 400 px y la centra para
     la reja de la portada. En una reja de dos columnas eso deja huecos. */
  .product-card {
    max-width: none;
  }

  .checkout-modal__content {
    max-height: 92vh;
  }
}

@media (max-width: 640px) {
  /* Siete filtros no caben en un renglón: se deslizan en vez de envolver en
     tres. `-webkit-overflow-scrolling` no hace falta desde iOS 13. */
  .filtros-categoria {
    flex-wrap: nowrap;
    justify-content: flex-start;
    overflow-x: auto;
    scrollbar-width: none;
    padding-inline: 0.25rem;
  }

  .filtros-categoria::-webkit-scrollbar { display: none; }
  .filtro-categoria { flex-shrink: 0; }
}

@media (max-width: 480px) {
  .store-container {
    /* A ≤480 el logo del navbar baja a 40 px y el navbar mide ~70. */
    padding: calc(70px + 1.25rem) 0.75rem 2.5rem;
  }

  .filtros-categoria {
    top: 70px;
  }

  .products-grid {
    grid-template-columns: 1fr;
    gap: 1rem;
  }

  .product-card {
    max-width: 26rem;
    margin: 0 auto;
    width: 100%;
  }

  .product-card__content {
    padding: 1rem 1rem 1.125rem;
  }

  /* En una sola columna la lata tiene ancho de sobra: se le da menos alto para
     que quepan más productos en pantalla. */
  .product-card__foto {
    aspect-ratio: 5 / 4;
  }

  .quantity-btn,
  .quantity-input {
    /* 44 px en la mano; 40 basta con raton. */
    width: 44px;
    height: 44px;
  }

  .quantity-input {
    width: 3.5rem;
  }

  .ml-checkout-item {
    flex-wrap: wrap;
  }

  .ml-checkout-item .btn-mercadolibre-details {
    flex-basis: 100%;
  }
}
