/* ══════════════════════════════════════════════════════════════════════
   MEGA MAYORISTA — mm-base.css
   Estilos de página + primitivos reutilizables (maqueta 2026)
   ══════════════════════════════════════════════════════════════════════
   Depende de tokens.css. Se carga DESPUÉS de las cuatro hojas legacy
   (design-system / cards / futuristic / ecommerce), que quedan congeladas.

   Acá NO hay reglas de header, footer ni tarjeta: eso vive en
   mm-shell.css y mm-card.css.

   ──────────────────────────────────────────────────────────────────────
   PARA EL INTEGRADOR — enlaces que hay que agregar a web/index.html
   (este archivo no puede tocarlo). Todos DESPUÉS de ecommerce.css y en
   este orden, con el mismo ?v= que ya usan las demás hojas:

     <link rel="stylesheet" href="/css/tokens.css?v=..." />
     <link rel="stylesheet" href="/css/mm-base.css?v=..." />
     <link rel="stylesheet" href="/css/mm-shell.css?v=..." />
     <link rel="stylesheet" href="/css/mm-card.css?v=..." />
     ... (mm-home.css, mm-catalogo.css, mm-cuenta.css de las otras tareas)

   Y en web/js/utils/components.js, dentro de scriptsEnOrden, "/js/ui/mm-shell.js"
   va INMEDIATAMENTE DESPUÉS de "/app.js" y ANTES de "/js/ui/catalogo.js"
   (catalogo.js llama a mmPrecioHtml al pintar la tarjeta).
   Además, subir ASSET_V y el ?v= de components.js en index.html a la vez.
   ────────────────────────────────────────────────────────────────────── */

/* ── 0. NEUTRALIZACIÓN DE LA TIPOGRAFÍA LEGACY ─────────────────────────
   design-system.css declara Manrope (sans), Playfair Display (display y
   serif) y Geist Mono, y las consume desde ~90 selectores vía variables.
   Redefinir las variables acá las apaga TODAS de una sola vez sin editar
   la hoja congelada: mismo selector :root, hoja posterior, gana la
   cascada. Lo que queda hardcodeado ('Archivo' / 'Geist') se apaga abajo
   por selector. */
:root {
  --ds-font-sans:    var(--mm-font);
  --ds-font-display: var(--mm-font);
  --ds-font-serif:   var(--mm-font);
  --ds-font-mono:    var(--mm-font-mono);
}

body,
button,
input,
select,
textarea,
.ds-btn,
.section-title {
  font-family: var(--mm-font) !important;
}

/* Restos hardcodeados de 'Archivo' / 'Geist' en ecommerce.css, más los
   elementos reemplazados (<video>) que no heredan la fuente del body y
   caen al serif del navegador en su contenido de reserva. */
video,
.section-title em,
.feature-item h3,
.hero-deco-mega-num,
.hero-deco-mini-num,
.hero-deco-label,
.hero-slide-title em {
  font-family: var(--mm-font) !important;
}

/* Tailwind: body lleva la clase .font-sans (Geist) desde index.html. */
.font-sans { font-family: var(--mm-font) !important; }
.font-mono { font-family: var(--mm-font-mono) !important; }

/* ── 1. PÁGINA ─────────────────────────────────────────────────────── */
/* Sin `scroll-behavior: smooth` global a propósito: volvería animado
   TODO scroll programático del sitio, incluidos los saltos instantáneos
   con que el router reposiciona la vista. El único scroll suave del
   chasis es el del ancla #contacto, que lo pide explícitamente en
   mmIrAContacto(). */
html { -webkit-text-size-adjust: 100%; }

body {
  background: var(--mm-page);
  color: var(--mm-text);
  font-size: var(--mm-t-base);
  line-height: var(--mm-lh-normal);
  font-weight: var(--mm-w-regular);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Red de seguridad contra el scroll horizontal: cualquier banda
     full-bleed que se pase de largo se recorta.
     `clip` y NO `hidden`: `hidden` obliga al otro eje a `auto`, convierte
     al body en contenedor de scroll y rompe cualquier `position: sticky`
     que cuelgue de él (el sidebar de filtros del listado, por ejemplo).
     `clip` recorta sin crear contenedor de scroll. */
  overflow-x: clip;
}

