/* ============================================================
   MELO TECH CALI — melo.css  (v6 · brand-true)
   Marca real: naranja plano #FF3D1B + crema #FFFEF7,
   Peace Sans (display) + Hanken Grotesk (cuerpo/UI).
   Mobile-first. Additivo — no toca styles.css viejo.
   ============================================================ */

/* ---------- Hanken Grotesk (autohospedada, variable 400-800) ----------
   Antes venía de fonts.googleapis.com con un <link> en el <head> de las 12 páginas:
   una hoja de estilo RENDER-BLOQUEANTE en un tercer origen, que además obliga a
   resolver DNS + TLS de dos hosts (googleapis y gstatic) antes de poder pintar.
   Medido en móvil con CPU 4x lenta: era una de las dos causas del FCP de ~2,8 s.
   Autohospedada es un solo archivo variable de 33 KB desde el mismo origen.
   Se conservan los dos subsets de Google (latin y latin-ext) con su unicode-range:
   así el navegador solo baja latin-ext si la página de verdad usa esos caracteres. */
@font-face {
  font-family: "Hanken Grotesk";
  src: url("../fonts/HankenGrotesk-latin-ext.woff2") format("woff2");
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Hanken Grotesk";
  src: url("../fonts/HankenGrotesk-latin.woff2") format("woff2");
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ---------- Peace Sans (autohospedada, OFL) ---------- */
@font-face {
  font-family: "Peace Sans";
  src: url("../fonts/PeaceSans.woff2") format("woff2");
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
}

/* ============================================================
   TOKENS
   ============================================================ */
:root {
  /* Marca */
  --orange:        #FF3D1B;   /* primario — el color exacto del logo */
  --orange-bright: #FF5A38;   /* highlight */
  --orange-deep:   #E22F0C;   /* sombra/tono profundo del naranja */
  --orange-darker: #C2260A;   /* pressed / bordes internos */
  --cream:         #FFFEF7;   /* secundario — papel / texto sobre naranja */
  --cream-2:       #FFF7EA;   /* superficie alterna cálida */
  --cream-3:       #FDEEDC;   /* tinte durazno suave */

  --ink:      #241611;        /* casi-negro cálido (texto sobre crema) */
  --ink-soft: #6E574B;        /* texto secundario */
  --ink-faint:#9C8578;        /* metadatos */
  --line:     #F0E2D2;        /* bordes cálidos */
  --line-2:   #E8D5C2;

  --wa:       #25D366;        /* verde WhatsApp — SOLO botones WA */
  --wa-deep:  #1EBE5A;
  --berry:    #FF2D6B;        /* SOLO ofertas/descuentos */
  --berry-deep:#E01456;

  /* Los 8 fondos alternos VALIDADOS del brand kit (02_MARCA/brand_kit/brandkit.md §Secundarios,
     extraídos de colores_y_logo/08–15.png). Regla de disciplina de marca: una pieza usa el
     naranja/crema primario O uno de estos ocho — nunca improvisa un color nuevo. */
  --bg-cielo:   #AFC9E8;
  --bg-oliva:   #A8B58A;
  --bg-gris:    #D8D8D8;
  --bg-vino:    #A34F68;
  --bg-carbon:  #2D2D2D;
  --bg-mostaza: #D4BE7B;
  --bg-rosa:    #E9A3B1;
  --bg-menta:   #A7D7C5;

  /* Categorías → fondos de marca (antes eran pasteles improvisados, fuera del sistema).
     El fondo se elige por CONTRASTE con la foto del producto: equipo oscuro sobre fondo
     claro y equipo claro sobre fondo oscuro. Un iPhone negro sobre Vino desaparecía. */
  --t-iphone:       var(--bg-mostaza);  /* iPhone negro */
  --t-samsung:      var(--bg-cielo);    /* Z Flip oscuro */
  --t-audifonos:    var(--bg-vino);     /* AirPods blancos */
  --t-macbooks:     var(--bg-menta);    /* MacBook Air Medianoche */
  --t-consolas:     var(--bg-carbon);   /* PS5 Pro blanca */
  --t-armatupc:     var(--bg-oliva);    /* torre gamer negra */
  --t-accesorios:   var(--bg-rosa);     /* watches blanco y negro */

  /* Ink por categoría — crema sobre los dos fondos oscuros, tinta sobre los claros */
  --ti-iphone:       var(--ink);
  --ti-samsung:      var(--ink);
  --ti-audifonos:    var(--cream);
  --ti-macbooks:     var(--ink);
  --ti-consolas:     var(--cream);
  --ti-armatupc:     var(--ink);
  --ti-accesorios:   var(--ink);

  /* Sombras cálidas (nunca negro duro) */
  --sh-sm: 0 2px 10px rgba(60, 30, 15, .07);
  --sh-md: 0 12px 30px -12px rgba(80, 35, 15, .22);
  --sh-lg: 0 30px 60px -24px rgba(90, 40, 20, .34);
  --sh-orange: 0 20px 45px -18px rgba(255, 61, 27, .5);

  /* Geometría — esquinas redondeadas generosas (eco de Peace Sans) */
  --r-sm: 12px;
  --r-md: 18px;
  --r-lg: 26px;
  --r-xl: 34px;
  --r-pill: 999px;

  /* Marco crema alrededor de los bloques naranja (look fresco 2026) */
  --frame:  clamp(.5rem, 2.2vw, .95rem);
  --r-hero: clamp(22px, 4.6vw, 42px);

  /* Ancho de página. Amplio a propósito: a 1440+ el contenido usa la pantalla en vez de
     quedar en una columna estrecha con márgenes muertos a los lados. */
  --maxw: 1480px;
  --pad: clamp(1.15rem, 4vw, 3.4rem);
  --header-h: 62px;
  --bottombar-h: 64px;

  --font-display: "Peace Sans", "Arial Black", system-ui, sans-serif;
  --font-body: "Hanken Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Textura de ruido, como token: el naranja plano a pantalla completa se lee digital
     y barato sin grano. Antes vivía incrustada solo en `.grain::after`; ahora cualquier
     superficie puede reusarla (la usa el mega menú móvil, que es naranja de borde a borde). */
  --noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");

  --ease-out: cubic-bezier(.22, .61, .36, 1);
  --ease-io:  cubic-bezier(.65, .05, .36, 1);
  /* Curvas tipo spring (principios de motion/framer traducidos a CSS puro):
     `spring` sobrepasa y vuelve — para entradas y estados activos;
     `gentle` frena sin rebote — para lo que se mueve mucho o es grande. */
  --ease-spring: cubic-bezier(.34, 1.4, .64, 1);
  --ease-gentle: cubic-bezier(.22, 1, .36, 1);
  --t-fast: .18s;   /* feedback de interacción (hover/tap) */
  --t-mid:  .34s;   /* cambios de estado */
  --t-slow: .58s;   /* entradas al viewport */
  --stagger: 70ms;  /* cascada entre hermanos */
}

/* ============================================================
   RESET / BASE
   ============================================================ */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--cream);
  line-height: 1.55;
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; border: none; background: none; color: inherit; }
input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }
h1, h2, h3, h4 { margin: 0; }
p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }
:focus-visible { outline: 3px solid var(--orange); outline-offset: 3px; border-radius: 4px; }
.no-scroll { overflow: hidden; }
/* Las anclas del nav no quedan tapadas por el header fijo */
section[id], [data-deal][id], .cta-final[id] { scroll-margin-top: calc(var(--header-h) + 16px); }

.wrap { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--pad); }

/* Display helper */
.display { font-family: var(--font-display); text-transform: uppercase; letter-spacing: -.01em; line-height: .92; font-weight: 400; }

/* Grain — le da dimensión al naranja plano (tendencia 2026: flat con textura) */
.grain { position: relative; }
.grain::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 1;
  background-image: var(--noise);
  opacity: .06; mix-blend-mode: overlay;
}

/* ============================================================
   BOTONES / CHIPS
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5em;
  font-family: var(--font-body); font-weight: 800; font-size: 1rem;
  padding: .85em 1.4em; border-radius: var(--r-pill);
  transition: transform .18s var(--ease-out), box-shadow .18s var(--ease-out), background .18s;
  text-align: center; line-height: 1.1;
}
/* El `will-change: transform` estaba en la regla base y le daba capa de composición
   propia a TODOS los botones de la página —dos por tarjeta, más de cincuenta en una
   página de categoría— de forma permanente, y todo para un hundido de .18s al pulsar.
   Se promueve al acercarse, que es para lo que sirve la propiedad, y se suelta al salir. */
.btn:hover, .btn:focus-visible { will-change: transform; }
.btn:active { transform: translateY(1px) scale(.99); }
.btn-sm { padding: .6em 1em; font-size: .9rem; }
.btn-block { display: flex; width: 100%; }

.btn-primary { background: var(--orange); color: var(--cream); box-shadow: var(--sh-orange); }
.btn-primary:hover { background: var(--orange-bright); transform: translateY(-2px); }

.btn-cream { background: var(--cream); color: var(--ink); box-shadow: var(--sh-md); }
.btn-cream:hover { transform: translateY(-2px); box-shadow: var(--sh-lg); }

.btn-ink { background: var(--ink); color: var(--cream); }
.btn-ink:hover { transform: translateY(-2px); }

/* El CTA que cierra el negocio. Late solo (anillo verde que se expande cada 3,4 s) y
   al pasar el mouse le cruza un brillo. Sin librerías: dos pseudo-elementos y
   keyframes. Bajo `prefers-reduced-motion` se queda quieto (ver el bloque de al final). */
.btn-wa {
  position: relative; overflow: hidden; isolation: isolate;
  background: var(--wa); color: #fff; box-shadow: 0 14px 30px -14px rgba(37,211,102,.7);
}
.btn-wa:hover { background: var(--wa-deep); transform: translateY(-2px); }
.btn-wa::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit;
  box-shadow: 0 0 0 0 rgba(37,211,102,.55);
  animation: wa-eco 3.4s var(--ease-gentle) infinite;
}
.btn-wa::after {
  content: ""; position: absolute; z-index: -1; top: 0; bottom: 0; width: 45%;
  left: -60%; transform: skewX(-18deg);
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.34), transparent);
  animation: wa-brillo 4.6s var(--ease-gentle) 1.2s infinite;
}
@keyframes wa-eco { 0% { box-shadow: 0 0 0 0 rgba(37,211,102,.5); } 62%, 100% { box-shadow: 0 0 0 16px rgba(37,211,102,0); } }
@keyframes wa-brillo { 0%, 62% { left: -60%; } 88%, 100% { left: 130%; } }
/* El logo hace un guiño cada tanto, como si llegara un mensaje. */
.btn-wa > svg { animation: wa-guino 4.6s var(--ease-spring) infinite; transform-origin: 50% 60%; }
@keyframes wa-guino {
  0%, 70%, 100% { transform: rotate(0) scale(1); }
  74% { transform: rotate(-11deg) scale(1.1); }
  78% { transform: rotate(9deg)   scale(1.1); }
  82% { transform: rotate(-6deg)  scale(1.05); }
  86% { transform: rotate(0)      scale(1); }
}

.btn-berry { background: var(--berry); color: #fff; box-shadow: 0 14px 30px -14px rgba(255,45,107,.6); }
.btn-berry:hover { background: var(--berry-deep); transform: translateY(-2px); }

.btn-ghost { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 2px var(--line-2); font-weight: 700; }
.btn-ghost:hover { box-shadow: inset 0 0 0 2px var(--orange); color: var(--orange); }

.btn-ghost-cream { background: rgba(255,254,247,.12); color: var(--cream); box-shadow: inset 0 0 0 2px rgba(255,254,247,.55); backdrop-filter: blur(2px); }
.btn-ghost-cream:hover { background: rgba(255,254,247,.2); }

.chip {
  display: inline-flex; align-items: center; gap: .35em;
  font-size: .72rem; font-weight: 800; letter-spacing: .01em;
  padding: .32em .7em; border-radius: var(--r-pill); line-height: 1;
}
.chip-badge { background: var(--ink); color: var(--cream); }
.chip-off { background: var(--berry); color: #fff; }
.kicker-semi { color: var(--berry-deep); font-weight: 800; }

/* Eyebrow de sección */
.eyebrow {
  display: inline-flex; align-items: center; gap: .5em;
  font-family: var(--font-body); font-weight: 800; text-transform: uppercase;
  font-size: .8rem; letter-spacing: .12em; color: var(--orange);
}
.eyebrow::before { content: ""; width: 26px; height: 3px; border-radius: 3px; background: var(--orange); }

.section { padding-block: clamp(2.2rem, 6vw, 4.4rem); }
.section-head { margin-bottom: clamp(1.1rem, 3vw, 1.9rem); }
.section-title {
  font-family: var(--font-body); text-transform: uppercase; font-weight: 800;
  font-size: clamp(1.9rem, 7vw, 3.2rem); line-height: 1; letter-spacing: -.025em;
  color: var(--ink); margin-top: .4em;
}
.section-title .accent { color: var(--orange); }
.section-sub { color: var(--ink-soft); max-width: 56ch; margin-top: .7rem; font-size: 1.02rem; }
.section-alt { background: var(--cream-2); }

/* ============================================================
   HEADER
   ============================================================ */
.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 60;
  height: var(--header-h);
  display: flex; align-items: center;
  transition: background .3s var(--ease-out), box-shadow .3s, backdrop-filter .3s;
}
.site-header .wrap { display: flex; align-items: center; gap: 1rem; width: 100%; }
.header-brand { display: flex; align-items: center; gap: .55rem; margin-right: auto; }
.header-brand .brand-mark {
  width: 34px; height: 34px; border-radius: 9px; object-fit: cover;
  box-shadow: 0 4px 12px -4px rgba(120,40,10,.5);
}
.header-brand .wordmark {
  font-family: var(--font-display); text-transform: lowercase;
  font-size: 1.32rem; letter-spacing: -.01em; line-height: 1; font-weight: 400;
  color: var(--ink);
}
.header-brand .wordmark .dot { color: var(--orange); }

.nav-desktop { display: none; align-items: center; gap: .2rem; }
.nav-item { position: relative; display: inline-flex; }
/* OJO con el selector: va por hijo directo (`> a` para "Ofertas", `> .nav-item > a` para
   las categorías, que initHoverMenu envuelve en un span). Escrito como `.nav-desktop a`
   alcanzaba TAMBIÉN a los links de dentro del flyout y les ganaba por especificidad:
   `.nav-desktop a` (0,1,1) le ganaba a `.ch-all` (0,1,0), así que "Ver todos los X"
   heredaba `color: var(--ink)` — invisible sobre el panel tinta, contraste 1:1 medido.
   Y `.nav-desktop a:hover` (0,2,1) le ganaba a `.ch-list a` (0,2,0), metiéndole fondo
   crema a los items del flyout y pisando la marca deslizante.

   El padding lateral respira según el ancho: apretado justo al aparecer el nav (1080px,
   donde las 8 categorías van al límite) y generoso de 1500px en adelante. */
.nav-desktop > a,
.nav-desktop > .nav-item > a {
  display: inline-flex; align-items: center; gap: .35em;
  font-weight: 700; font-size: .9rem; border-radius: var(--r-pill);
  padding: .5rem clamp(.42rem, 1.7vw - .95rem, .78rem);
  color: var(--ink); opacity: .82;
  transition: background var(--t-fast) var(--ease-out), opacity var(--t-fast), color var(--t-fast), transform var(--t-fast) var(--ease-spring);
}
.nav-desktop > a:hover,
.nav-desktop > .nav-item > a:hover { background: var(--cream-3); color: var(--orange); opacity: 1; }
.nav-desktop > a:active,
.nav-desktop > .nav-item > a:active { transform: scale(.96); }

/* ---------- Flyout de categoría en hover (solo escritorio) ----------
   Referencia: artezcom.com. Nada de mega-menú de 8 columnas colgando de "Catálogo" —
   el nav de arriba YA son las categorías, y cada una abre su propia tarjeta angosta,
   anclada justo debajo de ESE item. Mucho aire, tipografía grande, nada más.
   La píldora oscura "salta" con spring al abrir (--ease-spring sobrepasa y vuelve) y los
   ítems de la lista entran en cascada — el detalle que hace que un menú se sienta vivo. */
.nav-desktop > .nav-item > a.is-open { background: var(--ink); color: var(--cream); opacity: 1; transform: scale(1.04); }
/* El panel es tinta, no crema, y arranca pegado al item: la píldora oscura que ya
   aparece al abrir (`a.is-open`) y el panel son el mismo gesto — se lee como si la
   píldora se estirara hacia abajo. Sobre crema, un bloque oscuro es lo más fresco que
   se puede hacer sin inventar un color: `--ink` ya es de la marca. */
.cathover {
  position: absolute; top: 100%; left: 0; margin-top: .34rem; z-index: 61;
  width: max-content; min-width: 224px; max-width: 280px;
  background: var(--ink); border-radius: var(--r-md);
  box-shadow: 0 30px 55px -22px rgba(40, 15, 5, .55), inset 0 0 0 1px rgba(255,254,247,.07);
  padding: .55rem .55rem .5rem;
  opacity: 0; transform: translateY(-10px) scale(.94); transform-origin: top left;
  transition: opacity .16s var(--ease-out), transform var(--t-mid) var(--ease-spring);
}
.cathover.align-right { left: auto; right: 0; transform-origin: top right; }
.cathover.open { opacity: 1; transform: translateY(0) scale(1); }
.cathover[hidden] { display: none; }

.ch-list { position: relative; display: grid; gap: 0; }
/* La marca deslizante — un solo elemento que viaja con `transform` detrás del texto.
   Mover una caja es mucho más barato (y se ve mucho mejor) que encender y apagar un
   fondo por item: el recorrido es continuo y lo resuelve el compositor. */
/* Naranja de marca, NO el tinte de la categoría. Los 8 tintes están validados para
   contrastar contra la FOTO del producto, no contra un panel oscuro: sobre tinta
   (#241611), el carbón de PlayStation (#2D2D2D) desaparecía y el oliva y el vino
   quedaban sordos — medido. El naranja se lee siempre, y naranja sobre tinta con texto
   crema encima es el par canónico del logo. */
.ch-marker {
  position: absolute; left: 0; right: 0; top: 0; height: 0;
  border-radius: var(--r-sm); background: var(--orange);
  opacity: 0; transform: translateY(0);
  transition: transform .3s var(--ease-spring), height .3s var(--ease-spring), opacity .16s var(--ease-out);
  pointer-events: none;
}
.ch-marker.on { opacity: 1; }
.ch-list a {
  position: relative; z-index: 1; display: flex; align-items: baseline; gap: .5rem;
  font-family: var(--font-body); font-weight: 700; font-size: 1.02rem;
  letter-spacing: -.01em; color: rgba(255,254,247,.82);
  padding: .46rem .6rem; border-radius: var(--r-sm);
  transition: color .18s var(--ease-out);
  /* Cascada de entrada: cada link sale un pelo después del anterior (--i lo pone el JS) */
  opacity: 0; transform: translateX(-6px) translateY(0);
}
/* Crema sobre el naranja de la marca. La clase la pone JS junto con el movimiento de la
   marca, no `:hover` de CSS: con dos fuentes distintas se podían desincronizar y dejar
   texto ilegible a medio camino. */
.ch-list a.is-on { color: var(--cream); }
/* Conteo de equipos cuando el flyout lista MARCAS en vez de modelos (Audífonos).
   `margin-left:auto` lo manda al borde derecho del panel. */
.ch-n { margin-left: auto; font-size: .76rem; font-weight: 800; opacity: .55; }

.ch-all {
  display: flex; align-items: center; gap: .4em;
  margin-top: .4rem; padding: .5rem .6rem .18rem;
  border-top: 1px solid rgba(255,254,247,.12);
  font-weight: 800; font-size: .82rem; color: var(--orange-bright);
  transition: color .18s;
}
.ch-arrow { transition: transform .24s var(--ease-spring); }
.ch-all:hover { color: var(--cream); }
.ch-all:hover .ch-arrow { transform: translateX(5px); }
/* `forwards`, no `backwards`: sin retener el estado final, el link vuelve a opacity:0
   apenas termina de animar (el keyframe solo define el `to`, y sin `forwards` el
   elemento cae de nuevo a la regla base de arriba en cuanto la animación acaba). Bug
   real, cazado midiendo opacity computada en vez de confiar en la captura. */
.cathover.open .ch-list a { animation: ch-in .32s var(--ease-out) forwards; animation-delay: calc(var(--i, 0) * 35ms + 40ms); }
@keyframes ch-in { to { opacity: 1; transform: translateX(0); } }
.ch-list a:hover { background: var(--cream-3); color: var(--orange); transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) {
  .cathover, .nav-desktop > a, .nav-desktop > .nav-item > a { transition: none; }
  .nav-desktop > .nav-item > a.is-open { transform: none; }
  .cathover.open .ch-list a { animation: none; opacity: 1; transform: none; }
}

/* Ofertas: link simple (sin flyout), acento frambuesa + badge con el conteo del día */
.nav-desktop > a.nav-deal { color: var(--berry-deep); }
.nav-desktop > a.nav-deal:hover { background: rgba(255, 45, 107, .1); color: var(--berry-deep); }
.nav-badge {
  display: none; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 4px; border-radius: var(--r-pill);
  background: var(--berry); color: #fff; font-size: .68rem; font-weight: 800; line-height: 1;
}
.nav-badge.show { display: inline-flex; }

.header-actions { display: flex; align-items: center; gap: .35rem; }
.icon-btn {
  width: 42px; height: 42px; border-radius: var(--r-pill);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink); position: relative; transition: background .2s;
}
.icon-btn:hover { background: var(--cream-3); }
.icon-btn svg { width: 22px; height: 22px; }
.cart-count-badge {
  position: absolute; top: 3px; right: 3px; min-width: 18px; height: 18px; padding: 0 4px;
  background: var(--orange); color: var(--cream); font-size: .7rem; font-weight: 800;
  border-radius: var(--r-pill); display: none; align-items: center; justify-content: center; line-height: 1;
}
.cart-count-badge.show { display: inline-flex; }

/* Estado "scrolled": header crema sobre contenido */
.site-header.scrolled {
  background: rgba(255,254,247,.9); backdrop-filter: saturate(1.2) blur(12px);
  box-shadow: 0 1px 0 var(--line), 0 8px 24px -18px rgba(80,35,15,.35);
}
.site-header.scrolled .wordmark { color: var(--ink); }
.site-header.scrolled .wordmark .dot { color: var(--orange); }
.site-header.scrolled .nav-desktop > a,
.site-header.scrolled .nav-desktop > .nav-item > a { color: var(--ink); opacity: .85; }
.site-header.scrolled .nav-desktop > a:hover,
.site-header.scrolled .nav-desktop > .nav-item > a:hover { background: var(--cream-3); color: var(--orange); opacity: 1; }
.site-header.scrolled .icon-btn { color: var(--ink); }
.site-header.scrolled .icon-btn:hover { background: var(--cream-3); }
.site-header.scrolled .cart-count-badge { background: var(--orange); color: var(--cream); }