::selection {
  background: var(--mm-red-tint);
  color: var(--mm-red);
}

/* Compensación del header fijo. Mobile-first: la base es el header de tres
   barras y sólo ≥1024 se pasa al de dos filas.
   Esta hoja es el ÚNICO dueño del offset: las dos reglas gemelas de
   ecommerce.css (110px/116px !important, medidas para el header viejo +
   top-strip) se eliminaron. El !important se conserva porque #mainContent
   también recibe utilidades de padding desde el markup. */
#mainContent { padding-top: var(--mm-header-h-mobile) !important; }

@media (min-width: 1024px) {
  #mainContent { padding-top: var(--mm-main-pt) !important; }
}

/* Cualquier salto a un ancla (#contacto, #catalogo…) debe frenar debajo
   del header fijo, no detrás. :where() para no sumar especificidad. */
:where([id]) { scroll-margin-top: calc(var(--mm-header-h-mobile) + var(--mm-s-4)); }

@media (min-width: 1024px) {
  :where([id]) { scroll-margin-top: calc(var(--mm-main-pt) + var(--mm-s-4)); }
}

/* ── 2. LAYOUT ─────────────────────────────────────────────────────── */
.mm-container {
  width: 100%;
  max-width: var(--mm-container);
  margin-inline: auto;
  padding-inline: var(--mm-gutter);
}

.mm-container-narrow {
  width: 100%;
  max-width: var(--mm-container-narrow);
  margin-inline: auto;
  padding-inline: var(--mm-gutter);
}

.mm-section    { padding-block: var(--mm-section-y); }
.mm-section-sm { padding-block: var(--mm-section-y-sm); }

.mm-band      { background: var(--mm-band); }
.mm-band-deep { background: var(--mm-band-deep); }
.mm-band-red  { background: var(--mm-red); color: var(--mm-on-red); }

/* Rompe el contenedor y llega borde a borde de la ventana.
   OJO: 100vw INCLUYE la barra de scroll, así que en escritorio la banda
   sobresale ~15px por la derecha. No genera scroll horizontal sólo porque
   body lo recorta con `overflow-x: clip`; por eso ningún otro selector
   debe usar 100vw suelto, y el contenido de la banda va siempre dentro de
   un .mm-container (nada pegado al borde, que quedaría medio tapado). */
.mm-bleed {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
}

/* ── 3. ENCABEZADOS DE SECCIÓN ─────────────────────────────────────── */
.mm-eyebrow {
  font-size: var(--mm-t-eyebrow);
  font-weight: var(--mm-w-bold);
  text-transform: uppercase;
  letter-spacing: var(--mm-ls-eyebrow);
  color: var(--mm-text-soft);
  margin: 0;
}

.mm-title {
  font-size: var(--mm-t-2xl);
  font-weight: var(--mm-w-bold);
  color: var(--mm-ink);
  letter-spacing: var(--mm-ls-tight);
  line-height: var(--mm-lh-tight);
  margin: 0;
}

.mm-title-on-red {
  font-size: var(--mm-t-2xl);
  font-weight: var(--mm-w-black);
  color: var(--mm-on-red);
  letter-spacing: var(--mm-ls-tight);
  line-height: var(--mm-lh-tight);
  margin: 0;
}

.mm-subtitle {
  font-size: var(--mm-t-sm);
  font-weight: var(--mm-w-regular);
  color: var(--mm-text-soft);
  line-height: var(--mm-lh-body);
  margin: 0;
}

/* ── 4. BOTONES ────────────────────────────────────────────────────── */
.mm-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--mm-s-2);
  height: var(--mm-ctl-h-touch);
  padding-inline: var(--mm-ctl-pad-x);
  border: 1px solid transparent;
  border-radius: var(--mm-r-sm);
  font-family: var(--mm-font);
  font-size: var(--mm-t-sm);
  font-weight: var(--mm-w-bold);
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  /* transform además del color: el hover levanta 2px y el :active hunde un
     3%. Las dos son propiedades compuestas por la GPU, así que el botón no
     relayoutea ni repinta aunque haya veinte en pantalla. */
  transition: var(--mm-tr-color), transform var(--mm-dur-fast) var(--mm-ease);
  -webkit-appearance: none;
  appearance: none;
}

.mm-btn svg { width: 18px; height: 18px; flex: 0 0 auto; }

.mm-btn-primary {
  background: var(--mm-red);
  border-color: var(--mm-red);
  color: var(--mm-on-red);
}

.mm-btn-ghost {
  background: var(--mm-surface);
  border-color: var(--mm-line);
  color: var(--mm-text);
}

.mm-btn-dark {
  background: var(--mm-ink);
  border-color: var(--mm-ink);
  color: var(--mm-on-red);
  text-transform: uppercase;
  letter-spacing: var(--mm-ls-wide);
}

.mm-btn-pill {
  height: var(--mm-ctl-h-touch);
  padding-inline: var(--mm-s-8);
  border-radius: var(--mm-r-full);
  background: var(--mm-surface);
  border-color: var(--mm-line);
  color: var(--mm-text);
}

.mm-btn-wa {
  background: var(--mm-surface);
  border-color: var(--mm-wa);
  color: var(--mm-wa-deep);
}

/* ── Hover: SOLO con mouse ─────────────────────────────────────────────
   En táctil el :hover se queda pegado después del tap y el botón se ve
   "encendido" hasta que tocás otra cosa. Todo el hover del sistema vive
   dentro de esta consulta; la respuesta táctil la da el :active de abajo. */
@media (hover: hover) and (pointer: fine) {
  .mm-btn:hover { transform: translate3d(0, var(--mm-lift, -2px), 0); }

  .mm-btn-primary:hover {
    background: var(--mm-red-hover);
    border-color: var(--mm-red-hover);
    color: var(--mm-on-red);
  }

  .mm-btn-ghost:hover {
    background: var(--mm-red);
    border-color: var(--mm-red);
    color: var(--mm-on-red);
  }

  .mm-btn-dark:hover { background: #000000; border-color: #000000; }

  .mm-btn-pill:hover {
    border-color: var(--mm-red);
    color: var(--mm-red);
  }

  .mm-btn-wa:hover {
    background: var(--mm-wa);
    border-color: var(--mm-wa);
    color: var(--mm-on-red);
  }
}

/* ── Presión ───────────────────────────────────────────────────────────
   Va DESPUÉS del bloque de hover: misma especificidad, gana por orden, así
   que apretar cancela el levantamiento y el botón se hunde. Es la única
   confirmación que existe en pantallas táctiles y la más barata de todas. */
.mm-btn:active { transform: scale(var(--mm-press, 0.97)); }
.mm-btn-primary:active { background: var(--mm-red-active); border-color: var(--mm-red-active); }

.mm-btn[disabled],
.mm-btn:disabled,
.mm-btn[aria-disabled="true"] {
  background: var(--mm-disabled-bg);
  border-color: var(--mm-disabled-bg);
  color: var(--mm-disabled-text);
  cursor: not-allowed;
  pointer-events: none;
}

.mm-btn-block { width: 100%; }

/* ── 5. CAMPOS ─────────────────────────────────────────────────────── */
.mm-input,
.mm-select {
  width: 100%;
  height: var(--mm-ctl-h);
  padding-inline: var(--mm-s-3);
  background: var(--mm-surface);
  border: 1px solid var(--mm-line);
  border-radius: var(--mm-r-xs);
  color: var(--mm-ink);
  font-family: var(--mm-font);
  font-size: var(--mm-t-sm);
  line-height: 1;
  transition: var(--mm-tr-color), box-shadow var(--mm-dur-fast) var(--mm-ease);
  -webkit-appearance: none;
  appearance: none;
}

.mm-input::placeholder { color: var(--mm-text-faint); }

.mm-select {
  padding-right: var(--mm-s-8);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238A8A8A' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--mm-s-3) center;
  background-size: 16px 16px;
}

/* `outline: none` CON reemplazo visible: el indicador de foco del campo es
   el borde rojo más el halo. `transition: none` porque el indicador de foco
   tiene que aparecer en el mismo cuadro —es información de dónde estoy, no
   decoración—; al salir vuelve a mandar la transición de la regla base y se
   desvanece con suavidad. */
.mm-input:focus,
.mm-select:focus {
  outline: none;
  border-color: var(--mm-red);
  box-shadow: 0 0 0 3px var(--mm-red-tint);
  transition: none;
}

.mm-label {
  display: block;
  font-size: var(--mm-t-xs);
  font-weight: var(--mm-w-semi);
  color: var(--mm-text);
  margin-bottom: var(--mm-s-2);
}

/* Hasta 1024 el campo se toca con el dedo, tablet incluida: por eso el
   corte es 1023.98 y no 767.98. max-width porque la altura densa de 40px
   es la prestación exclusiva de escritorio que se apaga. */
@media (max-width: 1023.98px) {
  .mm-input,
  .mm-select { height: var(--mm-ctl-h-touch); }
}

/* ── 6. FOCO GLOBAL ──────────────────────────────────────────────────
   Nunca se transiciona: el anillo tiene que aparecer en el mismo cuadro en
   que el control recibe el foco. Es información de dónde estoy, no un
   efecto. Por eso `outline` y no `box-shadow`: outline no entra en ninguna
   transición del sistema y no ocupa espacio, así que tampoco mueve nada.

   :where() para especificidad 0, a propósito: cualquier hoja de sección
   puede afinarlo sin pelear. Dos afinados ya existen en mm-shell.css —
   anillo BLANCO para los controles apoyados sobre la banda roja (el rojo
   del token desaparece sobre el rojo del header) y anillo POR DENTRO
   (offset negativo) para los que viven en un contenedor con
   `overflow: hidden`, como el buscador. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: var(--mm-focus-ring);
  outline-offset: var(--mm-focus-offset);
}

/* ── 7. GRILLA DE PRODUCTO ─────────────────────────────────────────────
   La comparten home, listado, tendencias, favoritos y buscador.
   Única grilla del sistema con conteo EXPLÍCITO en vez de auto-fit: 2 / 3
   / 4 columnas es criterio de aceptación, y con auto-fill el ancho de
   1023px caía en 4 columnas y el de 768px en 2.
   `minmax(0, 1fr)` y no `1fr`: en grid el mínimo por defecto es `auto`, y
   un nombre de producto largo sin espacios ensancharía la columna. */
.mm-grid {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: stretch;
}

@media (min-width: 768px) {
  .mm-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--mm-grid-gap);
  }
}