.menu-btn { display: inline-flex; }
/* Comparador: herramienta, no categoría — vive como icon-button junto a Buscar/Carrito
   y solo en escritorio (en móvil ya está en el menú "Explora"). */
.icon-btn-cmp { display: none; }

/* ---------- Nav de escritorio: aparece a 1080px y va CENTRADO ----------
   Dos cosas a la vez, y la segunda es un bug real que estaba tapado:

   1. El breakpoint sube de 960 a 1080. Medido con CDP a 960px: marca (150) + nav (738)
      + acciones (137) + gaps + padding = 1068px de contenido dentro de 960px de ventana.
      Los botones de buscar/comparar/carrito quedaban literalmente fuera de pantalla y
      nadie lo veía porque `body { overflow-x: hidden }` se comía la barra de scroll.
      A 1080 el nav ya cabe con holgura; por debajo manda el menú hamburguesa, que para
      tablet es lo correcto de todos modos.

   2. `wrap` pasa de flex a grid `auto 1fr auto` y el nav se centra en la columna del
      medio, en vez de quedar empujado contra las acciones por el `margin-right: auto`
      de la marca (a 1440 el centro del nav caía 144px a la derecha del centro de la
      ventana). Como marca (150) y acciones (137) miden casi lo mismo, centrar en el
      hueco queda a ~6px del centro real de la ventana: imperceptible, y aguanta que
      cualquiera de los dos lados cambie de ancho sin descuadrarse. */
@media (min-width: 1080px) {
  .nav-desktop { display: flex; justify-self: center; }
  .menu-btn { display: none; }
  .icon-btn-cmp { display: inline-flex; }
  .site-header .wrap { display: grid; grid-template-columns: auto 1fr auto; }
  .header-brand { margin-right: 0; }
}

/* ============================================================
   MEGA MENÚ (móvil) — full screen
   ============================================================ */
/* El menú era un rectángulo de naranja plano con tarjetas de crema translúcido: la
   animación entraba bien pero la pantalla no decía nada de la marca. Tres capas lo
   arreglan sin salirse del sistema de color: profundidad en el fondo (dos focos de luz
   sobre el naranja), el grano que ya usa el resto del sitio, y una "CALI" gigante en
   Peace Sans sangrando por la esquina. Los colores de categoría entran por los discos
   de los íconos (ver .mc-ic abajo). Cero colores nuevos. */
.mega {
  position: fixed; inset: 0; z-index: 80;
  color: var(--cream);
  background:
    radial-gradient(92% 62% at 6% -10%, var(--orange-bright) 0%, transparent 60%),
    radial-gradient(80% 60% at 108% 106%, var(--orange-darker) 0%, transparent 62%),
    var(--orange);
  transform: translateY(-100%); transition: transform .5s var(--ease-io);
  display: flex; flex-direction: column;
  /* overflow-x explícito: dejado en `visible` el navegador lo computa a `auto` y el
     contenedor se traga la rueda del ratón (mismo gotcha que mató el scroll en `.rail`). */
  overflow-y: auto; overflow-x: hidden;
  overscroll-behavior: contain;
}
/* Grano y marca de agua en `fixed`, no `absolute`: así cubren la pantalla completa aunque
   el menú tenga scroll (con `absolute` se cortarían al primer viewport) y no suman área
   desplazable. Se anclan a `.mega` porque su `transform` la vuelve el bloque contenedor,
   así que entran y salen con la cortina en vez de quedarse pegadas a la ventana. */
.mega::before {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background-image: var(--noise); opacity: .07; mix-blend-mode: overlay;
}
.mega::after {
  content: "CALI"; position: fixed; z-index: 0; pointer-events: none;
  /* Pegada al borde derecho, sin sangrado lateral: un `right` negativo desbordaba 12px y,
     aunque `overflow-x: hidden` lo tapa, Chrome igual lo cuenta como área desplazable
     (medido: scrollLeft llegaba a 12). El sangrado que importa es el de abajo. */
  right: 0; bottom: -.42em;
  font-family: var(--font-display); font-size: 40vw; line-height: .78;
  letter-spacing: -.02em; color: var(--cream); opacity: .045;
}
/* El contenido va por encima de las dos capas decorativas */
.mega-head, .mega-body, .mega-foot { position: relative; z-index: 1; }

.mega.open { transform: translateY(0); }
.mega-head { display: flex; align-items: center; justify-content: space-between; padding: 1rem var(--pad); }
.mega-head .wordmark { font-family: var(--font-display); text-transform: lowercase; font-size: 1.4rem; }
.mega-head .icon-btn { color: var(--cream); background: rgba(255,254,247,.14); }
.mega-body { padding: .5rem var(--pad) 2rem; }
.mega-label {
  font-family: var(--font-display); text-transform: uppercase; font-size: .8rem;
  letter-spacing: .05em; opacity: .72; margin: 1.4rem 0 .8rem;
  display: flex; align-items: center; gap: .6em;
}
/* Filete que completa la línea del rótulo — el mismo recurso que `.eyebrow` en el sitio */
.mega-label::after { content: ""; flex: 1; height: 1px; background: rgba(255,254,247,.24); }
.mega-cats { display: grid; grid-template-columns: repeat(2, 1fr); gap: .7rem; }
.mega-cat {
  display: flex; flex-direction: column; gap: .1rem;
  background: rgba(255,254,247,.12); border-radius: var(--r-md); padding: .9rem 1rem;
  box-shadow: inset 0 0 0 1px rgba(255,254,247,.15);
  transition: background var(--t-fast), transform var(--t-fast) var(--ease-spring), box-shadow var(--t-fast);
}
/* El `transform` lleva `!important` a la fuerza, y con razón: la cascada pone las
   animaciones CSS por encima de las declaraciones normales, y `mega-in` corre con
   `forwards`, así que al terminar la entrada se queda dueña del `transform` del item
   para siempre. Sin `!important` este `:active` no hacía absolutamente nada — medido
   inyectando la misma declaración y viendo que el valor computado no se movía.
   El `background` sí funciona: la animación no lo toca. */
.mega-cat:hover, .mega-cat:active {
  background: rgba(255,254,247,.22);
  box-shadow: inset 0 0 0 1px rgba(255,254,247,.3);
  transform: translateY(-2px) scale(1.02) !important;
}
/* El disco de color de la categoría: es lo único que rompe el monocromo naranja, y usa
   los mismos tokens --t- y --ti- que el banner de categoría y el hover de las tarjetas.
   `--tint`/`--tink` los pone bindHeader() al pintar cada item, así que una categoría
   nueva trae su color sola, sin CSS nuevo. */
.mega-cat .mc-ic {
  width: 44px; height: 44px; border-radius: 50%; margin-bottom: .15rem;
  align-items: center; justify-content: center;
  background: var(--tint, rgba(255,254,247,.22)); color: var(--tink, var(--ink));
  box-shadow: 0 8px 16px -10px rgba(50, 18, 8, .75);
  transition: transform var(--t-mid) var(--ease-spring);
}
.mega-cat .mc-ic svg { width: 24px; height: 24px; }
.mega-cat:hover .mc-ic, .mega-cat:active .mc-ic { transform: rotate(-7deg) scale(1.08); }
.mega-cat .mc-name { font-family: var(--font-body); font-weight: 800; font-size: 1.05rem; line-height: 1.05; margin-top: .3rem; }
.mega-cat .mc-n { font-size: .8rem; opacity: .8; }
/* Marcas de la categoría en móvil. No hay hover en el celular, así que el equivalente
   del flyout de escritorio son estos chips, siempre visibles bajo su categoría.
   El wrap es flex-columna para que dos categorías de la misma fila queden a la misma
   altura aunque solo una tenga chips. */
.mega-cat-wrap { display: flex; flex-direction: column; gap: .4rem; }
.mega-cat-wrap > .mega-cat { flex: 1; }
.mc-brands { display: flex; flex-wrap: wrap; gap: .32rem; }
.mc-brand {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .3rem .6rem; border-radius: var(--r-pill);
  background: var(--tint); color: var(--tink);
  font-size: .78rem; font-weight: 800; line-height: 1.2;
  box-shadow: 0 6px 14px -10px rgba(50,18,8,.8);
  transition: transform var(--t-fast) var(--ease-spring);
}
.mc-brand:active { transform: scale(.95); }
.mega-links { display: flex; flex-direction: column; gap: .1rem; margin-top: .5rem; }
.mega-links a {
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
  font-family: var(--font-body); font-weight: 800; font-size: 1.35rem; letter-spacing: -.01em;
  padding: .55rem 0; border-bottom: 1px solid rgba(255,254,247,.16);
  transition: padding-left var(--t-fast) var(--ease-spring), opacity var(--t-fast);
}
/* Flecha siempre visible (en táctil no hay hover que la revele): a media tinta indica
   "esto lleva a algún lado", y se enciende al tocar. */
.mega-links a::after {
  content: "→"; font-size: 1.05rem; opacity: .45;
  transition: transform var(--t-fast) var(--ease-spring), opacity var(--t-fast);
}
.mega-links a:hover, .mega-links a:active { padding-left: .5rem; opacity: .85; }
.mega-links a:hover::after, .mega-links a:active::after { opacity: 1; transform: translateX(4px); }
.mega-foot { margin-top: auto; padding: 1.4rem var(--pad); display: flex; gap: .7rem; }
.mega-foot .btn { flex: 1; }

/* Cascada de entrada: categorías y links salen uno a uno cuando el menú se abre.
   `--i` lo pone bindHeader() en melo.js al pintar cada item.
   `forwards`, no `backwards` — con `backwards` el item vuelve a opacity:0 apenas
   termina de animar (mismo bug que en el flyout de escritorio, cazado midiendo). */
.mega-cat, .mega-links a, .mc-brands { opacity: 0; transform: translateY(14px); }
.mega.open .mega-cat, .mega.open .mega-links a, .mega.open .mc-brands {
  animation: mega-in .5s var(--ease-spring) forwards;
  animation-delay: calc(var(--i, 0) * 45ms + 120ms);
}
/* Los chips de marca entran un pelín después que su categoría, no a la vez: leen como
   consecuencia de la tarjeta, no como una fila más. `--i` lo hereda del .mega-cat-wrap. */
.mega.open .mc-brands { animation-delay: calc(var(--i, 0) * 45ms + 220ms); }
@keyframes mega-in { to { opacity: 1; transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) {
  .mega-cat, .mega-links a, .mc-brands { animation: none !important; opacity: 1; transform: none; }
}

/* ============================================================
   PRELOADER
   ============================================================ */
.preloader {
  position: fixed; inset: 0; z-index: 200;
  background: var(--orange);
  display: grid; place-items: center;
  /* .8s → .62s en v23. La cortina sale en CADA navegación, así que su duración es un
     impuesto sobre todas las páginas: bajarla 180 ms se nota en el conjunto y el gesto
     sigue leyéndose igual de intencional. Si alguna vez se quiere más pausado, este número
     y `PRE_PISO`/`PRE_TECHO` en melo.js son las tres perillas — no hay más. */
  transition: transform .62s cubic-bezier(.76,0,.24,1);
  will-change: transform;
}
.preloader.lift { transform: translateY(-100.5%); }
.preloader.done { display: none; }
.pre-stage {
  position: relative; z-index: 2; display: grid; place-items: center;
  gap: clamp(1.5rem, 6vw, 2.2rem); text-align: center;
  padding: clamp(1.5rem, 6vw, 2.5rem);
}
/* El arte va con fondo transparente (logo-cream.png, extraído del logo maestro por
   flood-fill) directamente sobre el naranja de marca. Antes se usaba el PNG completo,
   que es un azulejo NARANJA: su borde se recortaba contra el fondo del mismo color y
   esa costura se tapaba con un aro de vidrio. Sin azulejo no hay costura que tapar,
   así que no hay anillo, ni borde, ni radio — solo la marca sobre su color. */
.pre-logo {
  display: block; width: min(66vw, 268px); height: auto;
  opacity: 0; transform: scale(.88) translateY(12px);
  animation: pre-pop .85s var(--ease-spring) .05s forwards;
}
/* En apaisado (móvil acostado, pantallas bajas) manda el alto, no el ancho */
@media (max-height: 460px) { .pre-logo { width: auto; height: min(46vh, 190px); } }
.pre-line {
  width: clamp(110px, 34vw, 168px); height: 3px; border-radius: 3px;
  background: rgba(255,254,247,.26); overflow: hidden;
  opacity: 0; animation: pre-fade .5s ease .42s forwards;
}
.pre-line i { display: block; height: 100%; width: 100%; border-radius: 3px; background: var(--cream); transform-origin: left; transform: scaleX(0); animation: pre-load 1.05s cubic-bezier(.5,0,.2,1) .45s forwards; }
@keyframes pre-pop { to { opacity: 1; transform: scale(1) translateY(0); } }
@keyframes pre-fade { to { opacity: 1; } }
@keyframes pre-load { to { transform: scaleX(1); } }

/* ============================================================
   HERO
   ============================================================ */
/* El guiño de Cali NO es una ilustración ni una foto de banco: es una foto REAL de la
   marca — producto en la mano frente a La Ermita (pieza 26 del feed, ver
   02_MARCA/MELOTECH/AUDITORIA.md). Es el activo que ningún competidor tiene. Se le quitó
   el logo incrustado porque el header ya lleva el wordmark. Los dos intentos anteriores
   (silueta SVG y foto de banco en duotono) fueron rechazados por el dueño. */
.hero {
  position: relative; overflow: hidden; isolation: isolate;
  background: var(--orange);
  color: var(--cream);
  margin: var(--frame); margin-top: calc(var(--header-h) + var(--frame));
  border-radius: var(--r-hero);
  display: flex; flex-direction: column; justify-content: center;
  padding-top: clamp(1.6rem, 5vw, 2.6rem); padding-bottom: clamp(1.5rem, 5vw, 2.4rem);
  box-shadow: var(--sh-lg);
}
@media (min-width: 960px) { .hero { min-height: 78vh; padding-top: clamp(2rem, 4vw, 3.2rem); padding-bottom: 2.8rem; }
  .hero-inner { padding-bottom: 0; } }
/* halos de luz cálida — dan profundidad y "bien llamativo" al naranja plano */
.hero::before {
  content: ""; position: absolute; z-index: 0; inset: -25% -15% auto -15%; height: 80%;
  background: radial-gradient(55% 75% at 28% 8%, rgba(255,140,95,.6), transparent 72%);
  pointer-events: none;
}
.hero::after {
  content: ""; position: absolute; z-index: 0; right: -18%; bottom: -12%; width: 65%; height: 55%;
  background: radial-gradient(closest-side, rgba(255,45,27,.55), transparent 75%);
  pointer-events: none; filter: blur(6px);
}
/* Sello giratorio — sticker de marca pegado a la esquina de la foto (gesto editorial:
   el sello monta sobre la imagen en vez de flotar suelto en el naranja). */
.hero-seal {
  display: none;
  position: absolute; z-index: 4; left: -30px; bottom: -24px;
  width: 108px; height: 108px; color: var(--cream);
  /* Disco oscuro translúcido — mismo tratamiento que el pie de foto, para que el texto
     crema se lea igual sobre la foto clara que sobre el naranja. Sin él, el sello queda
     a caballo entre los dos fondos y no se lee en ninguno. */
  border-radius: 50%;
  background: rgba(36, 22, 17, .5);
  backdrop-filter: blur(10px) saturate(1.25);
  box-shadow: inset 0 0 0 1px rgba(255,254,247,.2);
}
@media (min-width: 700px) { .hero-seal { display: block; } }
/* El giro va en el SVG, no en el contenedor: el disco debe quedarse quieto */
.hero-seal > svg { width: 100%; height: 100%; animation: seal-spin 16s linear infinite; }
.hero-seal text { font-family: var(--font-display); font-size: 8.6px; letter-spacing: .6px; fill: currentColor; }
.hero-seal .seal-dot {
  position: absolute; inset: 0; margin: auto; width: 40px; height: 40px;
  display: grid; place-items: center; border-radius: 50%;
  background: var(--cream); color: var(--orange);
  animation: seal-spin 16s linear infinite reverse;
}
.hero-seal .seal-dot svg { width: 19px; height: 19px; }
@keyframes seal-spin { to { transform: rotate(360deg); } }
@media (min-width: 1100px) { .hero-seal { width: 128px; height: 128px; left: -42px; bottom: -32px; } }

/* Retícula del hero: copy a la izquierda, foto real a la derecha. En cel se apila y la
   foto va primero abajo (el titular manda arriba). */
.hero-inner {
  position: relative; z-index: 2; width: 100%; max-width: var(--maxw);
  margin-inline: auto; padding: 0 var(--pad) clamp(1.2rem, 3vw, 2.4rem);
  display: grid; gap: clamp(1.6rem, 4vw, 3rem); align-items: center;
}
@media (min-width: 960px) { .hero-inner { grid-template-columns: 1.06fr .94fr; gap: clamp(2rem, 4vw, 4rem); } }

/* La foto real de Cali. Marco crema + leve rotación = polaroid, no banner de stock. */
.hero-shot { position: relative; margin: 0; justify-self: center; width: 100%; max-width: 380px; }
@media (min-width: 960px) { .hero-shot { max-width: 470px; justify-self: end; } }
.hero-shot-frame {
  position: relative; display: block; overflow: hidden;
  border-radius: clamp(20px, 3vw, 30px);
  background: var(--cream); padding: 8px;
  box-shadow: 0 40px 80px -30px rgba(70, 20, 5, .58), 0 0 0 1px rgba(255,254,247,.18);
  transform: rotate(-1.8deg);
  transition: transform var(--t-slow) var(--ease-gentle);
}
.hero-shot-frame img {
  display: block; width: 100%; height: auto; border-radius: clamp(14px, 2.2vw, 22px);
  aspect-ratio: 4 / 5; object-fit: cover;
}
@media (hover: hover) { .hero-shot:hover .hero-shot-frame { transform: rotate(0deg) scale(1.015); } }
/* Pie de foto: ancla la imagen en un lugar real. Sin esto es "una foto bonita"; con esto
   es "esto lo tomamos nosotros, en Cali". */
.hero-shot figcaption {
  position: absolute; z-index: 3; left: 50%; bottom: 18px; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: .45em; white-space: nowrap;
  background: rgba(36, 22, 17, .58); backdrop-filter: blur(10px) saturate(1.3);
  color: var(--cream); font-size: .8rem; font-weight: 700; letter-spacing: .01em;
  padding: .48em .9em; border-radius: var(--r-pill);
  box-shadow: inset 0 0 0 1px rgba(255,254,247,.22);
}
.hero-shot figcaption .pin { width: 7px; height: 7px; border-radius: 50%; background: var(--orange-bright); box-shadow: 0 0 0 3px rgba(255,90,56,.3); flex: none; }

/* Entrada de la foto — escala + sube, con la curva spring */
.hero-shot { opacity: 0; transform: translateY(26px) scale(.96); }
.reveal-ready .hero-shot { animation: shot-in .9s var(--ease-spring) .3s forwards; }
@keyframes shot-in { to { opacity: 1; transform: translateY(0) scale(1); } }

/* Fila de confianza bajo los CTA — las 3 objeciones del mercado, resueltas de una */
.hero-trust {
  display: flex; flex-wrap: wrap; gap: .5rem .9rem; margin-top: clamp(1.1rem, 3vw, 1.5rem);
  opacity: 0; transform: translateY(12px);
}
.reveal-ready .hero-trust { animation: soft-in .7s var(--ease-out) .72s forwards; }
/* Antes eran tres líneas de texto crema con un ícono fino al lado: sobre el naranja
   se leían apagadas y planas (el dueño: «se ven solo letras blancas»). Ahora cada una
   es una píldora con el ícono dentro de un disco CREMA — el naranja del ícono contra
   el crema del disco da el contraste que faltaba, y el disco recorta la píldora del
   fondo. Los íconos se animan (ver "íconos animados" más abajo). */
.hero-trust li {
  display: inline-flex; align-items: center; gap: .5em;
  font-size: .86rem; font-weight: 800; color: var(--cream);
  background: rgba(38,16,8,.2); border: 1px solid rgba(255,254,247,.34);
  border-radius: var(--r-pill); padding: .34rem .85rem .34rem .34rem;
  backdrop-filter: blur(3px);
  transition: transform var(--t-fast) var(--ease-spring), background var(--t-fast);
}
.hero-trust li:hover { transform: translateY(-2px); background: rgba(38,16,8,.3); }
.hero-trust .ht-ic {
  display: grid; place-items: center; flex: none;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--cream); color: var(--orange);
  box-shadow: 0 2px 6px -2px rgba(60,20,5,.5);
}
.hero-trust .ht-ic svg { width: 15px; height: 15px; }
.hero-eyebrow {
  font-weight: 700; font-size: clamp(.82rem, 2.6vw, .98rem); letter-spacing: .01em;
  color: rgba(255,254,247,.92); margin-bottom: clamp(.6rem, 2vw, 1rem);
  display: inline-flex; align-items: center; gap: .5em;
}
.hero-eyebrow .pin { width: 8px; height: 8px; border-radius: 50%; background: var(--cream); box-shadow: 0 0 0 4px rgba(255,254,247,.25); }

.hero-title {
  font-family: var(--font-display); text-transform: uppercase; color: var(--cream);
  /* Tope más bajo que antes: ahora comparte fila con la foto, no ocupa el ancho completo */
  font-size: clamp(3rem, 13vw, 6.5rem); line-height: .92; letter-spacing: -.02em; font-weight: 400;
  margin-bottom: clamp(.9rem, 2.4vw, 1.3rem);
}
/* La máscara de la entrada solo necesita el borde de ABAJO: las letras suben desde
   translateY(120%), o sea que aparecen cruzando el borde inferior. El `overflow: hidden`
   que había cerraba los cuatro lados, y el de arriba estaba cortando a CALI en pleno
   movimiento — medido con CDP: la placa se salía 9.5px y el punto 8.7px en el pico del
   vaivén (rotate -2.35deg + scale 1.01 sobre 285px de ancho), más el sobrepaso de -4%
   de `cali-pop` al entrar. `clip-path` abre 0.22em arriba y deja abajo y los costados
   cerrados igual que antes (los costados son la red de seguridad del `nowrap`). */