@media (min-width: 1024px) {
  .mm-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ── 8. CARRUSEL HORIZONTAL ────────────────────────────────────────── */
/* min-width: 0 en los dos: si el rail cuelga de un grid o un flex, el
   mínimo automático del contenedor sería la suma de todas las tarjetas y
   el `overflow-x: auto` no llegaría a scrollear nada — ensancharía la
   página entera. */
.mm-rail-wrap {
  position: relative;
  min-width: 0;
}

.mm-rail {
  display: flex;
  min-width: 0;
  gap: var(--mm-grid-gap);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
  -webkit-overflow-scrolling: touch;
}

.mm-rail::-webkit-scrollbar { display: none; }

.mm-rail > * {
  flex: 0 0 auto;
  scroll-snap-align: start;
  width: clamp(200px, 42vw, 280px);
}

.mm-rail-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: var(--mm-z-rail);
  width: var(--mm-icon-btn);
  height: var(--mm-icon-btn);
  display: grid;
  place-items: center;
  border: none;
  border-radius: var(--mm-r-full);
  background: var(--mm-surface);
  color: var(--mm-red);
  box-shadow: var(--mm-sh-arrow);
  cursor: pointer;
  transition: var(--mm-tr-color),
              opacity var(--mm-dur-fast) var(--mm-ease),
              transform var(--mm-dur-fast) var(--mm-ease);
}

.mm-rail-arrow svg { width: 20px; height: 20px; }
/* Media flecha por fuera del panel, como en la maqueta. */
.mm-rail-arrow-prev { left: calc(var(--mm-icon-btn) / -2); }
.mm-rail-arrow-next { right: calc(var(--mm-icon-btn) / -2); }

/* El translateY(-50%) que la centra se REPITE en el :active: un transform
   reemplaza al anterior, no se suma, y sin él la flecha saltaría media
   altura al apretarla. Por lo mismo el token lleva valor de reserva: si
   --mm-press faltara, la declaración entera sería inválida y el salto
   volvería. Es el único sitio del archivo donde el transform es
   estructural y no decorativo. */
.mm-rail-arrow:active { transform: translateY(-50%) scale(var(--mm-press, 0.97)); }