.hero-title .line { display: block; white-space: nowrap; padding-top: .06em; clip-path: inset(-.22em 0 0 0); }
.hero-title .word { display: inline-flex; }
.hero-title .word + .word { margin-left: .26em; }
.hero-title .ltr { display: inline-block; transform: translateY(120%); will-change: transform; }
.hero-title .dot { color: var(--cream); margin-left: .02em; }
.reveal-ready .hero-title .ltr { animation: ltr-up .72s cubic-bezier(.2,.72,.24,1) both; animation-delay: calc(var(--i, 0) * 42ms); }
@keyframes ltr-up { from { transform: translateY(120%); } to { transform: translateY(0); } }

/* "CALI" = placa crema con letras naranja — el ADN del logo invertido.
   Simple, plano, premium y 100% marca (adiós foto-en-letra). */
.cali-word { display: inline-flex; align-items: baseline; transform: translateY(120%); }
.reveal-ready .hero-title .cali-word { animation: cali-pop .78s cubic-bezier(.2,.9,.24,1) both; animation-delay: calc(10 * 42ms); }
.cali-plate {
  display: inline-block; background: var(--cream);
  border-radius: .12em; padding: 0 .16em .02em; line-height: 1;
  box-shadow: 0 .06em 0 rgba(120,40,20,.16), var(--sh-md);
  transform: rotate(-1.6deg); transform-origin: left center;
}
/* "CALI" — letras naranja sólido sobre la placa crema (como estaba) */
.cali-ink { display: inline-block; color: var(--orange); }
.cali-dot { color: var(--cream); margin-left: .06em; }
@keyframes cali-pop { 0% { transform: translateY(120%); } 70% { transform: translateY(-4%); } 100% { transform: translateY(0); } }

/* Vaivén continuo de "CALI" — sigue vivo después de la entrada.
   Tres decisiones, todas a propósito:
   1. Va sobre .cali-plate y .cali-dot, NO sobre .cali-word: esa ya gasta su
      `transform` en la entrada (cali-pop), y dos animaciones de transform en el
      mismo elemento se pisan — la segunda gana y se pierde la entrada.
   2. Los keyframes están mal repartidos a propósito (dos tandas de nudges con
      pausas largas de ~1.5s en medio, no un vaivén parejo). Un seno regular se
      lee como metrónomo y el ojo lo apaga en dos ciclos; esto no.
   3. Los dos ciclos (8.7s y 6.1s) no son múltiplos, así que placa y punto no
      vuelven a coincidir en la misma pose hasta pasados ~9 minutos: nunca se
      alcanza a ver el bucle.
   Empieza en 1.25s = cuando termina la entrada (retraso .42s + duración .78s). */
.reveal-ready .cali-plate { animation: cali-vaiven 8.7s var(--ease-gentle) 1.25s infinite; }
@keyframes cali-vaiven {
  0%, 100% { transform: rotate(-1.6deg)  scale(1); }
  7%       { transform: rotate(-3deg)    scale(1.016); }
  14%      { transform: rotate(-1.3deg)  scale(1.003); }
  21%      { transform: rotate(-2.2deg)  scale(1.008); }
  27%, 46% { transform: rotate(-1.6deg)  scale(1); }        /* quieta */
  53%      { transform: rotate(-.5deg)   scale(1.019); }
  60%      { transform: rotate(-2.5deg)  scale(1.006); }
  65%      { transform: rotate(-1.45deg) scale(1.002); }
  71%, 86% { transform: rotate(-1.6deg)  scale(1); }        /* quieta */
  93%      { transform: rotate(-2.35deg) scale(1.01); }
}
/* El punto rebota por su cuenta, con su propio ritmo */
.reveal-ready .cali-dot { animation: cali-punto 6.1s var(--ease-gentle) 1.4s infinite; }
@keyframes cali-punto {
  0%, 100% { transform: translateY(0) scale(1); }
  6%       { transform: translateY(-.07em) scale(1.16); }
  13%      { transform: translateY(0) scale(1); }
  19%      { transform: translateY(-.03em) scale(1.06); }
  25%, 61% { transform: translateY(0) scale(1); }           /* quieto */
  68%      { transform: translateY(-.09em) scale(1.2); }
  76%      { transform: translateY(0) scale(1); }
}

.hero-sub {
  max-width: 46ch; font-size: clamp(1rem, 2.9vw, 1.18rem); color: rgba(255,254,247,.95);
  margin-bottom: clamp(1.1rem, 3vw, 1.5rem); line-height: 1.45;
  opacity: 0; transform: translateY(12px);
}
.reveal-ready .hero-sub { animation: soft-in .7s var(--ease-out) .45s forwards; }
.hero-cta { display: flex; flex-wrap: wrap; gap: .7rem; opacity: 0; transform: translateY(12px); }
.reveal-ready .hero-cta { animation: soft-in .7s var(--ease-out) .58s forwards; }
.hero-cta .btn { font-size: 1.02rem; padding: .95em 1.6em; }
@keyframes soft-in { to { opacity: 1; transform: translateY(0); } }

/* Ticker de valor — funcional + on-brand */
.hero-ticker {
  position: relative; z-index: 2; margin-top: clamp(1.6rem, 5vw, 2.4rem);
  border-top: 2px solid rgba(255,254,247,.28); border-bottom: 2px solid rgba(255,254,247,.28);
  overflow: hidden; padding-block: .7rem;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.ticker-track { display: inline-flex; white-space: nowrap; will-change: transform; animation: ticker 26s linear infinite; }
.ticker-track span {
  font-family: var(--font-body); font-weight: 800; text-transform: uppercase; font-size: clamp(.82rem, 2.6vw, 1rem);
  letter-spacing: .12em; color: var(--cream); padding-inline: 1.1rem;
  display: inline-flex; align-items: center; gap: 1.1rem;
}
.ticker-track span::after { content: "✦"; color: rgba(255,254,247,.55); font-size: .8em; }
@keyframes ticker { to { transform: translateX(-50%); } }

.scroll-hint {
  position: absolute; bottom: .6rem; left: 50%; transform: translateX(-50%); z-index: 2;
  display: none; align-items: center; flex-direction: column; gap: .2rem;
  font-size: .7rem; letter-spacing: .1em; text-transform: uppercase; color: rgba(255,254,247,.7);
}
.scroll-hint svg { animation: hint-bob 1.9s var(--ease-io) infinite; }
@keyframes hint-bob { 0%, 100% { transform: translateY(0); opacity: .7; } 50% { transform: translateY(5px); opacity: 1; } }
@media (min-width: 960px) { .scroll-hint { display: flex; } }

/* ============================================================
   CATEGORÍAS — pieza clave de navegación
   ============================================================ */
.cats-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(.7rem, 2.4vw, 1.1rem); }
.cat-card {
  position: relative; overflow: hidden; min-width: 0;
  border-radius: var(--r-lg); padding: 1.1rem 1.1rem 1.2rem;
  background: var(--tint, var(--cream-3)); color: var(--tink, var(--ink));
  min-height: clamp(158px, 42vw, 230px);
  display: flex; flex-direction: column;
  transition: transform .3s var(--ease-out), box-shadow .3s var(--ease-out);
  box-shadow: var(--sh-sm);
  transform-style: preserve-3d;
}
.cat-card:hover { transform: translateY(-6px) rotateX(var(--rx,0)) rotateY(var(--ry,0)); box-shadow: var(--sh-lg); }
/* Barrido de luz al pasar el mouse (interacción premium) */
.cat-card::before {
  content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none; border-radius: inherit;
  background: linear-gradient(115deg, transparent 34%, rgba(255,255,255,.4) 48%, transparent 60%);
  transform: translateX(-130%); transition: transform .75s var(--ease-out);
}
.cat-card:hover::before { transform: translateX(130%); }
.cat-card .cc-name {
  font-family: var(--font-display); text-transform: uppercase; font-weight: 400;
  font-size: clamp(.92rem, 3.3vw, 1.38rem); line-height: .92; letter-spacing: -.03em;
  color: var(--tink); position: relative; z-index: 2; max-width: 100%; overflow-wrap: normal; hyphens: none;
}
.cat-card .cc-count {
  font-size: .78rem; font-weight: 700; color: var(--tink); opacity: .72;
  margin-top: .2rem; position: relative; z-index: 2;
}
.cat-card .cc-go {
  margin-top: auto; align-self: flex-start; position: relative; z-index: 2;
  display: inline-flex; align-items: center; gap: .3rem;
  /* Tinta fija, no --tink: sobre Vino y Carbón el tink es crema y la píldora clara
     dejaba texto crema sobre blanco (ilegible). */
  font-weight: 800; font-size: .84rem; color: var(--ink);
  background: rgba(255,255,255,.78); padding: .35rem .7rem; border-radius: var(--r-pill);
  transition: gap .2s, background .2s;
}
.cat-card:hover .cc-go { gap: .55rem; background: var(--cream); }
/* El equipo va COMPLETO dentro de la tarjeta, no sangrando por la esquina.
   Antes: `right/bottom: -3%` + `rotate(-7deg)` con origen en la esquina inferior derecha,
   y al hacer hover encima `scale(1.07)`. Resultado medido: la foto se salía 18px por
   abajo y 10px por la derecha, y el producto quedaba cortado por la mitad — en
   Computadores solo se veía una esquina negra del iPad, imposible saber qué era.
   Un sangrado bonito no sirve de nada si no se reconoce el producto. */
.cat-card .cc-img {
  position: absolute; z-index: 1; right: 3.5%; bottom: 8%;
  width: 56%; height: 58%; object-fit: contain; object-position: bottom right;
  filter: drop-shadow(0 14px 20px rgba(60,25,10,.26));
  /* La inclinación y el margen de abajo van atados: al girar sobre la esquina inferior
     DERECHA, la esquina inferior izquierda baja ancho_imagen x sen(angulo). Con -5deg
     eran ~16px contra 10px de margen, y seguía saliéndose 5px (medido). A -4deg con 8%
     de margen entra con holgura en todos los anchos. */
  transform: rotate(-4deg) translateZ(30px);
  transform-origin: bottom right;
  transition: transform .45s var(--ease-gentle), filter .45s var(--ease-out);
}
/* Al pasar el cursor el equipo se endereza y se levanta, en vez de solo crecer. Con el
   origen en la esquina inferior derecha, `scale` crece hacia arriba y a la izquierda —
   o sea, ALEJÁNDOSE de los dos bordes contra los que antes se recortaba. */
.cat-card:hover .cc-img {
  transform: rotate(0deg) translateY(-9px) scale(1.06) translateZ(40px);
  filter: drop-shadow(0 22px 26px rgba(60,25,10,.32));
}

/* Ofertas — tarjeta igual (llena la 8ª celda), gradiente frambuesa (color permitido para ofertas) */
/* ---- Tarjeta "Combos" del home (8ª casilla, ago 2026) ----
   Reemplaza a la de Ofertas: esa se apaga con `preciosPorConfirmar` y dejaba la
   grilla en 7 tarjetas, descuadrada. Combos no depende del precio.
   Usa el ink de la marca (no un degradado nuevo) y repite el abanico de la
   tarjeta grande de combo, para que se lean como la misma familia. */
.cat-card.is-combos { background: var(--ink); color: var(--cream); }
.cat-card.is-combos .cc-name { color: var(--cream); position: relative; z-index: 2; }
.cat-card.is-combos .cc-count { color: rgba(255, 254, 247, .82); opacity: 1; font-weight: 700; position: relative; z-index: 2; }
.cat-card.is-combos .cc-go { background: var(--orange); color: var(--cream); position: relative; z-index: 2; }
.cat-card.is-combos:hover .cc-go { background: var(--orange-bright); }
.cc-combo-fan {
  position: absolute; right: -6%; bottom: 4%; width: 74%; height: 62%;
  pointer-events: none;
}
.cc-combo-layer {
  position: absolute; left: 50%; top: 50%; width: 56%; height: 100%;
  z-index: var(--z, 1);
  transform: translate(-50%, -50%) translateX(var(--x)) rotate(var(--r));
  transition: transform .45s var(--ease-spring);
}
.cc-combo-layer img { width: 100%; height: 100%; object-fit: contain; }
.cc-combo-layer.is-ph { display: none; }
@media (hover: hover) {
  .cat-card.is-combos:hover .cc-combo-layer {
    transform: translate(-50%, -50%) translateX(calc(var(--x) * 1.35)) rotate(calc(var(--r) * 1.6));
  }
}
@media (prefers-reduced-motion: reduce) { .cc-combo-layer { transition: none; } }

.cat-card.is-offers { background: linear-gradient(145deg, #FF4D6B 0%, #F5245F 46%, #D6134E 100%); color: var(--cream); }
.cat-card.is-offers .cc-flame {
  position: absolute; z-index: 0; right: -6%; top: -9%;
  width: clamp(96px, 30%, 150px); height: auto; color: rgba(255,255,255,.16);
  transform: rotate(6deg); transition: transform .45s var(--ease-out);
}
.cat-card.is-offers:hover .cc-flame { transform: rotate(-2deg) scale(1.07); }
.cat-card.is-offers .cc-name { color: var(--cream); position: relative; z-index: 2; }
.cat-card.is-offers .cc-count { color: rgba(255,254,247,.92); opacity: 1; font-weight: 700; position: relative; z-index: 2; }
.cat-card.is-offers .cc-go { background: var(--cream); color: var(--berry-deep); position: relative; z-index: 2; }
.cat-card.is-offers:hover .cc-go { background: #fff; transform: translateY(-1px); }

@media (min-width: 820px) {
  .cats-grid { grid-template-columns: repeat(4, 1fr); gap: 1.1rem; }
  .cat-card { min-height: 240px; }
}

/* ============================================================
   TARJETA DE PRODUCTO (destacados / grids / modal upsell)
   ============================================================ */
.rail {
  display: grid; grid-auto-flow: column; grid-auto-columns: 78%;
  gap: 1rem; overflow-x: auto; scroll-snap-type: x mandatory;
  /* `overflow-y` DEBE ir explícito. Si se deja en `visible`, el CSS lo convierte en `auto`
     porque el otro eje no es visible: el riel se vuelve scrollable también en vertical y
     con el cursor encima se traga la rueda del mouse — la página dejaba de bajar. Medido
     con CDP: sobraban 18px de scroll vertical en Destacados y Combos. */
  overflow-y: hidden;
  /* Aire arriba pa' el lift de la tarjeta (-5px) y su sombra, ahora que recortamos en Y.
     El margen negativo lo compensa para que el riel no se corra de sitio. */
  padding-block: .75rem 1rem; margin-block-start: -.75rem;
  /* Que el rebote horizontal no se propague a la página (ni dispare el gesto de "atrás"). */
  overscroll-behavior-inline: contain;
  margin-inline: calc(var(--pad) * -1); padding-inline: var(--pad);
  /* Sin esto el snap ignora el padding lateral: el riel nacía desplazado justo el ancho
     del gutter y la primera tarjeta quedaba descuadrada del título de la sección. */
  scroll-padding-inline: var(--pad);
  scrollbar-width: none;
}
.rail::-webkit-scrollbar { display: none; }
.rail > * { scroll-snap-align: start; }

/* ---------- Carrusel: flechas sobre el riel ---------- */
.rail-wrap { position: relative; }
.rail-nav { position: absolute; bottom: calc(100% + .7rem); right: 0; display: none; gap: .5rem; z-index: 3; }
.rail-nav[hidden] { display: none !important; }
@media (min-width: 720px) { .rail-nav { display: flex; } }
.rail-btn {
  width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center;
  background: var(--cream); color: var(--ink); box-shadow: var(--sh-sm);
  border: 1px solid var(--line); cursor: pointer;
  transition: background .18s, color .18s, border-color .18s, transform .18s var(--ease-out), opacity .18s;
}
.rail-btn:hover:not(:disabled) { background: var(--orange); color: var(--cream); border-color: var(--orange); transform: translateY(-2px); }
.rail-btn:disabled { opacity: .3; cursor: default; }
.rail-btn svg { width: 20px; height: 20px; }
/* Pista de progreso — sustituye a la barra de scroll oculta */
.rail-bar { height: 3px; border-radius: 3px; background: var(--line); margin-top: .9rem; overflow: hidden; }
.rail-bar i { display: block; height: 100%; border-radius: 3px; background: var(--orange); transition: width .15s linear, transform .15s linear; }
.grid {
  display: grid; gap: clamp(.8rem, 2.4vw, 1.2rem);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  /* Todas las filas iguales: sin esto cada fila se ajusta a su tarjeta más alta y la
     grilla queda escalonada. El dueño pidió simetría estricta. */
  grid-auto-rows: 1fr;
}
/* Los combos son fichas anchas: menos por pantalla que las tarjetas de producto */
.rail-wide { grid-auto-columns: 86%; }
@media (min-width: 560px) { .rail { grid-auto-columns: 45%; } .rail-wide { grid-auto-columns: 56%; } }
@media (min-width: 720px) { .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } .rail { grid-auto-columns: 32%; } .rail-wide { grid-auto-columns: 40%; } }
@media (min-width: 1000px) { .rail-wide { grid-auto-columns: 31%; } }
@media (min-width: 1000px) { .grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.card {
  position: relative; min-width: 0; display: flex; flex-direction: column;
  background: var(--cream); border: 1px solid var(--line); border-radius: var(--r-lg);
  overflow: hidden; transition: transform .25s var(--ease-out), box-shadow .25s, border-color .25s;
  box-shadow: var(--sh-sm); cursor: pointer;
}
/* El `transform` del hover NO va aquí: `.reveal.in { transform: none }` (al final del
   archivo, misma especificidad) le ganaba por orden y el levantamiento de la tarjeta
   llevaba tiempo muerto — todas las tarjetas nacen con `.reveal`. Vive abajo, en el
   bloque (hover: hover), con especificidad doblada. */
.card:hover { box-shadow: var(--sh-md); border-color: var(--line-2); }
.card-media {
  position: relative; aspect-ratio: 1 / 1; background: var(--cream-3);
  padding: 1rem; overflow: hidden;
}
/* Absoluta a propósito: en flujo, el alto en % de la imagen pisaba el aspect-ratio
   y la caja variaba 273–287px según la foto, descuadrando el tamaño del producto.

   El 76% (antes 84%) es el arreglo del recorte: la foto necesita AIRE para poder crecer.
   Medido antes: a 84% + zoom la caja llegaba al 92% del alto del panel, se salía 5px por
   arriba y le sobraban 32px por abajo — el producto quedaba cortado y descentrado, que es
   justo lo que se veía mal. A 76%, con el zoom del hover llega al 80%: nunca toca el
   borde, pase lo que pase con la foto. */
.card-media img {
  position: absolute; top: 50%; left: 50%; width: 76%; height: 76%;
  object-fit: contain; transform: translate(-50%, -50%);
  transition: transform .42s var(--ease-gentle), opacity .34s var(--ease-out);
  /* z-index explícito: el disco de color y la sombra de contacto son ::before y ::after,
     y los pseudo-elementos posicionados pintan por orden de DOM — sin esto la sombra
     saldría ENCIMA del producto. */
  z-index: 1;
}
/* Aparición suave (v23): una foto en diferido no se "ve cargando" — no hay nada y de
   pronto está el equipo, de golpe. `melo.js` marca `por-cargar` SOLO en las que todavía
   no han bajado (las que ya están, y las de prioridad alta del hero, ni se tocan) y les
   quita el freno al terminar. El fundido es sobre el crema de la caja, así que se lee
   como que la foto se asienta, no como que la página parpadea. */
img.por-cargar { opacity: 0; transition: opacity .5s var(--ease-out), transform .5s var(--ease-out); }
.card-media img.por-cargar { transform: translate(-50%, -50%) scale(.97); }
img.por-cargar.ya-cargo { opacity: 1; }
.card-media img.por-cargar.ya-cargo { transform: translate(-50%, -50%); }

/* ============================================================
   CRUCE DE COLOR  (v23)
   ------------------------------------------------------------
   Antes al tocar un swatch la foto se desvanecía a cero y volvía: la caja quedaba
   vacía un instante — y si la foto nueva todavía estaba bajando, bastante más que un
   instante. Ahora `swapImg()` la baja y la DECODIFICA aparte, la monta encima de la
   que está puesta y las cruza: la que entra crece un pelo desde el fondo, la que sale
   se encoge y se apaga. Nunca hay caja vacía, y el gesto se lee como el equipo girando
   a otro color en vez de como una carga.
   `switching` se queda para el respaldo (reduced-motion y navegadores sin `decode()`).
   ============================================================ */
.card-media img.switching { opacity: 0; transform: translate(-50%, -50%) scale(.94); }
.card-media img.foto-entra { opacity: 0; transform: translate(-50%, -50%) scale(1.07); }
.card-media img.foto-sale  { opacity: 0; transform: translate(-50%, -50%) scale(.95); }
/* La capa que se va no debe comerse el toque siguiente mientras se apaga. */
.card-media img.foto-sale, .pdp-shot img.foto-sale { pointer-events: none; }

/* Sombra de contacto: la elipse blanda bajo el producto. Es lo que convierte el zoom en
   "el equipo se despega de la superficie" — sin ella, crecer es solo crecer. Se aplana y
   se ensancha al levantarse, como haría una sombra real al alejarse el objeto. */
.card-media::after {
  content: ""; position: absolute; z-index: 0; left: 50%; bottom: 11%;
  width: 46%; height: 13px; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(60, 25, 10, .38), transparent);
  transform: translateX(-50%) scale(.7); opacity: 0;
  transition: opacity .34s var(--ease-out), transform .46s var(--ease-gentle);
  pointer-events: none;
}

/* ---------- Hover de escritorio: el disco de color de la categoría ----------
   Antes el hover era solo "sube 5px y la foto crece": correcto pero mudo, idéntico en las
   62 tarjetas. Ahora, al pasar el cursor, detrás del producto florece un disco con el
   color de marca de SU categoría (`--tint`, que pone cardHTML) — el mismo lenguaje que ya
   usa el banner de categoría, donde el equipo insignia posa sobre su disco tintado. Le da
   variedad real a la grilla sin meter un solo color fuera del sistema.

   Va en ::before y no en ::after porque entre elementos posicionados con z-index:auto
   manda el orden del DOM: ::before es el primer hijo, así que pinta DEBAJO de la foto;
   con ::after el disco habría tapado el producto.

   Este bloque va DESPUÉS de `.card:hover .card-media img` de arriba a propósito: misma
   especificidad, así que decide el orden de aparición — más arriba, la regla vieja
   ganaba y el zoom nuevo no se aplicaba nunca.

   Y todo detrás de (hover: hover): en táctil el :hover se queda pegado después del tap
   y la tarjeta quedaría encendida al volver atrás. */
@media (hover: hover) {
  .card-media::before {
    content: ""; position: absolute; z-index: 0;
    /* 152% no es un número al azar: el panel es cuadrado y el disco está centrado en
       (50%, 54%), así que la esquina más lejana queda a √(50² + 54²) ≈ 73.6% del ancho.
       Con radio 76% (152% / 2) el círculo la alcanza y el panel queda lleno. A 122% se
       quedaba corto y dejaba una muesca redondeada en las esquinas de arriba que se leía
       como un recorte mal hecho, no como una intención. */
    left: 50%; top: 54%; width: 152%; aspect-ratio: 1; border-radius: 50%;
    background: var(--tint, var(--cream-3));
    transform: translate(-50%, -50%) scale(.5); opacity: 0;
    transition: opacity .28s var(--ease-out), transform .52s var(--ease-gentle);
  }
  .card:hover .card-media::before,
  .card:focus-visible .card-media::before { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  /* Sin foto real no hay disco ni sombra: el placeholder "Foto en camino" ya trae su
     propio fondo pastel, y superponerle el disco deja dos rectángulos de color peleando.
     La marca `is-ph` la pone __meloImg al agotar la cadena de respaldo. */
  .card-media.is-ph::before, .card-media.is-ph::after { display: none; }

  /* El producto se LEVANTA: sube 9px reales y crece apenas un 5%. El desplazamiento va en
     píxeles y no en % (el % del `translate` se mide contra el propio tamaño de la imagen,
     que cambia con cada foto — por eso el intento anterior con -57% descuadraba unas fotos
     sí y otras no). Con la foto al 76% en reposo, un 1.05 la deja al 80% del panel: queda
     aire por los cuatro lados y no se recorta nunca. */
  .card:hover .card-media img,
  .card:focus-visible .card-media img { transform: translate(-50%, -50%) translateY(-9px) scale(1.05); }
  /* La sombra aparece y se ensancha a la vez que el equipo sube — es lo que vende que se
     despegó de la superficie en vez de solo agrandarse. */
  .card:hover .card-media::after,
  .card:focus-visible .card-media::after { opacity: 1; transform: translateX(-50%) scale(1); }

  /* El nombre toma el naranja de marca, NO el tinte: los 8 tintes están validados para
     contraste contra la foto del producto, no contra crema — el naranja sí. */
  .card:hover .card-name { color: var(--orange); }
  /* `.card.card` — especificidad doblada a propósito. `.reveal.in { transform: none }`
     está ~1000 líneas más abajo con la misma especificidad (0,2,0) y ganaba por orden de
     aparición, así que la tarjeta nunca se levantaba: solo cambiaba la sombra, y por eso
     el hover se sentía sordo. Medido con CSS.forcePseudoState, no a ojo. */
  .card.card:hover { transform: translateY(-6px); box-shadow: var(--sh-md), 0 22px 40px -26px rgba(80, 35, 15, .5); }
}
@media (prefers-reduced-motion: reduce) {
  .card-media::before, .card-media::after { transition: opacity .01s; }
  .card:hover .card-media img, .card:focus-visible .card-media img { transform: translate(-50%, -50%); }
  .card.card:hover { transform: none; }
}
.card-media .chip { position: absolute; top: .6rem; z-index: 2; }
.card-media .chip-badge { left: .6rem; }
.card-media .chip-off { right: .6rem; }

/* Sello de estado — la confianza es el argumento central de este mercado */
.card-state {
  position: absolute; left: .6rem; bottom: .6rem; z-index: 2;
  display: inline-flex; align-items: center; gap: .4em;
  font-size: .66rem; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
  padding: .34em .68em; border-radius: var(--r-pill);
  background: rgba(255, 254, 247, .93); color: var(--ink); box-shadow: var(--sh-sm);
}
.card-state::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--orange); }
.card-state.is-semi::before { background: var(--ink-faint); }
.swatches { display: flex; gap: .3rem; flex-wrap: wrap; }
.swatch {
  width: 18px; height: 18px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(0,0,0,.15);
  transition: transform .15s; position: relative;
}
.swatch:hover { transform: scale(1.15); }
.swatch.active { box-shadow: inset 0 0 0 1px rgba(0,0,0,.15), 0 0 0 2px var(--cream), 0 0 0 4px var(--orange); }
.swatches-lg .swatch { width: 26px; height: 26px; }
.card-body { padding: .8rem .9rem 1rem; display: flex; flex-direction: column; gap: .18rem; flex: 1; }
.card-kicker { font-size: .72rem; font-weight: 700; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .02em; }
/* Dos líneas fijas: un nombre corto y uno largo tienen que ocupar lo mismo, o el precio
   y los botones de tarjetas vecinas quedan a distinta altura. */
.card-name {
  font-weight: 800; font-size: 1rem; line-height: 1.2; color: var(--ink);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 2.4em;
}
/* Banda de variantes de alto reservado (ver optsRow en cardHTML) */
.card-opts { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; min-height: 26px; margin-top: .3rem; }
/* Bloque de precio de alto reservado: "Ahorras $X" y "Precio por confirmar" son
   opcionales, así que sin un mínimo las tarjetas se desalinean entre sí. */
.card-pricewrap { display: flex; flex-direction: column; min-height: 3.5em; justify-content: flex-start; }
.card-rating { font-size: .78rem; color: var(--ink-soft); display: flex; align-items: center; gap: .35rem; }
.stars { color: var(--orange); letter-spacing: -1px; }
.rating-n { color: var(--ink-faint); }
.gb-chips { display: flex; gap: .3rem; margin-top: .2rem; flex-wrap: wrap; }
.gb-chip { font-size: .74rem; font-weight: 700; padding: .2rem .55rem; border-radius: var(--r-pill); background: var(--cream-3); color: var(--ink-soft); transition: background .15s, color .15s; }
.gb-chip.active { background: var(--ink); color: var(--cream); }
.card-price { margin-top: .35rem; font-size: 1.12rem; color: var(--ink); font-weight: 500; }
.card-price strong { font-family: var(--font-body); font-weight: 800; font-size: 1.16rem; letter-spacing: -.01em; }
.card-price s { color: var(--ink-faint); font-size: .82rem; margin-right: .25rem; font-family: var(--font-body); }
.card-price.on-sale strong { color: var(--berry-deep); }
.card-save { font-size: .76rem; font-weight: 800; color: var(--berry-deep); margin-top: .1rem; display: inline-flex; align-items: center; gap: .3em; }
.card-save::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--berry); }
/* `hidden` pierde contra el display de la clase — hay que decirlo explícito */
.card-save[hidden] { display: none; }
/* Precio de referencia sin confirmar por el dueño — visible a propósito, para que no
   se publique un precio equivocado sin que nadie lo note */
.card-draft {
  display: inline-flex; align-items: center; gap: .35em; margin-top: .3rem;
  font-size: .68rem; font-weight: 800; letter-spacing: .02em; text-transform: uppercase;
  color: var(--ti-accesorios); background: var(--bg-mostaza); opacity: .95;
  padding: .24em .6em; border-radius: var(--r-pill); align-self: flex-start;
}
.card-draft::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }

/* ---------- "Precio por confirmar" (CONFIG.preciosPorConfirmar) ----------
   Ocupa el sitio del precio en tarjeta, ficha y combos. Va en mostaza como el sello
   `.card-draft` —es el mismo mensaje— pero **sin caja**: acá no es una etiqueta encima
   del precio, ES el precio, así que se comporta como texto y no como chip. Peso 800
   para que siga leyéndose como la línea importante de la tarjeta. */
.price-tbd {
  display: inline-flex; align-items: center; gap: .4em;
  font-family: var(--font-body); font-weight: 800; font-size: .98rem;
  letter-spacing: -.01em; color: var(--ink-soft);
}
.price-tbd::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto;
  background: var(--bg-mostaza); box-shadow: inset 0 0 0 1px rgba(0,0,0,.14);
}
/* En carrito, buscador y comparador el texto es corto ("Por confirmar") y compite con
   cifras que ya no están: se baja de tono para no gritar donde antes había un número. */
.cart-price.is-tbd, .cart-total.is-tbd strong, .search-item-price.is-tbd,
.cmp-pick-price.is-tbd, .cmp-price.is-tbd {
  color: var(--ink-soft); font-weight: 700; font-size: .84em; white-space: nowrap;
}
.card-actions { display: flex; gap: .4rem; margin-top: auto; padding-top: .7rem; }
/* min-width:0 obligatorio: por defecto los flex items no encogen bajo su contenido
   y en tarjeta de 171px (2 columnas a 390px) "Cotizar" se salía y quedaba recortado */
.card-actions .btn { flex: 1 1 0; min-width: 0; }
@media (max-width: 560px) {
  .card:not(.card-hero) .card-actions { gap: .35rem; }
  .card:not(.card-hero) .card-actions .btn { padding: .68em .5em; font-size: .82rem; }
}

/* ---------- Tarjeta destacada — rompe la retícula, da jerarquía al catálogo ---------- */
.card-hero { grid-column: span 2; }
.card-hero .card-media { aspect-ratio: 5 / 4; }
.card-hero .card-name { font-size: clamp(1.15rem, 3.4vw, 1.6rem); }
.card-hero .card-desc { font-size: .92rem; color: var(--ink-soft); line-height: 1.5; margin-top: .45rem; }
.card-hero .swatches { padding-inline: 0; }
.kicker-pick { color: var(--orange); }

.card-specs { display: grid; gap: .1rem; margin: .7rem 0 .3rem; }
.card-specs li {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  font-size: .82rem; padding: .34rem 0; border-bottom: 1px dashed var(--line);
}
.card-specs span { color: var(--ink-faint); white-space: nowrap; }
.card-specs strong { color: var(--ink); font-weight: 700; text-align: right; }

.card-trust {
  display: flex; flex-wrap: wrap; gap: .45rem 1.1rem;
  margin-top: .9rem; padding-top: .85rem; border-top: 1px solid var(--line);
}
.card-trust span { display: inline-flex; align-items: center; gap: .38em; font-size: .76rem; font-weight: 700; color: var(--ink-soft); }
.card-trust svg { width: 15px; height: 15px; flex: none; color: var(--orange); }

@media (min-width: 560px) {
  .card-hero { flex-direction: row; }
  .card-hero .card-media { width: 45%; flex: none; aspect-ratio: auto; }
  .card-hero .card-body { flex: 1; padding: clamp(1rem, 2.4vw, 1.5rem) clamp(1rem, 2.4vw, 1.6rem); }
}

/* ============================================================
   OFERTA DEL DÍA
   ============================================================ */
.deal-wrap { background: var(--ink); color: var(--cream); border-radius: var(--r-xl); overflow: hidden; }
.deal-card { display: grid; gap: 0; }
.deal-media { background: linear-gradient(150deg, var(--orange), var(--orange-deep)); display: grid; place-items: center; padding: 1.6rem; position: relative; min-height: 230px; }
.deal-media img { max-width: 72%; max-height: 240px; width: auto; height: auto; object-fit: contain; filter: drop-shadow(0 24px 30px rgba(0,0,0,.3)); }
.deal-info { padding: clamp(1.4rem, 5vw, 2.4rem); display: flex; flex-direction: column; gap: .6rem; align-items: flex-start; }
.deal-name { font-family: var(--font-body); font-weight: 800; font-size: clamp(1.6rem, 6vw, 2.4rem); line-height: 1.02; letter-spacing: -.02em; }
.deal-price { font-size: 1.3rem; }
.deal-price s { color: rgba(255,254,247,.5); font-size: .95rem; margin-right: .4rem; }
.deal-price strong { font-family: var(--font-body); font-weight: 800; color: var(--cream); font-size: 1.6rem; }
.countdown { display: flex; align-items: center; gap: .6rem; font-size: .9rem; color: rgba(255,254,247,.85); }
.count-box { font-family: var(--font-body); font-weight: 800; font-size: 1.2rem; letter-spacing: .04em; background: rgba(255,254,247,.14); padding: .25rem .6rem; border-radius: var(--r-sm); }
.deal-info .modal-actions { display: flex; gap: .6rem; flex-wrap: wrap; margin-top: .4rem; }
@media (min-width: 760px) { .deal-card { grid-template-columns: 1fr 1fr; } .deal-media { min-height: 360px; } .deal-media img { max-height: 380px; } }

/* ============================================================
   COMBOS
   ============================================================ */
.combos-grid { display: grid; gap: clamp(.9rem, 2.4vw, 1.2rem); grid-template-columns: 1fr; }
@media (min-width: 640px) { .combos-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .combos-grid { grid-template-columns: repeat(3, 1fr); } }

/* ---- Tarjeta de combo (rediseño ago 2026) ----
   Antes: ficha blanca con una lista de miniaturas de 30px — el producto no se veía
   y las 17 tarjetas eran indistinguibles entre sí. Ahora manda la foto: un escenario
   tintado con el combo en abanico, y al pasar el mouse el abanico se ABRE.
   El tinte lo hereda de la categoría del producto principal (`comboTint()` en melo.js),
   así que cada combo llega con el color con el que su equipo se ve bien. */
.combo-card {
  background: var(--cream); border: 1px solid var(--line); border-radius: var(--r-lg);
  display: flex; flex-direction: column; box-shadow: var(--sh-sm); overflow: hidden;
  transition: transform .3s var(--ease-spring), box-shadow .3s; min-width: 0;
}
.combo-card.combo-card:hover { transform: translateY(-6px); box-shadow: var(--sh-lg, var(--sh-md)); }

.combo-stage {
  position: relative; aspect-ratio: 16 / 10; background: var(--combo-tint, var(--cream-3));
  overflow: hidden; isolation: isolate;
}
/* halo suave detrás del abanico: despega los productos del color plano */
.combo-stage::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(58% 62% at 50% 58%, rgba(255, 254, 247, .38), transparent 70%);
}
.combo-badge {
  position: absolute; top: .6rem; right: .6rem; z-index: 4;
  font-size: .7rem; font-weight: 800; letter-spacing: .02em; text-transform: uppercase;
  padding: .26rem .6rem; border-radius: var(--r-pill);
  background: var(--ink); color: var(--cream);
}
.combo-stage .combo-emoji {
  position: absolute; top: .5rem; left: .65rem; z-index: 4;
  font-size: 1.5rem; line-height: 1;
  filter: drop-shadow(0 2px 4px rgba(36, 22, 17, .22));
}
.combo-fan { position: absolute; inset: 0; }
.combo-layer {
  position: absolute; left: 50%; top: 52%; width: 62%; height: 78%;
  z-index: var(--z, 1);
  transform: translate(-50%, -50%) translateX(var(--x)) rotate(var(--r)) scale(var(--s));
  transition: transform .42s var(--ease-spring);
}
.combo-layer.is-hero { z-index: 3; }
/* capa cuya cadena de imagen terminó en placeholder: fuera del abanico */
.combo-layer.is-ph { display: none; }
.combo-layer-img,
.combo-layer img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* el abanico se abre en hover — solo donde hay puntero de verdad */
@media (hover: hover) {
  .combo-card:hover .combo-layer {
    transform: translate(-50%, -50%) translateX(calc(var(--x) + var(--d))) rotate(calc(var(--r) * 1.5)) scale(var(--s));
  }
  .combo-card:hover .combo-layer.is-hero {
    transform: translate(-50%, -50%) translateY(-3%) scale(calc(var(--s) * 1.05));
  }
}

.combo-body { padding: 1.05rem 1.15rem 1.2rem; display: flex; flex-direction: column; gap: .45rem; flex: 1; }
.combo-card h3 {
  font-family: var(--font-body); font-weight: 800; font-size: 1.2rem;
  line-height: 1.08; letter-spacing: -.02em; color: var(--ink);
}
.combo-desc { font-size: .85rem; color: var(--ink-soft); line-height: 1.45; }
/* la lista pasa de columna con miniaturas a chips compactos: ya se ven arriba */
.combo-items { display: flex; flex-wrap: wrap; gap: .3rem; margin: .15rem 0 .1rem; padding: 0; list-style: none; }
.combo-items li {
  font-size: .74rem; font-weight: 700; color: var(--ink-soft);
  background: var(--cream-2); border: 1px solid var(--line);
  padding: .2rem .52rem; border-radius: var(--r-pill); white-space: nowrap;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}
.combo-price { margin-top: auto; padding-top: .3rem; font-size: 1.05rem; }
.combo-price s { color: var(--ink-faint); font-size: .82rem; margin-right: .3rem; }
.combo-price strong { font-family: var(--font-body); font-weight: 800; color: var(--ink); font-size: 1.3rem; letter-spacing: -.01em; }
.combo-save { font-size: .82rem; font-weight: 800; color: var(--berry-deep); }
.combo-card .card-actions { margin-top: .5rem; }

@media (prefers-reduced-motion: reduce) {
  .combo-layer { transition: none; }
  .combo-card.combo-card:hover { transform: none; }
}

/* ============================================================
   CÓMO COMPRAR + PAGOS
   ============================================================ */
.steps { display: grid; gap: 1rem; grid-template-columns: 1fr; counter-reset: step; }
@media (min-width: 640px) { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .steps { grid-template-columns: repeat(4, 1fr); } }
.step {
  position: relative; background: var(--cream); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 1.4rem 1.2rem 1.2rem; box-shadow: var(--sh-sm);
}
.step::before {
  counter-increment: step; content: counter(step);
  font-family: var(--font-display); font-size: 2.4rem; color: var(--orange); line-height: 1;
  display: block; margin-bottom: .4rem;
}
.step-emoji { font-size: 1.5rem; }
.step h3 { font-weight: 800; font-size: 1.05rem; margin: .3rem 0 .25rem; color: var(--ink); }
.step p { font-size: .9rem; color: var(--ink-soft); }
.pays { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.6rem; align-items: center; }
.pay-badge {
  display: inline-flex; align-items: center; gap: .45rem; font-weight: 700; font-size: .9rem;
  background: var(--cream); border: 1px solid var(--line); border-radius: var(--r-pill); padding: .5rem .9rem;
  color: var(--ink); box-shadow: var(--sh-sm);
}
.pay-badge .dot { width: 10px; height: 10px; border-radius: 50%; }

/* ============================================================
   TESTIMONIOS
   ============================================================ */