@media (hover: hover) and (pointer: fine) {
  .mm-rail-arrow:hover { background: var(--mm-band); }
}

.mm-rail-arrow[disabled] { opacity: 0.4; cursor: default; }
/* display:grid pisa el display:none que el UA da a [hidden]: hay que
   reponerlo o la flecha oculta se sigue viendo. */
.mm-rail-arrow[hidden] { display: none; }

@media (max-width: 1023.98px) {
  /* En táctil se navega con swipe: las flechas sobran y además se salen
     del contenedor en pantallas angostas. */
  .mm-rail-arrow { display: none; }
}

/* ── 9. PRECIO ─────────────────────────────────────────────────────────
   Lo produce mmPrecioHtml() en js/ui/mm-shell.js. Contrato compartido con
   la tarjeta, el detalle y el carrito. */
.mm-price {
  display: inline-block;
  font-size: var(--mm-t-xl);
  font-weight: var(--mm-w-black);
  color: var(--mm-ink);
  line-height: var(--mm-lh-none);
  letter-spacing: var(--mm-ls-tight);
  white-space: nowrap;
}

.mm-price-cents {
  font-size: 55%;
  vertical-align: super;
  margin-left: 1px;
  letter-spacing: 0;
}

.mm-price-accent { color: var(--mm-red-accent); }
.mm-price-lg     { font-size: var(--mm-t-3xl); }

/* ── 10. SKELETON ──────────────────────────────────────────────────── */
.mm-skel {
  position: relative;
  overflow: hidden;
  background: var(--mm-band);
  border-radius: var(--mm-r-xs);
}

.mm-skel::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.7) 50%,
    rgba(255, 255, 255, 0) 100%
  );
  animation: mm-shimmer 1.4s var(--mm-ease) infinite;
}

@keyframes mm-shimmer {
  100% { transform: translateX(100%); }
}

@media (prefers-reduced-motion: reduce) {
  .mm-skel::after { animation: none; }

  /* AUDITORÍA: con tokens.css presente esto es redundante (--mm-press pasa a
     1 y --mm-lift a 0px), pero los `transform` de esta hoja llevan valor de
     respaldo escrito a mano, y un fallback NO lo apaga el interruptor por
     tokens. Sin estas reglas, quien pide movimiento reducido igual vería el
     hundido y el levantamiento. */
  .mm-btn,
  .mm-rail-arrow { transition: none; }

  .mm-btn:hover,
  .mm-btn:active { transform: none; }

  /* La flecha está centrada con translateY(-50%): acá NO va `none`, o se
     descuelga media altura del riel. Se le quita sólo la escala. */
  .mm-rail-arrow:active { transform: translateY(-50%); }
}

/* ── 11. UTILIDADES MÍNIMAS ────────────────────────────────────────── */
.mm-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.mm-clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ── 12. ÁREA TÁCTIL — patrón canónico ─────────────────────────────────
   Referencia del estándar: lleva el área activa de un control chico a
   44x44 SIN mover ni agrandar un solo píxel de lo que se ve. Es la única
   forma de cumplir el mínimo táctil en los íconos de la maqueta (favorito
   de 32, cerrar, flechas) sin rediseñarlos.

   El markup lo genera app.js y no se puede tocar, así que las hojas de
   sección no pueden agregar la clase: REPLICAN estas dos reglas sobre sus
   propios selectores. Ésta es la copia de referencia.

   Cuatro cuidados antes de usarlo — si alguno falla, NO va halo: se
   agranda la fila contenedora y se le da min-height a la caja real.
   1) Un ancestro con `overflow: hidden` recorta el halo (.mm-card lo
      tiene): el ícono necesita ≥ (44 − su alto) / 2 de aire al borde.
   2) El pseudo puede estar ocupado (.mm-nav a.is-active::after es el
      subrayado): si está, se usa ::before; si están los dos, padding.
   3) El halo roba clics a los vecinos: la separación al vecino tiene que
      ser ≥ el desborde, o se tapa un control ajeno.
   4) Si algo se movió después de aplicarlo, está mal: falta el
      `position: relative` en el host. */
.mm-tap { position: relative; }

.mm-tap::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(100%, var(--mm-tap));
  height: max(100%, var(--mm-tap));
  transform: translate(-50%, -50%);
}