.quotes { display: grid; gap: 1rem; grid-template-columns: 1fr; }
@media (min-width: 640px) { .quotes { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .quotes { grid-template-columns: repeat(4, 1fr); } }
.quote { background: var(--cream); border: 1px solid var(--line); border-radius: var(--r-lg); padding: 1.3rem; display: flex; flex-direction: column; gap: .6rem; box-shadow: var(--sh-sm); min-width: 0; }
.quote .stars { font-size: 1rem; }
.quote blockquote { margin: 0; font-size: .95rem; color: var(--ink); line-height: 1.5; }
.quote figcaption { font-size: .84rem; color: var(--ink-soft); font-weight: 700; }

/* ============================================================
   FOOTER
   ============================================================ */
/* Footer en Carbón, no naranja: el hero ya es un bloque naranja grande y dos slabs
   del mismo color aplastaban la página. Carbón es de los 8 fondos del brand kit. */
.site-footer { background: var(--bg-carbon); color: var(--cream); padding-block: clamp(2.6rem, 7vw, 4rem); margin: var(--frame); border-radius: var(--r-hero); position: relative; overflow: hidden; }
.site-footer .wordmark .dot { color: var(--orange); }
.site-footer a:hover { color: var(--orange); }
.footer-top { display: grid; gap: 2rem; grid-template-columns: 1fr; position: relative; z-index: 2; }
@media (min-width: 720px) { .footer-top { grid-template-columns: 1.4fr 1fr 1fr; } .site-footer { padding-bottom: clamp(2.6rem, 7vw, 4rem); } }
.footer-brand .wordmark { font-family: var(--font-display); text-transform: lowercase; font-size: 2rem; }
.footer-brand p { color: rgba(255,254,247,.9); max-width: 34ch; margin-top: .6rem; font-size: .95rem; }
.footer-socials { display: flex; gap: .6rem; margin-top: 1rem; }
.footer-socials a { width: 44px; height: 44px; border-radius: var(--r-pill); background: rgba(255,254,247,.14); display: grid; place-items: center; transition: background .2s, transform .2s; }
.footer-socials a:hover { background: rgba(255,254,247,.26); transform: translateY(-2px); }
.footer-socials svg { width: 22px; height: 22px; }
.footer-col h4 { font-family: var(--font-body); font-weight: 800; text-transform: uppercase; font-size: .92rem; margin-bottom: .8rem; letter-spacing: .1em; }
.footer-col a { display: block; color: rgba(255,254,247,.9); padding: .3rem 0; font-size: .95rem; transition: opacity .2s, padding-left .2s; }
.footer-col a:hover { opacity: 1; padding-left: .3rem; }
.footer-bottom { margin-top: 2.4rem; padding-top: 1.4rem; border-top: 1px solid rgba(255,254,247,.22); display: flex; flex-wrap: wrap; gap: .6rem 1.4rem; justify-content: space-between; font-size: .82rem; color: rgba(255,254,247,.8); position: relative; z-index: 2; }

/* ============================================================
   BARRA INFERIOR MÓVIL
   ============================================================ */
.bottom-bar {
  position: fixed; inset: auto 0 0 0; z-index: 70; height: var(--bottombar-h);
  background: rgba(255,254,247,.92); backdrop-filter: saturate(1.2) blur(14px);
  border-top: 1px solid var(--line);
  display: grid; grid-template-columns: repeat(5, 1fr); align-items: center;
}
.bottom-bar a, .bottom-bar button {
  display: flex; flex-direction: column; align-items: center; gap: 2px; justify-content: center;
  font-size: .64rem; font-weight: 700; color: var(--ink-soft); height: 100%; position: relative;
}
.bottom-bar svg { width: 22px; height: 22px; }
.bottom-bar .bb-wa { color: var(--wa-deep); }
.bottom-bar .bb-cart-badge {
  position: absolute; top: 6px; right: 50%; margin-right: -22px; min-width: 16px; height: 16px; padding: 0 3px;
  background: var(--orange); color: var(--cream); font-size: .62rem; font-weight: 800; border-radius: var(--r-pill);
  display: none; align-items: center; justify-content: center; line-height: 1;
}
.bottom-bar .bb-cart-badge.show { display: inline-flex; }
body { padding-bottom: var(--bottombar-h); }
@media (min-width: 960px) { .bottom-bar { display: none; } body { padding-bottom: 0; } }

/* ============================================================
   BUSCADOR (overlay)
   ============================================================ */
/* ---- Liquid Glass ---- */
.search-overlay {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(36,22,17,.26);
  backdrop-filter: blur(16px) saturate(1.4); -webkit-backdrop-filter: blur(16px) saturate(1.4);
  opacity: 0; visibility: hidden; transition: opacity .3s var(--ease-out);
  display: flex; justify-content: center; align-items: flex-start;
  padding: clamp(1rem, 8vw, 6rem) var(--pad);
}
.search-overlay.open { opacity: 1; visibility: visible; }
.search-panel {
  position: relative; width: 100%; max-width: 640px; border-radius: 28px; overflow: hidden;
  background: linear-gradient(158deg, rgba(255,254,247,.74), rgba(255,246,232,.58));
  backdrop-filter: blur(30px) saturate(1.8) brightness(1.05);
  -webkit-backdrop-filter: blur(30px) saturate(1.8) brightness(1.05);
  border: 1px solid rgba(255,255,255,.55);
  box-shadow: 0 44px 100px -34px rgba(60,25,10,.6), inset 0 1px 0 rgba(255,255,255,.9), inset 0 -1px 0 rgba(255,255,255,.14);
  transform: translateY(-18px) scale(.97); transition: transform .42s var(--ease-out), opacity .3s;
  display: flex; flex-direction: column; max-height: 78vh;
}
/* brillo especular tipo cristal líquido */
.search-panel::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit; z-index: 4;
  background: linear-gradient(152deg, rgba(255,255,255,.65) 0%, rgba(255,255,255,0) 34%);
  mix-blend-mode: screen;
}
.search-overlay.open .search-panel { transform: translateY(0) scale(1); }
.search-head { position: relative; z-index: 5; display: flex; align-items: center; gap: .6rem; padding: 1rem 1.1rem; border-bottom: 1px solid rgba(255,255,255,.4); }
.search-head svg { width: 22px; height: 22px; color: var(--orange); flex-shrink: 0; }
.search-head input { flex: 1; border: none; outline: none; background: none; font-size: 1.12rem; font-weight: 600; min-width: 0; color: var(--ink); }
.search-head input::placeholder { color: var(--ink-faint); }
.search-results { position: relative; z-index: 5; overflow-y: auto; padding: .5rem; }
.search-item { display: flex; align-items: center; gap: .8rem; padding: .6rem; border-radius: var(--r-md); width: 100%; text-align: left; transition: background .15s, transform .15s; }
.search-item:hover { background: rgba(255,255,255,.55); transform: translateX(3px); }
.search-item-thumb { width: 46px; height: 46px; border-radius: 10px; background: var(--cream-3); display: grid; place-items: center; overflow: hidden; flex-shrink: 0; }
.search-item-thumb img { width: 82%; height: 82%; object-fit: contain; }
.search-item-info { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.search-item-name { font-weight: 700; font-size: .95rem; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.search-item-cat { font-size: .78rem; color: var(--ink-faint); }
.search-item-price { font-family: var(--font-body); font-weight: 800; font-size: 1rem; color: var(--orange); flex-shrink: 0; }
.search-empty { padding: 2rem 1rem; text-align: center; color: var(--ink-soft); }
.search-empty a { color: var(--orange); font-weight: 700; }

/* ============================================================
   CHROME (inyectado por JS): drawer, modal, toasts, WA flotante
   ============================================================ */
/* Flotante WA: solo en desktop — en cel la barra inferior ya tiene WhatsApp (evita duplicado y que tape contenido) */
.wa-float {
  position: fixed; z-index: 65; right: 22px; bottom: 22px;
  width: 56px; height: 56px; border-radius: var(--r-pill); background: var(--wa); color: #fff;
  display: none; place-items: center; box-shadow: 0 14px 34px -10px rgba(37,211,102,.65);
  transition: transform .2s, box-shadow .2s; animation: wa-pulse 3.5s ease-in-out infinite;
}
.wa-float:hover { transform: scale(1.08); }
@keyframes wa-pulse { 0%,100% { box-shadow: 0 14px 34px -10px rgba(37,211,102,.65), 0 0 0 0 rgba(37,211,102,.4);} 50% { box-shadow: 0 14px 34px -10px rgba(37,211,102,.65), 0 0 0 12px rgba(37,211,102,0);} }
@media (min-width: 960px) { .wa-float { display: grid; } }
/* Segundo anillo, más lento y desfasado: se lee como "está vivo" y no como parpadeo. */
.wa-float-eco {
  position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  border: 2px solid rgba(37,211,102,.55); animation: wa-eco-anillo 3.5s var(--ease-gentle) .9s infinite;
}
@keyframes wa-eco-anillo {
  0% { transform: scale(1); opacity: .7; }
  70%, 100% { transform: scale(1.65); opacity: 0; }
}
.wa-float-ic { position: relative; animation: wa-guino 5.2s var(--ease-spring) infinite; transform-origin: 50% 60%; }
/* Globito "Escríbenos": aparece al acercar el mouse, no ocupa espacio si no. */
.wa-float-globo {
  position: absolute; right: calc(100% + 12px); top: 50%; transform: translateY(-50%) translateX(6px);
  white-space: nowrap; font-size: .84rem; font-weight: 800; color: var(--ink);
  background: var(--cream); padding: .42rem .8rem; border-radius: var(--r-pill);
  box-shadow: var(--sh-md); opacity: 0; pointer-events: none;
  transition: opacity var(--t-fast), transform var(--t-fast) var(--ease-spring);
}
.wa-float:hover .wa-float-globo, .wa-float:focus-visible .wa-float-globo { opacity: 1; transform: translateY(-50%) translateX(0); }

.drawer-backdrop { position: fixed; inset: 0; z-index: 100; background: rgba(36,22,17,.5); opacity: 0; transition: opacity .3s; }
.drawer-backdrop.show { opacity: 1; }
.drawer {
  position: fixed; inset: 0 0 0 auto; z-index: 101; width: min(420px, 92vw); background: var(--cream);
  transform: translateX(100%); transition: transform .3s var(--ease-out); display: flex; flex-direction: column; box-shadow: var(--sh-lg);
}
.drawer.open { transform: translateX(0); }
.drawer-head { display: flex; align-items: center; justify-content: space-between; padding: 1.1rem 1.2rem; border-bottom: 1px solid var(--line); }
.drawer-title { font-family: var(--font-body); font-weight: 800; font-size: 1.2rem; letter-spacing: -.01em; }
.drawer .icon-btn { color: var(--ink); width: 38px; height: 38px; }
.drawer .icon-btn:hover { background: var(--cream-3); }
.drawer-body { flex: 1; overflow-y: auto; padding: 1rem 1.2rem; }
.drawer-foot { padding: 1.1rem 1.2rem; border-top: 1px solid var(--line); }
.cart-line { display: grid; grid-template-columns: 56px 1fr auto; gap: .7rem; align-items: center; padding: .7rem 0; border-bottom: 1px solid var(--line); }
.cart-thumb { width: 56px; height: 56px; border-radius: 12px; background: var(--cream-3); display: grid; place-items: center; overflow: hidden; }
.cart-thumb img { width: 82%; height: 82%; object-fit: contain; }
.combo-thumb { font-size: 1.7rem; }
.cart-info { min-width: 0; }
.cart-info strong { font-size: .92rem; color: var(--ink); display: block; }
.cart-meta { font-size: .76rem; color: var(--ink-soft); }
.cart-save { font-size: .74rem; color: var(--berry-deep); font-weight: 800; display: block; }
.cart-side { text-align: right; }
.cart-price { font-weight: 800; font-size: .92rem; color: var(--ink); display: block; }
.qty { display: inline-flex; align-items: center; gap: .5rem; margin-top: .3rem; }
.qty button { width: 26px; height: 26px; border-radius: 8px; background: var(--cream-3); font-weight: 800; color: var(--ink); font-size: 1rem; line-height: 1; }
.qty button:hover { background: var(--orange); color: var(--cream); }
.cart-empty { text-align: center; padding: 3rem 1rem; color: var(--ink-soft); }
.cart-empty-emoji { font-size: 3rem; margin-bottom: .5rem; }
.cart-upsell { margin-top: 1rem; padding-top: 1rem; }
.cart-upsell-title { font-weight: 800; font-size: .9rem; margin-bottom: .6rem; }
.cart-upsell-item { display: flex; align-items: center; gap: .6rem; width: 100%; padding: .5rem; border-radius: var(--r-md); background: var(--cream-3); margin-bottom: .4rem; transition: transform .15s; }
.cart-upsell-item:hover { transform: translateX(3px); }
.cart-upsell-thumb { width: 40px; height: 40px; border-radius: 8px; overflow: hidden; display: grid; place-items: center; background: var(--cream); }
.cart-upsell-thumb img { width: 82%; height: 82%; object-fit: contain; }
.cart-upsell-name { flex: 1; font-size: .84rem; font-weight: 700; text-align: left; }
.cart-upsell-price { font-weight: 800; color: var(--orange); font-size: .84rem; }
.cart-total { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: .8rem; }
.cart-total strong { font-family: var(--font-body); font-weight: 800; font-size: 1.4rem; letter-spacing: -.01em; }
.cart-note { font-size: .76rem; color: var(--ink-soft); text-align: center; margin-top: .7rem; }

/* Botonera de la tarjeta de Oferta del día (antes vivía en el modal de producto,
   retirado en v11 a favor de producto.html — ver bindDeal() en melo.js) */
.deal-actions { display: flex; gap: .6rem; flex-wrap: wrap; margin-top: .5rem; }
.deal-actions .btn { flex: 1; min-width: 150px; }

/* Toasts (prueba social) */
.toasts { position: fixed; z-index: 66; left: 16px; bottom: calc(var(--bottombar-h) + 14px); display: flex; flex-direction: column; gap: .6rem; max-width: 300px; }
@media (min-width: 960px) { .toasts { bottom: 22px; } }
.toast { display: flex; align-items: center; gap: .7rem; background: var(--cream); border: 1px solid var(--line); border-radius: var(--r-md); padding: .6rem .7rem; box-shadow: var(--sh-md); text-align: left; transform: translateX(-120%); opacity: 0; transition: transform .4s var(--ease-out), opacity .4s; }
.toast.show { transform: translateX(0); opacity: 1; }
.toast-thumb { width: 40px; height: 40px; border-radius: 8px; background: var(--cream-3); display: grid; place-items: center; overflow: hidden; flex-shrink: 0; }
.toast-thumb img { width: 82%; height: 82%; object-fit: contain; }
.toast-text { font-size: .78rem; color: var(--ink); line-height: 1.3; }
.toast-text small { display: block; color: var(--ink-faint); font-size: .68rem; margin-top: .1rem; }

.no-results { grid-column: 1 / -1; text-align: center; color: var(--ink-soft); padding: 2rem; }
.no-results a { color: var(--orange); font-weight: 700; }

/* ============================================================
   PÁGINAS DE CATEGORÍA — hero, toolbar, cond-tabs, ecosistema
   ============================================================ */
.cat-hero {
  position: relative; overflow: hidden; background: var(--orange); color: var(--cream);
  margin: var(--frame); margin-top: calc(var(--header-h) + var(--frame));
  border-radius: var(--r-hero); box-shadow: var(--sh-lg);
  padding: clamp(1.9rem, 6vw, 3rem) 0 clamp(1.7rem, 5vw, 2.6rem);
}
.cat-hero::before {
  content: ""; position: absolute; inset: -30% -10% auto -10%; height: 90%;
  background: radial-gradient(55% 80% at 25% 0%, rgba(255,120,80,.5), transparent 70%); pointer-events: none;
}
/* Rayas diagonales muy tenues: le quitan lo "plano" al naranja sin meter otro color.
   El dueño lo dijo así: «se ven todo muy blanco con naranja, no hay contraste». */
.cat-hero::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .5;
  background: repeating-linear-gradient(115deg,
    rgba(255,254,247,.055) 0 2px, transparent 2px 26px);
  -webkit-mask-image: linear-gradient(200deg, #000 10%, transparent 62%);
          mask-image: linear-gradient(200deg, #000 10%, transparent 62%);
}
.cat-hero .wrap { position: relative; z-index: 2; }

/* ---- Marca de agua: el sello de Melo Tech en vez de un ícono genérico ----
   El dueño pidió «mejor el propio logo de la marca pero ubicado diferente».
   Son dos capas de identidad propia: el sello circular (el mismo del home,
   girando) y el wordmark gigante desbordando por abajo. Ambas decorativas y
   `aria-hidden`, así que no ensucian el lector de pantalla. */
.cat-hero-mark {
  position: absolute; z-index: 1; pointer-events: none;
  top: clamp(-18px, -1.4vw, -6px); right: clamp(-26px, -2vw, -10px);
  width: clamp(140px, 22vw, 220px); aspect-ratio: 1;
  color: rgba(255, 254, 247, .32);
}
.cat-hero-seal { width: 100%; height: 100%; animation: seal-spin 22s linear infinite; }
.cat-hero-seal text { font-family: var(--font-display); font-size: 7.4px; letter-spacing: .5px; fill: currentColor; }
.cat-hero-wm {
  position: absolute; z-index: 0; pointer-events: none; user-select: none;
  /* Desborda por abajo a propósito: solo se ve la mitad de arriba de las letras,
     que es lo que la hace leer como marca de agua y no como un título más. */
  left: clamp(-10px, -1vw, 0px); bottom: clamp(-72px, -5.6vw, -34px);
  font-family: var(--font-display); text-transform: lowercase;
  font-size: clamp(4.5rem, 15vw, 10rem); line-height: .78;
  color: rgba(255, 254, 247, .085); letter-spacing: -.03em;
}
.cat-hero-wm i { font-style: normal; color: rgba(255, 254, 247, .17); }
@media (max-width: 819px) {
  /* En móvil el wordmark competía con el texto: se deja solo el sello. */
  .cat-hero-wm { display: none; }
}
/* Banner en dos columnas: copy a la izquierda, equipo insignia a la derecha.
   En móvil se apila y la foto va primero — es lo que vende. */
.cat-hero-in { display: grid; gap: clamp(1.2rem, 4vw, 2.5rem); align-items: center; }
.cat-hero-copy { min-width: 0; }
@media (min-width: 820px) {
  .cat-hero-in { grid-template-columns: minmax(0, 1fr) minmax(0, .82fr); }
}

/* Chips de confianza + conteo real de equipos */
.cat-hero-chips { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.1rem; list-style: none; }
.cat-hero-chips[hidden] { display: none; }
.cat-chip {
  display: inline-flex; align-items: center; gap: .4em;
  font-size: .82rem; font-weight: 800; letter-spacing: .01em;
  color: var(--cream); background: rgba(38,16,8,.22);
  border: 1px solid rgba(255,254,247,.4); border-radius: var(--r-pill);
  padding: .44rem .9rem; backdrop-filter: blur(3px);
}
.cat-chip svg { width: 14px; height: 14px; flex: none; opacity: .95; }
.cat-chip.is-count { background: var(--cream); color: var(--orange); border-color: transparent; }
.cat-chip.is-count b { font-weight: 800; }

/* El equipo insignia sobre un disco del color de marca de su categoría (--cat-tint),
   que es el que se eligió por contraste con esa misma foto. */
.cat-hero-shot {
  position: relative; display: grid; place-items: center;
  min-height: clamp(240px, 40vw, 360px); max-width: 460px; margin-inline: auto; width: 100%;
}
.cat-hero-shot[hidden] { display: none; }
.cat-hero-disc {
  position: absolute; width: clamp(190px, 30vw, 300px); aspect-ratio: 1; border-radius: 50%;
  background: var(--cat-tint, var(--bg-mostaza));
  box-shadow: 0 30px 70px -30px rgba(60,20,5,.55);
}
.cat-hero-disc::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  background: radial-gradient(60% 60% at 50% 30%, rgba(255,255,255,.4), transparent 70%);
}
/* Se dimensiona por ALTO, no por ancho: las fotos de producto son verticales y al
   fijarles el ancho el equipo se desbordaba muchísimo del disco. */
.cat-hero-shot img {
  position: relative; z-index: 2; height: clamp(215px, 34vw, 330px); width: auto;
  max-width: 82%; object-fit: contain; filter: drop-shadow(0 26px 34px rgba(40,12,4,.42));
  animation: cat-float 6s var(--ease-gentle, ease-in-out) infinite;
}
.cat-hero-tag {
  position: relative; z-index: 3; align-self: end; justify-self: center;
  margin-bottom: -.2rem; font-size: .8rem; font-weight: 800; color: var(--ink);
  background: var(--cream); border-radius: var(--r-pill); padding: .34rem .8rem;
  box-shadow: var(--sh-sm); white-space: nowrap;
}
@keyframes cat-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-12px); } }
/* El título ya no es texto crema sobre naranja (3,6:1 y se leía apagado): va en una
   PLACA CREMA con letras naranja, el mismo gesto que "CALI" en el home. Es el ADN del
   logo invertido, da un borde duro contra el fondo y sube muchísimo el contraste. */
.cat-hero h1 {
  font-family: var(--font-display); text-transform: uppercase; font-weight: 400;
  font-size: clamp(2.6rem, 12vw, 5.5rem); line-height: .9; letter-spacing: -.02em; color: var(--cream);
  margin-top: .1rem;
}
.cat-plate {
  display: inline-block; background: var(--cream); color: var(--orange);
  border-radius: .1em; padding: .06em .16em .08em; line-height: 1;
  box-shadow: 0 .05em 0 rgba(120,40,20,.18), var(--sh-md);
  transform: rotate(-1.4deg); transform-origin: left center;
  animation: cat-plate-in .7s var(--ease-spring) both;
}
@keyframes cat-plate-in {
  from { transform: rotate(-1.4deg) translateY(.32em) scale(.97); opacity: 0; }
  to   { transform: rotate(-1.4deg) translateY(0) scale(1); opacity: 1; }
}
.cat-hero p { max-width: 52ch; color: rgba(255,254,247,.94); margin-top: .9rem; font-size: clamp(1rem, 2.8vw, 1.15rem); }
.cat-hero-crumbs { font-size: .85rem; font-weight: 700; color: rgba(255,254,247,.85); margin-bottom: .8rem; }
.cat-hero-crumbs a { text-decoration: underline; text-underline-offset: 2px; }

.cat-tools { padding-top: clamp(1.4rem, 4vw, 2rem); }
/* ---------- Barra de marcas: sub-navegación DENTRO de la página de categoría ----------
   El corte por marca es más grueso que nuevo/seminuevo, así que va arriba de todo.
   No navega a otra página: filtra la misma grilla y deja `?marca=` en la URL.
   `--tint`/`--tink` los pone renderBrandBar() por marca desde BRANDS (data.js). */
.brand-bar { margin-bottom: 1rem; }
.bb-track {
  display: flex; gap: .5rem; padding-block: .15rem .4rem;
  /* overflow-y EXPLÍCITO: dejado en `visible` el CSS lo computa a `auto` y el riel se
     traga la rueda del mouse — el mismo bug que tuvo `.rail` en v12. */
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x proximity; scrollbar-width: none; -ms-overflow-style: none;
}
.bb-track::-webkit-scrollbar { display: none; }
.bb-pill {
  flex: 0 0 auto; scroll-snap-align: start;
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .58rem 1.05rem; border-radius: var(--r-pill);
  background: var(--cream-2); color: var(--ink-soft);
  border: 1px solid var(--line); font-weight: 800; font-size: .95rem; white-space: nowrap;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast),
              transform var(--t-fast) var(--ease-spring);
}
.bb-pill:hover { transform: translateY(-2px); }
.bb-dot {
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--tint, var(--orange)); box-shadow: inset 0 0 0 1px rgba(0,0,0,.16);
}
.bb-n { font-size: .74rem; font-weight: 800; opacity: .62; }
.bb-pill.active {
  background: var(--tint, var(--orange)); color: var(--tink, var(--cream)); border-color: transparent;
}
.bb-pill.active .bb-dot { background: currentColor; opacity: .5; box-shadow: none; }
.bb-pill.active .bb-n { opacity: .82; }
.bb-blurb {
  margin: .75rem 0 0; padding-left: .75rem; font-size: .95rem; color: var(--ink-soft);
  border-left: 3px solid var(--tint, var(--orange));
}

/* ---------- Grilla agrupada por marca ----------
   `.grid` normal reparte `grid-auto-rows: 1fr` para que todas las tarjetas midan igual;
   un encabezado a todo el ancho DENTRO de esa grilla se estiraría al alto de una fila
   entera de tarjetas. Por eso al agrupar el contenedor pasa a bloque y cada marca lleva
   su propia `.grid` anidada — la simetría se conserva dentro del grupo, que es donde el
   ojo la compara. */
.grid.is-grouped { display: block; }
.brand-group + .brand-group { margin-top: clamp(1.7rem, 4.5vw, 2.6rem); }
.brand-sep {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  margin-bottom: .9rem; padding-bottom: .55rem; border-bottom: 1px solid var(--line);
}
.bs-dot {
  width: 15px; height: 15px; border-radius: 50%; flex: 0 0 auto;
  background: var(--tint); box-shadow: inset 0 0 0 1px rgba(0,0,0,.16);
}
/* Peace Sans (display) — vale porque es un nombre de marca, corto y grande, igual que
   los nombres de categoría. OJO: la fuente NO trae acentos; si algún día entra una
   marca con tilde hay que pasar este nombre a --font-body. */
.bs-name { font-family: var(--font-display); font-size: clamp(1.15rem, 3.4vw, 1.5rem); line-height: 1; margin: 0; }
.bs-tag { font-size: .9rem; color: var(--ink-soft); font-weight: 600; }
.bs-n { margin-left: auto; font-size: .78rem; font-weight: 800; color: var(--ink-soft); opacity: .8; }

.cond-tabs { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: 1rem; }
.cond-tab {
  display: inline-flex; align-items: center; gap: .4rem; font-weight: 700; font-size: .9rem;
  padding: .5rem .95rem; border-radius: var(--r-pill); background: var(--cream-2); color: var(--ink-soft);
  border: 1px solid var(--line); transition: background .18s, color .18s, border-color .18s;
}
.cond-tab span { font-size: .74rem; opacity: .7; font-weight: 800; }
.cond-tab.active { background: var(--orange); color: var(--cream); border-color: var(--orange); }
.cond-tab.active span { opacity: .85; }
.toolbar { display: flex; gap: .7rem; flex-wrap: wrap; align-items: center; margin-bottom: 1.4rem; }
.search-wrap { flex: 1 1 220px; min-width: 170px; position: relative; }
.search-wrap::before {
  content: ""; position: absolute; left: 1rem; top: 50%; transform: translateY(-50%);
  width: 18px; height: 18px; pointer-events: none; opacity: .5;
  background: no-repeat center / contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236E574B' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.2-3.2'/%3E%3C/svg%3E");
}
.search-wrap input {
  width: 100%; padding: .72rem 1rem .72rem 2.7rem; border-radius: var(--r-pill); border: 1px solid var(--line);
  background: var(--cream); outline: none; font-weight: 500; transition: border-color .18s, box-shadow .18s;
}
.search-wrap input:focus { border-color: var(--orange); box-shadow: 0 0 0 3px rgba(255,61,27,.14); }
.toolbar-count { font-weight: 700; font-size: .86rem; color: var(--ink-soft); white-space: nowrap; padding-inline: .2rem; }
.toolbar select {
  appearance: none; -webkit-appearance: none;
  padding: .72rem 2.5rem .72rem 1.1rem; border-radius: var(--r-pill); border: 1px solid var(--line);
  background: var(--cream) no-repeat right 1rem center / 14px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23241611' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  font-weight: 700; font-size: .92rem; color: var(--ink); cursor: pointer; transition: border-color .18s, box-shadow .18s;
}
.toolbar select:hover { border-color: var(--line-2); }
.toolbar select:focus { border-color: var(--orange); outline: none; box-shadow: 0 0 0 3px rgba(255,61,27,.14); }

/* ============================================================
   FILTROS FACETADOS (categorías / ofertas) — estilo artez
   ============================================================ */
.filter-btn {
  display: inline-flex; align-items: center; gap: .5rem; font-weight: 800; font-size: .92rem;
  padding: .72rem 1.1rem; border-radius: var(--r-pill); border: 1px solid var(--line);
  background: var(--cream); color: var(--ink); box-shadow: var(--sh-sm);
  transition: border-color .18s, box-shadow .18s; white-space: nowrap;
}
.filter-btn:hover { border-color: var(--line-2); box-shadow: var(--sh-md); }
.filter-btn svg { width: 18px; height: 18px; }
.filter-btn .fb-count {
  min-width: 20px; height: 20px; padding: 0 5px; display: none; align-items: center; justify-content: center;
  background: var(--orange); color: var(--cream); border-radius: var(--r-pill); font-size: .72rem; font-weight: 800; line-height: 1;
}
.filter-btn.has-active { border-color: var(--orange); color: var(--orange); }
.filter-btn.has-active .fb-count { display: inline-flex; }

/* Chips de filtros activos (encima de la grilla) */
.filter-chips { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 1.2rem; align-items: center; }
.filter-chips:empty { display: none; }
.filter-chip {
  display: inline-flex; align-items: center; gap: .45rem; font-weight: 700; font-size: .82rem;
  padding: .34rem .34rem .34rem .8rem; border-radius: var(--r-pill);
  background: var(--cream); color: var(--ink); border: 1px solid var(--line-2); box-shadow: var(--sh-sm);
}
.filter-chip .fc-sw { width: 12px; height: 12px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(0,0,0,.15); }
.filter-chip button {
  width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center;
  background: var(--cream-3); color: var(--ink-soft); font-size: .82rem; line-height: 1; transition: background .15s, color .15s;
}
.filter-chip button:hover { background: var(--berry); color: #fff; }
.filter-clear-all { background: none; border: none; color: var(--orange); font-weight: 800; font-size: .82rem; cursor: pointer; padding: .34rem .5rem; }
.filter-clear-all:hover { text-decoration: underline; }

/* Panel/drawer de filtros (izquierda) */
.filter-drawer-backdrop { position: fixed; inset: 0; z-index: 100; background: rgba(36,22,17,.5); opacity: 0; transition: opacity .3s; }
.filter-drawer-backdrop.show { opacity: 1; }
.filter-drawer {
  position: fixed; inset: 0 auto 0 0; z-index: 101; width: min(380px, 92vw); background: var(--cream);
  transform: translateX(-100%); transition: transform .3s var(--ease-out); display: flex; flex-direction: column; box-shadow: var(--sh-lg);
}
.filter-drawer.open { transform: translateX(0); }
.filter-drawer-head { display: flex; align-items: center; justify-content: space-between; padding: 1.1rem 1.2rem; border-bottom: 1px solid var(--line); }
.filter-drawer-head h3 { font-family: var(--font-body); font-weight: 800; font-size: 1.2rem; letter-spacing: -.01em; }
.filter-drawer .icon-btn { color: var(--ink); width: 38px; height: 38px; }
.filter-drawer .icon-btn:hover { background: var(--cream-3); }
.filter-drawer-body { flex: 1; overflow-y: auto; padding: .4rem 1.2rem; }
.filter-sec { padding: .9rem 0; border-bottom: 1px solid var(--line); }
.filter-sec:last-child { border-bottom: none; }
.filter-sec h4 { font-family: var(--font-body); font-weight: 800; text-transform: uppercase; letter-spacing: .06em; font-size: .8rem; color: var(--ink-soft); margin-bottom: .7rem; }
.filter-opts { display: flex; flex-direction: column; gap: .1rem; }
.filter-opt { display: flex; align-items: center; gap: .6rem; padding: .45rem .3rem; border-radius: var(--r-sm); cursor: pointer; transition: background .15s; }
.filter-opt:hover { background: var(--cream-3); }
.filter-opt input {
  appearance: none; -webkit-appearance: none; width: 20px; height: 20px; border-radius: 6px;
  border: 2px solid var(--line-2); flex-shrink: 0; display: grid; place-items: center; cursor: pointer;
  transition: background .15s, border-color .15s;
}
.filter-opt input:checked { background: var(--orange); border-color: var(--orange); }
.filter-opt input:checked::after { content: "✓"; color: var(--cream); font-size: .78rem; font-weight: 900; line-height: 1; }
.filter-opt .fo-sw { width: 16px; height: 16px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(0,0,0,.18); flex-shrink: 0; }
.filter-opt .fo-l { flex: 1; font-weight: 600; font-size: .92rem; color: var(--ink); }
.filter-opt .fo-n { font-size: .8rem; color: var(--ink-faint); font-weight: 700; }
.filter-opt.is-zero { opacity: .38; pointer-events: none; }
.filter-opts-chips { display: flex; flex-direction: row; flex-wrap: wrap; gap: .5rem; }
.filter-gb {
  display: inline-flex; align-items: center; gap: .35rem; font-weight: 700; font-size: .86rem;
  padding: .45rem .85rem; border-radius: var(--r-pill); background: var(--cream-3); color: var(--ink-soft);
  border: 1px solid var(--line); transition: background .15s, color .15s, border-color .15s;
}
.filter-gb .fg-n { font-size: .72rem; opacity: .65; font-weight: 800; }
.filter-gb.on { background: var(--ink); color: var(--cream); border-color: var(--ink); }
.filter-gb.on .fg-n { opacity: .85; }
.filter-gb.is-zero { opacity: .38; pointer-events: none; }
.filter-drawer-foot { padding: 1rem 1.2rem; border-top: 1px solid var(--line); display: flex; gap: .7rem; align-items: center; }
.filter-drawer-foot .btn-primary { flex: 1; }

/* Ecosistema "sigue el parche" */
.eco-grid { display: grid; gap: .8rem; grid-template-columns: 1fr; }
@media (min-width: 560px) { .eco-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .eco-grid { grid-template-columns: repeat(3, 1fr); } }
.eco-card {
  display: flex; align-items: center; gap: .9rem; min-width: 0;
  background: var(--cream); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 1rem 1.1rem; box-shadow: var(--sh-sm); transition: transform .22s var(--ease-out), box-shadow .22s;
}
.eco-card:hover { transform: translateY(-4px); box-shadow: var(--sh-md); }
.eco-emoji { font-size: 1.7rem; flex-shrink: 0; }
.eco-info { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.eco-label { font-family: var(--font-display); text-transform: uppercase; font-size: 1.05rem; line-height: 1; color: var(--ink); }
.eco-note { font-size: .82rem; color: var(--ink-soft); margin-top: .2rem; }
.eco-img { width: 46px; height: 46px; object-fit: contain; flex-shrink: 0; }
.eco-arrow { font-family: var(--font-display); color: var(--orange); font-size: 1.3rem; flex-shrink: 0; }

.cta-final { padding-block: clamp(3rem, 8vw, 5rem); }
.cta-panel {
  background: var(--ink); color: var(--cream); border-radius: var(--r-xl); padding: clamp(2rem, 6vw, 3.4rem);
  text-align: center; position: relative; overflow: hidden;
}
.cta-panel h2 { font-family: var(--font-body); font-weight: 800; text-transform: uppercase; font-size: clamp(1.7rem, 5.5vw, 2.6rem); line-height: 1.02; letter-spacing: -.02em; }
.cta-panel p { color: rgba(255,254,247,.9); max-width: 48ch; margin: .8rem auto 1.4rem; }
.cta-panel .cta-note { font-size: .82rem; color: rgba(255,254,247,.7); margin-top: 1rem; }

/* ============================================================
   COMPARADOR
   ============================================================ */
.cmp-cats { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: 1.4rem; }
.cmp-cat {
  font-weight: 700; font-size: .9rem; padding: .5rem 1rem; border-radius: var(--r-pill);
  background: var(--cream-2); color: var(--ink-soft); border: 1px solid var(--line);
  transition: background .18s, color .18s, border-color .18s;
}
.cmp-cat.active { background: var(--orange); color: var(--cream); border-color: var(--orange); }
.cmp-picker { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: .7rem; }
@media (min-width: 640px) { .cmp-picker { grid-template-columns: repeat(3, minmax(0,1fr)); } }
@media (min-width: 960px) { .cmp-picker { grid-template-columns: repeat(4, minmax(0,1fr)); } }
.cmp-pick {
  position: relative; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: .1rem;
  background: var(--cream); border: 2px solid var(--line); border-radius: var(--r-md); padding: .8rem;
  text-align: left; transition: border-color .18s, transform .18s, box-shadow .18s;
}
.cmp-pick:hover { transform: translateY(-3px); box-shadow: var(--sh-md); }
.cmp-pick.on { border-color: var(--orange); box-shadow: 0 0 0 3px rgba(255,61,27,.14); }
.cmp-pick-thumb { position: relative; display: block; width: 100%; aspect-ratio: 4/3; overflow: hidden; }
/* Centrado en absoluto, igual que `.card-media img`, y no como ítem de grid.
   El motivo es un detalle del modelo de cajas que costó dos intentos: cuando la altura del
   contenedor sale de `aspect-ratio`, un hijo NORMAL no consigue resolver `height: 78%` ni
   `max-height: 78%` contra ella — el porcentaje cae a `auto` y la imagen se queda con su
   alto natural. Medido: 230x229 dentro de una caja de 295x221, o sea 40px recortados por
   abajo, y se notaba con fotos verticales como el iPhone (1097x1400).
   En cambio, un hijo POSICIONADO EN ABSOLUTO resuelve el porcentaje contra la caja de
   relleno del ancestro posicionado, que sí tiene altura usada. Mismo truco que ya usaba la
   tarjeta de producto, que nunca tuvo este problema. */
.cmp-pick-thumb img {
  position: absolute; top: 50%; left: 50%; width: 78%; height: 78%;
  object-fit: contain; transform: translate(-50%, -50%);
}
.cmp-pick-name { font-weight: 700; font-size: .86rem; line-height: 1.15; color: var(--ink); }
.cmp-pick-price { font-family: var(--font-body); font-weight: 800; font-size: .98rem; color: var(--orange); }
.cmp-pick-tick {
  position: absolute; top: .5rem; right: .5rem; width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center; font-weight: 800; background: var(--cream-3); color: var(--ink-soft); line-height: 1;
}
.cmp-pick.on .cmp-pick-tick { background: var(--orange); color: var(--cream); }

.cmp-bar {
  position: sticky; bottom: calc(var(--bottombar-h) + 10px); z-index: 40; margin-top: 1.4rem;
  display: none; align-items: center; justify-content: space-between; gap: 1rem;
  background: var(--ink); color: var(--cream); border-radius: var(--r-pill); padding: .7rem .7rem .7rem 1.3rem;
  box-shadow: var(--sh-lg);
}
.cmp-bar.show { display: flex; }
.cmp-bar-count { font-weight: 700; font-size: .92rem; }
.cmp-bar-count strong { font-family: var(--font-body); font-weight: 800; font-size: 1.1rem; }
.cmp-bar-actions { display: flex; gap: .5rem; }
@media (min-width: 960px) { .cmp-bar { bottom: 14px; } }

.cmp-table-scroll { overflow-x: auto; margin-top: 2rem; border-radius: var(--r-lg); border: 1px solid var(--line); }
.cmp-table { border-collapse: collapse; width: 100%; min-width: calc(120px + var(--cols, 2) * 160px); background: var(--cream); }
.cmp-table th, .cmp-table td { padding: .8rem .9rem; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; font-size: .88rem; }
.cmp-table tr:nth-child(even) td { background: var(--cream-2); }
.cmp-table .cmp-k { font-weight: 800; color: var(--ink-soft); width: 120px; background: var(--cream-2); }
.cmp-h { position: relative; min-width: 150px; background: var(--cream-3); }
.cmp-h-thumb { display: grid; place-items: center; height: 70px; }
.cmp-h-thumb img { max-height: 68px; width: auto; object-fit: contain; }
.cmp-h-name { display: block; font-family: var(--font-body); font-weight: 800; font-size: .9rem; line-height: 1.1; margin-top: .4rem; color: var(--ink); letter-spacing: -.01em; }
.cmp-h-rm { position: absolute; top: .4rem; right: .4rem; width: 24px; height: 24px; border-radius: 50%; background: var(--cream); color: var(--ink-soft); font-weight: 800; box-shadow: var(--sh-sm); }
.cmp-h-rm:hover { background: var(--berry); color: #fff; }
.cmp-price { font-family: var(--font-body); font-weight: 800; font-size: 1.02rem; color: var(--ink); }
.cmp-price s { display: block; font-family: var(--font-body); font-size: .78rem; color: var(--ink-faint); }
.cmp-empty { text-align: center; color: var(--ink-soft); padding: 2rem; }

/* ============================================================
   FRANJA DE VALOR (marquee) + PARED DE MARCAS
   ============================================================ */
/* Franja de valor (banner que corre al inicio) */
.value-strip {
  position: relative;
  background: var(--ink); color: var(--cream); overflow: hidden; padding-block: .8rem;
  margin: 0 var(--frame) var(--frame); border-radius: var(--r-lg);
}
/* El desvanecido va HACIA EL COLOR DE LA BARRA, no a transparente. Con `mask-image` la barra
   se volvía translúcida en los bordes y asomaba el crema de la página: se veía como un
   manchón blanco encima de la barra oscura, y además se comía las esquinas redondeadas. */
.value-strip::before,
.value-strip::after {
  content: ""; position: absolute; top: 0; bottom: 0; z-index: 2;
  width: clamp(26px, 6%, 64px); pointer-events: none;
}
.value-strip::before { left: 0; background: linear-gradient(90deg, var(--ink), transparent); }
.value-strip::after { right: 0; background: linear-gradient(270deg, var(--ink), transparent); }
.value-strip .ticker-track { display: inline-flex; white-space: nowrap; will-change: transform; animation: ticker 24s linear infinite; }
.value-strip .ticker-track span {
  font-family: var(--font-body); font-weight: 800; text-transform: uppercase; font-size: clamp(.8rem, 2.4vw, .98rem);
  letter-spacing: .1em; padding-inline: 1.1rem; display: inline-flex; align-items: center; gap: 1.1rem; color: var(--cream);
}
.value-strip .ticker-track span::after { content: "✦"; color: var(--orange); }
@keyframes ticker { to { transform: translateX(-50%); } }

/* Pared de marcas (estática, con hover) */
.brands { padding-block: clamp(2.2rem, 6vw, 3.4rem); }
.brands-label { text-align: center; font-weight: 700; font-size: .84rem; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 1.4rem; }
.brand-wall { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: clamp(1.6rem, 6vw, 3.4rem); }
/* Los logos van en el COLOR OFICIAL de cada marca (Samsung azul, Lenovo rojo, JBL naranja,
   PlayStation azul; Apple/Sony/Asus son negros de verdad en su guía). Por eso son <img> y
   no `mask-image`: una máscara pinta todo el trazo de UN solo color, así que era imposible
   respetar el color de marca mientras se usara. Los archivos coloreados viven en
   assets/img/brands/color/ y los monocromos originales se dejan por si alguna vez se
   necesita una versión a una tinta.

   Los SVG están recortados a su contenido (viewBox ajustado al bbox del trazo): antes
   traían viewBox cuadrado de 24×24 y, como el logotipo de Samsung ocupa apenas el 15% de
   ese cuadro, `object-fit: contain` lo dejaría en ~7px de alto — se ve el hueco pero no
   el logo.

   Cada marca trae su proporción real (`--ar`) y un factor óptico (`--k`): un logotipo
   ancho como SAMSUNG no puede medir de alto lo mismo que el ícono de Apple o domina la
   fila. Los dos valores van inline en el HTML. */
.brand-logo {
  --ar: 3; --k: 1;
  display: inline-block;
  height: calc(clamp(19px, 3.6vw, 27px) * var(--k));
  aspect-ratio: var(--ar); width: auto;
  object-fit: contain; object-position: center;
  transition: transform .25s, filter .25s;
}
/* Sin recolorear en hover: el color ES el punto. Solo levanta y aviva un poco. */
.brand-logo:hover { transform: translateY(-3px) scale(1.06); filter: saturate(1.15); }

/* ============================================================
   FICHA DE PRODUCTO (producto.html) — donde se decide la compra
   ============================================================ */
.pdp-crumbs {
  display: flex; flex-wrap: wrap; gap: .4rem; align-items: center;
  padding-top: calc(var(--header-h) + clamp(1rem, 3vw, 1.6rem));
  font-size: .84rem; color: var(--ink-faint);
}
.pdp-crumbs a { color: var(--ink-soft); font-weight: 600; }
.pdp-crumbs a:hover { color: var(--orange); }
.pdp-crumbs b { color: var(--ink); font-weight: 700; }

.pdp { display: grid; gap: clamp(1.4rem, 4vw, 3rem); padding-block: clamp(1.2rem, 3vw, 2rem); }
@media (min-width: 900px) { .pdp { grid-template-columns: 1.05fr .95fr; align-items: start; } }

/* --- Galería --- */
@media (min-width: 900px) { .pdp-gallery { position: sticky; top: calc(var(--header-h) + 1rem); } }
.pdp-stage {
  position: relative; overflow: hidden;
  border-radius: var(--r-xl); background: var(--cream-3);
  aspect-ratio: 1 / 1; display: grid; place-items: center;
}
.pdp-shot { position: absolute; inset: 8%; display: grid; place-items: center; }
.pdp-shot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; transition: opacity var(--t-mid) var(--ease-out), transform var(--t-mid) var(--ease-gentle); }
.pdp-shot img.switching { opacity: 0; transform: scale(.95); }
/* Mismo cruce que en la tarjeta, un poco más suave: acá la foto es grande y un salto
   de escala fuerte se nota como un tirón. */
.pdp-shot img.foto-entra { opacity: 0; transform: scale(1.045); }
.pdp-shot img.foto-sale  { opacity: 0; transform: scale(.975); }
.pdp-off { position: absolute; top: 1rem; right: 1rem; z-index: 2; }
.pdp-state { left: 1rem; bottom: 1rem; }
.pdp-thumbs { display: flex; gap: .5rem; margin-top: .8rem; flex-wrap: wrap; }
.pdp-thumb {
  width: 68px; height: 68px; padding: 6px; border-radius: var(--r-md);
  background: var(--cream-3); box-shadow: inset 0 0 0 2px transparent;
  transition: box-shadow var(--t-fast), transform var(--t-fast) var(--ease-spring);
}
.pdp-thumb img { width: 100%; height: 100%; object-fit: contain; }
.pdp-thumb:hover { transform: translateY(-2px); }
.pdp-thumb.active { box-shadow: inset 0 0 0 2px var(--orange); }
.pdp-shotnote { margin-top: .8rem; font-size: .8rem; color: var(--ink-faint); }

/* --- Info --- */
.pdp-kicker { font-size: .84rem; font-weight: 700; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .06em; }
.pdp-name {
  font-family: var(--font-body); font-weight: 800; letter-spacing: -.025em;
  font-size: clamp(1.7rem, 5vw, 2.7rem); line-height: 1.05; margin: .3rem 0 .5rem; color: var(--ink);
}
.pdp-desc { color: var(--ink-soft); font-size: 1.02rem; line-height: 1.55; margin-top: .8rem; max-width: 52ch; }
.pdp-pricebox {
  margin: clamp(1rem, 3vw, 1.5rem) 0; padding: clamp(.9rem, 2.4vw, 1.2rem);
  background: var(--cream-2); border-radius: var(--r-lg); border: 1px solid var(--line);
}
.pdp-price { font-size: 1.3rem; color: var(--ink); font-weight: 500; }
.pdp-price strong { font-weight: 800; font-size: clamp(1.7rem, 4.4vw, 2.2rem); letter-spacing: -.02em; }
.pdp-price s { color: var(--ink-faint); font-size: 1rem; margin-right: .4rem; }
.pdp-price.on-sale strong { color: var(--berry-deep); }
.pdp-opt { margin-bottom: clamp(1rem, 2.6vw, 1.3rem); }
.pdp-opt-label { font-size: .84rem; font-weight: 800; color: var(--ink); margin-bottom: .5rem; }
.pdp-opt-label span { color: var(--ink-soft); font-weight: 600; }
.pdp-gbs { display: flex; flex-wrap: wrap; gap: .5rem; }
.pdp-gb {
  display: flex; flex-direction: column; gap: .1rem; align-items: flex-start;
  padding: .6rem .9rem; border-radius: var(--r-md); background: var(--cream-2);
  box-shadow: inset 0 0 0 2px var(--line); transition: box-shadow var(--t-fast), transform var(--t-fast) var(--ease-spring);
}
.pdp-gb b { font-size: .95rem; font-weight: 800; color: var(--ink); }
.pdp-gb span { font-size: .78rem; color: var(--ink-faint); }
.pdp-gb:hover { transform: translateY(-2px); }
.pdp-gb.active { box-shadow: inset 0 0 0 2px var(--orange); background: var(--cream-3); }
.pdp-actions { display: grid; gap: .6rem; margin-top: clamp(1.2rem, 3vw, 1.6rem); }
@media (min-width: 520px) { .pdp-actions { grid-template-columns: 1fr 1fr; } }
.pdp-trust { display: grid; gap: .7rem; margin-top: clamp(1.3rem, 3vw, 1.8rem); padding-top: clamp(1.2rem, 3vw, 1.5rem); border-top: 1px solid var(--line); }
.pdp-trust li { display: grid; grid-template-columns: auto 1fr; gap: .1rem .7rem; align-items: center; }
.pdp-trust svg { width: 20px; height: 20px; color: var(--orange); grid-row: span 2; }
.pdp-trust b { font-size: .92rem; font-weight: 800; color: var(--ink); }
.pdp-trust span { font-size: .84rem; color: var(--ink-soft); }

/* --- Ficha técnica --- */
.pdp-specs { display: grid; gap: .1rem; }
@media (min-width: 720px) { .pdp-specs { grid-template-columns: repeat(2, 1fr); gap: .1rem 2.4rem; } }
.pdp-spec {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1.4rem;
  padding: .85rem .2rem; border-bottom: 1px solid var(--line);
}
.pdp-spec dt { color: var(--ink-soft); font-size: .92rem; }
.pdp-spec dd { margin: 0; color: var(--ink); font-weight: 700; font-size: .95rem; text-align: right; }
.pdp-404 { padding-top: calc(var(--header-h) + 3rem); text-align: center; }
.pdp-404 .hero-cta { justify-content: center; }

/* --- Cantidad --- */
.pdp-qty { margin-top: clamp(1rem, 2.6vw, 1.3rem); }
.qty-lg { gap: .7rem; margin-top: .45rem; padding: .3rem; border: 1px solid var(--line); border-radius: var(--r-pill); background: var(--cream); }
.qty-lg button { width: 36px; height: 36px; border-radius: 50%; font-size: 1.15rem; }
.qty-lg button:disabled { opacity: .35; cursor: default; }
.qty-lg button:disabled:hover { background: var(--cream-3); color: var(--ink); }
.qty-lg > span { min-width: 2ch; text-align: center; font-weight: 800; font-size: 1.02rem; }

/* --- Métodos de pago --- */
.pdp-pays { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-top: 1.2rem; }
.pdp-pays-label { font-size: .82rem; font-weight: 800; color: var(--ink-faint); margin-right: .2rem; }
.pdp-pays .pay-logo { margin: 0; }

/* --- Preguntas frecuentes (details/summary: abre y cierra sin JS) --- */
.pdp-faq { display: grid; gap: .6rem; max-width: 860px; }
.faq-item { background: var(--cream); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--sh-sm); overflow: hidden; }
.faq-item summary {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1.05rem 1.2rem; cursor: pointer; list-style: none;
  font-weight: 800; font-size: clamp(.95rem, 2.4vw, 1.05rem); color: var(--ink);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover { color: var(--orange); }
.faq-plus { position: relative; width: 18px; height: 18px; flex-shrink: 0; }
.faq-plus::before, .faq-plus::after {
  content: ""; position: absolute; inset: 50% 0 auto 0; height: 2.4px; border-radius: 2px;
  background: var(--orange); transform: translateY(-50%); transition: transform .25s var(--ease-out);
}
.faq-plus::after { transform: translateY(-50%) rotate(90deg); }
.faq-item[open] .faq-plus::after { transform: translateY(-50%) rotate(0deg); }
.faq-body { padding: 0 1.2rem 1.15rem; }
.faq-body p { color: var(--ink-soft); font-size: .94rem; line-height: 1.6; max-width: 68ch; }
.faq-item[open] .faq-body { animation: faq-open .28s var(--ease-out) both; }
@keyframes faq-open { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }

/* --- Barra fija de compra (móvil) ---
   Va ENCIMA de la barra inferior de navegación, no sobre ella. Solo aparece cuando los
   botones de compra de arriba ya salieron de pantalla (lo decide un IntersectionObserver). */
.pdp-bar {
  position: fixed; inset: auto 0 var(--bottombar-h) 0; z-index: 69;
  display: flex; align-items: center; gap: .9rem;
  padding: .7rem clamp(.9rem, 4vw, 1.2rem);
  background: rgba(255,254,247,.96); backdrop-filter: saturate(1.2) blur(14px);
  border-top: 1px solid var(--line); box-shadow: 0 -10px 30px -18px rgba(60,20,5,.5);
  transform: translateY(120%); transition: transform .3s var(--ease-out);
}
.pdp-bar.show { transform: translateY(0); }
.pdp-bar-info { display: grid; min-width: 0; flex: 1; }
.pdp-bar-price { font-weight: 800; font-size: 1.06rem; color: var(--ink); line-height: 1.15; }
.pdp-bar-price .strike { display: none; }
.pdp-bar-variant { font-size: .78rem; color: var(--ink-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pdp-bar-btn { flex-shrink: 0; padding-inline: clamp(1.1rem, 5vw, 1.8rem); }
@media (min-width: 960px) { .pdp-bar { display: none; } }

/* ============================================================
   SCROLL-EXPANSION — la foto se abre a pantalla completa al bajar
   ------------------------------------------------------------
   Patrón "scroll expansion hero": una pista de scroll alta con un escenario sticky
   adentro. `--p` (0→1) lo publica initScrollExpand() en melo.js y acá se interpola
   ancho/alto/radio con calc(). El texto entra recién pasada la mitad del recorrido,
   cuando la imagen ya llena la pantalla.
   ============================================================ */
.expand { position: relative; height: 210vh; --p: 0; }
.expand-stage {
  position: sticky; top: 0; height: 100vh;
  display: grid; place-items: center; overflow: hidden;
  background: var(--cream);
}
.expand-media {
  position: relative; overflow: hidden; margin: 0;
  width: calc(86vw + 14vw * var(--p));
  height: calc(54vh + 46vh * var(--p));
  border-radius: calc(var(--r-xl) * (1 - var(--p)));
  box-shadow: 0 40px 90px -40px rgba(70, 20, 5, calc(.5 * (1 - var(--p))));
}
@media (min-width: 860px) { .expand-media { width: calc(56vw + 44vw * var(--p)); height: calc(62vh + 38vh * var(--p)); } }
.expand-media > img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* Contra-zoom sutil: la foto arranca un pelo acercada y se asienta al expandirse */
  transform: scale(calc(1.12 - .12 * var(--p)));
  transition: none;
}
/* Velo inferior para que el texto crema se lea sobre cualquier zona de la foto */
.expand-media::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top, rgba(36,22,17,.82) 0%, rgba(36,22,17,.35) 34%, transparent 62%);
  opacity: var(--p);
}
.expand-copy {
  position: absolute; z-index: 2; left: 0; right: 0; bottom: 0;
  padding: clamp(1.6rem, 5vw, 3.6rem); color: var(--cream); text-align: center;
  /* aparece en el último tramo del recorrido; opacity satura sola fuera de [0,1] */
  opacity: calc((var(--p) - .45) * 2.6);
  transform: translateY(calc(28px * (1 - var(--p))));
}
.expand-kicker {
  display: inline-flex; align-items: center; gap: .5em;
  font-weight: 800; text-transform: uppercase; letter-spacing: .14em;
  font-size: clamp(.68rem, 2vw, .8rem); color: var(--orange-bright); margin-bottom: .7rem;
}
.expand-kicker::before { content: ""; width: 22px; height: 3px; border-radius: 3px; background: var(--orange-bright); }
.expand-title {
  font-family: var(--font-display); text-transform: uppercase; font-weight: 400;
  font-size: clamp(1.9rem, 6.4vw, 4.6rem); line-height: .95; letter-spacing: -.02em;
  margin-bottom: .5rem;
}
.expand-sub { max-width: 54ch; margin-inline: auto; font-size: clamp(.95rem, 2.4vw, 1.12rem); color: rgba(255,254,247,.9); }
.expand-actions { display: flex; flex-wrap: wrap; gap: .7rem; justify-content: center; margin-top: clamp(1rem, 3vw, 1.5rem); }
/* Sin motion: nada de pista alta ni sticky — una foto grande y ya */
@media (prefers-reduced-motion: reduce) {
  .expand { height: auto; --p: 1; }
  .expand-stage { position: static; height: auto; padding-block: clamp(2rem, 5vw, 3rem); }
  .expand-media { width: min(100%, var(--maxw)); height: auto; aspect-ratio: 16 / 10; border-radius: var(--r-xl); }
  .expand-media > img { transform: none; }
}

/* ============================================================
   FEED DE INSTAGRAM — piezas reales, coverflow 3D tipo app-switcher
   ============================================================ */
.feed-rail { perspective: 1400px; }
.feed-rail > * { flex: 0 0 clamp(210px, 56vw, 280px); }
.feed-card {
  position: relative; display: block; overflow: hidden;
  border-radius: var(--r-lg); background: var(--cream-3);
  box-shadow: var(--sh-md);
  transform-style: preserve-3d; will-change: transform, opacity;
  transition: box-shadow var(--t-mid) var(--ease-out);
}
.feed-card img { width: 100%; height: 100%; aspect-ratio: 4 / 5; object-fit: cover; display: block; }
.feed-card:hover { box-shadow: var(--sh-lg); }
.feed-place {
  position: absolute; left: 12px; bottom: 12px; z-index: 2;
  display: inline-flex; align-items: center; gap: .35em;
  background: rgba(36,22,17,.58); backdrop-filter: blur(10px) saturate(1.3);
  color: var(--cream); font-size: .76rem; font-weight: 700;
  padding: .4em .75em; border-radius: var(--r-pill);
  box-shadow: inset 0 0 0 1px rgba(255,254,247,.2);
}
.feed-place svg { width: 13px; height: 13px; }
@media (prefers-reduced-motion: reduce) { .feed-rail { perspective: none; } .feed-card { transform: none !important; opacity: 1 !important; } }

/* ============================================================
   BANNERS — espacios de promoción editables (BANNERS en data.js)
   ============================================================ */
.banners { display: grid; gap: clamp(.9rem, 2.4vw, 1.3rem); grid-template-columns: 1fr; }
@media (min-width: 720px)  { .banners { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .banners { grid-template-columns: repeat(3, 1fr); } }
.banner {
  position: relative; overflow: hidden; isolation: isolate;
  display: flex; align-items: flex-end; min-height: clamp(190px, 26vw, 250px);
  padding: clamp(1.1rem, 2.6vw, 1.5rem);
  border-radius: var(--r-lg); background: var(--banner-bg, var(--bg-carbon));
  color: var(--banner-ink, var(--ink));
  transition: transform var(--t-mid) var(--ease-spring), box-shadow var(--t-mid) var(--ease-out);
}
.banner:hover { transform: translateY(-4px); box-shadow: var(--sh-lg); }
.banner-img { position: absolute; inset: 0; z-index: -1; width: 100%; height: 100%; object-fit: cover; }
/* Con arte de fondo hace falta velo para que el texto siga legible */
.banner:has(.banner-img)::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to top, rgba(36,22,17,.78), rgba(36,22,17,.12) 62%);
}
.banner:has(.banner-img) { color: var(--cream); }
.banner-copy { display: flex; flex-direction: column; gap: .25rem; }
.banner-kicker { font-size: .72rem; font-weight: 800; text-transform: uppercase; letter-spacing: .12em; opacity: .78; }
.banner-title { font-family: var(--font-body); font-weight: 800; font-size: clamp(1.15rem, 2.6vw, 1.4rem); line-height: 1.12; letter-spacing: -.01em; }
.banner-sub { font-size: .9rem; opacity: .82; max-width: 32ch; }
.banner-cta { display: inline-flex; align-items: center; gap: .4em; margin-top: .5rem; font-weight: 800; font-size: .9rem; }
.banner-cta svg { width: 15px; height: 15px; transition: transform var(--t-fast) var(--ease-spring); }
.banner:hover .banner-cta svg { transform: translateX(4px); }

/* ============================================================
   STATS (contador)
   ============================================================ */
.stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(1rem, 3vw, 1.6rem); }
@media (min-width: 720px) { .stats { grid-template-columns: repeat(4, 1fr); } }
.stat { text-align: center; padding: 1.2rem .6rem; }
.stat-num { font-family: var(--font-display); font-size: clamp(2.4rem, 9vw, 4rem); line-height: 1; color: var(--orange); }
.stat-num .u { font-size: .5em; }
.stat-label { font-weight: 700; font-size: .9rem; color: var(--ink-soft); margin-top: .35rem; }

/* ============================================================
   ÍCONOS DE CATEGORÍA (monoline custom) + medios de pago
   ============================================================ */
.mc-ic, .step-ic, .cc-ic { display: inline-flex; }
/* El tamaño del ícono del mega menú vive con el resto del mega menú (sección MEGA MENÚ),
   no aquí — aquí quedaba más abajo en el archivo y le ganaba por cascada. */
.step-ic { width: 44px; height: 44px; border-radius: 14px; background: var(--cream-3); color: var(--orange); align-items: center; justify-content: center; margin-bottom: .3rem; }
.step-ic svg { width: 24px; height: 24px; }

.pays { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.6rem; align-items: center; }
.pay-badge {
  display: inline-flex; align-items: center; gap: .5rem; font-weight: 800; font-size: .9rem;
  background: var(--cream); border: 1px solid var(--line); border-radius: var(--r-pill); padding: .5rem .95rem .5rem .55rem;
  color: var(--ink); box-shadow: var(--sh-sm); transition: transform .2s, box-shadow .2s;
}
.pay-badge:hover { transform: translateY(-2px); box-shadow: var(--sh-md); }
.pay-ic { width: 30px; height: 30px; border-radius: 9px; display: grid; place-items: center; color: #fff; flex-shrink: 0; }
.pay-ic svg { width: 18px; height: 18px; }
.pay-nequi { background: #200020; }
.pay-banco { background: #FDDA24; color: #12100b; }
.pay-breb { background: linear-gradient(135deg, #00C2A8, #0090C7); }
.pay-cash { background: var(--wa); }

/* Chips con logos REALES de medios de pago */
.pays-label { font-weight: 700; font-size: .86rem; color: var(--ink-soft); margin-right: .2rem; }
.pay-logo {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  background: var(--cream); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: .55rem .95rem; min-height: 50px; box-shadow: var(--sh-sm);
  transition: transform .2s var(--ease-out), box-shadow .2s;
}
.pay-logo:hover { transform: translateY(-2px); box-shadow: var(--sh-md); }
.pay-logo img { display: block; width: auto; max-height: 30px; }
.pay-logo-breb { padding: .4rem .7rem; }
.pay-logo-cash { font-weight: 800; font-size: .92rem; color: var(--ink); }
.pay-logo-cash svg { width: 22px; height: 22px; color: var(--wa-deep); }

/* ============================================================
   CTA v2 (bloque final) + trust
   ============================================================ */
.cta-panel { position: relative; }
.cta-panel.grain::after { border-radius: inherit; }
.cta-panel::before {
  content: ""; position: absolute; z-index: 0; inset: auto -10% -40% -10%; height: 80%;
  background: radial-gradient(50% 90% at 50% 100%, rgba(255,61,27,.55), transparent 70%); pointer-events: none;
}
.cta-panel > * { position: relative; z-index: 2; }
.cta-badge {
  display: inline-flex; align-items: center; gap: .5rem; font-weight: 800; font-size: .8rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--cream); background: rgba(255,254,247,.14); border: 1px solid rgba(255,255,255,.2);
  padding: .4rem .9rem; border-radius: var(--r-pill); margin-bottom: 1rem;
}
.cta-actions { display: flex; flex-wrap: wrap; gap: .7rem; justify-content: center; }
.trust-row { display: flex; flex-wrap: wrap; gap: .6rem 1.6rem; justify-content: center; margin-top: 1.4rem; }
.trust-item { display: inline-flex; align-items: center; gap: .45rem; font-size: .86rem; font-weight: 600; color: rgba(255,254,247,.9); }
.trust-item svg { width: 18px; height: 18px; color: var(--cream); }

/* ============================================================
   REVEAL ON SCROLL (variantes "bien llamativo")
   ============================================================ */
/* `will-change` solo MIENTRAS falta revelarse. Antes estaba en la regla base, así que
   cada elemento con `.reveal` se quedaba para siempre en su propia capa de composición
   —19 solo en el home, 52 en el sitio— gastando memoria de GPU por una animación que ya
   había terminado. Al colgarlo de `:not(.in)` la capa se suelta al revelarse, que es
   justo para lo que sirve la propiedad. */
.reveal { opacity: 0; transform: translateY(34px); transition: opacity .75s var(--ease-out), transform .75s var(--ease-out); transition-delay: calc(var(--i, 0) * 80ms); }
.reveal:not(.in), .reveal-scale:not(.in), .reveal-left:not(.in), .reveal-blur:not(.in) { will-change: opacity, transform; }
.reveal.in { opacity: 1; transform: none; }
.reveal-scale { opacity: 0; transform: scale(.86); transition: opacity .7s var(--ease-out), transform .7s var(--ease-out); transition-delay: calc(var(--i, 0) * 80ms); }
.reveal-scale.in { opacity: 1; transform: none; }
.reveal-left { opacity: 0; transform: translateX(-40px); transition: opacity .8s var(--ease-out), transform .8s var(--ease-out); transition-delay: calc(var(--i, 0) * 80ms); }
.reveal-left.in { opacity: 1; transform: none; }
.reveal-blur { opacity: 0; filter: blur(14px); transform: translateY(20px) scale(1.04); transition: opacity .9s var(--ease-out), transform .9s var(--ease-out), filter .9s var(--ease-out); transition-delay: calc(var(--i, 0) * 80ms); }
.reveal-blur.in { opacity: 1; filter: none; transform: none; }
/* parallax (JS setea --py) */
.parallax { transform: translate3d(0, var(--py, 0), 0); will-change: transform; }

/* ============================================================
   REDUCED MOTION
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  .reveal, .reveal-scale, .reveal-left, .reveal-blur { opacity: 1; transform: none; filter: none; }
  .hero-title .ltr, .hero-title .cali-word, .hero-sub, .hero-cta, .hero-trust { transform: none !important; opacity: 1; }
  .hero-shot { opacity: 1 !important; transform: none !important; }
  .hero-shot-frame { transform: rotate(-1.8deg) !important; }
  .cali-plate { transform: rotate(-1.6deg) !important; }
  .cali-dot { transform: none !important; }
  .pre-logo, .pre-line, .pre-line i { opacity: 1; transform: none; }
  .cat-hero-shot img { animation: none; transform: none; }
  .parallax { transform: none !important; }
  .hero-seal > svg { animation: none; }
  .ticker-track { animation: none; }
  .wa-float { animation: none; }
  .preloader { transition: none; }
}

/* ============================================================
   ARMA TU PC — configurador (armatupc.html)
   ------------------------------------------------------------
   Metáfora: banco de trabajo. A la izquierda las piezas que vas
   metiendo, a la derecha —pegada— la máquina cobrando vida.
   El gancho no es el precio (el sitio no muestra precios): es
   ver subir el medidor y ver los FPS moverse juego por juego.
   Solo CSS + rAF, sin librerías (regla del proyecto).
   ============================================================ */
.pcb { --pcb-score: 0; }

/* ---- presets ---- */
.pcb-presets {
  display: flex; flex-wrap: wrap; align-items: center; gap: .6rem;
  margin-bottom: clamp(1.2rem, 3vw, 1.9rem);
}
.pcb-presets-lab {
  font-weight: 800; font-size: .95rem; color: var(--ink-soft);
  margin-right: .3rem;
}
.pcb-preset {
  display: flex; align-items: center; gap: .6rem; text-align: left;
  padding: .6rem .95rem .6rem .7rem; border-radius: var(--r-pill);
  border: 2px solid var(--line-2); background: var(--cream);
  cursor: pointer; transition: transform var(--t-fast) var(--ease-spring),
    border-color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast);
}
.pcb-preset:hover { transform: translateY(-2px); border-color: var(--orange); box-shadow: var(--sh-sm); }
.pcb-preset.is-on { background: var(--ink); border-color: var(--ink); color: var(--cream); }
.pcb-preset-emoji { font-size: 1.35rem; line-height: 1; }
.pcb-preset-txt { display: grid; }
.pcb-preset-txt strong { font-size: .95rem; }
.pcb-preset-txt small { font-size: .78rem; opacity: .72; }

/* ---- layout: piezas + panel pegado ---- */
.pcb-main { display: grid; gap: clamp(1rem, 2.5vw, 1.8rem); }
@media (min-width: 1000px) {
  .pcb-main { grid-template-columns: minmax(0, 1fr) 27rem; align-items: start; }
  .pcb-panel { position: sticky; top: calc(var(--header-h) + 1rem); }
}

/* ---- una pieza ---- */
.pcb-parts { display: grid; gap: .8rem; }
.pcb-part {
  background: var(--cream); border: 2px solid var(--line);
  border-radius: var(--r-lg); padding: clamp(.9rem, 2.2vw, 1.25rem);
  transition: border-color var(--t-mid), box-shadow var(--t-mid);
}
.pcb-part:hover { border-color: var(--line-2); box-shadow: var(--sh-sm); }
.pcb-part-head { display: flex; align-items: flex-start; gap: .7rem; margin-bottom: .85rem; }
.pcb-part-n {
  font-family: var(--font-display); font-size: 1.05rem; color: var(--orange);
  line-height: 1; padding-top: .15rem; min-width: 1.7rem;
}
.pcb-part-emoji { font-size: 1.5rem; line-height: 1.1; }
.pcb-part-head h3 { font-size: 1.06rem; margin: 0 0 .12rem; }
.pcb-part-head p { font-size: .84rem; color: var(--ink-soft); margin: 0; line-height: 1.4; }

/* ---- niveles ---- */
.pcb-levels { display: grid; gap: .5rem; grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); }
.pcb-level {
  position: relative; display: grid; gap: .18rem; text-align: left;
  padding: .65rem .8rem .75rem; border-radius: var(--r-md);
  border: 2px solid var(--line); background: var(--cream-2); cursor: pointer;
  transition: transform var(--t-fast) var(--ease-spring), border-color var(--t-fast),
    background var(--t-fast), color var(--t-fast);
}
.pcb-level:hover { transform: translateY(-2px); border-color: var(--orange); }
/* El elegido va en TINTA, no en naranja. Con seis piezas visibles a la vez, seis
   bloques naranja saturados era exactamente lo que el dueño describió como «se ve
   todo como muy cargado, mucho naranja». El naranja se queda de acento: el punto
   de "elegido" y la barrita de potencia. */
.pcb-level.is-on {
  background: var(--ink); border-color: var(--ink); color: var(--cream);
  box-shadow: 0 10px 22px -14px rgba(30,14,8,.9);
}
.pcb-level.is-on::after {
  content: ""; position: absolute; top: .5rem; right: .55rem;
  width: 7px; height: 7px; border-radius: 50%; background: var(--orange);
  box-shadow: 0 0 0 3px rgba(255,61,27,.24);
}
.pcb-level-name { font-weight: 800; font-size: .9rem; line-height: 1.2; }
.pcb-level-sub { font-size: .76rem; opacity: .75; }
/* barrita de potencia del nivel: se lee de un vistazo cuál es el más bravo */
.pcb-level-bar { display: block; height: 3px; border-radius: 2px; background: var(--line-2); margin-top: .3rem; overflow: hidden; }
.pcb-level-bar i { display: block; height: 100%; width: var(--w); background: var(--orange); border-radius: 2px; }
.pcb-level.is-on .pcb-level-bar { background: rgba(255, 254, 247, .22); }
.pcb-level.is-on .pcb-level-bar i { background: var(--orange-bright); }

@keyframes pcb-pop { 0% { transform: scale(1); } 42% { transform: scale(1.055); } 100% { transform: scale(1); } }
.pcb-level.pcb-pop { animation: pcb-pop .32s var(--ease-spring); }

/* ---- panel de la máquina ---- */
.pcb-panel {
  background: var(--ink); color: var(--cream); border-radius: var(--r-xl);
  padding: clamp(1.1rem, 2.6vw, 1.5rem); box-shadow: var(--sh-md);
}
.pcb-gauge-wrap { position: relative; margin: .2rem auto .1rem; max-width: 15rem; }
.pcb-gauge { display: block; width: 100%; height: auto; overflow: visible; }
.pcb-gauge path { fill: none; stroke-width: 13; stroke-linecap: round; }
.pcb-gauge-track { stroke: rgba(255, 254, 247, .14); }
.pcb-gauge-fill {
  stroke: var(--orange);
  transition: stroke-dashoffset .7s var(--ease-gentle), stroke .5s linear;
  filter: drop-shadow(0 0 10px rgba(255, 61, 27, .45));
}
.pcb-gauge-num {
  position: absolute; left: 50%; bottom: .1rem; transform: translateX(-50%);
  display: flex; align-items: baseline; gap: .12rem;
}
.pcb-gauge-num strong { font-family: var(--font-display); font-size: clamp(2.6rem, 7vw, 3.4rem); line-height: .9; }
.pcb-gauge-num span { font-size: .9rem; opacity: .5; }
.pcb-rango {
  font-family: var(--font-display); font-size: clamp(1.3rem, 3.4vw, 1.65rem);
  text-align: center; margin: .5rem 0 .2rem; color: var(--orange-bright);
}
.pcb-rango-sub { text-align: center; font-size: .87rem; opacity: .78; margin: 0 0 1rem; line-height: 1.45; }
.pcb-res {
  display: flex; align-items: center; justify-content: center; gap: .4rem;
  font-size: .85rem; padding: .45rem; border-radius: var(--r-pill);
  background: rgba(255, 254, 247, .08); margin-bottom: 1.1rem;
}
.pcb-res strong { color: var(--orange-bright); }

/* ---- lista de juegos ---- */
.pcb-games-title { font-size: .95rem; margin: 0 0 .6rem; }
.pcb-games { list-style: none; margin: 0 0 .8rem; padding: 0; display: grid; gap: .4rem; }
.pcb-game {
  display: grid; align-items: center; gap: .1rem .55rem;
  grid-template-columns: 1.4rem minmax(0, 1fr) auto;
  grid-template-areas: "e n f" ". b v";
  padding: .42rem .3rem; border-radius: var(--r-sm);
  animation: pcb-game-in .42s var(--ease-gentle) both;
  animation-delay: calc(var(--i) * 22ms);
}
@keyframes pcb-game-in { from { opacity: 0; transform: translateX(8px); } to { opacity: 1; transform: none; } }
.pcb-game-emoji { grid-area: e; font-size: 1.05rem; }
.pcb-game-name { grid-area: n; font-weight: 700; font-size: .88rem; display: grid; line-height: 1.2; }
.pcb-game-name small { font-size: .7rem; opacity: .5; font-weight: 500; }
.pcb-game-fps { grid-area: f; font-size: .72rem; opacity: .8; white-space: nowrap; }
.pcb-game-fps strong { font-size: 1rem; opacity: 1; }
.pcb-game-bar { grid-area: b; height: 4px; border-radius: 2px; background: rgba(255, 254, 247, .12); overflow: hidden; }
.pcb-game-bar i {
  display: block; height: 100%; width: var(--w); border-radius: 2px; background: currentColor;
  transition: width .6s var(--ease-gentle);
}
.pcb-game-verdict { grid-area: v; font-size: .7rem; font-weight: 800; white-space: nowrap; text-transform: uppercase; letter-spacing: .02em; }
/* el color del veredicto viaja por `currentColor` a la barra */
.pcb-game.is-mal     { color: #E8836F; }
.pcb-game.is-regular { color: var(--bg-mostaza); }
.pcb-game.is-bien    { color: var(--bg-menta); }
.pcb-game.is-top     { color: var(--orange-bright); }

.pcb-disclaimer { font-size: .72rem; opacity: .48; line-height: 1.45; margin: 0 0 1rem; }
.pcb-cta { display: grid; gap: .5rem; }
.pcb-cta .btn-ghost { border-color: rgba(255, 254, 247, .3); color: var(--cream); }
.pcb-cta .btn-ghost:hover { background: rgba(255, 254, 247, .1); }

@media (prefers-reduced-motion: reduce) {
  .pcb-gauge-fill, .pcb-game-bar i { transition: none; }
  .pcb-game { animation: none; }
  .pcb-level.pcb-pop { animation: none; }
}
/* "·tope": la máquina da más FPS de los que el monitor puede mostrar */
.pcb-game-fps em { font-style: normal; font-size: .62rem; opacity: .55; margin-left: .12rem; }

/* Respaldo de la tarjeta de categoría: cuando el producto insignia todavía no tiene
   foto, en vez del placeholder pastel (que dentro de un bloque de color se lee como
   error de carga) sale el ícono monoline de la categoría. Es material de marca y no
   finge ser una fotografía — importante en Arma tu PC, donde las torres las arma la
   tienda y las fotos reales todavía no existen. */
.cc-fallback { display: none; }
.cat-card.is-noimg .cc-img { display: none; }
.cat-card.is-noimg .cc-fallback {
  display: block; position: absolute; right: -4%; bottom: -6%;
  width: 62%; color: currentColor; opacity: .3;
  transition: transform .45s var(--ease-spring), opacity .3s;
}
.cat-card.is-noimg .cc-fallback svg { width: 100%; height: auto; stroke-width: 1.1; }
@media (hover: hover) {
  .cat-card.is-noimg:hover .cc-fallback { transform: translate(-4%, -6%) rotate(-4deg); opacity: .42; }
}
@media (prefers-reduced-motion: reduce) { .cat-card.is-noimg .cc-fallback { transition: none; } }

/* ============================================================
   ÍCONOS ANIMADOS (v25)
   ------------------------------------------------------------
   Reemplazan la idea de traer Lordicon. Motivo: su reproductor es un
   `<script>` de cdn.lordicon.com y v23 se dedicó a sacar terceros del
   camino crítico (fuentes de Google incluidas); además sus íconos gratis
   piden atribución y son Lottie de 20-60 KB cada uno. Estos son los SVG
   que ya estaban, con el movimiento puesto en CSS: 0 KB de red, heredan
   `currentColor` y se apagan solos con `prefers-reduced-motion`.

   El marcado lo emite `ICONOS` en melo.js (y el HTML del hero/pasos usa
   las mismas clases). Cada parte que se mueve tiene su propia clase.
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {

  /* Escudo: el chulo se dibuja solo cada 5,2 s y el escudo respira. */
  .ic-escudo .ic-check { stroke-dasharray: 12; stroke-dashoffset: 0; animation: ic-chulo 5.2s var(--ease-gentle) infinite; }
  .ic-escudo .ic-cuerpo { transform-origin: 50% 55%; animation: ic-respira 5.2s var(--ease-gentle) infinite; }
  @keyframes ic-chulo { 0%, 8% { stroke-dashoffset: 12; } 26%, 100% { stroke-dashoffset: 0; } }
  @keyframes ic-respira { 0%, 100% { transform: scale(1); } 14% { transform: scale(1.08); } 30% { transform: scale(1); } }

  /* Billete: la moneda "cae" dentro cada 4,8 s. */
  .ic-plata .ic-moneda { transform-origin: 50% 50%; animation: ic-cae 4.8s var(--ease-spring) infinite; }
  @keyframes ic-cae { 0%, 55% { transform: translateY(0) scale(1); } 66% { transform: translateY(-3px) scale(.86); } 78% { transform: translateY(0) scale(1.1); } 86%, 100% { transform: translateY(0) scale(1); } }

  /* Camión: ruedas girando, carrocería con bache y líneas de viento. */
  .ic-camion .ic-rueda { transform-origin: center; animation: ic-gira 1.5s linear infinite; }
  .ic-camion .ic-caja { animation: ic-bache 1.5s var(--ease-gentle) infinite; }
  .ic-camion .ic-viento { stroke-dasharray: 4 3; animation: ic-viento 1.1s linear infinite; }
  @keyframes ic-gira { to { transform: rotate(360deg); } }
  @keyframes ic-bache { 0%, 100% { transform: translateY(0); } 46% { transform: translateY(-.7px); } }
  @keyframes ic-viento { to { stroke-dashoffset: -14; } }

  /* Caja sellada: se cierra la tapa. */
  .ic-sello .ic-tapa { stroke-dasharray: 26; animation: ic-tapa 5.6s var(--ease-gentle) infinite; }
  @keyframes ic-tapa { 0%, 10% { stroke-dashoffset: 26; } 32%, 100% { stroke-dashoffset: 0; } }

  /* Chat: los tres puntos escribiendo. */
  .ic-chat .ic-pto { animation: ic-escribe 1.4s var(--ease-gentle) infinite; }
  .ic-chat .ic-pto-2 { animation-delay: .16s; }
  .ic-chat .ic-pto-3 { animation-delay: .32s; }
  @keyframes ic-escribe { 0%, 60%, 100% { transform: translateY(0); opacity: .55; } 30% { transform: translateY(-2px); opacity: 1; } }

  /* Reloj: la aguja avanza a tirones, como un segundero. */
  .ic-reloj .ic-aguja { transform-origin: 12px 12px; animation: ic-segundero 6s steps(6) infinite; }
  @keyframes ic-segundero { to { transform: rotate(360deg); } }
}
/* Sin animación, los íconos deben verse COMPLETOS: los `stroke-dashoffset`
   iniciales viven dentro del @media de arriba justo por esto. */

/* ============================================================
   "COMPRAR ES MELO" — pasos rediseñados (v25)
   ------------------------------------------------------------
   Lo que había: número naranja arriba, ícono en un cuadrito debajo, y luego
   el texto. El dueño: «me molesta que esté el 1 y abajo de eso otro icono,
   tipo no me termina de convencer... el 1 grande dentro de la tarjeta pero
   aparte, efecto desbordar».
   Lo que hay ahora: el número es una MARCA DE AGUA gigante en Peace Sans que
   se sale de la tarjeta por la esquina (recortada por `overflow:hidden`), y
   el ícono sube a la misma línea del título, dentro de un disco naranja.
   Las tarjetas se unen con una línea punteada en escritorio.
   ============================================================ */
.steps { position: relative; }
/* Hilo que une los cuatro pasos (solo escritorio, solo decorativo) */
@media (min-width: 1000px) {
  .steps::before {
    content: ""; position: absolute; z-index: 0; left: 8%; right: 8%; top: 3.1rem; height: 2px;
    background: repeating-linear-gradient(90deg, var(--line-2) 0 7px, transparent 7px 15px);
  }
}
.step {
  position: relative; z-index: 1; overflow: hidden;
  padding: 1.15rem 1.2rem 1.25rem;
  transition: transform var(--t-mid) var(--ease-spring), box-shadow var(--t-mid), border-color var(--t-mid);
}
.step.step:hover { transform: translateY(-4px); box-shadow: var(--sh-md); border-color: var(--orange); }
/* El número, desbordando */
.step::before {
  counter-increment: step; content: counter(step, decimal-leading-zero);
  position: absolute; z-index: 0; right: -.14em; bottom: -.26em; margin: 0;
  font-family: var(--font-display); font-size: 7rem; line-height: .8;
  color: var(--orange); opacity: .15; letter-spacing: -.04em; pointer-events: none;
  transition: transform var(--t-slow) var(--ease-spring), opacity var(--t-mid);
}
.step.step:hover::before { transform: translate(-5px, -8px) rotate(-4deg); opacity: .24; }
/* Cabecera: disco naranja + título, en la misma línea */
.step-top { position: relative; z-index: 1; display: flex; align-items: center; gap: .65rem; margin-bottom: .5rem; }
.step-ic {
  display: grid; place-items: center; flex: none;
  width: 42px; height: 42px; border-radius: 50%;
  background: var(--orange); color: var(--cream);
  box-shadow: 0 8px 18px -8px rgba(255,61,27,.75);
  transition: transform var(--t-mid) var(--ease-spring);
}
.step.step:hover .step-ic { transform: scale(1.09) rotate(-6deg); }
.step-ic svg { width: 22px; height: 22px; }
.step h3 { position: relative; z-index: 1; font-weight: 800; font-size: 1.05rem; margin: 0; color: var(--ink); }
.step p { position: relative; z-index: 1; font-size: .9rem; color: var(--ink-soft); margin: 0; }

@media (prefers-reduced-motion: reduce) {
  .btn-wa::before, .btn-wa::after, .btn-wa > svg,
  .wa-float-eco, .wa-float-ic, .cat-hero-seal, .cat-plate { animation: none !important; }
  .step::before, .step-ic { transition: none; }
}


/* ============================================================
   ARMA TU PC — barra de progreso pegajosa (v25)
   ------------------------------------------------------------
   En escritorio el panel de la máquina va pegado al lado (grid de dos
   columnas), así que el medidor siempre está a la vista. En móvil ese panel
   queda DESPUÉS de las seis piezas, y elegir era a ciegas — reporte del
   dueño: «en celular no es tan fácil revisar el progreso de los componentes
   que selecciono». Esta barra es el espejo compacto del panel: número,
   rango, resolución y un "+N/-N" que salta cuando la elección mueve algo.
   Se esconde a partir de 1000px, donde el panel ya cumple ese papel.
   ============================================================ */
.pcb-mini {
  position: sticky; z-index: 40; top: calc(var(--header-h) + .4rem);
  display: grid; align-items: center; gap: .1rem .7rem;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  grid-template-areas: "num txt delta ver" "bar bar bar bar";
  background: var(--ink); color: var(--cream);
  border-radius: var(--r-pill); padding: .5rem .5rem .5rem .85rem;
  box-shadow: var(--sh-md); margin-bottom: 1rem; overflow: hidden;
}
@media (min-width: 1000px) { .pcb-mini { display: none; } }
.pcb-mini-num { grid-area: num; display: flex; align-items: baseline; gap: .08rem; }
.pcb-mini-num strong { font-family: var(--font-display); font-size: 1.75rem; line-height: 1; }
.pcb-mini-num small { font-size: .68rem; opacity: .5; }
.pcb-mini-txt { grid-area: txt; display: grid; min-width: 0; line-height: 1.2; }
.pcb-mini-txt b { font-family: var(--font-display); font-size: .98rem; color: var(--orange-bright); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pcb-mini-txt small { font-size: .72rem; opacity: .68; }
.pcb-mini-delta {
  grid-area: delta; font-weight: 800; font-size: .8rem; color: var(--bg-menta);
  opacity: 0; transform: translateY(4px); transition: opacity .2s, transform .2s var(--ease-spring);
}
.pcb-mini-delta.is-baja { color: #E8836F; }
.pcb-mini-delta.is-on { opacity: 1; transform: translateY(0); }
.pcb-mini-ver {
  grid-area: ver; font: inherit; font-size: .76rem; font-weight: 800; cursor: pointer;
  background: rgba(255,254,247,.14); color: var(--cream); border: 1px solid rgba(255,254,247,.28);
  border-radius: var(--r-pill); padding: .38rem .72rem; white-space: nowrap;
}
.pcb-mini-ver:hover { background: rgba(255,254,247,.24); }
.pcb-mini-bar {
  grid-area: bar; display: block; height: 3px; border-radius: 2px;
  background: rgba(255,254,247,.16); margin-top: .45rem; overflow: hidden;
}
.pcb-mini-bar i { display: block; height: 100%; width: 0; background: var(--orange); border-radius: 2px; transition: width .55s var(--ease-gentle); }
@media (max-width: 420px) {
  /* A 390px el botón se comía el texto: se queda el número, el rango y la barra. */
  .pcb-mini { grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "num txt delta" "bar bar bar"; }
  .pcb-mini-ver { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .pcb-mini-bar i, .pcb-mini-delta { transition: none; }
}

/* ============================================================
   AVISO DE OFERTA (v25) — el "pop in" que no bloquea
   ------------------------------------------------------------
   Pedido del dueño al sacar "Ofertas" del nav: «algo como un pop in que no
   bloquee navegación... tipo mensaje a la derecha... en toda la página».
   Por eso NO hay backdrop, NO hay `position:fixed` sobre el body con scroll
   bloqueado y NO roba el foco: es una tarjeta en una esquina y ya.
   Va a la DERECHA y por encima del botón flotante de WhatsApp; los toasts
   de prueba social viven a la izquierda, así que nunca se pisan.
   La lógica (cuándo sale, cuándo se calla) está en `initOfertaPop()`.
   ============================================================ */
.oferta-pop {
  position: fixed; z-index: 64;
  right: 16px; bottom: calc(var(--bottombar-h) + 14px);
  width: min(310px, calc(100vw - 32px));
  background: var(--cream); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--sh-lg);
  padding: .75rem .8rem .6rem; text-align: left;
  transform: translateY(14px) scale(.97); opacity: 0; pointer-events: none;
  transition: transform .42s var(--ease-spring), opacity .32s;
}
.oferta-pop.show { transform: none; opacity: 1; pointer-events: auto; }
/* En escritorio no hay barra inferior, pero sí el botón flotante de WhatsApp:
   la tarjeta se sienta encima de él, no sobre él. */
@media (min-width: 960px) { .oferta-pop { bottom: 94px; right: 22px; } }
.oferta-pop-x {
  position: absolute; top: 6px; right: 6px; z-index: 2;
  width: 26px; height: 26px; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--line); background: var(--cream-2); color: var(--ink-soft);
  font-size: .74rem; line-height: 1; display: grid; place-items: center;
}
.oferta-pop-x:hover { background: var(--ink); color: var(--cream); border-color: var(--ink); }
.oferta-pop-link {
  position: relative; display: grid; grid-template-columns: 62px minmax(0, 1fr);
  gap: .65rem; align-items: center; color: inherit;
}
.oferta-pop-foto {
  display: grid; place-items: center; width: 62px; height: 62px;
  border-radius: var(--r-md); background: var(--cream-3); overflow: hidden;
}
.oferta-pop-foto img { width: 84%; height: 84%; object-fit: contain; }
.oferta-pop-txt { display: grid; gap: .12rem; min-width: 0; padding-right: 1.4rem; }
.oferta-pop-kicker { font-size: .68rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--berry); }
.oferta-pop-name {
  font-size: .92rem; font-weight: 800; line-height: 1.2; color: var(--ink);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.oferta-pop-precio { font-size: .82rem; color: var(--ink-soft); }
.oferta-pop-precio s { opacity: .55; margin-right: .25rem; }
.oferta-pop-precio b { color: var(--ink); font-size: .94rem; }
.oferta-pop-off { position: absolute; right: 0; bottom: -2px; }
.oferta-pop-todas {
  display: block; margin-top: .55rem; padding-top: .5rem; border-top: 1px solid var(--line);
  font-size: .78rem; font-weight: 800; color: var(--orange);
}
.oferta-pop-todas:hover { text-decoration: underline; }
.oferta-pop:hover { box-shadow: 0 26px 60px -22px rgba(60,20,5,.5); }
@media (prefers-reduced-motion: reduce) {
  .oferta-pop { transition: opacity .2s; transform: none; }
}

/* Nota del comparador: explica la regla de "misma categoría" antes de que
   el cliente choque con ella, y avisa cuando cambiar de pestaña le limpió
   la selección. Ver `initComparador()` en melo.js. */
.cmp-nota { font-size: .84rem; color: var(--ink-soft); margin: .6rem 0 1rem; line-height: 1.45; }
.cmp-nota.is-aviso { color: var(--orange); font-weight: 800; }
.cmp-nota.flash { animation: cmp-nota-flash .9s var(--ease-gentle); }
@keyframes cmp-nota-flash { 0% { opacity: 0; transform: translateY(-3px); } 100% { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .cmp-nota.flash { animation: none; } }

/* ============================================================
   BUSCADOR — sugerencias y estados (v25)
   ------------------------------------------------------------
   Ver `bindSearch()` en melo.js. La pantalla vacía ya no lista
   productos al azar: muestra chips de "lo más buscado" y las
   búsquedas recientes del propio cliente.
   ============================================================ */
.search-sug { padding: .35rem .6rem .5rem; }
.search-sug-lab {
  font-size: .72rem; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ink-faint); margin: .35rem 0 .5rem;
}
.search-chips { display: flex; flex-wrap: wrap; gap: .45rem; }
.search-chip {
  font: inherit; font-size: .84rem; font-weight: 700; cursor: pointer;
  background: rgba(255,255,255,.6); border: 1px solid var(--line);
  border-radius: var(--r-pill); padding: .42rem .8rem; color: var(--ink);
  animation: chip-in .38s var(--ease-spring) both;
  animation-delay: calc(var(--i, 0) * 42ms);
  transition: transform .16s var(--ease-spring), background .16s, border-color .16s;
}
.search-chip:hover { transform: translateY(-2px); background: var(--orange); border-color: var(--orange); color: var(--cream); }
.search-chip.is-rec { color: var(--ink-soft); }
@keyframes chip-in { from { opacity: 0; transform: translateY(7px) scale(.96); } to { opacity: 1; transform: none; } }

/* Resultados: entran en cascada y la coincidencia va resaltada */
.search-item { animation: chip-in .3s var(--ease-gentle) both; animation-delay: calc(var(--i, 0) * 26ms); }
.search-item-name mark { background: rgba(255,61,27,.18); color: inherit; border-radius: 3px; padding: 0 .1em; }
.search-item.is-marcado { background: rgba(255,255,255,.75); box-shadow: inset 0 0 0 2px var(--orange); }

@media (prefers-reduced-motion: reduce) {
  .search-chip, .search-item { animation: none; }
}

/* Franja de reseñas de Google (sobre "Lo dice la gente"). Solo aparece cuando
   `CONFIG.google.perfil` está lleno — ver el comentario de `CONFIG.google` en
   data.js para por qué las reseñas NO se traen por API. */
.gg-franja {
  display: flex; flex-wrap: wrap; align-items: center; gap: .8rem 1.2rem;
  background: var(--cream); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: .85rem 1.1rem; margin-bottom: 1.3rem; box-shadow: var(--sh-sm);
}
.gg-marca { display: inline-flex; align-items: center; gap: .45rem; font-size: .9rem; }
.gg-rating { display: inline-flex; align-items: baseline; gap: .45rem; }
.gg-rating strong { font-family: var(--font-display); font-size: 1.5rem; line-height: 1; color: var(--ink); }
.gg-rating .stars { color: var(--orange); font-size: .95rem; }
.gg-rating small { color: var(--ink-soft); font-size: .82rem; }
.gg-acciones { display: flex; flex-wrap: wrap; gap: .5rem; margin-left: auto; }
@media (max-width: 560px) { .gg-acciones { margin-left: 0; width: 100%; } }
