/* QueCompro — hoja de estilo base.
   Sigue DOCS/100-BRANDING.md: azul sobrio, mucho espacio en blanco, una sola
   familia tipográfica, negrita escasa, nada de estética de liquidación.

   Sobre las animaciones: son cortas, suaves y ocurren una sola vez al
   cargar. Nada parpadea, nada rebota, nada pide atención de forma
   insistente — eso contradiría la calma que el producto busca transmitir
   (DOCS/20-PRODUCTO.md §5). Se desactivan por completo para quien pide
   menos movimiento en su sistema (§8, accesibilidad). */

:root {
  /* Identidad azul compartida — septiembre 2026. */
  --azul: #2459d3;
  --azul-claro: #3268e4;
  --azul-tenue: #eaf0fd;
  --marca-inicio: #163d9d;
  --marca-medio: #2459d3;
  --marca-fin: #5687ed;

  /* Verde: muy poco y con significado — solo señales positivas reales. */
  --verde: #15803d;
  --verde-tenue: #f0fdf4;

  /* Rojo: solo errores y avisos, nunca ofertas. */
  --rojo: #b91c1c;

  --texto: #18202f;
  --texto-suave: #5c6777; /* 4,4:1 sobre los fondos celestes (`--azul-tenue`) no llegaba al 4,5:1 de WCAG AA; ahora 5:1 (2026-10-02). */
  --borde: #e2e8f0;
  --fondo-suave: #f7f9fb;
  /* El relleno tenue de tarjetas/paneles seleccionados o "activos"
     (filtros, imagen de producto, columna de atributos del comparador,
     opción marcada). Antes cada lugar escribía su propio blanco-violeta
     a mano — `#f6f8fc` y `#f9fbff`, dos hex a 2 unidades de distancia en
     RGB, indistinguibles a simple vista pero dos valores sueltos en vez
     de uno solo reusado (2026-08-13). */
  --fondo-tenue: #f6f8fc;

  /* Mismo ancho editorial que la Home; las vistas densas conservan su grid. */
  --ancho: 84rem;
  --radio: 20px;
  --radio-chico: 12px;

  /* Sombras neutras compartidas, con profundidad suave. */
  --sombra: 0 1px 2px rgba(23, 45, 83, .05), 0 2px 8px rgba(23, 45, 83, .04);
  --sombra-alta: 0 2px 4px rgba(23, 45, 83, .06), 0 12px 28px rgba(23, 45, 83, .12);
  --borde-suave: #e6eaf1;

  --transicion: 180ms cubic-bezier(.2, .7, .3, 1);

  /* Íconos decorativos como máscara CSS: no llevan información, así que no
     tienen por qué estar en el HTML. Van acá para no repetir el `data:` en
     cada regla que los use. */
  --icono-rayo: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M13 2 4.5 13.5H11l-1 8.5 8.5-11.5H12l1-8.5Z'/%3E%3C/svg%3E");
  /* Tilde blanca, para pintar sobre un fondo ya coloreado (la marca de
     selección del comparador). */
  --icono-tilde: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 5 5 9-11'/%3E%3C/svg%3E");

  /* Escala tipográfica y de espaciado (DOCS/100-BRANDING.md §10).
     Se adopta gradualmente: se usa en las secciones que se van rediseñando,
     no se sale a convertir cada valor suelto existente de una vez. */
  --t-xs: 0.75rem;
  --t-sm: 0.875rem;
  --t-base: 1rem;
  --t-md: 1.125rem;
  --t-lg: 1.5rem;
  --t-xl: 2rem;

  --e-1: 0.25rem;
  --e-2: 0.5rem;
  --e-3: 0.75rem;
  --e-4: 1rem;
  --e-5: 1.5rem;
  --e-6: 2.25rem;
  --e-7: 3.5rem;
  --e-8: 5.5rem;
}

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

/* Foco global: cubre todo lo interactivo que no define su propio anillo
   (tarjetas, botones de texto, íconos de nav, migas de pan). Donde ya hay
   un tratamiento a medida (`.buscador input`, `.filtro select`) ese
   selector es más específico y gana, así que conviven sin pisarse — esto
   es la red de base, no un reemplazo. */
:focus-visible {
  outline: 2px solid var(--azul-claro);
  outline-offset: 2px;
}

body {
  margin: 0;
  overflow-x: clip;
  /* Inter es la familia definida en branding; hasta incorporarla como
     archivo propio, se usa la del sistema como reserva. */
  font-family: Inter, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 16px;
  line-height: 1.55;
  color: var(--texto);
  background: #fff;
  -webkit-font-smoothing: antialiased;
}

/* Las bandas de ancho completo se dibujan con `100vw`, que incluye el ancho
   de la barra de scroll. Sin esto aparece un desplazamiento horizontal de
   unos pocos píxeles en Windows. `clip` y no `hidden`: `hidden` convierte al
   elemento en un contenedor scrolleable — recorta la barra pero la página
   sigue desplazándose esos píxeles con la rueda o el trackpad. `clip`
   recorta y además impide el desplazamiento, que es lo que se busca. */
html { overflow-x: clip; }

main {
  max-width: var(--ancho);
  margin: 0 auto;
  padding: 0 1.5rem 6rem;
}

a { color: var(--azul-claro); }

/* Los títulos pasan de 600 a 700 con el tracking más cerrado. En la
   referencia los encabezados tienen bastante más peso que el texto, y ese
   contraste es la mitad de lo que hace que la página se vea ordenada: con
   600 y tracking flojo todo queda en un gris tipográfico parejo. */
h1, h2 { font-weight: 700; letter-spacing: -0.03em; }
h2 { font-size: 1.6rem; line-height: 1.2; margin: 0 0 0.35rem; }

/* Accesible para lectores de pantalla, invisible en pantalla (§8). */
.oculto {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* --- Animación de entrada --------------------------------------------
   Un desplazamiento mínimo y un fundido.

   Antes esto llevaba `backwards` y un `--retraso` que escalonaba las
   secciones. Tenía un problema serio: `backwards` aplica el fotograma
   inicial —`opacity: 0`— durante toda la espera previa, así que si la
   animación no llega a arrancar (pestaña en segundo plano, motor que
   throttlea, cualquier caso donde el navegador no compone la página) la
   sección se queda invisible para siempre. No es teórico: así apareció,
   con la Home entera en blanco salvo la cabecera y el pie.

   El contenido no puede depender de que una animación termine para ser
   visible. Sin `backwards` y sin espera, el estado en reposo es el
   visible: si la animación corre se ve el fundido, y si no corre se ve la
   página. El escalonado se pierde — es un adorno de 180ms y no vale el
   riesgo de servir una página vacía. */

@keyframes aparecer {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

.aparece {
  animation: aparecer 460ms var(--transicion);
}

/* --- Cabecera --- */

/* `position: relative` + `z-index` para que la cabecera se pinte por
   encima del contenido, no solo el menú que cuelga de ella.
   `.menu-mas-lista` ya traía `z-index: 25`, pero como la cabecera era
   `static` ese número competía en el apilamiento de la página contra
   secciones que vienen después en el documento y ganan por orden.
   Resultado: al abrir el ☰ en tablet, la lista quedaba **debajo** del
   bloque de la pregunta y del `h1` — se veía «Comparador» cruzado con el
   título, y ninguno de los tres enlaces se podía tocar (2026-08-21).

   Es la cabecera la que lleva el z-index y no la lista: cualquier otra
   cosa que cuelgue de acá —el buscador con sugerencias, el bloque de
   cuenta— tiene el mismo problema y esta es la única forma de
   resolverlo para todas de una vez. */
.cabecera {
  position: relative;
  z-index: 50;
  background: #fff;
  border-bottom: 1px solid var(--borde-suave);
}

.cabecera-interior {
  max-width: var(--ancho);
  margin: 0 auto;
  padding: 0 1.5rem;
  /* `min-height` y no `height`: por debajo de 34rem la nav envuelve en
     más de una línea (ver el media query de `.nav-cabecera` más abajo) y
     una altura fija recortaba ese contenido en vez de dejar crecer la
     caja — quedaba fuera del área visible en vez de apilado debajo. */
  min-height: 4.5rem;
  display: flex;
  align-items: center;
  gap: 2.5rem;
}

/* La navegación arranca pegada al logo y el bloque de cuenta se va al
   extremo derecho: `margin-left: auto` sobre el primer ícono parte la nav
   en dos grupos sin necesidad de dos contenedores.

   `flex-wrap: wrap` de base (no solo bajo el quiebre de 34rem de más
   abajo): en anchos de tablet (~700-850px) el conjunto completo de
   enlaces + buscador + cuenta no entra en una sola línea pero tampoco
   dispara el quiebre mobile — sin esto, el sobrante empujaba la
   página entera a scroll horizontal en vez de simplemente pasar a una
   segunda línea. En desktop, donde todo entra de sobra, no cambia nada
   (envolver es un no-op si no hace falta). */
.nav-cabecera {
  flex: 1;
  display: flex;
  flex-wrap: wrap;
  row-gap: 0.6rem;
  align-items: center;
  /* Con la sesión iniciada la barra lleva, además del catálogo, cinco
     accesos de cuenta y el selector de moneda. Con 1.75rem de
     separación no entraba en una línea **ni al ancho máximo del
     contenedor** (1200px, medido 2026-08-20): la fila de cuenta caía
     debajo y la barra se veía partida. */
  gap: 1.25rem;
}

.nav-cabecera a {
  color: #3f4756;
  text-decoration: none;
  font-size: 0.95rem;
  font-weight: 500;
  transition: color var(--transicion), opacity var(--transicion);
}

.nav-cabecera a:hover { color: var(--azul); }

.nav-cuenta {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.9rem;
  transition: opacity var(--transicion);
}

/* Con el buscador de la cabecera abierto (`.buscando`, prendida por
   `buscador-cabecera.js`), los enlaces y el bloque de cuenta se
   desvanecen en vez de quedarse ahí compitiendo con la caja que se
   expande encima: no hay ancho de sobra en la nav para los ~336px del
   buscador sin superponerse a algún enlace, y taparlo a mitad de palabra
   se leía como una caja rota, no como una intencional. Se desvanecen
   pero no se mueven de su lugar — es justo lo que pide la consigna,
   nada de la nav se corre. */
.nav-cabecera.buscando a,
.nav-cabecera.buscando > .nav-cuenta {
  opacity: 0;
  pointer-events: none;
}

/* Las sugerencias del buscador también son enlaces dentro de la nav: la
   regla de arriba las dejaba invisibles y sin clic, y el buscador de la
   cabecera parecía no sugerir nada (2026-10-16). Una clase más de
   especificidad las devuelve. */
.nav-cabecera.buscando .sugerencias a {
  opacity: 1;
  pointer-events: auto;
}

/* --- Menú "Más" (Marcas/Tiendas/Comparador) ---
   En desktop es invisible como estructura: `display: contents` en los dos
   niveles hace que los tres `<a>` se vean como hermanos sueltos de
   `.nav-cabecera`, exactamente como estaban antes de envolverlos (mismo
   truco que `.tarjeta-cuerpo`). El checkbox y el botón ☰ solo existen
   para mobile. */
.menu-mas { display: contents; }
.menu-mas-lista { display: contents; }
/* `.nav-icono` (más abajo en la hoja) también pone `display: inline-flex`
   — misma especificidad (una clase), y por orden en el archivo le
   ganaría a este `display: none`. Se repite el selector a propósito,
   mismo truco que ya usa `.nav-duplica-mobile.nav-duplica-mobile`, para
   no depender de en qué orden queden las dos reglas. */
.menu-mas-boton.menu-mas-boton { display: none; }
.menu-mas-check {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* 64rem y no 40rem: con la sesión iniciada, entre 40rem y 64rem la barra
   ya no entra en una línea ni con los accesos de cuenta en solo ícono
   (medido 2026-08-20). Antes de ese ajuste este colapso era solo para
   teléfonos, y en el medio la cabecera se partía en dos y hasta tres
   filas. Los tres destinos siguen a un toque, en el mismo menú que ya
   existía, y sin JavaScript. */
@media (max-width: 64rem) {
  .menu-mas {
    display: inline-flex;
    position: relative;
  }

  /* Especificidad doblada por el mismo motivo que la regla de arriba —
     tiene que ganarle a `.nav-icono` acá también. */
  .menu-mas-boton.menu-mas-boton { display: inline-flex; }

  .menu-mas-check:checked + .menu-mas-boton {
    background: var(--azul-tenue);
    color: var(--azul);
  }

  /* Colapsado por defecto: mismo criterio que el acordeón de specs y
     filtros (§ Acordeón) — todo el contenido sigue en el DOM, solo
     cambia si se ve o no, así que funciona igual sin JavaScript
     (`:checked` es puramente CSS). */
  .menu-mas-lista {
    display: none;
    position: absolute;
    top: calc(100% + 0.5rem);
    left: 0;
    z-index: 25;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 9.5rem;
    padding: 0.4rem;
    border: 1px solid var(--borde-suave);
    border-radius: var(--radio);
    background: #fff;
    box-shadow: var(--sombra-alta);
  }

  .menu-mas-check:checked ~ .menu-mas-lista { display: flex; }

  .menu-mas-lista a {
    padding: 0.65rem 0.75rem;
    border-radius: 8px;
    min-height: 2.75rem; /* mínimo táctil, igual criterio que `.nav-icono` */
    display: flex;
    align-items: center;
  }

  .menu-mas-lista a:hover { background: var(--azul-tenue); }
}

/* --- Comparador: portada editorial y encuadre parejo (agosto 2026) --- */

.comparador-portada {
  position: relative;
  z-index: 5;
  isolation: isolate;
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(15rem, .75fr);
  align-items: center;
  gap: clamp(2rem, 6vw, 6rem);
  min-height: 25rem;
  margin: var(--e-4) 0 var(--e-8);
  padding: clamp(2rem, 6vw, 5rem);
  /* Las sugerencias del buscador salen por debajo de la portada. Recortar
     acá también las recortaba a ellas: la decoración queda contenida por
     sus propias medidas, mientras el desplegable puede superponerse a la
     sección siguiente como cualquier autocomplete. */
  overflow: visible;
  border-radius: 2rem;
  color: #fff;
  background:
    radial-gradient(circle at 78% 25%, rgba(117, 156, 215, .55), transparent 28%),
    linear-gradient(125deg, #15243a 0%, #203b65 52%, #3463a6 100%);
  box-shadow: 0 1.4rem 3.5rem rgba(21, 36, 58, .18);
}

.comparador-portada::after {
  content: "";
  position: absolute;
  z-index: -1;
  width: 22rem;
  height: 22rem;
  right: 0;
  bottom: 0;
  border: 1px solid rgba(255, 255, 255, .2);
  border-radius: 50%;
  /* Sin anillos exteriores: ahora que el contenedor deja salir el
     autocomplete, una sombra expansiva también saldría del borde. */
  box-shadow: none;
}

/* El panel es absoluto para quedar pegado al campo, pero se reserva debajo
   el espacio que ocupa: así no tapa el título de Categorías ni parece que
   termina cortado contra la siguiente sección. */
.comparador-portada:has(.comparador-sugerencias-panel) {
  margin-bottom: calc(var(--e-8) + 13.5rem);
}

.comparador-portada:has(.comparador-sugerencias-panel.sin-resultados) {
  margin-bottom: calc(var(--e-8) + 3.5rem);
}

.comparador-portada-contenido { max-width: 43rem; }

.comparador-etiqueta {
  display: inline-block;
  margin-bottom: var(--e-3);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: .11em;
  text-transform: uppercase;
}

.comparador-portada .comparador-etiqueta { color: #c8d9f4; }

.comparador-portada h1 {
  max-width: 9ch;
  margin: 0 0 var(--e-4);
  font-size: clamp(3rem, 7vw, 5.8rem);
  line-height: .93;
  letter-spacing: -.065em;
  color: #fff;
  text-wrap: balance;
}

.comparador-portada p {
  max-width: 38rem;
  margin: 0;
  font-size: clamp(1rem, 1.7vw, 1.25rem);
  line-height: 1.6;
  color: rgba(255, 255, 255, .82);
}

.comparador-portada-buscador {
  display: flex;
  gap: .55rem;
  width: min(100%, 39rem);
  margin-top: var(--e-5);
  padding: .4rem;
  border: 1px solid rgba(255, 255, 255, .2);
  border-radius: 999px;
  background: rgba(255, 255, 255, .96);
  box-shadow: 0 1rem 2.2rem rgba(0, 0, 0, .18);
}

.comparador-portada-campo {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  min-width: 0;
}

.comparador-sugerencias {
  position: absolute;
  z-index: 50;
  top: calc(100% + .8rem);
  left: -.4rem;
  right: -.4rem;
  color: var(--texto);
}

.comparador-sugerencias:empty { display: none; }

.comparador-sugerencias-panel {
  display: block;
  /* La caja completa queda dentro del viewport incluso en una ventana
     baja. El contenido sí scrollea adentro, con bordes superior e inferior
     siempre visibles. */
  max-height: min(22rem, 42vh);
  padding: .45rem;
  overflow-y: auto;
  border: 1px solid var(--borde-suave);
  border-radius: 1rem;
  background: #fff;
  box-shadow: 0 1.25rem 3rem rgba(21, 36, 58, .24);
}

.comparador-sugerencias-panel > a {
  display: grid;
  grid-template-columns: 3.3rem minmax(0, 1fr) auto;
  align-items: center;
  gap: .75rem;
  min-width: 0;
  padding: .55rem;
  border-radius: .75rem;
  color: var(--texto);
  text-decoration: none;
}

.comparador-sugerencias-panel > a:hover,
.comparador-sugerencias-panel > a:focus-visible {
  outline: 0;
  background: var(--azul-tenue);
}

.comparador-sugerencia-imagen {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.3rem;
  height: 3.3rem;
  overflow: hidden;
  border-radius: .65rem;
  background: var(--fondo-tenue);
}

.comparador-sugerencia-imagen .miniatura { width: 100%; height: 100%; object-fit: contain; }
.comparador-sugerencia-imagen .miniatura-monograma { width: 2.5rem; height: 2.5rem; }
.comparador-sugerencia-texto { display: flex; flex-direction: column; min-width: 0; text-align: left; }
.comparador-sugerencia-texto strong { overflow-wrap: anywhere; line-height: 1.25; }
.comparador-sugerencia-texto small { margin-top: .15rem; color: var(--texto-suave); }
.comparador-sugerencias-panel > a > svg { color: var(--azul); }
.comparador-sugerencias-vacio { display: block; padding: .9rem; color: var(--texto-suave); text-align: left; }

.comparador-portada-campo > svg {
  position: absolute;
  left: .9rem;
  color: var(--texto-suave);
  pointer-events: none;
}

.comparador-portada-campo input {
  width: 100%;
  min-width: 0;
  padding: .75rem .8rem .75rem 2.7rem;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--texto);
  font: inherit;
}

.comparador-portada-buscador:focus-within {
  box-shadow: 0 0 0 3px rgba(190, 211, 245, .34), 0 1rem 2.2rem rgba(0, 0, 0, .18);
}

.comparador-portada-buscador button {
  flex: 0 0 auto;
  min-width: 6.5rem;
  padding: .7rem 1.1rem;
  border: 0;
  border-radius: 999px;
  background: var(--azul);
  color: #fff;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

.comparador-portada-buscador button:hover { background: #163d9d; }

.comparador-beneficios {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-2);
  margin: var(--e-5) 0 0;
  padding: 0;
  list-style: none;
}

.comparador-beneficios li {
  padding: .55rem .85rem;
  border: 1px solid rgba(255, 255, 255, .2);
  border-radius: 999px;
  background: rgba(255, 255, 255, .09);
  font-size: var(--t-xs);
  font-weight: 600;
  backdrop-filter: blur(8px);
}

.comparador-portada-visual {
  position: relative;
  min-height: 17rem;
}

.comparador-portada-tarjeta {
  position: absolute;
  top: 50%;
  width: clamp(9rem, 15vw, 13rem);
  aspect-ratio: 3 / 4;
  border: 1px solid rgba(255, 255, 255, .28);
  border-radius: 1.7rem;
  background: linear-gradient(150deg, rgba(255,255,255,.3), rgba(255,255,255,.08));
  box-shadow: 0 1.5rem 3rem rgba(0,0,0,.24);
  backdrop-filter: blur(12px);
}

.comparador-portada-tarjeta::before,
.comparador-portada-tarjeta::after {
  content: "";
  position: absolute;
  left: 16%;
  right: 16%;
  border-radius: 999px;
  background: rgba(255,255,255,.3);
}

.comparador-portada-tarjeta::before { top: 15%; height: 48%; border-radius: 1rem; }
.comparador-portada-tarjeta::after { bottom: 15%; height: .55rem; }
.comparador-portada-tarjeta-a { left: 3%; transform: translateY(-52%) rotate(-8deg); }
.comparador-portada-tarjeta-b { right: 3%; transform: translateY(-48%) rotate(8deg); }

.comparador-portada-vs {
  position: absolute;
  z-index: 2;
  top: 50%;
  left: 50%;
  display: grid;
  place-items: center;
  width: 4.4rem;
  height: 4.4rem;
  transform: translate(-50%, -50%);
  border: 1px solid rgba(255,255,255,.45);
  border-radius: 50%;
  background: #fff;
  color: var(--azul);
  font-size: 1.1rem;
  font-weight: 800;
  box-shadow: 0 1rem 2rem rgba(0,0,0,.2);
}

.comparador-categorias { margin-bottom: var(--e-8); }

.comparador-resultados { margin: 0 0 var(--e-8); }

.comparador-resultados-grilla {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--e-3);
}

.comparador-resultado {
  display: grid;
  grid-template-columns: 5.4rem minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--e-3);
  min-width: 0;
  padding: var(--e-3);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
  color: var(--texto);
  text-decoration: none;
  box-shadow: 0 .7rem 1.8rem rgba(23, 45, 83, .055);
  transition: transform var(--transicion), border-color var(--transicion), box-shadow var(--transicion);
}

.comparador-resultado:hover {
  transform: translateY(-2px);
  border-color: #bfd0ee;
  box-shadow: 0 1rem 2.2rem rgba(29, 53, 91, .11);
}

.comparador-resultado-imagen {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 5.4rem;
  height: 5.4rem;
  overflow: hidden;
  border-radius: .9rem;
  background: linear-gradient(145deg, #f9fbff, #f2f5fa);
}

.comparador-resultado-imagen .miniatura { width: 100%; height: 100%; object-fit: contain; }
.comparador-resultado-imagen .miniatura-monograma { width: 3.2rem; height: 3.2rem; }

.comparador-resultado-texto { display: flex; flex-direction: column; min-width: 0; }
.comparador-resultado-categoria { font-size: var(--t-xs); font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--azul); }
.comparador-resultado-texto strong { overflow-wrap: anywhere; line-height: 1.3; }
.comparador-resultado-texto > span:last-child { margin-top: .25rem; font-size: var(--t-xs); color: var(--texto-suave); }
.comparador-resultado-flecha { flex-shrink: 0; color: var(--azul); }

.comparador-seccion-encabezado { max-width: 42rem; margin-bottom: var(--e-5); }
.comparador-seccion-encabezado .comparador-etiqueta,
.comparador-categoria-portada .comparador-etiqueta { color: var(--azul); }
.comparador-seccion-encabezado h2 { margin: 0 0 var(--e-2); font-size: clamp(1.8rem, 4vw, 2.7rem); }
.comparador-seccion-encabezado p { margin: 0; color: var(--texto-suave); }

.comparador-categorias .categoria-icono {
  min-height: 10.5rem;
  border: 1px solid var(--borde-suave);
  background: linear-gradient(145deg, #fff 35%, #f5f7fc 100%);
  box-shadow: 0 .8rem 2rem rgba(23, 45, 83, .06);
}

.comparador-categorias .categoria-icono:hover {
  transform: translateY(-3px);
  border-color: #bfd0ee;
  box-shadow: 0 1rem 2.5rem rgba(29, 53, 91, .12);
}

.comparador-categoria-portada {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 2rem);
  margin: var(--e-4) 0 var(--e-5);
  padding: clamp(1.5rem, 4vw, 2.6rem);
  border: 1px solid #e0e8f5;
  border-radius: 1.6rem;
  background:
    radial-gradient(circle at 90% 0, rgba(65, 112, 184, .15), transparent 30%),
    linear-gradient(120deg, #f9fbff, #edf3fd);
}

.comparador-categoria-portada h1 { margin: 0 0 var(--e-2); font-size: clamp(2rem, 5vw, 3.2rem); letter-spacing: -.045em; }
.comparador-categoria-portada .apoyo { max-width: 50rem; }

.comparador-categoria-icono {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: clamp(4.5rem, 9vw, 6.5rem);
  aspect-ratio: 1;
  border-radius: 1.4rem;
  background: var(--azul);
  color: #fff;
  box-shadow: 0 1rem 2rem rgba(36, 89, 160, .2);
}

.comparador-categoria-icono svg { width: 42%; height: 42%; }

.comparador-herramientas {
  margin-bottom: var(--e-5);
  padding: var(--e-4);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
  box-shadow: 0 .8rem 2.2rem rgba(23, 45, 83, .055);
}

.comparador-herramientas .comparador-buscador { margin-bottom: 0; }

.elegible-imagen,
.vs-hero-imagen {
  position: relative;
  overflow: hidden;
  border-radius: 1.2rem;
  background: linear-gradient(145deg, #f9fbff, #f4f6fb);
}

[data-encuadre-producto] img.imagen-encuadrada {
  transform-origin: 0 0;
  transform: translate(var(--encuadre-x), var(--encuadre-y)) scale(var(--encuadre-escala));
}

/* La regla general del comparador agranda la miniatura al pasar el mouse.
   En una foto ya encuadrada eso borraría temporalmente la traslación que
   centra el contenido y la haría saltar. Se conserva el encuadre exacto. */
[data-encuadre-producto]:hover img.imagen-encuadrada {
  transform: translate(var(--encuadre-x), var(--encuadre-y)) scale(var(--encuadre-escala));
}

@media (max-width: 48rem) {
  .comparador-portada { grid-template-columns: 1fr; min-height: auto; }
  .comparador-portada-visual { display: none; }
  .comparador-portada h1 { font-size: clamp(3rem, 15vw, 4.8rem); }
  .comparador-resultados-grilla { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 40rem) {
  .comparador-portada { margin-top: var(--e-3); padding: 1.5rem 1.35rem; border-radius: 1.35rem; }
  .comparador-portada h1 {
    max-width: none;
    font-size: clamp(2.25rem, 10vw, 2.8rem);
    line-height: 1.05;
  }
  .comparador-beneficios { gap: .4rem; }
  .comparador-beneficios li { padding: .45rem .65rem; }
  .comparador-portada-buscador { border-radius: 1rem; }
  .comparador-portada-buscador button { min-width: auto; padding-inline: .9rem; }
  .comparador-resultados-grilla { grid-template-columns: 1fr; }
  .comparador-resultado { grid-template-columns: 4.7rem minmax(0, 1fr) auto; }
  .comparador-resultado-imagen { width: 4.7rem; height: 4.7rem; }
  .comparador-categoria-portada { align-items: flex-start; padding: 1.25rem; border-radius: 1.2rem; }
  .comparador-categoria-icono { width: 3.6rem; border-radius: 1rem; }
  .comparador-herramientas { padding: var(--e-3); }
}

/* Ícono solo: el SVG mide 20px, pero el área de toque no puede ser el
   ícono mismo (§8, accesibilidad — 44px es el mínimo cómodo en mobile). El
   padding negativo compensa el espacio extra para que no empuje el resto
   del nav. */
.nav-icono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  margin: -0.875rem;
  border-radius: 999px;
  transition: background var(--transicion), color var(--transicion);
}

.nav-icono:hover { background: var(--fondo-suave); }

/* El botón de salir vive en la misma nav que los enlaces: se lo despoja de
   su apariencia de botón para que no rompa el ritmo visual de la lista. */
.salir-cuenta { display: contents; }

.salir-cuenta button {
  font: inherit;
  color: var(--texto-suave);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  transition: color var(--transicion);
}

.salir-cuenta button:hover { color: var(--azul); }

/* El wordmark gana presencia con peso y tracking cerrado. «Qué» queda en
   700 para sostener la lectura y «Compro» sube a 800: la diferencia es
   deliberada, pero no tan grande como para partir el nombre en dos. */
.marca {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 1.55rem;
  font-weight: 700;
  text-decoration: none;
  letter-spacing: -0.04em;
  transition: opacity var(--transicion);
}

/* El nombre en dos tonos: «Qué» en tinta y «Compro» en degradado violeta.
   Es lo que separa las dos palabras sin un espacio ni una mayúscula que
   corte la lectura — viene de la propuesta de logotipo del operador
   (2026-08-21, `DOCS/100-BRANDING.md` §12).

   El isotipo sigue en violeta y la primera palabra en tinta: con las dos
   palabras en violeta el logo pierde el contraste interno que lo hace
   reconocible de lejos, que es todo lo que un isotipo tiene que lograr.
   El tramo violeta es el segundo, no el primero, porque el ojo entra por
   la izquierda y ahí ya está el símbolo. */
.marca-isotipo { flex-shrink: 0; }
.marca-que { color: var(--texto); font-weight: 700; }
.marca-compro {
  /* El tracking negativo reduce la caja: el degradado necesita este
     margen de pintura para no cortar el borde derecho de la última o. */
  display: inline-block;
  padding-inline-end: .12em;
  margin-inline-end: -.12em;
  color: var(--azul);
  font-weight: 800;
  background: linear-gradient(
    135deg,
    var(--marca-inicio) 0%,
    var(--marca-medio) 52%,
    var(--marca-fin) 100%
  );
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* En contraste forzado el degradado deja paso al color que el sistema
   garantiza legible. */
@media (forced-colors: active) {
  .marca-compro {
    background: none;
    color: LinkText;
    -webkit-text-fill-color: currentColor;
  }
  .marca-isotipo circle,
  .marca-isotipo path { stroke: LinkText; }
}

.marca:hover { opacity: .65; }

/* Variante del ícono de nav que sí muestra su etiqueta: deja de ser un
   círculo de 44px y pasa a ser una píldora, para que el área de toque
   siga cubriendo texto e ícono juntos. */
.nav-icono-texto {
  width: auto;
  gap: 0.4rem;
  margin: -0.875rem 0;
  padding: 0 0.7rem;
  font-size: 0.95rem;
}

/* En mobile la cabecera no entra en una línea. Se parte en dos —logo
   arriba, navegación abajo— en vez de dejar que el `overflow-x: clip` del
   documento recorte enlaces y los vuelva inalcanzables.

   La regla iba sobre `.cabecera` (el `<header>`, que no es flex) en vez de
   `.cabecera-interior` (el contenedor flex real) — no tenía efecto, y sin
   este quiebre el logo y la nav se quedaban forzados en la misma fila
   angosta. No se notaba con pocos enlaces, pero al sumar el buscador acá
   (§ buscador de la cabecera) la nav quedaba comprimida contra el logo. */
@media (max-width: 34rem) {
  /* `justify-content: flex-start` y no `center`: el logo es la única
     cosa en su fila así que centrarlo se ve bien solo, pero la fila de
     enlaces de abajo (`.nav-cabecera`) ya quedó alineada a la
     izquierda (ver su comentario) — con el logo centrado arriba y los
     enlaces pegados al borde izquierdo debajo, las dos filas no
     comparten ningún borde y el conjunto se lee descentrado igual,
     aunque cada fila esté bien centrada/alineada por separado. Todo
     arrancando del mismo borde izquierdo (logo incluido) es lo que
     finalmente hace que las dos filas se vean como parte de un mismo
     bloque prolijo. */
  .cabecera-interior {
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: 0.75rem;
    padding-top: 0.85rem;
    padding-bottom: 0.85rem;
  }

  /* Antes forzaba a `.nav-cuenta` a su propia fila completa
     (`flex: 1 1 100%`), centrada aparte de los enlaces de catálogo.
     Con seis enlaces (o menos, ya recortado por `.nav-duplica-mobile`)
     eso no entra en una sola línea de 327px, así que igual arma dos
     filas — pero `.nav-cuenta` como bloque no cabe junto a Marcas/
     Tiendas/Comparador, y termina en su propia línea de un ancho
     distinto al de arriba. Centradas cada una por separado, ninguna
     alinea su borde con la de encima: eso es lo que se lee
     "descentrado", no un error de cálculo — es que centrar dos líneas
     de ancho distinto nunca alinea sus bordes entre sí.

     Alineado a la izquierda en vez de centrado esquiva el problema de
     raíz: un bloque de texto que envuelve a varias líneas se lee
     prolijo cuando arranca todas las líneas desde el mismo borde,
     tenga las que tenga — center solo se ve prolijo con una única
     línea, que es como está el resto de esta cabecera (logo). */
  .nav-cabecera {
    flex: 1 1 auto;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.6rem;
    row-gap: 0.7rem;
  }

  /* El menú plegado permite compartir fila con el logo. El panel se
     ancla a la derecha del botón para no salir del viewport angosto. */
  .menu-mas-lista {
    left: auto;
    right: 0;
  }

  /* `.nav-icono-texto` (Historial/Alertas) trae `padding: 0 0.7rem` para
     agrandar el área de toque sin achicar el ícono — pensado para vivir
     en medio de una fila, con vecinos a los dos lados que absorben ese
     padding en el espacio entre ellos. Acá el primer ícono visible del
     grupo (Historial: Favoritos/Configuración siguen en el DOM antes,
     solo ocultos por `.nav-duplica-mobile`, así que `:first-child` los
     agarra a ellos y no sirve) queda con ese padding empujando su
     ícono 0.7rem a la derecha del borde real — mientras "Marcas"
     (arriba, sin padding) arranca justo en ese borde. Es el
     desalineado que seguía viéndose con las dos filas ya ancladas al
     mismo `left`: borde de caja igual no es contenido visible igual
     cuando una fila tiene relleno y la otra no.

     Se corrige corriendo el GRUPO entero 0.7rem a la izquierda (no un
     hijo puntual, por el problema de arriba) — Historial/Alertas/Salir
     mantienen su espaciado relativo entre sí, todo el bloque se mueve
     junto. */
  .nav-cuenta {
    margin-left: -0.7rem;
    gap: 1.1rem;
  }

  .marca { font-size: 1.35rem; }
}

/* --- Nav inferior (mobile) ---

   Los cinco accesos que en mobile hay que poder tocar sin abrir ningún
   menú: Inicio, Buscar, Categorías, Favoritos, Perfil. La cabecera de
   arriba sigue existiendo pero recortada a lo que esta barra no cubre
   (`.nav-duplica-mobile`, más abajo) — Marcas/Tiendas/Comparador y, con
   sesión, Historial/Alertas/Salir. Repetir el mismo destino en las dos
   barras es lo que se veía desarmado: no hay forma de meter los nueve
   destinos en una sola barra sin que cada uno quede minúsculo, y estos
   cinco son los que se usan todos los días.

   `40rem` es el corte que usa toda la reconstrucción mobile de agosto
   2026 — nav inferior, acordeones, comparador por pestañas — para no
   sumar un ancho más a los que ya conviven en el resto de la hoja (ver
   nota en el media query de la ficha de producto). Las variables CSS no
   sirven adentro de un `@media` (la especificación no lo permite), así
   que el número va escrito literal en cada uno; si cambia, cambia en
   los tres lugares que lo usan. */
.nav-inferior { display: none; }

@media (max-width: 40rem) {
  .nav-inferior {
    position: fixed;
    z-index: 30;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    justify-content: space-around;
    background: #fff;
    border-top: 1px solid var(--borde-suave);
    /* `env(safe-area-inset-bottom)` es el hueco de la barra de gestos en
       iPhone: sin esto el último ícono queda pegado al borde curvo de la
       pantalla, debajo de donde el dedo puede tocar cómodo. */
    padding: 0.4rem 0.25rem calc(0.4rem + env(safe-area-inset-bottom));
    box-shadow: 0 -2px 12px rgba(23, 45, 83, .06);
  }

  .nav-inferior a {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.2rem;
    flex: 1;
    /* Sin esto, el mínimo de contenido de "Categorías"/"Favoritos" (el
       ancho de la palabra más larga que un ítem flex no encoge por
       debajo de eso por defecto) empuja los cinco accesos más allá de
       320px de viewport — recién se notaba en el teléfono más chico
       que probamos, no en 375px+. `min-width: 0` deja que `flex: 1`
       encoja de verdad; la etiqueta pasa a partirse en dos líneas si
       hace falta en vez de forzar scroll horizontal a toda la página. */
    min-width: 0;
    padding: 0.3rem 0.25rem;
    min-height: 2.75rem; /* mínimo táctil, igual criterio que `.nav-icono` */
    border-radius: 10px;
    color: var(--texto-suave);
    text-decoration: none;
    /* 0.72rem ≈ 11,5 px: 0.68rem quedaba en 10,9, debajo del mínimo de
       11 pt de Apple para texto en iOS (revisión de diseño, 2026-10-24). */
    font-size: 0.72rem;
    font-weight: 500;
    text-align: center;
    transition: color var(--transicion);
  }

  .nav-inferior a span:last-child { line-height: 1; }

  .nav-inferior-actual { color: var(--azul); }

  /* El contenido no puede terminar tapado detrás de la barra fija —
     mismo motivo por el que `comparador.html` ya reserva aire debajo de
     `.barra-comparar` cuando esta queda fija. */
  main { padding-bottom: calc(4.5rem + env(safe-area-inset-bottom)); }

  /* Categorías, Favoritos, Configuración, Entrar y el buscador de la
     cabecera ya están en `.nav-inferior` — mostrarlos también acá
     arriba era la barra "desarmada" (mismo destino en dos lugares a la
     vez, marcado dos veces en el DOM). Sin sesión, `.nav-cuenta` queda
     vacío (su único enlace era "Entrar") y no ocupa espacio real.

     El selector repite `.nav-duplica-mobile` a propósito: como clase
     única empata en especificidad con `.buscador-cabecera-wrap` (más
     abajo en el archivo, misma especificidad gana por orden), y esa
     regla lo hubiera dejado visible igual. Repetida, la especificidad
     ya no empata y esta gana sin depender del orden en el archivo. */
  .nav-duplica-mobile.nav-duplica-mobile { display: none; }
}

/* --- Acordeón (specs de producto, filtros de categoría) ---

   `<details>`/`<summary>` nativo: colapsa y expande sin una línea de
   JavaScript, con foco de teclado y semántica de "expandido/colapsado"
   gratis para lectores de pantalla — nadie tiene que reinventar eso a
   mano. El contenido está en el DOM esté abierto o cerrado, así que
   nada de esto le esconde información a un buscador (DOCS/110-SEO.md §4).

   Colapsado es el comportamiento nativo por defecto (sin el atributo
   `open`). Eso es justo lo que se quiere en mobile — pero en pantallas
   más anchas el mismo contenido tiene que verse siempre abierto, como
   estaba antes de este componente. La regla de abajo fuerza eso: un
   `display` de autor le gana al `display: none` que el navegador aplica
   por dentro a `<details>` cerrado, sin necesidad de `!important` (un
   estilo de autor siempre le gana a la hoja del user-agent). El
   `<summary>` sigue mostrando el título en desktop, solo pierde el
   cursor de "clickeable" porque ahí no hay nada que abrir o cerrar. */
.acordeon summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e-3);
  min-height: 2.75rem;
  cursor: pointer;
  list-style: none;
}

.acordeon summary::-webkit-details-marker { display: none; }

.acordeon summary::after {
  content: "";
  flex-shrink: 0;
  width: 0.6rem;
  height: 0.6rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform var(--transicion);
}

.acordeon[open] summary::after { transform: rotate(-135deg); }

@media (min-width: 40.01rem) {
  /* Dos reglas para dos modelos de motor, ninguna de las dos de más: los
     navegadores viejos (Firefox, Safari a la fecha) esconden un
     `<details>` cerrado poniendo `display: none` directo en sus hijos
     via hoja de usuario — un `display` de autor le gana sin
     `!important` porque el autor siempre pisa al user-agent. Chrome/Edge
     recientes cambiaron ese mecanismo: envuelven el contenido en un
     `::details-content` interno y lo esconden con `content-visibility`
     en vez de `display`, así que ahí la primera regla no tiene nada que
     pisar y hace falta apuntar directo a ese pseudo-elemento. */
  .acordeon:not([open]) > *:not(summary) { display: block; }
  /* Salvo lo que no es un bloque: las especificaciones son una grilla de
     tarjetas, y con `block` se veían en una sola columna a todo el ancho
     en pantalla ancha (operador, 2026-10-25). */
  .especificaciones.acordeon:not([open]) > ul { display: grid; }
  .acordeon::details-content {
    content-visibility: visible;
    block-size: auto;
    overflow: visible;
  }
  .acordeon summary { cursor: default; pointer-events: none; }
  .acordeon summary::after { display: none; }
}

/* --- La Home: una pregunta, no un catálogo (§6) ---

   El hero se apoya en una banda tenue que llega de borde a borde. No es
   decoración: separa "el lugar donde empezás" del contenido que sigue, y
   hace que el buscador y las categorías se lean como un solo gesto en vez
   de tres bloques sueltos. Encima va un gradiente radial apenas perceptible
   centrado detrás del buscador, que concentra la mirada sin que nada se
   mueva — el movimiento permanente competiría con el buscador, que es el
   protagonista. */

.pregunta {
  position: relative;
  max-width: var(--ancho);
  margin: 0 auto;
  padding: 4.25rem 1.5rem 3.5rem;
  text-align: center;
}

/* La banda tiene que salirse del ancho de `main`, que está acotado por
   `--ancho`. `100vw` centrado con `left: 50%` es la forma de hacerlo sin
   sacar la sección de su lugar en el flujo; el `overflow-x` del body
   absorbe el ancho de la barra de scroll, que si no genera desplazamiento
   horizontal. */
.pregunta::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 100vw;
  margin-left: -50vw;
  z-index: -1;
  /* Más claro que `--azul-tenue` a propósito: las tarjetas de categoría van
     en `--azul-tenue` y si la banda es del mismo tono desaparecen dentro
     del fondo. La banda es el papel; las tarjetas tienen que despegarse. */
  background:
    /* La luz entra desde arriba. Es profundidad sin movimiento: sirve en
       cualquier navegador y tambien para quien pidio menos movimiento,
       que es la mitad del problema — una pagina puede dejar de ser plana
       sin que nada se desplace. */
    radial-gradient(120% 70% at 50% -10%, rgba(255, 255, 255, .9), transparent 60%),
    radial-gradient(55% 60% at 50% 35%, rgba(36, 89, 211, .05), transparent 72%),
    #f7f9fd;
  pointer-events: none;
}

/* Salto tipográfico decidido respecto del logo y del subtítulo: la
   jerarquía se construye con tamaño y espacio, no con cajas ni color. */
/* El título del hero va en el negro del texto, no en violeta. En la
   referencia el violeta está en el logo, los íconos y los botones — si el
   título también lo lleva, el color deja de señalar nada. */
.pregunta h1 {
  font-size: clamp(2rem, 4.6vw, 2.9rem);
  line-height: 1.12;
  margin: 0 0 0.85rem;
  color: var(--texto);
  font-weight: 700;
  letter-spacing: -0.035em;
}

/* El mismo hero fuera de la Home: mismo lenguaje, menos aire y un título
   más chico. La Home puede permitirse el salto tipográfico completo porque
   es lo único que hay en pantalla; una página interna, no. */
.pregunta-seccion {
  padding-top: var(--e-6);
  padding-bottom: var(--e-6);
}

.pregunta-seccion h1 { font-size: clamp(1.9rem, 4.5vw, 2.75rem); }
.pregunta-seccion .apoyo { margin-bottom: var(--e-5); font-size: 1.05rem; }

.miga-hero { margin: 0 0 var(--e-5); text-align: left; }

.apoyo {
  max-width: 34rem;
  margin: 0 auto 2.25rem;
  color: #657082;
  font-size: 1.02rem;
  line-height: 1.55;
}

/* El buscador es una sola pieza blanca sobre la banda del hero: campo y
   botón comparten caja, borde y radio. Que se lean como un objeto y no
   como dos controles sueltos es lo que lo vuelve el centro de la pantalla
   sin necesidad de agrandarlo. */
.buscador {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  max-width: 44rem;
  margin: 0 auto;
  padding: 0.45rem 0.45rem 0.45rem 0;
  border: 1px solid #e0e7f2;
  border-radius: 16px;
  background: #fff;
  box-shadow: var(--sombra);
  transition: border-color var(--transicion), box-shadow var(--transicion);
}

.buscador:focus-within {
  border-color: var(--azul-claro);
  box-shadow: 0 0 0 4px rgba(50, 104, 228, .12);
}

/* El ícono no es decorativo puro: es lo que hace reconocible al campo como
   "buscador" antes de leer el placeholder. Sin eventos de puntero para que
   un clic sobre él caiga igual en el input. */
.buscador-icono {
  position: absolute;
  left: 1.25rem;
  top: 50%;
  transform: translateY(-50%);
  color: #9aa5b1;
  pointer-events: none;
}

/* El campo ya no dibuja su propio borde: la caja la pone `.buscador`. El
   anillo de foco también vive ahí (`:focus-within`), así que acá se anula
   el propio para no tener dos. */
.buscador input {
  flex: 1;
  min-width: 0;
  padding: 0.85rem 1rem 0.85rem 3.1rem;
  font: inherit;
  font-size: 1.05rem;
  border: 0;
  background: transparent;
  outline: 0;
}

.buscador input::placeholder { color: #9aa5b1; }

/* --- Autocompletado ---
   El desplegable no empuja el contenido: aparece por encima, así la página
   no salta mientras se escribe. */

.buscador-campo { position: relative; flex: 1; min-width: 0; }
.buscador-campo input { width: 100%; }

.sugerencias {
  position: absolute;
  z-index: 20;
  left: 0;
  right: 0;
  top: calc(100% + 0.4rem);
  text-align: left;
}

.sugerencias-lista {
  list-style: none;
  margin: 0;
  padding: 0.35rem;
  border: 1px solid var(--borde);
  border-radius: 14px;
  background: #fff;
  box-shadow: var(--sombra-alta);
  overflow: hidden;
}

.sugerencias-lista a {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.65rem 0.85rem;
  border-radius: 10px;
  color: var(--texto);
  text-decoration: none;
  transition: background var(--transicion);
}

.sugerencias-lista a:hover { background: var(--fondo-suave); }

/* Opción marcada con las flechas. Comparte el fondo del `:hover` a
   propósito: teclado y mouse señalan lo mismo, así que tienen que verse
   igual. La barra violeta a la izquierda es lo que la distingue de un
   hover casual — con la lista larga, el fondo solo se pierde de vista. */
.opcion-activa,
.sugerencias-lista .opcion-activa,
.candidatos-lista .opcion-activa {
  background: var(--azul-tenue);
  box-shadow: inset 3px 0 0 var(--azul);
}

.sugerencia-texto { font-size: 0.98rem; }

.sugerencia-tipo {
  flex-shrink: 0;
  font-size: 0.75rem;
  color: var(--texto-suave);
  text-transform: lowercase;
}

.buscador button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.85rem 1.9rem;
  font: inherit;
  font-size: 1.02rem;
  font-weight: 500;
  color: #fff;
  background: var(--azul);
  border: 0;
  border-radius: 12px;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--transicion);
}

.buscador button:hover { background: var(--azul-claro); }

/* El ícono va oculto salvo en el botón del hero bajo 400px (ver más
   abajo): en el resto de los usos de `.buscador button` (que no traen
   este SVG en su HTML) no cambia nada. */
.buscador-btn-icono { display: none; }

/* `rgba(50, 104, 228, .12)` es `--azul-claro` con alpha — el mismo anillo
   de foco que ya usa `.buscador:focus-within` (arriba) y `.buscador-campo
   input:focus` en el resto del sitio. El valor anterior, `rgba(44, 82,
   130, .25)`, es un azul-gris que no corresponde a ningún token de la
   paleta violeta actual — quedó del branding azul previo al pivot de
   agosto 2026 (DOCS/100-BRANDING.md §3) y nunca se actualizó acá. */
.buscador button:focus-visible {
  outline: none;
  box-shadow: 0 0 0 4px rgba(50, 104, 228, .12);
}

/* Enlaces de texto simples separados por «·» — mismo lenguaje que
   `.nav-cabecera`/`.nav-pie`: la jerarquía se construye con tipografía y
   espacio, no con pastillas con borde (DOCS/100-BRANDING.md §2). */
.categorias {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.6rem;
  justify-content: center;
  margin-top: var(--e-6);
  font-size: var(--t-sm);
}

.categorias a {
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  color: #4a5568;
  text-decoration: none;
  background: transparent;
  transition: color var(--transicion), background var(--transicion);
}

.categorias a:hover,
.categorias a:focus-visible {
  color: var(--azul);
  background: var(--azul-tenue);
}

.categorias span[aria-hidden] { color: var(--borde); }

/* Enlace al mapa completo: mismo trato que las categorías, con el color de
   acento en vez de gris — se ve como un destino más, no como algo aparte. */
.categorias a.ver-todas { color: var(--azul-claro); }

.categorias a.actual { color: var(--azul); font-weight: 500; }

/* `.categorias-marca` filtra de verdad (subcategoría, marca dentro de
   categoría): acá la pastilla con borde sí cumple una función — marca qué
   opción está activa entre varias mutuamente excluyentes — así que
   conserva ese tratamiento en vez del texto plano de arriba. */
.categorias-marca {
  justify-content: flex-start;
  gap: 0.55rem;
  margin: var(--e-5) 0 0;
  font-size: var(--t-base);
}

.categorias-marca a {
  padding: 0.55rem 1.2rem;
  border: 1px solid #e6ebf1;
  border-radius: 999px;
  background: #fff;
  transition: border-color var(--transicion), color var(--transicion);
}

.categorias-marca a:hover { border-color: #c3cfdb; }

.categorias-marca a.actual {
  border-color: var(--azul);
  background: var(--azul-tenue);
  font-weight: 500;
}

/* --- Grilla de categorías (pivot de identidad, agosto 2026) ---
   Reemplaza los enlaces de texto: son pocas categorías (hoy ~8), entran
   cómodas como tarjetas con ícono sin volverse un menú
   (DOCS/160-CATALOGO.md §6, revisado). */

.grilla-categorias {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
  gap: 0.9rem;
  margin-top: var(--e-6);
}

/* Sobre la banda del hero la tarjeta va en blanco, no en violeta tenue:
   ahí el violeta ya es el fondo y una tarjeta del mismo color desaparece.
   Fuera del hero (página Categorías, donde también hay banda) vale lo
   mismo, así que la regla es una sola. */
/* La tarjeta es violeta tenue con el ícono suelto encima, sin disco de
   fondo. Probé al revés (tarjeta blanca, ícono sobre disco violeta) y se
   ve distinto de la referencia: el color pasa a ser un detalle chico en
   vez de ser la tarjeta entera, y la fila pierde el bloque de color que la
   hace legible de un vistazo. */
.categoria-icono {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 1.35rem 0.75rem 1.1rem;
  border: 1px solid #dfe7f3;
  border-radius: var(--radio);
  background: var(--azul-tenue);
  color: var(--azul);
  text-decoration: none;
  transition: transform var(--transicion), box-shadow var(--transicion),
              border-color var(--transicion);
}

.categoria-icono:hover {
  transform: translateY(-2px);
  box-shadow: var(--sombra-alta);
  border-color: #d5e1f3;
}

.categoria-icono-caja {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.categoria-icono-caja svg { width: 26px; height: 26px; }

.categoria-nombre {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--texto);
  letter-spacing: -0.01em;
}

.categoria-accion {
  font-size: 0.82rem;
  color: var(--texto-suave);
}

/* --- Banner "¿Cómo funciona?" ---
   El título va a la izquierda, en la misma línea que los pasos, y no
   arriba: el bloque explica el sitio una sola vez y no merece ocupar el
   alto de una sección propia. */

.banner-como-funciona {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--e-6);
  padding: 1.35rem 1.75rem;
  border-radius: var(--radio);
  background: var(--azul-tenue);
}

.banner-como-funciona h2 {
  margin: 0;
  font-size: 1.05rem;
  max-width: 8rem;
}

.pasos-banner {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--e-5);
}

.paso-banner {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

.paso-icono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 999px;
  background: #fff;
  color: var(--azul);
}

/* El número va montado sobre el disco del ícono, no al lado: en una banda
   de tres columnas cada elemento que ocupa ancho propio le roba lugar al
   texto, y el texto termina en tres líneas. Así el orden se sigue leyendo
   y el paso entra en dos. */
.paso-banner .paso-numero {
  position: absolute;
  left: 1.55rem;
  /* El ícono mide 2.4rem y está centrado verticalmente en el paso: su
     borde superior queda en `50% - 1.2rem`. El número se apoya ahí. */
  top: calc(50% - 1.35rem);
  margin-bottom: 0;
  width: 1.3rem;
  height: 1.3rem;
  font-size: var(--t-xs);
  background: var(--azul);
  color: #fff;
  border: 2px solid var(--azul-tenue);
}

.paso-banner .paso-titulo { display: block; color: var(--azul); }
.paso-banner .paso-texto { display: block; }

/* En pantallas angostas el título vuelve arriba: dos columnas con un
   título de 9rem dejarían los pasos en una franja inusable. */
@media (max-width: 48rem) {
  .banner-como-funciona { grid-template-columns: 1fr; }
  .banner-como-funciona h2 { max-width: none; }
}

/* La etiqueta "Nuevo" en una tarjeta no arrastra el margen pensado para
   ir pegada a un texto anterior (§ .etiqueta) — acá es el primer
   elemento de una columna. */
.etiqueta-tarjeta { margin-left: 0; align-self: flex-start; }

/* --- Encabezado de marca --- */

.encabezado-marca {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin: 1rem 0 0.5rem;
}

.encabezado-marca h1 { margin: 0; }

.logo-marca {
  height: 2.5rem;
  width: 9rem;
  max-width: 9rem;
  object-fit: contain;
}

/* Logos blancos o casi blancos, pensados para ir sobre el header oscuro
   del sitio de origen — no traen su propio fondo dentro del archivo,
   así que sobre el fondo blanco de esta página quedaban invisibles
   (2026-08-14). Selector por archivo, no una regla general para todos
   los logos: la mayoría (Apple, Samsung, Intel...) ya vienen con fondo
   propio o son de un color que se distingue solo, y ponerles una caja
   oscura de más los afearía sin necesidad. `object-fit: contain` deja
   espacio vacío alrededor del logo dentro de su caja — ese espacio es
   justo donde aparece este fondo, sin agrandar la caja ni recortar
   nada. Mismo criterio para `.logo-tienda`, más abajo. */
/* Se comparan con `*=` y no con `$=`: cuando Django guarda un archivo
   cuyo nombre ya existe le agrega un sufijo al azar
   —`house-of-marley_SJztxgm.svg`— y un selector anclado al final deja de
   alcanzarlo sin que nada avise. El logo queda invisible sobre el fondo
   claro y no hay forma de notarlo salvo mirando (2026-08-28).
   House of Marley salió de estas listas el 2026-10-12: su logo actual es
   casi negro (#231F20), no blanco, y la placa oscura lo tapaba. */
.logo-marca[src*="tcl."],
.logo-marca[src*="kolke"],
.logo-marca[src*="hoco"],
.logo-marca[src*="netac"],
.logo-marca[src*="trust."] {
  background: var(--texto);
  border-radius: 6px;
}

/* Los mismos logos claros, donde más se ven: el monograma del listado de
   marcas y de cada categoría, y la franja de marcas de la Home. Medidos
   dibujándolos sobre blanco (2026-10-02): HOCO, Kolke, Netac y Trust
   quedaban por debajo del 1 % de píxeles visibles — un cuadrado vacío. */
.monograma-marca[src*="hoco"],
.monograma-marca[src*="kolke"],
.monograma-marca[src*="netac"],
.monograma-marca[src*="trust."],
.monograma-marca[src*="tcl."],
.inicio-marcas-logos img[src*="hoco"],
.inicio-marcas-logos img[src*="kolke"],
.inicio-marcas-logos img[src*="netac"],
.inicio-marcas-logos img[src*="trust."],
.inicio-marcas-logos img[src*="tcl."] {
  background: var(--texto);
  border-radius: 6px;
}

/* En su propia página, la tienda gana el mismo tamaño de presencia que la
   marca — el monograma de 1.6rem de las tablas de precio es demasiado
   chico como para ser el sujeto de la pantalla. */
.encabezado-marca .logo-tienda {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  font-size: 1.1rem;
}

/* --- Bloques de la Home --- */

/* La referencia respira, pero no tanto: --e-8 (5.5rem) entre secciones
   dejaba huecos que en pantalla se leen como que la página se cortó. */
.bloque { margin-top: var(--e-7); }

.bloque > h2 { margin-bottom: var(--e-4); }

.apoyo-bloque {
  margin: 0 0 1.5rem;
  color: #4a5568;
  font-size: 1rem;
}

.grilla {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13.5rem, 1fr));
  gap: 1rem;
}

/* Borde y sombra suave en reposo, no solo en hover. La versión anterior
   dejaba la tarjeta sin caja hasta pasar el cursor, y una grilla de
   tarjetas invisibles se lee como una lista desordenada de texto e
   imágenes sueltas — que es exactamente lo que se veía "desprolijo".
   La elevación del hover sigue existiendo, más marcada. */
.tarjeta {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 1rem 1rem 1.05rem;
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
  box-shadow: var(--sombra);
  text-decoration: none;
  color: var(--texto);
  transition: transform var(--transicion), box-shadow var(--transicion),
              border-color var(--transicion);
}

.tarjeta:hover {
  transform: translateY(-3px);
  box-shadow: var(--sombra-alta);
  border-color: #d5e1f3;
}

/* La imagen pasa a ser la protagonista de la tarjeta, no un acento: en una
   grilla de productos es lo que se reconoce antes que el texto. La caja
   fija el alto para que todas las filas queden alineadas aunque las
   imágenes vengan con proporciones distintas de cada tienda. */
.tarjeta-imagen {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 8.5rem;
  margin-bottom: 0.75rem;
}

/* Ojo con el selector: va anclado a `.tarjeta-imagen`, no a `.tarjeta`.
   Hay tarjetas que no son de producto (Configuración, Favoritos, Alertas)
   y no tienen esta caja — sin el ancla, la miniatura quedaría con
   `height: 100%` contra un padre de alto automático. */
.tarjeta-imagen .miniatura {
  width: auto;
  height: 100%;
  max-width: 100%;
  border-radius: 8px;
  object-fit: contain;
  background: none;
}

/* El `background` vuelve explícito: `.tarjeta-imagen .miniatura` lo apaga
   con dos clases de especificidad y le gana a `.miniatura-monograma`, que
   tiene una sola. Sin esto el monograma queda como una letra suelta en el
   aire en vez de la placa violeta que debería ser. */
.tarjeta-imagen .miniatura-monograma {
  width: 4.5rem;
  height: 4.5rem;
  font-size: 1.7rem;
  background: var(--azul-tenue);
}

.tarjeta-titulo {
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.015em;
}

.tarjeta-marca {
  font-size: 0.82rem;
  color: var(--texto-suave);
}

/* No es un botón real (ver el comentario en `_tarjeta_producto.html`):
   `margin-top: auto` lo empuja al pie para que quede a la misma altura en
   todas las tarjetas de la fila, tengan o no precio o meta. */
.tarjeta-boton {
  /* `auto` en una columna flex empuja el botón al pie: todas las tarjetas
     de una fila lo muestran a la misma altura, tengan o no precio y meta.
     Las filas de la grilla estiran a la más alta, así que casi siempre hay
     holgura; el `gap` de la tarjeta cubre el caso en que no la hay. */
  margin-top: auto;
  padding: 0.55rem;
  border: 1px solid #d9e4f4;
  border-radius: var(--radio-chico);
  background: #fff;
  color: var(--azul);
  font-size: 0.85rem;
  font-weight: 600;
  text-align: center;
  transition: background var(--transicion), border-color var(--transicion);
}

/* `tarjeta-cuerpo` envuelve todo lo que no es la imagen (ver el
   comentario en `_tarjeta_producto.html`). `display: contents` lo hace
   desaparecer como caja: para el layout, `.tarjeta` sigue viendo a sus
   nietos (título, precio, botón...) como si fueran hijos directos —
   pixel a pixel lo mismo que antes de que existiera este contenedor —
   pero los selectores de acá abajo sí necesitan pasar por él, porque
   `display: contents` cambia el layout, no el árbol real del DOM que
   estos selectores recorren. Se pisa a un ancho mobile específico más
   abajo, donde sí hace falta la caja real. */
.tarjeta-cuerpo { display: contents; }

/* Lo que precede al botón varía (precio, meta, marca), así que el aire se
   pide desde el botón hacia atrás con `:has`. Es la única forma de darlo
   sin pisar el `margin-top: auto` que lo empuja al pie — y solo alcanza a
   las tarjetas que efectivamente tienen botón.

   Dos selectores y no uno: Favoritos/Alertas/Historial/Configuración
   arman su tarjeta sin `.tarjeta-cuerpo` (no tienen imagen, no
   necesitan el arreglo de esta sección) — el primero las sigue
   cubriendo tal cual estaba; el segundo es lo que ahora hace falta para
   las que sí pasaron a envolver su contenido. */
.tarjeta > :has(+ .tarjeta-boton),
.tarjeta-cuerpo > :has(+ .tarjeta-boton) {
  margin-bottom: 0.55rem;
}

/* Tarjetas que terminan en el precio y no en un botón —las de Tienda— lo
   empujan al pie igual. Sin esto, una meta que ocupa dos líneas dejaba ese
   precio un renglón más abajo que el de sus vecinos y la fila se veía
   despareja. Mismo motivo de arriba para los dos selectores. */
.tarjeta > .tarjeta-precio:last-child,
.tarjeta-cuerpo > .tarjeta-precio:last-child {
  margin-top: auto;
}

.tarjeta:hover .tarjeta-boton {
  background: var(--azul-tenue);
  border-color: var(--azul-tenue);
}

.tarjeta-precio {
  margin-top: 0.35rem;
  font-size: 1.2rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--azul);
}

.tarjeta-precio-desde { font-size: .7rem; font-weight: 400; color: var(--texto-suave); }
/* Sin stock en ninguna tienda: el último precio, sin el azul de «comprable». */
.tarjeta-precio-sin-stock { color: var(--texto-suave); font-weight: 600; }
.tarjeta-precio-sin-stock .estado-stock { margin: 0 0.35em 0 0; }
.tarjeta-boton > span { margin-left: .35rem; }

.saltar-contenido {
  position: fixed;
  top: .5rem;
  left: .5rem;
  z-index: 100;
  padding: .7rem 1rem;
  border-radius: 8px;
  background: var(--azul);
  color: #fff;
  transform: translateY(-150%);
}
.saltar-contenido:focus { transform: none; }

/* Cartel de beta (2026-10-12): una franja fina arriba de la cabecera.
   Con variables, así el modo oscuro la acompaña sin hoja aparte. */
.aviso-beta {
  /* Capa propia: el fondo decorativo de la portada (`.portada::before`)
     sube 90px para verse detrás de la cabecera y tapaba la segunda línea
     del cartel en el celular. */
  position: relative;
  z-index: 60;
  background: var(--azul-tenue);
  border-bottom: 1px solid var(--borde);
  color: var(--texto);
  font-size: .85rem;
  line-height: 1.4;
}
.aviso-beta-interior {
  max-width: var(--ancho);
  margin: 0 auto;
  padding: .45rem 1rem;
  display: flex;
  align-items: baseline;
  gap: .6rem;
}
.aviso-beta-etiqueta {
  flex: none;
  padding: .05rem .5rem;
  border-radius: 999px;
  background: #2459d3; /* fijo: en oscuro --azul es claro y el blanco no se leía */
  color: #fff;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.aviso-beta-corto { display: none; }
@media (max-width: 640px) {
  .aviso-beta-largo { display: none; }
  .aviso-beta-corto { display: inline; }
}
.aviso-beta a {
  color: var(--azul);
  font-weight: 600;
  overflow-wrap: anywhere;
  /* El cartel mide 16 px de alto; el relleno con margen negativo agranda
     lo que se puede tocar a 44 px sin cambiar cómo se ve. */
  display: inline-block;
  padding-block: .8rem;
  margin-block: -.8rem;
}
/* Cartel de consentimiento de analítica (2026-10-12): abajo, sin tapar
   el contenido entero. Los dos botones con el mismo estilo a propósito
   (ver comentario en base.html). Con variables, para que el modo oscuro
   lo acompañe. */
.cartel-analitica {
  position: fixed;
  z-index: 70;
  left: 1rem;
  right: 1rem;
  bottom: 1rem;
  max-width: 44rem;
  margin: 0 auto;
  background: var(--fondo-suave);
  color: var(--texto);
  border: 1px solid var(--borde);
  border-radius: var(--radio-chico);
  box-shadow: var(--sombra-alta);
  font-size: .9rem;
  line-height: 1.45;
}
.cartel-analitica-interior {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .75rem 1rem;
  padding: .9rem 1rem;
}
.cartel-analitica-interior p { flex: 1 1 20rem; margin: 0; }
.cartel-analitica a { color: var(--azul); font-weight: 600; }
.cartel-analitica-botones { display: flex; gap: .5rem; flex: none; }
.boton-cartel {
  padding: .5rem 1rem;
  border: 1px solid var(--azul);
  border-radius: 999px;
  background: transparent;
  color: var(--azul);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.boton-cartel:hover,
.boton-cartel:focus-visible { background: var(--azul-tenue); }
/* En mobile, por encima de la barra inferior (`.nav-inferior`, mismo
   corte de 40rem): si la tapara, no se podría navegar sin contestar. */
.cartel-corto { display: none; }
@media (max-width: 40rem) {
  .cartel-analitica {
    left: .5rem;
    right: .5rem;
    bottom: calc(4.5rem + env(safe-area-inset-bottom));
    font-size: .82rem;
    line-height: 1.35;
  }
  .cartel-largo { display: none; }
  .cartel-corto { display: inline; }
  .cartel-analitica-interior { padding: .6rem .75rem; gap: .5rem; }
  .cartel-analitica-interior p { flex-basis: 100%; }
  .cartel-analitica-botones { width: 100%; }
  .cartel-analitica-botones .boton-cartel { flex: 1; padding: .4rem .5rem; }
}
main:focus { outline: none; }
.estado-comparacion {
  position: fixed;
  z-index: 60;
  top: 5.5rem;
  left: 50%;
  width: max-content;
  max-width: calc(100% - 2rem);
  transform: translateX(-50%);
  padding: .85rem 1.2rem;
  border: 1px solid var(--borde-suave);
  border-radius: 12px;
  box-shadow: var(--sombra-alta);
  background: #fff;
  color: var(--texto);
  font-size: .85rem;
  opacity: 0;
  pointer-events: none;
}
.estado-comparacion.visible { opacity: 1; }
.tarjeta-comparar-boton[aria-busy="true"] { opacity: .55; cursor: wait; }

.tarjeta-precio .antes {
  margin-left: 0.4rem;
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--texto-suave);
}

.tarjeta-nota {
  font-size: 0.85rem;
  font-weight: 500;
}

.tarjeta-nota.baja,
.tarjeta-nota.ahorro-nota { color: var(--verde); }

.tarjeta-meta {
  font-size: 0.8rem;
  color: var(--texto-suave);
  line-height: 1.4;
}

/* Oculto por defecto: en la grilla de escritorio (varias columnas
   angostas) tres líneas más por tarjeta la sobrecargan sin necesidad —
   el dato extra solo hace falta cuando la tarjeta ya pasó a fila de
   lista, más abajo bajo `max-width: 40rem`. Mismo estilo de viñeta que
   ya usa `.resultado-spec` en los resultados de búsqueda. */
.tarjeta-specs { display: none; margin-top: 0.3rem; }

.tarjeta-spec {
  display: block;
  position: relative;
  padding-left: 0.85rem;
  font-size: var(--t-xs);
  line-height: 1.6;
  color: var(--texto-suave);
}

.tarjeta-spec::before {
  content: "";
  position: absolute;
  left: 0.15rem;
  top: 0.6em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--azul-claro);
}

/* --- Tarjetas de producto en mobile ---

   Desde el 2026-10-14, dos columnas en todo el sitio salvo la Home (ver
   «dos columnas» más abajo). Lo que sigue es la «fila de lista» de antes,
   que hoy solo alcanza a la Home: su tarjeta la arma `inicio.css` encima
   de estas reglas, y el cambio no era sobre ella. `:where()` no suma
   especificidad, así que la Home se ve exactamente igual que antes.

   Fila de lista (historia):

   Mismo cambio que ya llevó `.resultado` para los resultados de
   búsqueda (§ arriba): apiladas en una grilla de 2 columnas cada dato
   queda comprimido contra ~11rem de ancho — acá se lee en una columna,
   con la imagen achicada a un costado, para que entre más información
   (specs incluidas) sin tener que abrir cada producto.

   Acotado a `:has(.tarjeta-imagen)`: `.tarjeta` también la usan
   Configuración/Favoritos/Alertas, que no tienen imagen ni deberían
   pasar a este formato de fila.

   `.tarjeta-cuerpo` pasa de invisible (`display: contents`, versión de
   escritorio de más arriba) a una caja de verdad: es la columna de
   texto de la fila. Sin esta caja, título/meta/specs/precio quedaban
   sueltos como hijos directos de la grilla y el motor le daba a la
   primera fila (la del título) el alto completo de la imagen —72px—
   aunque el título solo ocupara la mitad, dejando un hueco en blanco
   antes de la meta. Con la caja, la imagen y el bloque de texto son
   los dos únicos ítems de la grilla (una fila real), y adentro de la
   caja el texto se apila con su propio alto natural, sin huecos. */
@media (max-width: 40rem) {
  :where(.pagina-inicio) .tarjeta:has(.tarjeta-imagen) {
    display: grid;
    grid-template-columns: 4.5rem 1fr;
    align-items: center;
    column-gap: 0.85rem;
    padding: 0.85rem;
  }

  :where(.pagina-inicio) .tarjeta:has(.tarjeta-imagen) > .tarjeta-imagen {
    height: 4.5rem;
    width: 4.5rem;
    margin-bottom: 0;
    border-radius: var(--radio-chico);
    background: var(--fondo-tenue);
  }

  :where(.pagina-inicio) .tarjeta:has(.tarjeta-imagen) > .tarjeta-imagen .miniatura-monograma {
    width: 2.6rem;
    height: 2.6rem;
    font-size: 1.1rem;
  }

  :where(.pagina-inicio) .tarjeta:has(.tarjeta-imagen) > .tarjeta-cuerpo {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
  }

  :where(.pagina-inicio) .tarjeta-specs { display: block; }
  :where(.pagina-inicio) .tarjeta:has(.tarjeta-imagen) .tarjeta-precio { margin-top: 0.3rem; }
  :where(.pagina-inicio) .tarjeta:has(.tarjeta-imagen) .tarjeta-boton {
    margin-top: 0.4rem;
    display: inline-block;
    width: max-content;
  }
}

/* --- Tarjetas de producto en mobile: dos columnas (2026-10-14) ---

   Hasta el 2026-10-14 cada producto era una fila de lista a todo el
   ancho (arriba), con la foto de 72px a un costado y tres specs: entraban
   unos tres productos por pantalla. Pedido del operador, con la
   referencia de las tiendas de supermercado: dos columnas, cuatro
   productos a la vista. Decisión en DOCS/100-BRANDING.md §12 («Tarjeta
   de producto»); §6 ya pedía dos columnas en móvil para la Home.

   Lo que se resigna son las specs de la tarjeta: en ~170px no entran sin
   apretar todo lo demás. La ficha las sigue mostrando completas; la
   tarjeta es para encontrar, la ficha para decidir.

   La tarjeta es la misma columna de escritorio (foto arriba, texto
   abajo) con medidas más chicas. `:has(.tarjeta-imagen)`: `.tarjeta`
   también la usan Configuración/Favoritos/Alertas, sin foto. */
@media (max-width: 40rem) {
  .grilla { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.6rem; }

  :where(body:not(.pagina-inicio)) .tarjeta:has(.tarjeta-imagen) { padding: 0.65rem 0.65rem 0.75rem; }

  :where(body:not(.pagina-inicio)) .tarjeta:has(.tarjeta-imagen) > .tarjeta-imagen {
    height: 7rem;
    margin-bottom: 0.45rem;
  }

  :where(body:not(.pagina-inicio)) .tarjeta:has(.tarjeta-imagen) > .tarjeta-imagen .miniatura-monograma {
    width: 3.2rem;
    height: 3.2rem;
    font-size: 1.25rem;
  }

  /* Dos renglones como máximo: un modelo largo («27" V277e Fhd Ips 4ms
     Con Dp») no desalinea los precios de la fila. El nombre completo
     sigue en la ficha. */
  :where(body:not(.pagina-inicio)) .tarjeta:has(.tarjeta-imagen) .tarjeta-titulo {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    font-size: 0.85rem;
  }

  :where(body:not(.pagina-inicio)) .tarjeta:has(.tarjeta-imagen) .tarjeta-marca,
  :where(body:not(.pagina-inicio)) .tarjeta:has(.tarjeta-imagen) .tarjeta-meta { font-size: 0.72rem; }

  :where(body:not(.pagina-inicio)) .tarjeta:has(.tarjeta-imagen) .tarjeta-precio { font-size: 1rem; }

  :where(body:not(.pagina-inicio)) .tarjeta:has(.tarjeta-imagen) .tarjeta-boton {
    padding: 0.45rem 0.3rem;
    font-size: 0.78rem;
  }
}

/* --- Cómo funciona --- */

.pasos {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--e-6);
  padding: 0;
  margin: var(--e-5) 0 0;
}

/* Sin caja de fondo: el número circular y el espacio ya jerarquizan cada
   paso, sin encajonarlo (DOCS/100-BRANDING.md §2). */
.pasos li {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.paso-numero {
  display: grid;
  place-items: center;
  width: 1.8rem;
  height: 1.8rem;
  margin-bottom: 0.3rem;
  border-radius: 999px;
  background: var(--azul-tenue);
  color: var(--azul);
  font-size: 0.9rem;
  font-weight: 600;
}

.paso-titulo { font-weight: 600; font-size: 0.9rem; }
.paso-texto { font-size: 0.82rem; line-height: 1.4; color: var(--texto-suave); }

/* --- Invitación a crear cuenta ---
   Única sección de la Home con fondo propio: es un cierre, no un dato más
   que comparar — se lo distingue con espacio y un color tenue, no con un
   banner grande ni urgencia (DOCS/100-BRANDING.md §2). */
.cta-cuenta {
  padding: var(--e-6) var(--e-5);
  border-radius: var(--radio);
  background: var(--fondo-suave);
  text-align: center;
}

.cta-cuenta .apoyo-bloque {
  max-width: 26rem;
  margin-left: auto;
  margin-right: auto;
}

.cta-cuenta .nota { margin-top: var(--e-3); }

/* --- Imágenes y monogramas ---

   Cuando falta una imagen no se muestra un ícono de "imagen rota": se
   muestra un monograma tipografiado, que se ve deliberado en vez de
   defectuoso (§2). Mejora solo cuando se carguen imágenes propias. */

.miniatura {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 4rem;
  height: 4rem;
  border-radius: var(--radio);
  object-fit: contain;
  background: var(--fondo-suave);
}

/* Red de contención, no la solución. El fondo se recorta de verdad con
   `productos/recorte.py` (`manage.py recortar_imagenes`), que deja PNG con
   transparencia. Esto cubre las que ese proceso salteó y las que entren
   por el importador antes de volver a correrlo: `multiply` multiplica cada
   píxel por el fondo, así que el blanco puro desaparece y el producto, más
   oscuro, se mantiene. Solo sirve con blanco puro — con (250,250,250) deja
   un rectángulo apenas visible, que es lo que motivó el recorte real.

   Se aplica solo a `img` y no al monograma, que es un `span` con su propio
   fondo violeta y quedaría teñido. */
img.miniatura { mix-blend-mode: multiply; }

.miniatura-monograma {
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--azul);
  letter-spacing: -0.03em;
  background: var(--azul-tenue);
}

/* --- Ficha de producto: encabezado en 3 columnas ---
   Imagen | título + destacados | panel de precio. En pantallas chicas se
   apila: imagen, título, precio (DOCS/100-BRANDING.md §3, pivot agosto
   2026). */

/* Índice corto de la ficha. En productos con muchas especificaciones evita
   que precio, puntuación o comparador queden a varios scrolls de distancia.
   Es navegación real por anclas y funciona igual sin JavaScript. */
.ficha-navegacion {
  display: flex;
  align-items: center;
  gap: .35rem;
  margin: var(--e-4) 0 var(--e-5);
  padding: .3rem;
  overflow-x: auto;
  scrollbar-width: none;
  border: 1px solid var(--borde-suave);
  border-radius: 999px;
  background: #fff;
  box-shadow: var(--sombra);
}

.ficha-navegacion::-webkit-scrollbar { display: none; }

.ficha-navegacion a {
  flex: 1 0 auto;
  min-height: 2.75rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: .55rem .9rem;
  border-radius: 999px;
  color: var(--texto-suave);
  font-size: var(--t-sm);
  font-weight: 600;
  text-decoration: none;
  transition: color var(--transicion), background var(--transicion);
}

.ficha-navegacion a:first-child,
.ficha-navegacion a:hover,
.ficha-navegacion a:focus-visible {
  color: var(--azul);
  background: var(--azul-tenue);
}

/* La navegación de la ficha es por anclas: el desplazamiento acompaña el
   cambio de contexto y la pastilla activa confirma adónde llegó. Todo se
   resuelve con CSS, así los enlaces siguen funcionando sin JavaScript. */
html:has(.ficha-navegacion) { scroll-behavior: smooth; }

body:has(#tiendas:target, #especificaciones:target, #indice:target, #comparar-productos:target)
  .ficha-navegacion a:first-child {
  color: var(--texto-suave);
  background: transparent;
}

body:has(#tiendas:target) .ficha-navegacion a[href="#tiendas"],
body:has(#especificaciones:target) .ficha-navegacion a[href="#especificaciones"],
body:has(#indice:target) .ficha-navegacion a[href="#indice"],
body:has(#comparar-productos:target) .ficha-navegacion a[href="#comparar-productos"] {
  color: var(--azul);
  background: var(--azul-tenue);
}

@keyframes ficha-destino {
  0% { box-shadow: 0 0 0 0 rgba(36, 89, 211, 0); }
  38% { box-shadow: 0 0 0 .45rem rgba(36, 89, 211, .14); }
  100% { box-shadow: 0 0 0 0 rgba(36, 89, 211, 0); }
}

#resumen:target,
#tiendas:target,
#especificaciones:target,
#indice:target,
#comparar-productos:target {
  border-radius: var(--radio);
  animation: ficha-destino .72s ease-out;
}

#resumen,
#tiendas,
#indice,
#especificaciones,
#comparar-productos { scroll-margin-top: var(--e-5); }

.ficha-encabezado {
  display: grid;
  grid-template-columns: minmax(0, 20rem) minmax(0, 1fr) minmax(19.5rem, 21rem);
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: start;
  margin: 0 0 var(--e-7);
}

.ficha-info { min-width: 0; padding-top: .2rem; }

/* Tercera columna: pila de tarjetas (precio, salvedades). */
.ficha-lateral {
  display: flex;
  flex-direction: column;
  gap: var(--e-4);
}

@media (min-width: 56.01rem) {
  /* El precio sigue disponible mientras se terminan de leer las
     características del encabezado; la columna deja de acompañar al
     llegar al final de la propia grilla. */
  .ficha-lateral { position: sticky; top: var(--e-4); }
}

/* La alerta de precio: la otra mitad de lo que antes vivía junto al
   favorito, ahora en el lateral donde tiene contexto (justo debajo del
   precio). Un botón de ancho completo, discreto — es una acción
   secundaria, el precio y "Ver tiendas" siguen siendo lo principal. */
.panel-alerta { margin: 0; }

/* Tercer nivel: texto con campana, sin caja. Con borde y a todo el ancho
   competía con «Ir a la tienda», que es la única acción principal del
   panel (auditoría de la ficha, 2026-10-19). La altura mínima mantiene
   un área táctil de 44 px. */
.boton-alerta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  width: 100%;
  min-height: 2.75rem;
  padding: 0.5rem 1rem;
  border: 0;
  border-radius: var(--radio-chico);
  background: transparent;
  color: var(--azul);
  font: inherit;
  font-size: var(--t-sm);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--transicion);
}
.boton-alerta:hover { background: var(--azul-tenue); }
.panel-alerta.nota { margin: 0; text-align: center; }

/* Las salvedades comparten la caja del panel de precio pero sin su tinte:
   son una nota al pie de la decisión, no la decisión. */
.panel-saber {
  padding: var(--e-4) var(--e-5);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
  box-shadow: var(--sombra);
}

.panel-saber h2 {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0 0 0.6rem;
  font-size: 0.95rem;
  font-weight: 700;
}

.panel-saber h2 svg { color: var(--azul); flex-shrink: 0; }

.panel-saber ul {
  margin: 0;
  padding-left: 1.1rem;
  display: grid;
  gap: 0.4rem;
}

.panel-saber li {
  font-size: var(--t-sm);
  line-height: 1.45;
  color: var(--texto-suave);
}

/* --- Galería de la ficha ---
   Dos columnas independientes: la tira de miniaturas y la foto grande.
   Todas las fotos grandes ocupan el mismo lugar y solo se ve la del radio
   marcado, así cambiar de foto no mueve nada de la página.

   El emparejamiento «radio N ↔ miniatura N ↔ foto N» se escribe posición
   por posición más abajo. Es repetitivo, pero es lo que permite que la
   tira no comparta filas con la foto grande — cuando lo hacían, la foto
   estiraba las filas y las miniaturas quedaban separadas por huecos. */

/* Foto grande arriba y la tira horizontal debajo. Al costado, la tira le
   come ancho a la foto —que es lo que se vino a ver— y limita cuántas
   miniaturas entran antes de tener que apilarlas. */
.ficha-galeria {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.galeria-radio {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

/* `order` en vez de reordenar el HTML: los radios tienen que quedar antes
   de las dos columnas para que los selectores de hermano funcionen, pero en
   pantalla la tira va debajo de la foto. */
.galeria-tira {
  order: 2;
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.galeria-fotos { order: 1; min-width: 0; }

.galeria-miniatura {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 4.5rem;
  height: 4.5rem;
  flex-shrink: 0;
  padding: 0.35rem;
  border: 2px solid var(--borde-suave);
  border-radius: var(--radio-chico);
  background: var(--fondo-tenue);
  cursor: pointer;
  transition: border-color var(--transicion);
}

.galeria-miniatura img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  mix-blend-mode: multiply;
}

.galeria-miniatura:hover { border-color: #d5e1f3; }

.galeria-principal {
  display: none;
  align-items: center;
  justify-content: center;
  padding: var(--e-5);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: var(--fondo-tenue);
}

/* Emparejamiento posición por posición. El borde violeta marca cuál se
   está viendo: es lo único que lo indica, así que también responde al foco
   de teclado — sin eso, quien navega con tabulador no sabe dónde está. */
.galeria-radio:nth-of-type(1):checked ~ .galeria-fotos > .galeria-principal:nth-child(1),
.galeria-radio:nth-of-type(2):checked ~ .galeria-fotos > .galeria-principal:nth-child(2),
.galeria-radio:nth-of-type(3):checked ~ .galeria-fotos > .galeria-principal:nth-child(3),
.galeria-radio:nth-of-type(4):checked ~ .galeria-fotos > .galeria-principal:nth-child(4),
.galeria-radio:nth-of-type(5):checked ~ .galeria-fotos > .galeria-principal:nth-child(5),
.galeria-radio:nth-of-type(6):checked ~ .galeria-fotos > .galeria-principal:nth-child(6),
.galeria-radio:nth-of-type(7):checked ~ .galeria-fotos > .galeria-principal:nth-child(7),
.galeria-radio:nth-of-type(8):checked ~ .galeria-fotos > .galeria-principal:nth-child(8) {
  display: flex;
}

.galeria-radio:nth-of-type(1):checked ~ .galeria-tira > .galeria-miniatura:nth-child(1),
.galeria-radio:nth-of-type(2):checked ~ .galeria-tira > .galeria-miniatura:nth-child(2),
.galeria-radio:nth-of-type(3):checked ~ .galeria-tira > .galeria-miniatura:nth-child(3),
.galeria-radio:nth-of-type(4):checked ~ .galeria-tira > .galeria-miniatura:nth-child(4),
.galeria-radio:nth-of-type(5):checked ~ .galeria-tira > .galeria-miniatura:nth-child(5),
.galeria-radio:nth-of-type(6):checked ~ .galeria-tira > .galeria-miniatura:nth-child(6),
.galeria-radio:nth-of-type(7):checked ~ .galeria-tira > .galeria-miniatura:nth-child(7),
.galeria-radio:nth-of-type(8):checked ~ .galeria-tira > .galeria-miniatura:nth-child(8) {
  border-color: var(--azul);
}

.galeria-radio:nth-of-type(1):focus-visible ~ .galeria-tira > .galeria-miniatura:nth-child(1),
.galeria-radio:nth-of-type(2):focus-visible ~ .galeria-tira > .galeria-miniatura:nth-child(2),
.galeria-radio:nth-of-type(3):focus-visible ~ .galeria-tira > .galeria-miniatura:nth-child(3),
.galeria-radio:nth-of-type(4):focus-visible ~ .galeria-tira > .galeria-miniatura:nth-child(4),
.galeria-radio:nth-of-type(5):focus-visible ~ .galeria-tira > .galeria-miniatura:nth-child(5),
.galeria-radio:nth-of-type(6):focus-visible ~ .galeria-tira > .galeria-miniatura:nth-child(6),
.galeria-radio:nth-of-type(7):focus-visible ~ .galeria-tira > .galeria-miniatura:nth-child(7),
.galeria-radio:nth-of-type(8):focus-visible ~ .galeria-tira > .galeria-miniatura:nth-child(8) {
  outline: 2px solid var(--azul-claro);
  outline-offset: 2px;
}

.galeria-principal img {
  width: 100%;
  height: 15rem;
  object-fit: contain;
  mix-blend-mode: multiply;
}

.ficha-columna-imagen { position: relative; }

/* El corazón de favorito, montado sobre la esquina de la imagen. Blanco
   sólido y sombra propia: tiene que leerse igual sobre una foto de
   producto oscura que sobre una clara, así que no puede depender del
   contraste del fondo que tenga debajo. */
.favorito-flotante {
  position: absolute;
  top: var(--e-3);
  right: var(--e-3);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--sombra-alta);
  color: var(--texto-suave);
  cursor: pointer;
  transition: color var(--transicion), transform var(--transicion);
}

/* La versión para quien inició sesión es un `<form>` con un `<button>`
   adentro — el círculo blanco y su sombra están en `.favorito-flotante`
   (arriba), pensado para un `<a>` (que no trae chrome propio del
   navegador). Un `<button>` sí lo trae: sin resetearlo quedaba su propio
   recuadro con borde y fondo apilado dentro del círculo, la caja
   desprolija superpuesta al corazón que se veía en la ficha. Acá se lo
   estira para llenar el círculo entero y se le saca todo lo propio. */
.favorito-flotante button {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.favorito-flotante:hover,
.favorito-flotante button:hover { color: var(--rojo); transform: scale(1.06); }

/* Marcado como favorito: el corazón relleno solo necesita el color, la
   forma ya la da el `fill="currentColor"` que pone la plantilla. Rojo y
   no violeta a propósito — es la convención universal del corazón de
   favoritos, distinta de "nunca rojo para ofertas" (`--rojo` en :root),
   que habla de precios, no de esto. El `aria-pressed` vive en el
   `<button>`, no en el `.favorito-flotante` que lo envuelve, así que el
   selector tiene que calificarlo como descendiente. */
.favorito-flotante button[aria-pressed="true"] { color: var(--rojo); }

/* La imagen va sobre su propia superficie clara y con borde, como en la
   referencia: un producto recortado sobre blanco puro flota sin apoyo, y
   con fondo propio la columna se lee como una pieza. */
.ficha-imagen {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--e-5);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background:
    radial-gradient(circle at 50% 40%, #fff 0 34%, transparent 68%),
    linear-gradient(145deg, #f9fbff, #eef3fc);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .8), var(--sombra);
}

/* En la ficha la imagen es la protagonista, no un acento chico como en
   los listados — tiene que reconocerse el producto de un vistazo. */
.ficha-imagen .miniatura {
  width: 100%;
  height: 19rem;
  background: none;
}

.ficha-imagen .miniatura-monograma { font-size: 3.5rem; background: var(--azul-tenue); }

.ficha-info .etiqueta-nuevo { margin-bottom: 0.6rem; }

.ficha-insignias {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}

.ficha-insignias .etiqueta-nuevo { margin: 0; }

/* Resumen de la Puntuación en el encabezado. Deja de ser una insignia
   decorativa: es el puente entre el nombre del producto y la explicación
   completa. El número, una evidencia y el enlace conviven en una sola pieza
   para que se entienda antes de hacer scroll. */
.puntuacion-resumen {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--e-3);
  align-items: center;
  margin-top: var(--e-4);
  padding: var(--e-3);
  border: 1px solid #d5e1f3;
  border-radius: var(--radio);
  background: linear-gradient(135deg, #f3f6fc, #fff 78%);
  color: var(--texto);
  text-decoration: none;
  box-shadow: var(--sombra);
  transition: border-color var(--transicion), box-shadow var(--transicion), transform var(--transicion);
}

.puntuacion-resumen:hover {
  border-color: var(--azul-claro);
  box-shadow: var(--sombra-alta);
  transform: translateY(-1px);
}

.puntuacion-resumen-numero {
  display: flex;
  align-items: baseline;
  justify-content: center;
  min-width: 5.15rem;
  padding: .7rem .55rem;
  border-radius: var(--radio-chico);
  background: var(--azul);
  color: #fff;
  font-variant-numeric: tabular-nums;
}

.puntuacion-resumen-numero strong {
  font-size: 2rem;
  line-height: 1;
  letter-spacing: -.04em;
}

.puntuacion-resumen-numero span { font-size: .75rem; opacity: .75; }

.puntuacion-resumen-contenido { display: grid; gap: .2rem; min-width: 0; }

.puntuacion-resumen-titulo {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .4rem;
  font-size: var(--t-sm);
  font-weight: 700;
}

.puntuacion-resumen-razon {
  color: var(--texto-suave);
  font-size: var(--t-xs);
  line-height: 1.35;
}

.puntuacion-resumen-enlace {
  color: var(--azul);
  font-size: var(--t-xs);
  font-weight: 700;
}

.insignia-indice-beta {
  padding: 0.05rem 0.4rem;
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  opacity: .8;
}

.ficha-info h1 {
  margin: 0 0 0.2rem;
  /* Los nombres que trae el importador automático son el título crudo de
     la tienda, no uno curado a mano — pueden pasar los 80 caracteres. El
     tamaño de un h1 normal los vuelve un bloque de texto, no un título. */
  font-size: clamp(1.7rem, 2.25vw, 2.15rem);
  line-height: 1.18;
  letter-spacing: -.035em;
}

.ficha-info .marca-eyebrow {
  display: block;
  font-size: var(--t-sm);
  color: var(--texto-suave);
}

/* Descripción breve (posición 4 de la jerarquía, DOCS/100-BRANDING.md):
   texto plano bajo el título, sin caja — la referencia no le pone tarjeta,
   es la frase de apoyo del título. */
.ficha-subtitulo {
  margin: 0.3rem 0 0;
  max-width: 42rem;
  font-size: var(--t-md);
  line-height: 1.5;
  color: var(--texto-suave);
}

/* "¿Para quién es?" / "¿Por qué elegirlo?": dos tarjetas lado a lado
   cuando hay contenido para las dos, una sola a todo el ancho cuando falta
   uno de los dos textos — nunca una caja vacía rellenando el hueco
   (DOCS/30-PRINCIPIOS.md §4). `auto-fit` con un mínimo generoso hace las
   dos cosas con la misma regla. */
.ficha-tarjetas {
  display: grid;
  /* 13rem y no 15rem: la columna central de la ficha mide ~448px en
     desktop, y dos columnas de 15rem (240px) más el gap no entraban —
     el grid caía a una sola columna siempre, aunque las dos tarjetas
     tuvieran contenido (encontrado al agregar "¿Por qué elegirlo?" como
     segunda tarjeta real, 2026-08-11). Con 13rem entran las dos. */
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: var(--e-4);
  margin: var(--e-5) 0 0;
  /* Sin esto, el default de grid (`stretch`) estira la tarjeta más corta
     hasta igualar la altura de la más larga — "¿Para quién es?" suele
     ser una frase, "¿Por qué elegirlo?" dos o tres cláusulas, así que
     quedaba un hueco vacío enorme debajo del texto corto. Cada tarjeta
     mide lo que su propio contenido pide. */
  align-items: start;
}

.ficha-tarjeta {
  padding: var(--e-4);
  border: 1px solid #dce6f4;
  border-radius: var(--radio);
  background: linear-gradient(145deg, #f8faff, var(--azul-tenue));
  font-size: var(--t-sm);
  line-height: 1.55;
}

.ficha-tarjeta h2 {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.4rem;
  font-size: 1rem;
  font-weight: 700;
  color: var(--texto);
}

.ficha-tarjeta h2 svg { flex-shrink: 0; color: var(--azul); }

.ficha-tarjeta p { margin: 0; }

/* "Características principales": etiqueta y valor en columnas, el dato
   duro de la ficha — a diferencia de las tarjetas de arriba, que son
   texto editorial. `dl`/`dt`/`dd` porque es literalmente una lista de
   pares nombre-valor, no una lista de ítems sueltos. */
.ficha-caracteristicas { margin-top: var(--e-6); }

.ficha-caracteristicas h2 {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--texto);
  margin: 0 0 var(--e-3);
}

.ficha-caracteristicas h2 svg { color: var(--azul); flex-shrink: 0; }

.caracteristicas-lista { margin: 0; }

.caracteristica {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--e-4);
  padding: 0.65rem 0;
  border-bottom: 1px solid var(--borde-suave);
  font-size: var(--t-sm);
}

.caracteristica:last-child { border-bottom: 0; }

.caracteristica dt {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--texto-suave);
}

.caracteristica dt svg { flex-shrink: 0; color: var(--azul); }

.caracteristica dd {
  margin: 0;
  font-weight: 600;
  text-align: right;
}

.enlace-flecha {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: var(--e-3);
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--azul);
  text-decoration: none;
}

.enlace-flecha:hover { text-decoration: underline; }
.enlace-flecha span { transition: transform var(--transicion); }
.enlace-flecha:hover span { transform: translateX(2px); }

/* "Lo más destacado" del panel lateral: mismo criterio que el resto de la
   columna de precio — tarjeta con borde propio, no violeta tenue, para no
   competir visualmente con el panel de precio de arriba. */
.panel-destacado {
  padding: var(--e-4) var(--e-5);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
}

.panel-destacado h2 {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 var(--e-3);
  font-size: var(--t-md);
  font-weight: 700;
}

.panel-destacado h2 svg { color: var(--azul); flex-shrink: 0; }

.checklist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.55rem;
}

.checklist li {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  font-size: var(--t-sm);
}

/* Tilde verde: acá sí es una señal de confirmación ("esto lo tiene"), no
   solo decoración — es el mismo verde que el sistema reserva para lo que
   le conviene al usuario (`--verde`). */
.checklist .check {
  flex-shrink: 0;
  color: var(--verde);
}

/* --- Panel de precio --- */

/* El panel es la pieza más importante de la ficha: es lo que la persona
   vino a ver. Violeta sólido en vez de tenue a propósito (decisión
   revisada, DOCS/100-BRANDING.md §12): tiene que distinguirse del resto
   de la página al primer vistazo, no solo al leerlo. El degradé va de
   `--azul-claro` a `--azul` para que no quede una superficie plana. */
/* Superficie tenue con el botón sólido adentro — es lo que muestra la
   captura de referencia (2026-08-10), y revierte el degradé violeta a todo
   el panel que se había pedido el 2026-08-06. El motivo del cambio: con el
   panel entero pintado, el botón perdía su lugar de único punto de acción;
   sobre fondo tenue el ojo va directo al precio y después al botón. */
.panel-precio {
  padding: var(--e-5);
  border: 1px solid #d5e1f3;
  border-radius: var(--radio);
  background:
    radial-gradient(circle at 100% 0, rgba(50, 104, 228, .11), transparent 42%),
    var(--azul-tenue);
  color: var(--texto);
  box-shadow: 0 1rem 2.5rem rgba(23, 45, 83, .10);
}

/* La etiqueta lleva un rayo delante. Es un `::before` y no un SVG en la
   plantilla porque no aporta información: si desaparece, el texto sigue
   diciendo exactamente lo mismo. */
.panel-precio-etiqueta {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--azul);
}

.panel-precio-etiqueta::before {
  content: "";
  flex-shrink: 0;
  width: 1.1rem;
  height: 1.1rem;
  background: currentColor;
  -webkit-mask: var(--icono-rayo) center / contain no-repeat;
  mask: var(--icono-rayo) center / contain no-repeat;
}

/* El número más grande de la página: es lo que la persona vino a ver. */
.panel-precio-valor {
  margin: 0.35rem 0 0;
  font-size: clamp(2.55rem, 3.5vw, 3rem);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.035em;
  line-height: 1.05;
  color: var(--texto);
}

/* La tienda, pegada al precio: el número solo no alcanza para actuar. */
.panel-precio-tienda {
  margin: 0.25rem 0 0;
  font-size: var(--t-sm);
  color: var(--texto-suave);
}

.panel-precio-tienda strong { color: var(--texto); font-weight: 600; }

.panel-precio-meta {
  margin-top: var(--e-4);
  padding-top: var(--e-3);
  border-top: 1px solid rgba(36, 89, 211, .14);
}

.panel-precio-verificado {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  margin: 0;
  font-size: var(--t-xs);
  color: var(--texto-suave);
}

.panel-precio-titulo {
  margin: var(--e-5) 0 0.35rem;
  font-size: var(--t-sm);
  font-weight: 600;
  letter-spacing: 0;
}

/* El botón principal del panel va a todo el ancho: es el final del
   recorrido «cuánto sale / dónde / voy», y el único punto de acción de
   la tarjeta. Sólido sobre la superficie tenue del panel. */
.panel-ver-precios {
  /* 44 px de alto tocable aunque el texto sea chico: con `display: block`
     el enlace medía 22 px, debajo del mínimo de 28 (revisión 2026-10-24). */
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  margin-top: var(--e-2);
  text-align: center;
  font-size: 0.9rem;
  font-weight: 600;
}

.boton-panel {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  width: 100%;
  margin-top: var(--e-4);
  padding: 0.7rem 1.1rem;
  font-weight: 600;
  text-align: center;
}

.aviso-chico {
  margin: var(--e-4) 0 0;
  padding: 0.6rem 0.85rem;
  font-size: var(--t-xs);
  border-radius: 8px;
}

/* La diferencia entre la más barata y la más cara es un dato del precio,
   no una advertencia: va pegada al bloque de precio y sin caja. Con el
   padding y el margen de `.aviso-chico` quedaba flotando a media altura
   del panel, separada de lo que explica. */
.panel-precio-meta .precio-valor { white-space: nowrap; }

.panel-precio-meta > .aviso-chico {
  margin-top: 0.35rem;
  padding: 0;
  color: var(--texto-suave);
}

.tabs-moneda { margin-top: var(--e-4); }

.tab-moneda-radio { position: absolute; opacity: 0; pointer-events: none; }

.tab-moneda-label {
  display: inline-block;
  padding: 0.35rem 0.9rem;
  margin-right: 0.4rem;
  font-size: var(--t-sm);
  color: var(--texto-suave);
  border: 1px solid var(--borde);
  border-radius: 999px;
  cursor: pointer;
  transition: background var(--transicion), color var(--transicion);
}

.tab-moneda-radio:checked + .tab-moneda-label {
  color: var(--azul);
  background: var(--azul-tenue);
  border-color: transparent;
  font-weight: 500;
}

.panel-moneda { display: none; }
#tab-USD:checked ~ .panel-moneda[data-moneda="USD"],
#tab-UYU:checked ~ .panel-moneda[data-moneda="UYU"] {
  display: block;
}

/* Filas de tienda: una sola definición (antes había una para el panel
   lateral y otra, 3.000 líneas más abajo, que la pisaba en la tabla —
   la única que quedaba en uso desde que el panel pasó a un solo botón).
   En celular la fila envuelve: con una condición larga («Outlet /
   reacondicionado») el precio baja a una segunda línea en vez de
   desbordar. Desde 40rem es un renglón de tabla (ver media query). */
.lista-tiendas {
  list-style: none;
  margin: var(--e-4) 0 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}

.fila-tienda-item { display: block; }

.fila-tienda {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem 0.9rem;
  min-height: 3.5rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
  box-shadow: var(--sombra);
  color: var(--texto);
  text-decoration: none;
  transition: border-color var(--transicion), background var(--transicion);
}

.fila-tienda:hover { border-color: #d5e1f3; }

/* La más barata con stock: borde verde a la izquierda, no fondo entero.
   El fondo verde que tenía antes nunca se veía — la regla de la tabla lo
   pisaba con blanco. */
.fila-tienda.fila-mejor { box-shadow: inset 3px 0 0 var(--verde), var(--sombra); }

.fila-tienda .logo-tienda { width: 2.2rem; height: 2.2rem; }

/* `flex: 1 1 7rem` en vez de `flex: 1`: la base de 7rem es el punto a
   partir del cual el nombre de la tienda deja de entrar cómodo y conviene
   que el resto de la fila baje de línea. */
.fila-tienda-info { flex: 1 1 7rem; min-width: 0; }
.fila-tienda-nombre { display: block; font-size: 1rem; font-weight: 500; }
.fila-tienda-condicion {
  display: block;
  font-size: var(--t-xs);
  line-height: 1.35;
  color: var(--texto-suave);
}

/* Stock: etiqueta propia con punto + texto (no solo color), distinta de
   la condición. «Sin stock» atenúa la fila sin esconderla: que algo
   exista pero no se venda hoy también es información
   (DOCS/70-BASEDATOS.md §3). */
.estado-stock {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  margin-top: 0.15rem;
  font-size: var(--t-xs);
  font-weight: 600;
  line-height: 1.35;
}
.estado-stock::before {
  content: "";
  width: 0.5em;
  height: 0.5em;
  border-radius: 50%;
  background: currentColor;
}
.estado-stock-si { color: var(--verde); }
.estado-stock-no { color: var(--rojo); }
.fila-tienda.fila-sin-stock .fila-tienda-precio { color: var(--texto-suave); font-weight: 500; }
.fila-tienda.fila-sin-stock .logo-tienda { opacity: 0.6; }

.panel-precio-etiqueta-sin-stock { color: var(--rojo); }
.panel-precio-sin-stock {
  margin: 0.75rem 0 0;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radio-chico);
  background: var(--fondo-suave);
  font-size: var(--t-sm);
  line-height: 1.45;
  color: var(--texto-suave);
}
.panel-precio-sin-stock .estado-stock { margin: 0 0.4em 0 0; }
.panel-precio-sin-stock strong { color: var(--texto); font-weight: 600; }
.panel-precio-sin-stock .precio-valor { white-space: nowrap; }

.fila-tienda-derecha {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 1.1rem;
}

/* La flecha se tiñe y se corre al pasar por la fila: es la confirmación de
   que la fila entera es clicable, sin necesidad de subrayar nada. */
.fila-tienda-flecha {
  flex-shrink: 0;
  color: var(--azul-claro);
  transition: transform var(--transicion);
}

.fila-tienda:hover .fila-tienda-flecha { transform: translateX(2px); }

.fila-tienda-precio {
  font-size: 1.1rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Debajo del precio: «La más barata» o cuánto más cuesta que ella, que
   es la cuenta que el usuario hace mirando la lista. */
.fila-tienda-montos {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.1rem;
}
.fila-tienda-dif {
  font-size: var(--t-xs);
  color: var(--texto-suave);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.fila-tienda-dif-mejor { color: var(--verde); font-weight: 600; }

/* La guía de puntos solo existe en una sola línea (ver el bloque de
   40rem): en celular la fila se acomoda en dos y no hay hueco que unir. */
.fila-tienda-guia { display: none; }

.enlace-tienda {
  flex-shrink: 0;
  font-size: var(--t-sm);
  color: var(--azul-claro);
  text-decoration: none;
  white-space: nowrap;
}

.enlace-tienda:hover { text-decoration: underline; }

@media (max-width: 56rem) {
  .ficha-encabezado { grid-template-columns: 1fr; }
  .ficha-imagen .miniatura { height: 17rem; }
}

/* En móvil la identidad del producto debe aparecer antes de su foto y de
   cualquier precio. `display: contents` integra los bloques secundarios de
   `.ficha-info` a la grilla para poder ubicar título, imagen y precio sin
   duplicar contenido ni alterar el orden que leen las ayudas técnicas. */
@media (max-width: 40rem) {
  .ficha-navegacion {
    margin-inline: calc(-1 * var(--e-2));
    padding-inline: var(--e-2);
    border-inline: 0;
    border-radius: 0;
    box-shadow: none;
  }

  .ficha-navegacion a {
    flex: 1 1 auto;
    padding-inline: .5rem;
    font-size: var(--t-xs);
  }
  /* Un renglón de migas y menos aire entre migas, pestañas y título: el
     precio quedaba 45 px debajo de la barra inferior (375 x 812). */
  .ficha-navegacion { margin-top: 0; margin-bottom: var(--e-3); }
  /* Más junto que en desktop: título, resumen, foto y precio tienen que
     entrar en la primera pantalla de un teléfono. */
  .ficha-encabezado { gap: var(--e-3); }
  .ficha-info { display: contents; }
  /* La identidad también se integra: la puntuación iba entre el título y
     la foto, y empujaba el precio fuera de la primera pantalla (375 px,
     2026-10-02). Ahora el precio va antes que la puntuación, que lo
     explica. */
  .ficha-identidad { display: contents; }
  .ficha-identidad > * { order: 1; }
  .ficha-columna-imagen { order: 2; }
  .ficha-lateral { order: 3; }
  .ficha-identidad > .puntuacion-resumen { order: 4; }
  .ficha-tarjetas { order: 5; }
  .ficha-caracteristicas { order: 6; }
  .ficha-info h1 { font-size: 1.8rem; }
  .ficha-imagen { padding: var(--e-4); }
  .ficha-imagen .miniatura { height: 13rem; }
  .panel-precio-valor { font-size: 2.65rem; }
}

/* Alto fijo; el ancho lo define cada variante más abajo. Un logo real
   (`<img class="logo-tienda">`) no es cuadrado casi nunca — forzarlo a
   una caja cuadrada con `border-radius` le recorta las esquinas a
   cualquier logo que sea cuadrado o casi (encontrado 2026-08-14). El
   redondeo de esquinas/círculo queda solo para el placeholder de
   iniciales (`.logo-monograma`, abajo), que sí es una forma propia y no
   el recorte de un logo ajeno. */
.logo-tienda {
  display: inline-grid;
  place-items: center;
  flex-shrink: 0;
  font-size: 0.8rem;
  font-weight: 600;
  color: #fff;
  letter-spacing: -0.01em;
}

/* `max-height`/`max-width` como topes, no `height` fija: con `height`
   fija el navegador resuelve el ancho a partir de esa altura y la
   proporción intrínseca, y ahí se detiene — si `max-width` recorta ese
   ancho, el alto (que nunca fue `auto`) no se recalcula, así que la
   caja queda con el ancho topeado pero el alto fijo de antes, y el
   logo se estira para llenarla. Verificado con navegador real
   (2026-08-14): tres wordmarks de proporción real muy distinta
   (6.53/2.59/4.99) rendereaban los tres exactamente igual, a la
   proporción de la caja (1.62), no a la propia. Con `width`/`height`
   en `auto` y ambos topeados, el navegador sí achica el que haga
   falta para entrar en los dos límites a la vez, preservando la
   proporción real — es el mismo mecanismo que
   `max-width:100%;max-height:Npx` en cualquier `<img>` suelto. */
img.logo-tienda {
  width: auto;
  height: auto;
  max-width: 2.4rem;
  max-height: 1.6rem;
}

.logo-monograma {
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 6px;
}

/* Mismo problema que `.logo-marca[src$="tcl.svg"]` arriba, mismo
   arreglo: estos cinco vinieron 100% blancos, sin ningún fondo propio en
   el archivo (pensados para el header oscuro de su propio sitio, no
   para esta página) — sin esto eran invisibles (2026-08-14). El resto
   de las tiendas con logo ya se distinguen solas. */
.logo-tienda[src$="sampler.svg"],
.logo-tienda[src$="artcomputer.svg"],
.logo-tienda[src$="nstore.svg"],
.logo-tienda[src$="cover-company.svg"],
.logo-tienda[src*="laaca"],
.logo-tienda[src*="dimm"],
.logo-tienda[src*="divino"],
.logo-tienda[src$="banifox.svg"] {
  background: var(--texto);
}

.celda-tienda {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
}

/* --- Listados --- */

.miga {
  font-size: var(--t-sm);
  color: var(--texto-suave);
  margin: var(--e-4) 0 var(--e-5);
}
.miga a { color: var(--texto-suave); }
.miga span { margin: 0 0.35rem; }

/* Confirmado contra la escala: 1rem/0.75rem ya son --e-4/--e-3 — se
   referencian los tokens sin cambiar el valor, esta lista ya estaba bien
   calibrada. */
.lista-productos { list-style: none; padding: 0; margin: var(--e-5) 0 0; }

.lista-productos li { border-bottom: 1px solid var(--borde); }

.lista-productos a {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding: var(--e-4) var(--e-3);
  margin: 0 calc(var(--e-3) * -1);
  border-radius: 10px;
  text-decoration: none;
  color: var(--texto);
  transition: background var(--transicion);
}

.lista-productos a:hover { background: var(--fondo-suave); }

.lista-productos .nombre {
  font-weight: 500;
  /* Cada fila concatena dos títulos crudos ("X vs Y") — a tamaño de texto
     normal se lee como un párrafo, no como una comparación. */
  font-size: 0.85rem;
  line-height: 1.4;
}

.lista-productos .nombre-bloque {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

/* Cuando el nombre visible es solo el modelo («Asus X1504VA-BQ3131»),
   dos productos de la misma marca se ven casi iguales — este resumen es
   lo que permite diferenciarlos sin abrir cada ficha (DOCS/70-BASEDATOS.md
   §5). */
.specs-resumen {
  color: var(--texto-suave);
  font-size: 0.82rem;
}

.lista-productos .meta {
  color: var(--texto-suave);
  font-size: 0.9rem;
  text-align: right;
}

/* En listados la miniatura es un acento, no la protagonista: el nombre y
   el precio siguen mandando. */
.lista-productos .miniatura {
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 8px;
}

.lista-productos .miniatura-monograma { font-size: 1rem; }

/* --- Familia --- */

.resumen-familia {
  margin: 0.5rem 0 1.5rem;
  color: var(--texto-suave);
}
.resumen-familia .precio {
  color: var(--azul);
  font-variant-numeric: tabular-nums;
}

/* --- Compará antes de comprar --- */

/* Grilla de 3 columnas en pantallas anchas (ícono | texto | buscador) con
   la fila de accesos rápidos ocupando todo el ancho abajo. Superficie
   tenue, no blanca: es una invitación a una acción secundaria, no otra
   tarjeta de contenido compitiendo con las specs. */
.comparar-rapido {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--e-3) var(--e-5);
  margin-top: var(--e-6);
  padding: var(--e-5);
  border-radius: var(--radio);
  background: var(--azul-tenue);
}

.comparar-rapido-icono {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  flex-shrink: 0;
  border-radius: 999px;
  background: #fff;
  color: var(--azul);
}

.comparar-rapido-texto h2 {
  margin: 0 0 0.15rem;
  font-size: 1.05rem;
  font-weight: 700;
}

.comparar-rapido-texto p {
  margin: 0;
  font-size: var(--t-sm);
  color: var(--texto-suave);
  max-width: 38rem;
}

.comparar-rapido-form {
  display: flex;
  gap: 0.5rem;
  min-width: 18rem;
}

.comparar-rapido-campo {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: 1;
  /* Sin esto, ni el campo ni el `<input>` que tiene adentro encogen por
     debajo de su ancho de contenido por defecto — junto al botón
     "Comparar" (que tampoco envuelve) eso empujaba el formulario, y con
     él a toda la página, a desbordar en mobile. */
  min-width: 0;
  padding: 0 0.85rem;
  background: #fff;
  border: 1px solid var(--borde-suave);
  border-radius: 8px;
}

.comparar-rapido-campo svg { flex-shrink: 0; color: var(--texto-suave); }

.comparar-rapido-campo input {
  flex: 1;
  padding: 0.55rem 0;
  border: 0;
  font: inherit;
  font-size: var(--t-sm);
  background: transparent;
}

.comparar-rapido-campo input:focus { outline: none; }

.comparar-rapido-frecuentes {
  grid-column: 1 / -1;
  margin: 0;
  font-size: var(--t-sm);
  color: var(--texto-suave);
}

.comparar-rapido-frecuentes a {
  color: var(--azul);
  font-weight: 500;
  text-decoration: none;
}

.comparar-rapido-frecuentes a:hover { text-decoration: underline; }

@media (max-width: 48rem) {
  .comparar-rapido { grid-template-columns: auto 1fr; }
  /* `flex-wrap: wrap`: aunque el formulario ya podía encoger
     (`min-width: 0`), el campo de búsqueda y el botón "Comparar" juntos
     seguían sin entrar en una fila angosta — el `<input>` por defecto
     no encoge por debajo de un ancho de contenido propio aunque su
     contenedor sí pueda. Envolviendo, el botón baja a su propia línea
     en vez de forzar scroll horizontal a toda la página. */
  .comparar-rapido-form { grid-column: 1 / -1; min-width: 0; flex-wrap: wrap; }
  .comparar-rapido-campo { flex-basis: 100%; }
}

.variantes { margin-top: var(--e-8); }

/* Fila de fotos de las versiones (2026-10-15): como el selector de
   variantes de una tienda. Envuelve en vez de hacer scroll horizontal. */
.variantes-fotos {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  margin: 1rem 0 0;
  padding: 0;
  list-style: none;
}

.variante-foto {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .3rem;
  width: 7rem;
  padding: .5rem .4rem .6rem;
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio-chico);
  background: #fff;
  color: var(--texto);
  text-decoration: none;
  text-align: center;
  transition: border-color var(--transicion), box-shadow var(--transicion);
}

a.variante-foto:hover { border-color: var(--azul); box-shadow: var(--sombra); }

.variante-actual { border: 2px solid var(--azul); }

.variante-imagen {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 5rem;
  height: 5rem;
}

.variante-imagen .miniatura { max-width: 100%; max-height: 100%; object-fit: contain; }
.variante-imagen .miniatura-monograma { width: 3rem; height: 3rem; font-size: 1.2rem; }

.variante-nombre { font-size: .78rem; line-height: 1.25; }
.variante-precio { font-size: .75rem; font-weight: 600; color: var(--texto-suave); }

/* --- Tabla de precios --- */

.precios { margin-top: 1.5rem; }

.tabla-precios {
  width: 100%;
  border-collapse: collapse;
  margin: 1.25rem 0;
}

.tabla-precios th,
.tabla-precios td {
  padding: 0.9rem 0.7rem;
  text-align: left;
  border-bottom: 1px solid var(--borde);
}

.tabla-precios th {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--texto-suave);
}

.tabla-precios tbody tr { transition: background var(--transicion); }
.tabla-precios tbody tr:hover { background: var(--fondo-suave); }

/* Números tabulares: los precios en columna se alinean dígito con dígito y
   se comparan de un vistazo (§4). */
.tabla-precios .precio {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.tabla-precios tr.mejor { background: var(--verde-tenue); }
.tabla-precios tr.mejor:hover { background: #e7f9ee; }

/* La única acción principal de la ficha: ir a comprar al mejor precio.
   Mismo lenguaje visual que `.buscador button` — el único botón sólido de
   toda la pantalla, para que el ojo lo encuentre sin buscarlo
   (DOCS/100-BRANDING.md §2). Los demás links "Ver en la tienda" quedan
   como texto: solo hay una acción principal, no una por fila. */
.boton-primario {
  display: inline-block;
  padding: 0.5rem 1.1rem;
  /* Como `<button>` traía el borde negro en relieve y la letra de sistema
     del navegador: el «Comparar» del comparador se veía de otra página
     (operador, 2026-10-24). Como `<a>` estas dos líneas no cambian nada. */
  border: 0;
  font: inherit;
  font-weight: 500;
  cursor: pointer;
  color: #fff;
  background: var(--azul);
  /* `var(--radio-chico)` y no un `8px` suelto: es el mismo radio que ya
     usa `.boton-secundario` (más abajo), su pareja habitual en la misma
     pantalla (ficha de producto, comparador) — con valores distintos
     (8px vs 10px) las esquinas se ven "casi iguales pero no", un
     desajuste que se nota más al tenerlos uno al lado del otro. */
  border-radius: var(--radio-chico);
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--transicion);
}

.boton-primario:hover { background: var(--azul-claro); }

.tabla-precios .fecha {
  font-size: 0.9rem;
  color: var(--texto-suave);
  font-variant-numeric: tabular-nums;
}

.etiqueta {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0.1rem 0.55rem;
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--verde);
  border: 1px solid currentColor;
  border-radius: 999px;
  white-space: nowrap;
}

/* "Nuevo" es un estado del producto, no una señal positiva como "Más
   barato" — por eso va en violeta relleno y no en el verde de `.etiqueta`,
   que queda reservado a lo que le conviene al usuario.

   Va acá abajo y no junto a las reglas de tarjeta: tiene la misma
   especificidad que `.etiqueta`, así que gana la que se declara después.
   Escrita más arriba en el archivo, no pisaba nada. */
.etiqueta-nuevo {
  margin-left: 0;
  align-self: flex-start;
  padding: 0.15rem 0.6rem;
  border: 0;
  border-radius: 7px;
  background: var(--azul-tenue);
  color: var(--azul);
  font-size: 0.75rem;
  font-weight: 600;
}

/* Outlet / usado: mismo tratamiento que `.etiqueta-nuevo` (relleno,
   sin borde) pero en ámbar — no es un estado negativo como para usar
   rojo, pero sí es información que cambia la decisión de compra y
   tiene que distinguirse de un vistazo del violeta de "Nuevo". */
.etiqueta-condicion {
  margin-left: 0;
  align-self: flex-start;
  padding: 0.15rem 0.6rem;
  border: 0;
  border-radius: 7px;
  background: #fef3c7;
  color: #92400e;
  font-size: 0.75rem;
  font-weight: 600;
}

.etiqueta-aviso {
  display: block;
  font-size: 0.75rem;
  color: var(--rojo);
}

.ahorro { color: var(--texto); }

.aviso {
  padding: 0.95rem 1.15rem;
  background: var(--fondo-suave);
  border-left: 3px solid var(--azul-claro);
  border-radius: 4px;
  color: var(--texto-suave);
}

.vacio { color: var(--texto-suave); }

.aviso-busqueda {
  margin: 0.25rem 0 1rem;
  font-size: 0.95rem;
  color: var(--texto-suave);
}

.sugerencia {
  margin: 0.5rem 0 0;
  font-size: 1.02rem;
}

.nota {
  font-size: 0.85rem;
  color: var(--texto-suave);
  margin-top: 1.5rem;
}

.titulo-original { font-style: italic; }

/* --- Puntuación QuéCompro ---
   El elemento visual más distintivo del producto (DOCS/100-BRANDING.md §9):
   se lee de un vistazo, siempre en el mismo lugar, y su explicación es
   parte natural del bloque, no algo escondido detrás de un ícono. */

.puntuacion {
  margin: var(--e-5) 0 var(--e-6);
  padding: clamp(1.25rem, 3vw, 2rem);
  border: 1px solid #d5e1f3;
  border-radius: var(--radio);
  background:
    radial-gradient(circle at 8% 8%, rgba(50, 104, 228, .14), transparent 28%),
    linear-gradient(145deg, #f9fbff, #fff 62%);
  box-shadow: var(--sombra);
}

.puntuacion-cabecera {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: clamp(1.25rem, 3vw, 2.25rem);
  padding-bottom: var(--e-5);
  border-bottom: 1px solid var(--borde-suave);
}

.puntuacion-medidor {
  --avance: var(--puntuacion);
  position: relative;
  display: grid;
  place-items: center;
  width: 9.5rem;
  height: 9.5rem;
  flex-shrink: 0;
  border-radius: 50%;
  background: conic-gradient(var(--azul) var(--avance), #e6ebf4 0);
  box-shadow: inset 0 0 0 1px rgba(36, 89, 211, .08);
}

.puntuacion-medidor::before {
  content: "";
  position: absolute;
  inset: .7rem;
  border-radius: inherit;
  background: #fff;
  box-shadow: inset 0 0 0 1px var(--borde-suave);
}

.puntuacion-medidor-centro {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: baseline;
  color: var(--azul);
  font-variant-numeric: tabular-nums;
}

.puntuacion-medidor-centro strong {
  font-size: 3.25rem;
  font-weight: 750;
  line-height: 1;
  letter-spacing: -.055em;
}

.puntuacion-medidor-centro span { font-size: .9rem; opacity: .58; }

.puntuacion-intro { max-width: 42rem; }
.puntuacion-intro h2 { margin: .2rem 0 .55rem; font-size: clamp(1.65rem, 3vw, 2.15rem); }
.puntuacion-intro p { margin: 0; color: var(--texto-suave); line-height: 1.55; }

.puntuacion-eyebrow {
  color: var(--azul);
  font-size: var(--t-xs);
  font-weight: 750;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.etiqueta-beta {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0.1rem 0.55rem;
  font-size: 0.7rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  vertical-align: middle;
  color: var(--texto-suave);
  border: 1px solid var(--borde);
  border-radius: 999px;
  background: #fff;
}

.puntuacion-factores {
  list-style: none;
  padding: 0;
  margin: var(--e-5) 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--e-3);
}

.puntuacion-factores li {
  padding: var(--e-4);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio-chico);
  background: rgba(255, 255, 255, .78);
}

.puntuacion-factor-cabecera {
  display: flex;
  justify-content: space-between;
  gap: var(--e-3);
  align-items: baseline;
}

.puntuacion .factor-nombre { font-weight: 700; }
.factor-puntos { color: var(--azul); font-size: var(--t-xs); font-weight: 700; white-space: nowrap; }

.puntuacion-factores meter {
  display: block;
  width: 100%;
  height: .55rem;
  margin: .55rem 0 .65rem;
  border: 0;
  border-radius: 999px;
  background: #e6ebf4;
  overflow: hidden;
}

.puntuacion-factores meter::-webkit-meter-bar { background: #e6ebf4; border: 0; }
.puntuacion-factores meter::-webkit-meter-optimum-value { background: var(--azul); }
.puntuacion-factores meter::-moz-meter-bar { background: var(--azul); }

.puntuacion .factor-explicacion {
  margin: 0;
  color: var(--texto-suave);
  font-size: var(--t-sm);
  line-height: 1.45;
}

.puntuacion-pendientes {
  padding: var(--e-4);
  border-radius: var(--radio-chico);
  background: var(--fondo-suave);
}

.puntuacion-pendientes strong { display: block; margin-bottom: .3rem; }
.puntuacion-pendientes p { margin: 0; color: var(--texto-suave); font-size: var(--t-sm); line-height: 1.5; }

.puntuacion-garantia {
  display: flex;
  align-items: center;
  gap: var(--e-2);
  margin-top: var(--e-4);
  color: var(--azul);
  font-size: var(--t-sm);
  font-weight: 650;
}

.puntuacion-garantia svg { flex-shrink: 0; }

@media (max-width: 40rem) {
  .puntuacion-cabecera { grid-template-columns: 1fr; justify-items: center; text-align: center; }
  .puntuacion-medidor { width: 8.5rem; height: 8.5rem; }
  .puntuacion-factores { grid-template-columns: 1fr; }
  .puntuacion-garantia { align-items: flex-start; }
}

/* --- Ranking por categoría (Etapa 2.5) --- */

/* La intro (subtítulo + nota de metodología) se lee como un solo bloque,
   no como dos párrafos sueltos — se acorta el espacio entre ellos sin
   tocar `.nota`/`.apoyo-bloque` en general, que en otras pantallas sí
   necesitan su espacio por defecto. */
.ranking-intro .apoyo-bloque { margin-bottom: var(--e-2); }
.ranking-intro .nota { margin-top: 0; }

/* Ranking: mismo componente .tarjeta que el resto del sitio (Home,
   Categoría), con la posición y el puntaje del Índice como los dos datos
   que esta pantalla agrega por encima de una tarjeta común — antes era
   una fila horizontal densa, un lenguaje aparte del resto (§2 de la
   propuesta de rediseño). */
.tarjeta-ranking { position: relative; }

.ranking-indice {
  margin-top: 0.35rem;
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--azul);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.ranking-indice .indice-total {
  margin-left: 0.1rem;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--texto-suave);
}

/* Verde: es una señal positiva real (el mejor Índice de su categoría), no
   una novedad — mismo criterio de color que ya sigue el resto del sitio. */
/* Alto reservado, se muestre o no la insignia: es lo que mantiene títulos,
   precios e índices a la misma altura en toda la fila. */
/* --- Historial de precios --- */

/* Tarjeta propia con borde, como el resto de los bloques de la jerarquía
   nueva (`.bloque-comprar`, las tarjetas de arriba) — antes esta sección
   flotaba sin caja sobre la página; ahora es un bloque más de la misma
   familia visual. Existe siempre que haya oferta, con o sin evolución que
   mostrar: la diferencia la resuelve `.bloque-historial-cuerpo` adentro,
   no la sección entera. */
.bloque-historial {
  margin-top: var(--e-7);
  padding: var(--e-5) var(--e-6);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
}

.bloque-historial-intro h2 {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.3rem;
  font-size: 1.1rem;
  font-weight: 700;
}

.bloque-historial-intro h2 svg { color: var(--azul); flex-shrink: 0; }

.bloque-historial-intro p {
  margin: 0 0 var(--e-4);
  color: var(--texto-suave);
  font-size: var(--t-sm);
  max-width: 34rem;
}

/* Estado vacío: mismo lenguaje que "Sin ofertas disponibles" del panel de
   precio — un ícono chico y dos líneas, nunca un gráfico simulado ni una
   tendencia que no medimos (DOCS/30-PRINCIPIOS.md §1). */
.historial-vacio {
  display: flex;
  align-items: center;
  gap: var(--e-4);
  padding: var(--e-4) var(--e-5);
  border-radius: var(--radio-chico);
  background: var(--fondo-suave);
}

.historial-vacio svg { flex-shrink: 0; color: var(--texto-suave); }

.historial-vacio-titulo {
  margin: 0;
  font-weight: 600;
}

.historial-vacio-apoyo {
  margin: 0.15rem 0 0;
  font-size: var(--t-sm);
  color: var(--texto-suave);
}

/* --- ¿Dónde comprarlo? --- */

/* Cierre del recorrido: texto a la izquierda, acción a la derecha — la
   misma estructura que `.bloque-historial` pero horizontal, porque acá no
   hay contenido variable que mostrar, solo una invitación a bajar a la
   tabla de tiendas. */
.bloque-comprar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e-4);
  margin-top: var(--e-5);
  padding: var(--e-5) var(--e-6);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
}

.bloque-comprar-texto h2 {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.3rem;
  font-size: 1.1rem;
  font-weight: 700;
}

.bloque-comprar-texto h2 svg { color: var(--azul); flex-shrink: 0; }

.bloque-comprar-texto p {
  margin: 0;
  color: var(--texto-suave);
  font-size: var(--t-sm);
}

/* `.boton-secundario` (más abajo en este archivo) es `width: 100%` por
   default, pensado para botones apilados en el sidebar. Con la misma
   especificidad (una sola clase) gana el que aparece después en el
   archivo, así que un simple `.boton-comprar { width: auto }` no
   alcanza — hace falta el selector compuesto para pisarlo. Acá el botón
   convive con texto a su izquierda en una fila horizontal: sin este
   override ocupa casi todo el ancho de `.bloque-comprar` y empuja el
   texto a una columna angosta donde el título llega a partirse en dos
   líneas. */
.boton-secundario.boton-comprar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  width: auto;
  flex-shrink: 0;
  white-space: nowrap;
  padding: 0.65rem 1.4rem;
}

@media (max-width: 40rem) {
  .bloque-comprar { flex-direction: column; align-items: stretch; text-align: center; }
  .boton-comprar { width: 100%; justify-content: center; }
}

/* El marco lleva el SVG y, encima, lo que no se puede estirar: el punto
   de hoy y los montos del eje (busqueda/templatetags/grafico.py). */
.grafico-marco {
  position: relative;
  margin: 1.25rem 0 0;
  color: var(--azul);
}

.grafico {
  display: block;
  width: 100%;
  height: 220px;
  overflow: visible;
}

.grafico-guia {
  stroke: var(--borde);
  stroke-width: 1;
  stroke-dasharray: 4 4;
}

/* El monto va apoyado sobre su línea guía, al borde izquierdo útil. */
.grafico-eje {
  position: absolute;
  left: 3.75%;
  transform: translateY(calc(-100% - 4px));
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--texto-suave, #5a6572);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

.grafico-hoy {
  position: absolute;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 4px var(--azul-tenue);
  transform: translate(-50%, -50%);
  pointer-events: none;
}

/* Primera y última fecha de la serie, alineadas con los bordes útiles
   del gráfico (el margen interno del SVG es 24 de 640, 3,75 %). */
.grafico-fechas {
  display: flex;
  justify-content: space-between;
  margin: 0.5rem 3.75% 1.25rem;
  font-size: 0.8rem;
  color: var(--texto-suave, #5a6572);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 40rem) {
  .grafico { height: 160px; }
}

.resumen-historial {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 0.75rem;
  margin: 0;
}

.resumen-historial > div {
  padding: 0.9rem 1rem;
  background: var(--fondo-suave);
  border-radius: var(--radio);
}

.resumen-historial dt {
  font-size: 0.8rem;
  color: var(--texto-suave);
}

.resumen-historial dd {
  margin: 0.15rem 0 0;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* --- Marcas destacadas (chip con monograma) --- */

.marcas-destacadas {
  margin: var(--e-5) 0;
  padding: var(--e-4) var(--e-5);
  border-radius: var(--radio);
  background: var(--azul-tenue);
}

.marcas-destacadas-titulo {
  display: block;
  margin-bottom: 0.7rem;
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--azul);
}

.marcas-destacadas-lista {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

.marca-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.9rem 0.45rem 0.45rem;
  border-radius: 999px;
  background: #fff;
  color: var(--texto);
  text-decoration: none;
  font-size: 0.88rem;
  font-weight: 500;
  transition: box-shadow var(--transicion);
}

.marca-chip:hover { box-shadow: var(--sombra); }

/* Mismo criterio que `.logo-tienda`: alto fijo, el ancho lo define cada
   variante — un logo real no es un círculo, forzarlo a uno le recorta
   las esquinas a cualquier isotipo cuadrado (Asus, HP, Xiaomi, todos
   cerca de 1:1 de proporción). El círculo queda solo para el
   placeholder de iniciales, la única de las dos formas que sí es
   intencionalmente circular. */
.monograma-marca {
  display: grid;
  place-items: center;
  flex-shrink: 0;
}

/* El logo necesita una ranura explícita también en los chips chicos. Con
   ambos ejes en `auto`, una imagen diferida todavía no participa del ancho
   de la pastilla cuando Flexbox hace el primer cálculo; al cargar se pinta
   encima del nombre y este parece quedar afuera (Asus en Monitores). La
   caja fija reserva el lugar desde el inicio y `contain` mantiene intacta
   la proporción de isotipos y wordmarks. */
img.monograma-marca {
  width: 2.4rem;
  height: 1.6rem;
  max-width: none;
  max-height: none;
  object-fit: contain;
}

.monograma-marca-texto {
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  font-size: 0.75rem;
  font-weight: 700;
  background: var(--azul-tenue);
  color: var(--azul);
}

/* --- Listados de Marcas y Tiendas --- */

/* `.apoyo` (la bajada debajo del título) trae `margin: 0 auto` porque en
   el hero de la Home va centrada bajo un `<h1>` también centrado — acá
   el `<h1>` ("Marcas"/"Tiendas") es un bloque normal, alineado a la
   izquierda por default, así que ese `margin: 0 auto` la corría al
   centro de la página mientras el título se quedaba pegado al borde:
   quedaban a 300px de distancia entre sí en vez de arrancar los dos del
   mismo lugar (encontrado 2026-08-14, mismo problema en las dos
   páginas). */
.encabezado-marcas .apoyo,
.encabezado-tiendas .apoyo {
  margin-left: 0;
  margin-right: 0;
  max-width: none;
}

.grilla-marcas {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: var(--e-5);
}

.marca-chip-grande {
  flex-shrink: 0;
  padding: 0.65rem 1.2rem 0.65rem 0.65rem;
  font-size: 0.98rem;
  background: var(--fondo-suave);
}

/* En estos listados el logo ocupa una ranura con dimensiones explícitas.
   Así el ancho intrínseco de la pastilla siempre lo incluye: con ambos
   ejes en `auto`, los logos cargados de forma diferida podían quedar fuera
   del cálculo del contenedor flex y desbordar el fondo gris. `contain`
   conserva la proporción real tanto de isotipos como de wordmarks. */
.marca-chip-grande img.monograma-marca,
.marca-chip-grande img.logo-tienda {
  width: 3.4rem;
  height: 2.1rem;
  max-width: none;
  max-height: none;
  object-fit: contain;
}

.marca-chip-grande .monograma-marca-texto,
.marca-chip-grande .logo-monograma {
  width: 2.1rem;
  height: 2.1rem;
  font-size: 0.85rem;
}

/* Cuántos productos comparables tiene la marca — mismo criterio que ya
   usa `_categorias_con_productos()` en `busqueda/views.py`: un conteo
   real de la base, no una estimación. Va como bajada chica al lado del
   nombre, no compite con él. */
.marca-chip-cantidad {
  margin-left: 0.35rem;
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--texto-suave);
}

/* --- Categoría: barra lateral de filtros ---
   Todo se elige por enlace (marca, precio, características,
   disponibilidad) — un único mecanismo en vez de mezclar pastillas de
   navegación con un <select> y checkboxes de un <form> aparte. La
   sidebar es su propia columna, no un panel apilado arriba del
   contenido: en pantallas angostas se apila (media query más abajo). */
.pagina-categoria {
  display: grid;
  grid-template-columns: 15rem 1fr;
  gap: var(--e-6);
  align-items: start;
  margin-top: var(--e-5);
}

/* La barra lateral va dentro de una superficie propia, como en la
   referencia. Suelta sobre el fondo blanco competía visualmente con la
   grilla de productos: dos columnas del mismo peso, ninguna claramente
   secundaria. Con caja pasa a leerse como panel de apoyo. */
.sidebar-filtros {
  display: flex;
  flex-direction: column;
  gap: var(--e-5);
  align-self: start;
  padding: 1.35rem 1.15rem;
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: var(--fondo-tenue);
}

.sidebar-filtros .faceta-opcion:hover { background: #fff; }

.filtros-activos {
  display: inline-grid;
  place-items: center;
  min-width: 1.45rem;
  height: 1.45rem;
  margin-left: .45rem;
  padding: 0 .3rem;
  border-radius: 999px;
  background: var(--azul);
  color: #fff;
  font-size: var(--t-xs);
  vertical-align: .08em;
}

.limpiar-filtros {
  font-size: var(--t-sm);
  color: var(--azul-claro);
  text-decoration: none;
}

.limpiar-filtros:hover { text-decoration: underline; }

/* --- Resultados de categoría --- */

.resultados-cabecera {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
  margin-bottom: var(--e-4);
}

.resultados-cabecera .conteo { margin: 0; }

.orden {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.9rem;
  font-size: var(--t-sm);
}

.orden-etiqueta { color: var(--texto-suave); }

.orden a {
  color: var(--texto-suave);
  text-decoration: none;
}

.orden a:hover { color: var(--azul); }
.orden a.actual { color: var(--azul); font-weight: 500; }

@media (max-width: 48rem) {
  .pagina-categoria { grid-template-columns: 1fr; }
}

.conteo {
  margin: 1rem 0 0;
  font-size: 0.9rem;
  color: var(--texto-suave);
}

/* --- Facetas (barra lateral de Categoría) ---
   Marca, precio y características son la misma idea (¿qué valor de esta
   faceta quiero?): un solo componente vertical con aspecto de checkbox,
   cantidad a la vista antes de hacer clic (DOCS/160-CATALOGO.md §5). Son
   enlaces, no inputs — funcionan sin JavaScript y sin ningún <form> que
   enviar (DOCS/110-SEO.md §4). */

.facetas {
  display: flex;
  flex-direction: column;
  gap: var(--e-5);
}

.faceta {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.faceta-titulo {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--texto-suave);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.faceta-opciones {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.faceta-opcion {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.4rem 0.3rem;
  border-radius: 6px;
  color: var(--texto);
  text-decoration: none;
  font-size: 0.92rem;
  font-variant-numeric: tabular-nums;
  transition: background var(--transicion);
}

.faceta-opcion:hover { background: var(--fondo-suave); }

.faceta-opcion::before {
  content: "";
  flex-shrink: 0;
  width: 1rem;
  height: 1rem;
  border: 1.5px solid var(--borde);
  border-radius: 4px;
  background: #fff;
  transition: background var(--transicion), border-color var(--transicion);
}

.faceta-opcion.activa::before {
  border-color: var(--azul);
  background: var(--azul) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='white' stroke-width='2'%3E%3Cpath d='M3 8l3.5 3.5L13 4.5'/%3E%3C/svg%3E") center/0.7rem no-repeat;
}

.faceta-opcion.activa { color: var(--azul); font-weight: 500; }

.faceta-cantidad {
  margin-left: auto;
  font-size: 0.82rem;
  color: var(--texto-suave);
}

.faceta-opcion.activa .faceta-cantidad { color: var(--azul-claro); }

/* «Ver N más» (`_faceta.html`): las opciones plegadas se ven igual que las
   de arriba; el `summary` es un enlace de texto, no otro botón. */
.faceta-mas { display: flex; flex-direction: column; gap: 0.1rem; }
.faceta-mas > summary {
  order: 1;
  min-height: 2.25rem;
  display: flex;
  align-items: center;
  padding: 0.4rem 0.3rem;
  color: var(--azul);
  font-size: var(--t-sm);
  cursor: pointer;
  list-style: none;
}
.faceta-mas > summary::-webkit-details-marker { display: none; }
.faceta-mas[open] > summary { display: none; }

/* --- Comparador (rediseño 2026-08-18) ---
   Estructura de información tomada de versus.com por pedido explícito
   del responsable del proyecto: hero enfrentado con nombres grandes,
   veredicto, "cuál es para vos", tabla de diferencias decisivas con
   columna de veredicto, ficha técnica agrupada y plegable, y barra fija
   inferior. La PALETA y la tipografía son las de QuéCompro
   (DOCS/100-BRANDING.md): fondo blanco, violeta de marca, Inter, verde
   solo para ventajas reales — nada de tema oscuro ni de la identidad
   visual ajena.

   El rasgo tipográfico que define esa referencia —nombres de producto
   grandes, en mayúsculas y con mucho peso— sí se adopta: es lo que hace
   que la comparación se lea como un enfrentamiento y no como una
   planilla. */

.vs-hero {
  margin: var(--e-6) 0 var(--e-7);
}

.vs-hero-grilla {
  display: grid;
  /* Una columna por producto (2 a 4, `MAXIMO_PRODUCTOS`). `minmax(0,1fr)`
     y no `1fr` a secas: sin el mínimo en 0, un nombre largo sin espacios
     puede empujar su columna y romper el reparto parejo. */
  grid-template-columns: repeat(var(--columnas, 2), minmax(0, 1fr));
  gap: var(--e-5);
}

.vs-hero[data-productos="3"] .vs-hero-grilla { --columnas: 3; }
.vs-hero[data-productos="4"] .vs-hero-grilla { --columnas: 4; }

/* La línea entre productos, en vez de un badge "VS": separa sin agregar
   un elemento que compita por atención. */
.vs-hero-producto {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 0 var(--e-4);
  border-left: 1px solid var(--borde-suave);
}

.vs-hero-producto:first-child { border-left: 0; }

.vs-hero-nombre {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  margin: 0 0 var(--e-4);
  font-size: clamp(1.15rem, 2.4vw, 1.9rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  text-wrap: balance;
}

.vs-hero-marca {
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--texto-suave);
}

/* Caja CUADRADA y acotada, no una franja ancha: es lo que empareja las
   fotos entre sí, que es como se ven en la referencia.

   Por qué cuadrada: relevando el catálogo real (2026-08-18), la
   proporción MEDIANA es 1.00 en casi todas las categorías —celular,
   notebook, monitor, televisor, tablet, smartwatch— porque las tiendas
   publican la foto sobre un lienzo cuadrado. Los extremos van de 0.37
   (un celular muy vertical) a 2.15 (una consola apaisada).

   Con la franja ancha de la versión anterior (532×320 en dos columnas)
   esos extremos se veían de tamaños completamente distintos: una foto
   apaisada ocupaba ~131.000 px² y una vertical ~38.000 — más de 3× de
   diferencia entre dos productos de la misma comparación. En una caja
   cuadrada ninguna puede pasar de lado×lado, la mayoría (mediana 1.00)
   la llena entera, y las proporciones raras quedan centradas adentro
   del mismo cuadrado en vez de estirarse a lo ancho.

   `object-fit: contain` sigue: la foto nunca se recorta ni se deforma
   para llenar la caja — se muestra entera, que es lo que corresponde
   cuando la foto es el producto que se está por comprar. */
.vs-hero-imagen {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: 18rem;
  aspect-ratio: 1;
  margin: 0 auto var(--e-4);
}

.vs-hero-imagen .miniatura {
  width: 100%;
  height: 100%;
  background: none;
  object-fit: contain;
  transition: transform var(--transicion);
}

.vs-hero-imagen:hover .miniatura { transform: scale(1.03); }

.vs-hero-imagen .miniatura-monograma {
  width: 6rem;
  height: 6rem;
  background: var(--azul-tenue);
}

.vs-hero-datos {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  margin-bottom: var(--e-3);
}

/* El círculo de puntuación de la referencia, con el violeta de marca.
   Verde solo cuando es la más alta de la comparación — mismo criterio
   que el resto del sitio: el verde señala una ventaja real, no decora. */
.vs-puntuacion {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  border: 2px solid var(--azul);
  font-size: 1.05rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--azul);
}

.vs-puntuacion.ganador {
  border-color: var(--verde);
  color: var(--verde);
}

.vs-boton-ofertas {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  padding: 0.5rem 1.25rem;
  border-radius: 999px;
  border: 1px solid var(--borde);
  background: #fff;
  color: var(--texto);
  font-size: var(--t-sm);
  font-weight: 600;
  text-decoration: none;
  transition: background var(--transicion), border-color var(--transicion), color var(--transicion);
}

.vs-boton-ofertas:hover {
  background: var(--azul);
  border-color: var(--azul);
  color: #fff;
}

.ficha-lanzamiento {
  margin: var(--e-2) 0 0;
  font-size: var(--t-xs);
  color: var(--texto-suave);
}

.ficha-antiguedad {
  white-space: nowrap;
}

/* Antigüedad del producto en el hero del comparador. Deliberadamente
   discreto: es contexto para leer el resto, no un dato que compita con
   el precio ni con la Puntuación. */
.vs-hero-lanzamiento {
  margin: var(--e-2) 0 0;
  font-size: var(--t-xs);
  line-height: 1.4;
  color: var(--texto-suave);
  /* Fecha y antigüedad van siempre en dos líneas, y la columna que no
     tiene fecha reserva las mismas dos: así los precios de abajo quedan
     a la misma altura en pantallas angostas, donde antes una columna
     partía la línea y la otra no. */
  min-height: calc(2 * 1.4em);
}

.vs-hero-antiguedad {
  display: block;
  white-space: nowrap;
}

.vs-hero-precio {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  margin: 0;
}

.vs-hero-precio strong {
  font-size: var(--t-md);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--azul);
}

.vs-hero-precio.ganador strong { color: var(--verde); }
.vs-hero-precio > span { font-size: var(--t-xs); color: var(--texto-suave); }

/* --- Secciones --- */

.vs-seccion { margin: var(--e-7) 0; }

.vs-titulo-seccion {
  font-size: clamp(1.3rem, 2.6vw, 1.75rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  margin: 0 0 var(--e-2);
}

.vs-subtitulo-seccion {
  margin: 0 0 var(--e-5);
  color: var(--texto-suave);
  font-size: var(--t-sm);
}

/* --- El veredicto --- */

.vs-veredicto {
  padding: var(--e-5) var(--e-6);
  border-radius: var(--radio);
  background: var(--fondo-tenue);
}

.vs-veredicto-frase {
  margin: 0;
  font-size: var(--t-md);
  line-height: 1.6;
}

.vs-veredicto-etiqueta { color: var(--texto-suave); }
.vs-veredicto-frase strong { color: var(--azul); }
.vs-veredicto-frase em { font-style: normal; font-weight: 600; }

.vs-veredicto-nota {
  margin: var(--e-3) 0 0;
  font-size: var(--t-xs);
  color: var(--texto-suave);
}

/* --- ¿Cuál es para vos? --- */

.vs-cual-grilla {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: var(--e-5);
}

.vs-cual-card {
  padding: var(--e-5);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
  transition: border-color var(--transicion), box-shadow var(--transicion);
}

.vs-cual-card:hover {
  border-color: var(--borde);
  box-shadow: var(--sombra);
}

.vs-cual-titulo {
  margin: 0 0 var(--e-4);
  font-size: var(--t-sm);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--azul);
}

.vs-cual-titulo span { color: var(--texto-suave); font-weight: 500; }

.vs-ventajas { list-style: none; margin: 0; padding: 0; }

.vs-ventajas li {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: var(--e-3) 0;
  border-top: 1px solid var(--borde-suave);
}

.vs-ventajas li:first-child { padding-top: 0; border-top: 0; }

.vs-ventaja-etiqueta { font-weight: 600; }

.vs-ventaja-valor {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 600;
  color: var(--verde);
}

/* El "+4 GB" / "el doble" que ya calculaba `Fila.resumen` desde antes
   del rediseño — acá se muestra como la píldora de magnitud de la
   referencia. */
.vs-delta {
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  background: var(--verde-tenue);
  font-size: var(--t-xs);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.vs-ventaja-rival { font-size: var(--t-xs); color: var(--texto-suave); }

.vs-cual-vacio { margin: 0; font-size: var(--t-sm); color: var(--texto-suave); }

/* --- Tablas (diferencias decisivas y ficha técnica) --- */

.vs-tabla-scroll {
  overflow-x: auto;
  scrollbar-width: thin;
  /* Establece el bloque contenedor de sus descendientes posicionados.
     Sin esto, los `span.oculto` —el texto que solo leen los lectores de
     pantalla, que es `position: absolute`— tomaban como referencia la
     página entera. Como viven dentro de una tabla más ancha que la
     pantalla, caían fuera del viewport y estiraban el documento: en
     1024px la página scrolleaba 19px de costado sin que se viera nada
     ahí (medido 2026-08-19). Al posicionar el contenedor quedan dentro
     de su recorte, sin cambiar en nada lo que se ve ni lo que se lee. */
  position: relative;
}

.vs-tabla {
  width: 100%;
  min-width: 34rem;
  border-collapse: collapse;
}

.vs-tabla th,
.vs-tabla td {
  padding: var(--e-3) var(--e-4);
  text-align: left;
  vertical-align: middle;
  font-size: 0.9rem;
}

.vs-tabla thead th {
  padding-bottom: var(--e-2);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--texto-suave);
  border-bottom: 1px solid var(--borde);
  white-space: nowrap;
}

.vs-tabla tbody th {
  font-weight: 500;
  color: var(--texto);
  white-space: nowrap;
}

.vs-tabla tbody tr { border-bottom: 1px solid var(--borde-suave); }
.vs-tabla tbody tr:last-child { border-bottom: 0; }

.vs-tabla td { overflow-wrap: anywhere; }

/* El nombre del producto repetido dentro de cada celda. Acá sobra —lo
   dice el encabezado de la columna— y solo aparece cuando la tabla se
   apila en mobile, donde ya no hay columnas que lo digan. */
.vs-celda-producto { display: none; }

/* Verde: gana con un criterio objetivo. Negrita neutra: es el valor más
   alto, sin declarar que conviene (DOCS/30-PRINCIPIOS.md §2). */
.vs-tabla td.gana { color: var(--verde); font-weight: 700; }
.vs-tabla td.mayor { font-weight: 700; }

.vs-tabla tr.coincide th,
.vs-tabla tr.coincide td { color: var(--texto-suave); }

/* «No aplica: es con cable»: un dato verificado de ausencia, no un valor
   más. Las celdas «Sin dato verificado» ya no existen: desde el
   2026-10-15 la comparativa solo muestra filas verificadas en todos
   (DOCS/160-CATALOGO.md §10). */
.vs-tabla .vs-no-aplica { color: var(--texto-suave); }

.vs-col-veredicto { text-align: right; }

.vs-chip-veredicto {
  display: inline-block;
  max-width: 12rem;
  padding: 0.2rem 0.7rem;
  border-radius: 999px;
  background: var(--verde-tenue);
  color: var(--verde);
  font-size: var(--t-xs);
  font-weight: 600;
  line-height: 1.4;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: middle;
}

.vs-chip-veredicto.vs-chip-empate {
  background: var(--fondo-suave);
  color: var(--texto-suave);
}

/* --- Ficha técnica: grupos plegables ---
   `<details>` nativo: sin JavaScript, accesible por teclado, y el
   contenido sigue en el DOM esté abierto o cerrado — indexable
   (DOCS/110-SEO.md §4). */

.vs-grupo {
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  margin-bottom: var(--e-3);
  background: #fff;
  transition: border-color var(--transicion);
}

.vs-grupo[open] { border-color: var(--borde); }

.vs-grupo-resumen {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  padding: var(--e-4) var(--e-5);
  min-height: 3.5rem;
  cursor: pointer;
  list-style: none;
}

.vs-grupo-resumen::-webkit-details-marker { display: none; }

.vs-grupo-nombre {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  font-size: var(--t-sm);
}

.vs-grupo-numero {
  color: var(--texto-suave);
  font-variant-numeric: tabular-nums;
}

.vs-grupo-numero::after { content: "."; }

/* Es el NOMBRE el que empuja, no el chip ni el chevron: con
   `margin-left: auto` en los dos, flex repartía el espacio sobrante
   entre ambos y el chip quedaba flotando en el medio de la fila, a
   ~390px de cada lado (medido en el navegador, 2026-08-18). Empujando
   desde el nombre, chip y chevron quedan juntos contra el borde
   derecho, que es lo que se espera de un acordeón. */
.vs-grupo-nombre { margin-right: auto; }

/* El chevron: rota al abrir, con la misma transición que el resto. */
.vs-grupo-resumen::after {
  content: "";
  flex-shrink: 0;
  width: 0.55rem;
  height: 0.55rem;
  border-right: 2px solid var(--texto-suave);
  border-bottom: 2px solid var(--texto-suave);
  transform: rotate(45deg) translateY(-2px);
  transition: transform var(--transicion);
}

.vs-grupo[open] > .vs-grupo-resumen::after {
  transform: rotate(-135deg) translateY(-2px);
}

.vs-grupo > .vs-tabla-scroll { padding: 0 var(--e-5) var(--e-4); }

/* --- Qué significa cada diferencia --- */

.vs-significados {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--e-5);
}

.vs-significado h3 {
  margin: 0 0 0.3rem;
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--azul);
}

.vs-significado p {
  margin: 0;
  font-size: var(--t-sm);
  line-height: 1.55;
  color: var(--texto);
}

/* --- Agregar otro producto --- */

.vs-agregar-seccion {
  max-width: 32rem;
  padding-top: var(--e-6);
  border-top: 1px solid var(--borde-suave);
}

.vs-agregar-label {
  display: block;
  margin-bottom: var(--e-2);
  font-size: var(--t-sm);
  font-weight: 600;
}

/* --- Barra fija inferior ---
   Los productos comparados siempre a mano, sin volver arriba. Se oculta
   en pantallas chicas: ahí ya está el nav inferior y dos barras fijas
   se comerían la pantalla. */
.vs-barra-fija {
  position: sticky;
  bottom: 0;
  z-index: 20;
  display: flex;
  justify-content: center;
  gap: var(--e-6);
  flex-wrap: wrap;
  margin: var(--e-7) calc(-1 * var(--e-5)) 0;
  padding: var(--e-3) var(--e-5);
  border-top: 1px solid var(--borde-suave);
  background: rgba(255, 255, 255, .92);
  backdrop-filter: blur(8px);
}

.vs-barra-item {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  min-width: 0;
}

.vs-barra-imagen {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 2.2rem;
  height: 2.2rem;
}

.vs-barra-imagen .miniatura {
  width: 100%;
  height: 100%;
  background: none;
  object-fit: contain;
}

.vs-barra-imagen .miniatura-monograma {
  width: 2.2rem;
  height: 2.2rem;
  font-size: var(--t-xs);
  background: var(--azul-tenue);
}

.vs-barra-nombre {
  font-size: var(--t-sm);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 12rem;
}

.vs-boton-chico { min-height: 2.25rem; padding: 0.3rem 0.9rem; font-size: var(--t-xs); }

/* --- Responsive --- */

@media (max-width: 60rem) {
  /* Con 3-4 productos, las columnas del hero se vuelven ilegibles antes
     que con 2: se pasa a scroll horizontal con cada ficha a un ancho
     mínimo usable, en vez de comprimirlas. */
  .vs-hero[data-productos="3"] .vs-hero-grilla,
  .vs-hero[data-productos="4"] .vs-hero-grilla {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;

    /* `contain: layout` aísla el ancho que este carrusel necesita para
       sí mismo. Sin eso, sus 3 o 4 tarjetas de 14rem suman 696px de
       ancho intrínseco y el navegador agranda el viewport de layout
       hasta ahí —321px de pantalla, 609 de viewport—, aunque el
       carrusel tenga su propio `overflow-x` y no se salga de la
       pantalla. Todo lo que es `fixed` toma el ancho del viewport, así
       que el nav inferior se estiraba a 609 y sus últimos accesos
       quedaban fuera de la pantalla.

       `overflow-x: hidden`, `min-width: 0`, `max-width: 100%` y
       `contain: inline-size` no lo evitan; `contain: layout` sí,
       manteniendo el scroll del carrusel y su altura (medido en el
       navegador con 2, 3 y 4 productos, 2026-08-27). Es el mismo
       síntoma que ya había causado la tabla, y por eso vuelve a
       aparecer acá: no se arregla achicando el contenido, se arregla
       impidiendo que su ancho salga afuera. */
    contain: layout;
  }

  .vs-hero[data-productos="3"] .vs-hero-producto,
  .vs-hero[data-productos="4"] .vs-hero-producto {
    flex: 0 0 14rem;
    scroll-snap-align: start;
  }
}

@media (max-width: 40rem) {
  .vs-hero-grilla { gap: var(--e-3); }

  .vs-hero-producto { padding: 0 var(--e-2); }

  .vs-hero-nombre { font-size: 1rem; }

  .vs-hero-datos { flex-direction: column; gap: var(--e-2); }

  .vs-puntuacion { width: 2.5rem; height: 2.5rem; font-size: 0.9rem; }

  .vs-boton-ofertas { width: 100%; padding: 0.5rem 0.75rem; font-size: var(--t-xs); }

  .vs-seccion { margin: var(--e-6) 0; }

  .vs-veredicto { padding: var(--e-4); }

  .vs-grupo-resumen { padding: var(--e-4); }
  .vs-grupo > .vs-tabla-scroll { padding: 0 var(--e-4) var(--e-4); }

  /* En mobile la tabla se apila: una tarjeta por especificación y,
     adentro, una fila por producto.

     Antes acá había `table-layout: fixed`, que reparte el ancho en
     columnas parejas. Con 4 productos daban 65px cada una y "Apple
     MacBook Pro 14 M5 16GB 1TB" salía en 7 líneas de dos caracteres
     (medido en el navegador a 375px, 2026-08-27). Scrollear de costado
     tampoco resolvía: en una página de comparación, lo que se compara
     tiene que verse junto, y una tabla que se sale de la pantalla
     además estiraba el documento y cortaba el nav inferior —que es
     `fixed`, así que toma el ancho del documento, no el del viewport.

     Apilada, cada valor ocupa el ancho entero y los productos de una
     misma especificación quedan uno debajo del otro: se lee una
     especificación por vez sin perder la comparación, que es justamente
     lo que se pierde al mostrar un producto por vez. */
  .vs-tabla,
  .vs-tabla thead,
  .vs-tabla tbody,
  .vs-tabla tr,
  .vs-tabla th,
  .vs-tabla td {
    display: block;
    width: auto;
    min-width: 0;
  }

  /* La fila de encabezado sale de la pantalla —los nombres ya están
     arriba en las tarjetas y ahora también en cada celda— pero sigue en
     el DOM para quien recorre la tabla con lector de pantalla. */
  .vs-tabla thead {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
  }

  .vs-tabla tbody tr {
    padding: var(--e-3) var(--e-4);
    border: 1px solid var(--borde-suave);
    border-radius: var(--radio);
  }

  .vs-tabla tbody tr + tr { margin-top: var(--e-3); }

  .vs-tabla tbody th {
    white-space: normal;
    padding: 0 0 var(--e-2);
    font-size: var(--t-sm);
  }

  /* Etiqueta a la izquierda, valor a la derecha. `margin-right: auto`
     en la etiqueta en vez de `space-between` porque una celda puede
     tener más de un hijo —el valor y su delta («+4 GB»)— y
     `space-between` los separaría a los extremos en vez de dejarlos
     juntos donde se leen como una sola cosa. */
  .vs-tabla tbody td {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: flex-end;
    gap: 0 var(--e-2);
    padding: var(--e-2) 0 0;
    border-top: 1px solid var(--borde-suave);
    font-size: var(--t-sm);
    text-align: right;
  }

  /* Texto real y no `::before` con `attr()`: el contenido generado no
     lo anuncian todos los lectores de pantalla, y así además se puede
     seleccionar y copiar. */
  .vs-celda-producto {
    display: block;
    margin-right: auto;
    min-width: 0;
    text-align: left;
    font-weight: 500;
    color: var(--texto-suave);
    overflow-wrap: anywhere;
  }

  /* Apilada sobra el ancho, así que el veredicto vuelve: era lo primero
     que se sacrificaba cuando la tabla peleaba por 342px. */
  .vs-col-veredicto { display: flex; }


  /* La barra fija se oculta: el nav inferior ya ocupa ese lugar. */
  .vs-barra-fija { display: none; }
}

/* --- Selector para sumar productos --- */

.agregar-campo {
  position: relative;
  display: flex;
  align-items: center;
}

.agregar-campo svg {
  position: absolute;
  left: 0.75rem;
  color: #9aa5b1;
  pointer-events: none;
}

.agregar-campo input {
  width: 100%;
  padding: 0.55rem 0.6rem 0.55rem 1.95rem;
  font: inherit;
  /* Justo lo necesario para que «Agregar productos para comparar» entre
     entero en el ancho de la columna de atributos. Más grande se corta. */
  font-size: 0.82rem;
  border: 1px solid var(--borde-suave);
  border-radius: 999px;
  background: #fff;
  transition: border-color var(--transicion), box-shadow var(--transicion);
}

.agregar-campo input:focus {
  outline: 0;
  border-color: var(--azul-claro);
  box-shadow: 0 0 0 3px rgba(50, 104, 228, .12);
}

/* El desplegable se dibuja encima de la tabla, no dentro del flujo. Dentro
   del flujo estiraba la celda de encabezado y empujaba la comparación
   entera hacia abajo: abrir el selector movía de lugar justo lo que se
   vino a mirar. Es el mismo criterio que el autocompletado de la Home. */
.agregar-comparar { position: relative; }

#candidatos-comparar { position: absolute; z-index: 30; left: 0; right: 0; }

.candidatos-lista {
  list-style: none;
  margin: 0.4rem 0 0;
  padding: 0.3rem;
  display: grid;
  gap: 0.15rem;
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
  box-shadow: var(--sombra-alta);
  /* Con muchos candidatos el desplegable taparía la tabla entera. */
  max-height: 17rem;
  overflow-y: auto;
}

.candidatos-lista a {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.4rem 0.5rem;
  border-radius: var(--radio-chico);
  color: var(--texto);
  text-decoration: none;
  font-weight: 400;
  transition: background var(--transicion);
}

.candidatos-lista a:hover { background: var(--azul-tenue); }

.candidato-imagen {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 2rem;
  height: 2rem;
}

.candidato-imagen .miniatura {
  width: 100%;
  height: 100%;
  border-radius: 6px;
  background: none;
  object-fit: contain;
}

.candidato-imagen .miniatura-monograma {
  font-size: 0.75rem;
  background: var(--azul-tenue);
}

.candidato-info { min-width: 0; flex: 1; }

.candidato-nombre {
  display: block;
  font-size: var(--t-sm);
  line-height: 1.25;
  overflow-wrap: anywhere;
}

.candidato-marca {
  display: block;
  font-size: var(--t-xs);
  color: var(--texto-suave);
}

.candidato-mas {
  flex-shrink: 0;
  font-size: 1.1rem;
  color: var(--azul);
}

/* El mensaje de "no hay" comparte caja con la lista: también se dibuja
   encima de la tabla, así que necesita fondo propio para no leerse
   mezclado con lo que tapa. */
.candidatos-vacio {
  margin: 0.4rem 0 0;
  padding: 0.7rem 0.8rem;
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
  box-shadow: var(--sombra-alta);
  font-size: var(--t-xs);
  font-weight: 400;
  line-height: 1.45;
}

/* Este no va en el desplegable: reemplaza al campo cuando ya no se puede
   sumar nada, así que sigue en el flujo.

   Sin fondo ni borde propios: es una etiqueta de estado, no un bloque.
   Una frase corta metida en una píldora gris pesa más de lo que dice, y
   acá lo único que hay que decir es que ya no entran más productos. */
.agregar-lleno {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  color: var(--azul);
  font-size: var(--t-xs);
  font-weight: 600;
  line-height: 1.3;
}

.agregar-lleno svg { flex-shrink: 0; color: currentColor; }

/* --- Especificaciones --- */

.especificaciones { margin-top: var(--e-8); }

/* Una ficha por dato, con el nombre arriba y el valor abajo: el mismo
   recuadro que el resumen del historial, para que la ficha hable un solo
   idioma. Antes era una lista con un tilde verde en cada renglón, que no
   decía nada —todo dato publicado está verificado— y se leía como un
   formulario (pedido del operador, 2026-10-24). */
.especificaciones ul {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: 0.75rem;
}

.especificaciones li {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.9rem 1rem;
  background: var(--fondo-suave);
  border-radius: var(--radio-chico);
}

.especificaciones .spec-etiqueta {
  font-size: 0.8rem;
  color: var(--texto-suave);
}
.especificaciones .spec-valor {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

/* --- Pie --- */

.pie {
  max-width: var(--ancho);
  margin: 0 auto;
  padding: 2rem 1.25rem 3rem;
  border-top: 1px solid var(--borde);
  font-size: 0.9rem;
  color: var(--texto-suave);
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--e-5);
}

.pie-confianza { text-align: left; }

.pie p {
  max-width: 40rem;
  margin: 0.2rem 0 0;
}

.nav-pie {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--e-4);
}

.nav-pie a {
  color: var(--texto-suave);
  text-decoration: none;
}

.nav-pie a:hover { color: var(--azul); }

.pie-enlaces {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
}

.pie-redes {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--e-3);
  color: var(--texto);
  font-weight: 600;
}

.redes-iconos { display: flex; gap: var(--e-2); }

/* Botones de 44 px: el mínimo cómodo para tocar con el dedo. */
.redes-iconos a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  border: 1px solid var(--borde);
  color: var(--texto);
  transition: color 0.15s, border-color 0.15s, background-color 0.15s;
}

.redes-iconos a:hover,
.redes-iconos a:focus-visible {
  color: var(--azul);
  border-color: var(--azul);
  background: var(--azul-tenue);
}

/* --- Página de error --- */

.error {
  max-width: 32rem;
  margin: 0 auto;
  padding: 4rem 1.25rem;
  text-align: center;
}

.error h1 { color: var(--azul); }

.error .buscador { margin: 2rem auto; max-width: 26rem; }

/* --- Paginación --- */

.paginacion {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.25rem;
  margin: 2rem 0 1rem;
}

.paginacion a {
  color: var(--azul);
  text-decoration: none;
  font-weight: 500;
}

.paginacion a:hover { text-decoration: underline; }

.paginacion-actual {
  color: var(--texto-suave);
  font-size: 0.9rem;
}

/* --- Cuentas: entrar, registro, favoritos, alertas --- */

/* No `.bloque`: esa clase separa secciones apiladas dentro de una misma
   pantalla (Home); acá cada plantilla es la única sección de la página,
   así que el salto de `--e-8` sobraría. */
.pagina-cuenta { margin-top: var(--e-6); }

.autenticacion {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(18rem, 22rem);
  gap: var(--e-7);
  max-width: 54rem;
  margin-left: auto;
  margin-right: auto;
  padding: var(--e-6);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: linear-gradient(135deg, var(--fondo-tenue), #fff 62%);
}

.autenticacion-beneficios h1 { margin: 0 0 var(--e-3); }
.autenticacion-beneficios > p:not(.eyebrow) { color: var(--texto-suave); }
.autenticacion-beneficios ul { padding-left: 1.2rem; }
.autenticacion-beneficios li { margin: 0.45rem 0; }

.mensajes {
  list-style: none;
  padding: 0;
  margin: 0 0 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.formulario-cuenta {
  max-width: 22rem;
  width: 100%;
  margin: 0 auto;
  padding: var(--e-5);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
  box-shadow: var(--sombra);
}


/* Aviso de quien apretó el corazón sin sesión (`_aviso_favorito.html`). */
.aviso-favorito {
  display: flex;
  gap: 0.75rem;
  margin: 0 0 var(--e-4);
  padding: 0.85rem 1rem;
  border-radius: var(--radio-chico);
  background: var(--azul-tenue);
  font-size: var(--t-sm);
  line-height: 1.45;
  color: var(--texto);
}
.aviso-favorito p { margin: 0; }
.aviso-favorito p + p { margin-top: 0.35rem; }
.aviso-favorito-icono { flex: none; margin-top: 0.1rem; color: var(--azul); }
.aviso-favorito-titulo { font-weight: 600; }
.aviso-favorito-producto { color: var(--texto-suave); }
.formulario-cuenta h2 { margin-top: 0; }

.formulario-cuenta form {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.formulario-cuenta label {
  font-size: 0.85rem;
  color: var(--texto-suave);
  margin-top: 0.5rem;
}

.formulario-cuenta input {
  padding: 0.65rem 0.8rem;
  border: 1px solid var(--borde);
  border-radius: 8px;
  font: inherit;
}

.formulario-cuenta input:focus {
  outline: none;
  border-color: var(--azul-claro);
}

.formulario-cuenta button {
  margin-top: 1rem;
  padding: 0.75rem 1.25rem;
  border: 0;
  border-radius: 8px;
  background: var(--azul);
  color: #fff;
  font: inherit;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--transicion);
}

.formulario-cuenta button:hover { background: var(--azul-claro); }

/* Controles de una tienda extensa: buscar y acotar antes de recorrer una
   pared de tarjetas. No se ordena por precio entre monedas distintas. */
.filtros-tienda {
  display: grid;
  grid-template-columns: minmax(14rem, 2fr) repeat(2, minmax(10rem, 1fr)) auto;
  align-items: end;
  gap: var(--e-3);
  margin: var(--e-5) 0 var(--e-3);
  padding: var(--e-4);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: var(--fondo-tenue);
}

.filtros-tienda label { display: flex; flex-direction: column; gap: 0.3rem; }
.filtros-tienda label > span { font-size: var(--t-xs); color: var(--texto-suave); }
.filtros-tienda input,
.filtros-tienda select {
  min-height: 2.75rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--borde);
  border-radius: var(--radio-chico);
  background: #fff;
  font: inherit;
}
.filtros-tienda button {
  min-height: 2.75rem;
  padding: 0.55rem 1rem;
  border: 0;
  border-radius: var(--radio-chico);
  background: var(--azul);
  color: #fff;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

/* Sin `min-width: 0`, a propósito: es el patrón defensivo de flexbox para
   permitir que un hijo se achique por debajo de su contenido (evita que
   un texto largo empuje al hermano fuera del contenedor) — pero acá no
   hace falta achicar nada, porque `.grilla-marcas` ya envuelve las
   píldoras a la fila siguiente (`flex-wrap: wrap`) cuando no entran. Con
   `min-width: 0` el navegador SÍ dejaba angostar esta caja por debajo
   del ancho real del nombre, y como nada adentro tiene `overflow:
   hidden`, el texto no se truncaba: se dibujaba igual, pero por fuera de
   la píldora, invadiendo el chip de al lado ("ArtComputer", "NNET",
   "Fujitsu" con nombres o conteos largos, encontrado 2026-08-14). Sin
   esta línea, el hijo vuelve al `min-width: auto` por defecto —se ancha
   lo que el nombre necesite— y es la píldora entera la que crece o pasa
   a la fila siguiente, nunca el texto que se sale de su caja. */
.marca-chip-texto { display: flex; flex-direction: column; }
.marca-chip-texto small { color: var(--texto-suave); font-weight: 400; }

/* Altura táctil mínima para acciones primarias que antes quedaban debajo de
   los 44px recomendados en pantallas táctiles. */
.tarjeta-boton,
.tab-producto-label { min-height: 2.75rem; }

/* Acciones secundarias (favorito/alerta): enlaces de texto quietos, no
   botones — la acción principal de la ficha es ir a comprar al mejor
   precio (`.boton-primario`), esto no debe competir con esa jerarquía
   (DOCS/100-BRANDING.md §2). */
.acciones-cuenta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 1rem;
  margin: var(--e-4) 0 var(--e-6);
  font-size: var(--t-sm);
}

/* Dentro de una tarjeta chica (ej. "Cancelar alerta") el margen de página
   completa de arriba sobra — la tarjeta ya tiene su propio padding. */
.tarjeta .acciones-cuenta { margin: 0; }

.acciones-cuenta button {
  padding: 0;
  border: 0;
  background: none;
  color: var(--azul-claro);
  font: inherit;
  font-size: var(--t-sm);
  cursor: pointer;
  transition: color var(--transicion);
}

.acciones-cuenta button:hover { color: var(--azul); }

/* --- Adaptación a pantallas chicas --- */

@media (max-width: 40rem) {
  body { font-size: 16px; }
  .cabecera { padding-top: 1.75rem; }
  .marca { font-size: 1.5rem; }
  .pregunta { padding: 3.5rem 1.25rem 3rem; }
  .apoyo { margin-bottom: 2.5rem; font-size: 1.05rem; }
  .categorias { margin-top: 2.25rem; }
  .buscador { flex-direction: column; }
  .buscador button { padding: 1rem 2rem; }
  .lista-productos a { flex-direction: column; gap: 0.2rem; }
  .lista-productos .meta { text-align: left; }
  .especificaciones ul { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.5rem; }
  .tabla-precios { display: block; overflow-x: auto; }
  .pie { flex-direction: column; padding-bottom: 7rem; }
  .nav-pie { justify-content: flex-start; }
  .pie-redes { justify-content: flex-start; }
  .autenticacion { grid-template-columns: 1fr; padding: var(--e-4); gap: var(--e-5); }
  .filtros-tienda { grid-template-columns: 1fr; }
}

/* Bajo 400px "Buscar" con su padding ya no entra prolijo al lado del
   campo (`.buscador { flex-direction: column }` ya lo pone debajo, pero
   con el texto el botón queda más ancho de lo que hace falta en una
   pantalla tan angosta). El texto sigue en el DOM — `aria-label` en el
   botón (home.html) cubre la lectura por lector de pantalla. */
@media (max-width: 25rem) {
  .buscador-btn-icono { display: inline-flex; }
  .buscador-btn-texto { display: none; }
  .buscador button { padding: 0.85rem; border-radius: 999px; align-self: center; }
}

/* --- Grilla de categorías: columnas explícitas por ancho ---
   `auto-fit` dejaba la cuenta de columnas a lo que entrara, sin un
   número intencional por breakpoint. Acá se fija 2/3/4/6 (mobile/
   tablet chico/tablet grande/desktop) y en desktop, con columnas de
   ancho fijo en vez de `1fr`, `justify-content: center` centra la fila
   completa — si hoy hay menos de 6 categorías, o el día que dejen de
   ser múltiplo de 6, la última fila incompleta no queda pegada a la
   izquierda con un hueco a la derecha. */
.grilla-categorias { grid-template-columns: repeat(2, minmax(0, 1fr)); }

@media (min-width: 40.01rem) {
  .grilla-categorias { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 48.01rem) {
  .grilla-categorias { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Desktop pasa de grid a flex-wrap a propósito: con `grid-template-columns:
   repeat(6, ...)` fijo, una última fila de 3 ítems ocupa las columnas 1-3
   y las 4-6 quedan vacías — el grid no "cierra" los huecos de una fila
   incompleta, `justify-content` ahí solo centraría el bloque de 6
   columnas completo, no cada fila por separado. Flexbox con `flex-wrap`
   sí centra cada línea envuelta de forma independiente, que es lo que
   hace falta si el catálogo no es múltiplo de 6 (hoy 9 categorías: dos
   filas de 6 y 3, la segunda centrada). */
@media (min-width: 64rem) {
  .grilla-categorias {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
  }

  .grilla-categorias .categoria-icono { flex: 0 0 9.5rem; }
}

/* --- Novedades: carrusel horizontal, PC y mobile ---
   Es `.grilla-novedades` y no `.grilla` a secas a propósito: `.grilla`
   también arma el listado de categoría/marca/ranking/tienda, donde el
   usuario quiere ver TODOS los resultados en una lista vertical normal,
   no perder la mitad detrás de un swipe. Solo la vidriera de "Novedades"
   en la Home —unos pocos productos destacados, no un listado que hay
   que agotar— se presta al gesto de carrusel.

   `scroll-snap-type` + `scroll-snap-align` para que el dedo (o la
   flecha) "enganche" una tarjeta entera y no quede una tarjeta cortada a
   la mitad en el borde. El scroll en sí es nativo del navegador —
   arrastre táctil, trackpad o rueda con Shift funcionan sin JavaScript;
   `carrusel-novedades.js` (más abajo, flechas y puntos) es una mejora
   encima, no el mecanismo (DOCS/110-SEO.md §4). Sin ese gate de
   ancho que tenía antes: la vidriera es carrusel en cualquier tamaño de
   pantalla, no solo mobile. */
.grilla-novedades {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  gap: 0.9rem;
  /* Bleed hasta el borde de `main`: pone 1.5rem de padding lateral a
     cualquier ancho (ver `main` más arriba, no depende del viewport),
     acá se cancela para que la primera/última tarjeta no queden con un
     margen extra que no tiene el resto de las secciones. */
  margin: 0 -1.5rem;
  padding: 0.1rem 1.5rem 0.6rem;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.grilla-novedades::-webkit-scrollbar { display: none; }

/* El hijo directo, sea cual sea: cuando se agregó el botón de comparar
   se interpuso `.tarjeta-envoltorio` entre la pista y la tarjeta, esta
   regla dejó de aplicarse en silencio y las diez tarjetas se apretaron
   hasta 98px cada una. Peor todavía, así entraban todas a la vez: la
   pista no tenía nada que desplazar y las flechas no hacían nada
   (2026-08-21).

   15rem y no 13.5: con las tarjetas más anchas entran unas cinco por
   pantalla en vez de diez, que es lo que hace que se lean. */
.grilla-novedades > * {
  flex: 0 0 15rem;
  scroll-snap-align: start;
}

@media (max-width: 40rem) {
  /* Sin esto, la tarjeta seguía cayendo en la regla de "fila de lista"
     de más arriba (`.tarjeta:has(.tarjeta-imagen) { display: grid;
     grid-template-columns: 4.5rem 1fr; ... }`, pensada para `.grilla`
     apilada en una sola columna) — acá el resultado era una fila de
     4.5rem de alto embutida en una tarjeta de 13.5rem de ancho: achatada
     y con la imagen recortada a una miniatura chica. El carrusel no es
     una lista, es una vidriera de tarjetas verticales como en desktop
     (imagen arriba, texto abajo), solo que angostas y en fila. Se repite
     el selector `.grilla-novedades` para ganarle en especificidad a la
     regla de lista sin importar el orden en el archivo. Solo hace falta
     bajo 40rem: arriba de eso `.tarjeta` ya es vertical por defecto, no
     hay regla de fila de la que corregirse. */
  .grilla-novedades.grilla-novedades .tarjeta:has(.tarjeta-imagen) {
    display: flex;
    flex-direction: column;
    padding: 0.85rem 0.85rem 0.9rem;
  }

  .grilla-novedades.grilla-novedades .tarjeta:has(.tarjeta-imagen) > .tarjeta-imagen {
    height: 7.5rem;
    width: auto;
    margin-bottom: 0.65rem;
    background: none;
  }

  .grilla-novedades .tarjeta-cuerpo { display: contents; }
  .grilla-novedades .tarjeta-specs { display: none; }

  .grilla-novedades .tarjeta-boton {
    margin-top: auto;
    display: block;
    width: auto;
  }
}

/* Envoltorio con posición relativa: las flechas se anclan a sus bordes,
   no a los de la sección entera. */
.carrusel-novedades { position: relative; }

/* Ocultas hasta que `carrusel-novedades.js` confirma que puede manejar
   el clic — mismo criterio que `.buscador-cabecera-toggle`
   (`buscador-cabecera.js`): sin JavaScript el carrusel sigue siendo
   arrastrable a mano, así que un botón que no hace nada es peor que no
   mostrarlo. */
.carrusel-flecha {
  display: none;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  border: 1px solid var(--borde-suave);
  border-radius: 999px;
  background: #fff;
  color: var(--azul);
  box-shadow: var(--sombra-alta);
  cursor: pointer;
  transition: background var(--transicion), color var(--transicion);
}

.carrusel-novedades.js-listo .carrusel-flecha { display: flex; }

.carrusel-flecha:hover { background: var(--azul-tenue); }

/* Afuera de la pista, no encima: la flecha izquierda tapaba el nombre y
   la marca de la primera tarjeta (2026-08-21).
 
   Son 4.25rem y no 2.75 porque la pista sangra 1.5rem más allá de la
   columna de contenido (ver `.grilla-novedades`), y las flechas se
   anclan a la columna: hay que despejar las dos distancias. */
.carrusel-flecha-prev { left: -4.25rem; }
.carrusel-flecha-next { right: -4.25rem; }

/* Por debajo de 87rem ya no queda margen a los costados donde ponerlas.
   Ahí vuelven sobre la pista, y para que no tapen nada se corre el punto
   donde engancha el scroll: la tarjeta se detiene después de la flecha
   en vez de debajo. */
@media (min-width: 40.0625rem) and (max-width: 87rem) {
  .carrusel-flecha-prev { left: 0.15rem; }
  .carrusel-flecha-next { right: 0.15rem; }

  /* El `scroll-padding` solo corre el punto donde engancha el scroll, no
     dónde queda la primera tarjeta en reposo — que es justo donde la
     flecha la tapaba. Así que se corre el contenido de la pista: entra
     igual porque la pista sangra 1.5rem a cada lado. */
  .grilla-novedades {
    padding-inline: 4.75rem;
    scroll-padding-inline: 4.75rem;
  }
}

/* En un teléfono la forma natural de recorrer el carrusel es el dedo, y
   las flechas encima de una pantalla de 375px estorban más de lo que
   ayudan: correr el contenido para dejarles lugar se comía un quinto del
   ancho. Se ocultan y el carrusel queda como siempre fue, deslizable. */
@media (max-width: 40rem) {
  .carrusel-novedades.js-listo .carrusel-flecha { display: none; }
}

/* Puntos: solo indican posición, no son clickeables (por eso
   `aria-hidden` en el HTML) — la navegación real es arrastre, flechas o
   teclado sobre la pista, no un control aparte que haya que anunciar. */
.carrusel-puntos {
  display: none;
  justify-content: center;
  gap: 0.4rem;
  margin-top: 0.75rem;
}

.carrusel-novedades.js-listo ~ .carrusel-puntos { display: flex; }

.carrusel-punto {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--borde-suave);
  transition: background var(--transicion), transform var(--transicion);
}

.carrusel-punto.activo {
  background: var(--azul);
  transform: scale(1.35);
}

/* Quien pidió menos movimiento en su sistema tampoco recibe el scroll
   suave al usar las flechas (ver `carrusel-novedades.js`): salta directo
   en vez de animar, mismo criterio que ya aplica esta media query más
   abajo a las animaciones. */
@media (prefers-reduced-motion: reduce) {
  .grilla-novedades { scroll-behavior: auto; }
}

/* Quien pidió menos movimiento en su sistema no ve ninguna animación
   (DOCS/100-BRANDING.md §8). */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  html:has(.ficha-navegacion) { scroll-behavior: auto; }
}

/* --- Guiño del código Konami (`static/js/easter-egg.js`) ---------------
   No es contenido: si el script no carga, no pasa nada — ver el
   comentario de ese archivo. El toast usa la misma tipografía y el
   mismo violeta de marca para no leerse como un elemento ajeno al
   sitio, solo que aparece y se va solo. */
.easter-toast {
  position: fixed;
  left: 50%;
  bottom: 1.75rem;
  z-index: 100;
  transform: translate(-50%, 0.5rem);
  padding: 0.75rem 1.25rem;
  border-radius: 999px;
  background: var(--texto);
  color: #fff;
  font-size: var(--t-sm);
  font-weight: 600;
  box-shadow: var(--sombra-alta);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transicion), transform var(--transicion);
}

.easter-toast-visible {
  opacity: 1;
  transform: translate(-50%, 0);
}

.easter-confeti {
  position: fixed;
  top: -1rem;
  z-index: 99;
  width: 0.5rem;
  height: 0.9rem;
  border-radius: 2px;
  pointer-events: none;
  animation: easter-caer linear forwards;
}

@keyframes easter-caer {
  to {
    top: 100vh;
    transform: translateY(0) rotate(360deg);
    opacity: 0.6;
  }
}

/* --- Búsqueda: barra compacta y resultados en filas -------------------- */

/* Con la consulta puesta, el hero se va y queda esta barra. La flecha de
   volver es un enlace y no un `history.back()`: tiene que funcionar sin
   JavaScript y llevar siempre al mismo lugar. */
.barra-busqueda {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: var(--e-5) 0 var(--e-6);
}

.barra-volver {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 999px;
  color: var(--texto);
  transition: background var(--transicion);
}

.barra-volver:hover { background: var(--azul-tenue); }

/* Reusa `.buscador` pero con la lupa a la derecha y sin el botón violeta:
   buscando, el botón ya cumplió su función y lo que importa es el texto.
   `margin: 0` anula el centrado del buscador del hero, que acá dejaría la
   barra flotando en el medio en vez de ocupar la fila. */
.buscador-barra {
  flex: 1;
  max-width: none;
  margin: 0;
  padding-right: 0.35rem;
}

/* Calificado con el elemento para ganarle a `.buscador button`, que es lo
   que pinta la píldora violeta del hero. Sin eso, acá quedaba un botón
   violeta sólido sin texto. */
button.buscador-lupa {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 2.4rem;
  height: 2.4rem;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--texto-suave);
  cursor: pointer;
  transition: background var(--transicion), color var(--transicion);
}

button.buscador-lupa:hover { background: var(--azul-tenue); color: var(--azul); }

/* El campo de la barra no lleva la sangría que deja lugar a la lupa: acá
   la lupa está del otro lado. */
.buscador-barra input { padding-left: 1.1rem; }

/* --- Buscador de la cabecera --------------------------------------------

   Sin JavaScript, esta es toda la historia: el formulario compacto de
   siempre (`.buscador-cabecera`, misma pieza que `.buscador-barra` —
   campo y lupa a la derecha), acotado en ancho porque convive con los
   enlaces de navegación y el bloque de cuenta.

   Con JavaScript (clase `.js-listo`, agregada por `buscador-cabecera.js`
   recién cuando confirma que puede hacerse cargo del gesto), colapsa en
   el botón de lupa `.buscador-cabecera-toggle` y el formulario se
   expande por encima del resto de la cabecera al hacer clic —
   `position: absolute` es lo que le permite crecer sin empujar el logo,
   la nav ni el bloque de cuenta, que es justo lo que no podía hacer la
   versión siempre-inline de antes. */
.buscador-cabecera-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.buscador-cabecera {
  flex: 0 1 14rem;
  min-width: 6rem;
  padding: 0.3rem 0.3rem 0.3rem 0;
  /* Gana con más especificidad de origen a la regla de abajo de
     `.buscador { flex-direction: column }` (apila campo y botón en
     pantallas chicas para el buscador grande del hero) — acá, campo y
     lupa se quedan siempre en una fila: es una pieza chica de la
     cabecera, no el buscador protagonista de la Home. */
  flex-direction: row;
}

.buscador-cabecera input {
  padding: 0.5rem 0.85rem;
  font-size: 0.92rem;
}

/* Por debajo de 34rem la cabecera ya se parte en dos líneas — ahí el
   buscador (sin JS, o ya expandido con JS) vuelve a ocupar el ancho
   disponible en vez de quedar apretado en 14rem. */
@media (max-width: 34rem) {
  .buscador-cabecera { flex-basis: 100%; max-width: 22rem; }
}

/* El botón de lupa que colapsa/expande: arranca oculto. Mostrarlo antes
   de que el JS esté listo para atenderlo dejaría un botón muerto — sin
   JavaScript el formulario ya está visible más abajo, así que no hace
   falta.

   `.nav-icono` (el círculo de 44px) está pensado para los `<a>` del resto
   de la cabecera — un `<a>` no trae borde, fondo ni relleno propios del
   navegador, pero un `<button>` sí, y sin resetearlos acá quedaban
   apilados sobre el círculo: un botón nativo de más, grande y con borde,
   detrás del ícono. */
.buscador-cabecera-toggle {
  display: none;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--texto-suave);
  cursor: pointer;
}

.buscador-cabecera-toggle:hover { color: var(--azul); }

/* Limpia el texto si hay, cierra si no — mismo botón, dos funciones según
   corresponda (ver `buscador-cabecera.js`). Solo aparece expandido. */
button.buscador-cabecera-limpiar {
  display: none;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 1.9rem;
  height: 1.9rem;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--texto-suave);
  cursor: pointer;
  transition: background var(--transicion), color var(--transicion);
}

button.buscador-cabecera-limpiar:hover { background: var(--azul-tenue); color: var(--azul); }

@media (min-width: 34.01rem) {
  .buscador-cabecera-wrap.js-listo .buscador-cabecera-toggle {
    display: inline-flex;
  }

  /* Colapsado: la caja YA mide 21rem en el layout desde el arranque — lo
     que se anima es `transform: scaleX()` (compositor puro, no dispara
     layout en cada frame) y no `width` (si se anima, el navegador tiene
     que recalcular el layout de toda la fila en cada frame — más caro,
     y con el riesgo real de jank en equipos modestos, justo el tipo de
     animación "exagerada" que pide evitar la consigna).

     `position: absolute` saca la caja del flujo — es lo que evita que
     la nav y el bloque de cuenta se corran al abrirse — y
     `transform-origin: right` hace que crezca desde el botón de lupa,
     que es donde vive anclada (`right: 0`). Alto fijo (mismo alto que
     ese botón) y centrado con `margin-top` negativo, en vez del más
     usual `top: 50%; transform: translateY(-50%)`, para no mezclar un
     desplazamiento fijo con la escala animada dentro de la misma
     propiedad `transform`. */
  .buscador-cabecera-wrap.js-listo .buscador-cabecera-form {
    position: absolute;
    top: 50%;
    right: 0;
    height: 2.75rem;
    margin-top: -1.375rem;
    z-index: 30;
    width: 21rem;
    /* `--buscador-disponible` lo calcula `buscador-cabecera.js` al
       abrir: el espacio entre el logo y la lupa. Sin ese tope, en
       pantallas medianas (o con zoom) la caja se montaba sobre el logo. */
    max-width: min(21rem, calc(100vw - 2rem), var(--buscador-disponible, 21rem));
    /* `.buscador-cabecera` (siempre presente en la misma clase) le pone
       `flex: 0 1 14rem` para la versión sin JS — acá se anula del todo:
       una vez absoluto, ya no es un ítem flex de verdad, pero dejar el
       `flex-basis`/`flex-shrink` de esa regla en pie es una ambigüedad
       que no vale la pena arrastrar. */
    flex: none;
    transform-origin: right center;
    transform: scaleX(0);
    opacity: 0;
    pointer-events: none;
    transition: transform var(--transicion), opacity var(--transicion);
  }

  .buscador-cabecera-wrap.js-listo.expandido .buscador-cabecera-form {
    transform: scaleX(1);
    opacity: 1;
    pointer-events: auto;
  }
}

.buscador-cabecera-wrap.js-listo.expandido button.buscador-cabecera-limpiar {
  display: inline-flex;
}

/* Por debajo de 34rem no hay caja flotante: expandir empuja una fila
   propia dentro de la nav, que ya está partida en varias líneas en este
   ancho (regla de `.nav-cabecera` más abajo) — es el mismo criterio que
   pide la consigna para pantallas chicas, aprovechar el ancho disponible
   en vez de flotar una caja que podría no entrar. */
@media (max-width: 34rem) {
  .buscador-cabecera-wrap.js-listo .buscador-cabecera-toggle {
    display: inline-flex;
  }

  .buscador-cabecera-wrap.js-listo {
    flex: 0 0 auto;
  }

  .buscador-cabecera-wrap.js-listo.expandido {
    flex: 1 1 100%;
  }

  .buscador-cabecera-wrap.js-listo .buscador-cabecera-form {
    flex: 0 1 0;
    width: 0;
    min-width: 0;
    max-width: none;
    opacity: 0;
    overflow: hidden;
    pointer-events: none;
    transition: opacity var(--transicion);
  }

  .buscador-cabecera-wrap.js-listo.expandido .buscador-cabecera-form {
    flex: 1 1 auto;
    width: auto;
    opacity: 1;
    overflow: visible;
    pointer-events: auto;
  }
}

/* Expandido, el propio formulario ya tiene su lupa (`.buscador-lupa`,
   botón de enviar) y su X (`.buscador-cabecera-limpiar`) — mostrar
   además este botón de al lado lo duplicaba, y como los dos círculos
   casi se tocan, se veían superpuestos. Misma especificidad que las
   reglas de arriba que lo muestran (tres clases), pero declarada
   después: gana por orden sin necesitar `!important`. */
.buscador-cabecera-wrap.js-listo.expandido .buscador-cabecera-toggle {
  display: none;
}

/* El campo es `type="search"` y Chrome/Safari le agregan su propia X
   para borrar: al lado de `.buscador-cabecera-limpiar` se veían dos. */
.buscador-cabecera-form input[type="search"]::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

/* Una sola columna por defecto y dos solo cuando hay barra lateral. Fija
   en dos columnas, una búsqueda sin facetas —pocas marcas, pocos precios—
   metía los resultados en la franja de 15rem y quedaban ilegibles. */
/* Una sola columna por defecto y dos solo cuando hay barra lateral. Con
   `15rem 1fr` fijo, una búsqueda sin facetas —una sola marca, pocos
   precios distintos— dejaba los resultados apretados dentro de la columna
   de 15rem que nadie ocupaba. */
.busqueda-layout {
  display: grid;
  gap: var(--e-5);
  align-items: start;
}

.busqueda-layout:has(.filtros-busqueda) {
  grid-template-columns: 15rem 1fr;
}

.filtros-busqueda {
  padding: var(--e-4) var(--e-4) var(--e-5);
  border-radius: var(--radio);
  background: var(--fondo-tenue);
  border: 1px solid var(--borde-suave);
}

.filtros-busqueda h2 {
  font-size: 0.95rem;
  margin: 0;
}

/* Es un acordeón (`home.html`): el margen va en el `summary` abierto, así
   cerrado en un teléfono queda una sola línea. */
.filtros-busqueda[open] > summary { margin-bottom: var(--e-3); }

@media (min-width: 40.01rem) {
  .filtros-busqueda > summary { margin-bottom: var(--e-3); }
}

.filtros-limpiar {
  display: inline-block;
  margin-top: var(--e-4);
  font-size: var(--t-xs);
  color: var(--azul-claro);
}

.resultados-encabezado {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--e-3);
  margin-bottom: var(--e-4);
}

.resultados-encabezado h1 {
  font-size: 1.5rem;
  margin: 0;
}

.resultados-conteo {
  margin: 0.2rem 0 0;
  font-size: var(--t-sm);
  color: var(--texto-suave);
}

.orden-busqueda {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-size: var(--t-sm);
}

.orden-busqueda .orden-etiqueta { color: var(--texto-suave); }

.orden-busqueda a {
  color: var(--texto-suave);
  text-decoration: none;
}

.orden-busqueda a:hover { color: var(--azul); }
.orden-busqueda a.actual { color: var(--azul); font-weight: 600; }

.lista-resultados {
  display: grid;
  gap: 0.7rem;
}

.resultado {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--e-4);
  padding: var(--e-4);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
  box-shadow: var(--sombra);
  color: var(--texto);
  text-decoration: none;
  transition: transform var(--transicion), box-shadow var(--transicion),
              border-color var(--transicion);
}

.resultado:hover {
  transform: translateY(-2px);
  box-shadow: var(--sombra-alta);
  border-color: #d5e1f3;
}

.resultado-imagen {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 5.5rem;
  height: 5.5rem;
  border-radius: var(--radio-chico);
  background: var(--fondo-tenue);
}

.resultado-imagen .miniatura {
  width: auto;
  height: 100%;
  max-width: 100%;
  background: none;
  object-fit: contain;
}

.resultado-imagen .miniatura-monograma {
  width: 3rem;
  height: 3rem;
  background: var(--azul-tenue);
}

.resultado-info { min-width: 0; }

.resultado-nombre {
  display: block;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.015em;
}

.resultado-marca {
  display: block;
  margin-top: 0.1rem;
  font-size: var(--t-xs);
  color: var(--texto-suave);
}

.resultado-specs {
  display: block;
  margin-top: 0.5rem;
}

/* Viñeta con `::before` y no una lista: son tres datos sueltos, no un
   listado con sentido propio, y un `<ul>` dentro del enlace complica el
   marcado sin aportar nada. */
.resultado-spec {
  display: block;
  position: relative;
  padding-left: 0.85rem;
  font-size: var(--t-xs);
  line-height: 1.6;
  color: var(--texto-suave);
}

.resultado-spec::before {
  content: "";
  position: absolute;
  left: 0.15rem;
  top: 0.6em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--azul-claro);
}

.resultado-precio {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.1rem;
  text-align: right;
}

.resultado-desde {
  font-size: var(--t-xs);
  color: var(--texto-suave);
}

.resultado-monto {
  font-size: 1.25rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.resultado-boton {
  margin-top: 0.6rem;
  padding: 0.45rem 1rem;
  border: 1px solid #d9e4f4;
  border-radius: var(--radio-chico);
  background: var(--azul-tenue);
  color: var(--azul);
  font-size: var(--t-xs);
  font-weight: 600;
  white-space: nowrap;
  transition: background var(--transicion);
}

.resultado:hover .resultado-boton { background: #dce6f4; }

@media (max-width: 56rem) {
  /* Calificado con `:has` para empatarle en especificidad a la regla de
     dos columnas: sin eso, en mobile seguía ganando aquella y la barra
     lateral dejaba a los resultados en una franja inusable. */
  .busqueda-layout,
  .busqueda-layout:has(.filtros-busqueda) { grid-template-columns: 1fr; }
  .resultado {
    grid-template-columns: auto 1fr;
    row-gap: var(--e-3);
  }
  .resultado-precio {
    grid-column: 1 / -1;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    width: 100%;
  }
  .resultado-boton { margin-top: 0; }
}

/* --- Ficha: sección de tiendas a todo el ancho ------------------------- */

.seccion-tiendas { margin-top: var(--e-7); }

.seccion-tiendas h2 { font-size: 1.5rem; }

/* La acción se ve como acción, con el texto "Ver en {tienda}" en vez de
   solo una flecha: en celular alcanza la flecha, con más ancho hay
   espacio para decir qué hace — a partir de 40rem.

   Igual que `flex-wrap: nowrap` de acá abajo, este botón visible
   necesita ancho de sobra: "USD 777,00" + un botón con padding y borde
   no entran al lado del logo y el nombre en 320-375px, y como el botón
   en sí no envuelve internamente (no es un contenedor flex), forzaba a
   toda la fila — y a la lista entera — a desbordar el ancho de la
   página en vez de simplemente pasar a una segunda línea. Bajo 40rem
   vuelve a ser lo mismo que en el panel lateral: la flecha sola. */
@media (min-width: 40rem) {
  .fila-tienda { flex-wrap: nowrap; }

  .fila-tienda-info { flex: 0 1 auto; }
  .fila-tienda-guia {
    display: block;
    flex: 1 1 2rem;
    align-self: center;
    min-width: 2rem;
    border-bottom: 2px dotted #c3cad5;
  }
  .fila-tienda-derecha { margin-left: 0; }

  .fila-tienda-flecha { display: none; }

  .fila-tienda .oculto {
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    clip: auto;
    padding: 0.45rem 1rem;
    border: 1px solid #d9e4f4;
    border-radius: var(--radio-chico);
    background: var(--azul-tenue);
    color: var(--azul);
    font-size: var(--t-sm);
    font-weight: 600;
    white-space: nowrap;
  }
}



/* Panel de comparador: funcionalidad principal de QuéCompro.
   Aparece en la lateral al lado del panel de precio. Invita al usuario
   a comparar el producto actual con otros. */

.panel-comparador {
  padding: var(--e-5);
  border: 1px solid #d9e4f4;
  border-radius: var(--radio);
  background: linear-gradient(135deg, var(--fondo-tenue) 0%, #f1f5fc 100%);
  box-shadow: var(--sombra);
  margin-top: var(--e-4);
}

.panel-comparador-encabezado {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0 0 0.8rem 0;
}

.panel-comparador-encabezado svg {
  width: 1.3rem;
  height: 1.3rem;
  color: var(--azul);
  flex-shrink: 0;
}

.panel-comparador-encabezado h2 {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--texto);
  letter-spacing: -0.01em;
}

.panel-comparador-subtitulo {
  margin: 0 0 var(--e-4) 0;
  font-size: var(--t-sm);
  color: var(--texto-suave);
  line-height: 1.4;
}

.lista-comparables {
  list-style: none;
  margin: 0 0 var(--e-4) 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.lista-comparables li a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.65rem 0.75rem;
  border-radius: var(--radio-chico);
  background: rgba(255, 255, 255, 0.7);
  color: var(--texto);
  text-decoration: none;
  transition: background var(--transicion), box-shadow var(--transicion);
  border: 1px solid transparent;
}

.lista-comparables li a:hover {
  background: #fff;
  border-color: #d9e4f4;
  box-shadow: 0 1px 3px rgba(23, 45, 83, .08);
}

.comparable-nombre {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  flex: 1;
  min-width: 0;
}

.comparable-marca {
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--azul);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.comparable-modelo {
  font-size: var(--t-sm);
  color: var(--texto);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.lista-comparables li a svg {
  width: 1rem;
  height: 1rem;
  color: #3268e4;
  flex-shrink: 0;
  margin-left: 0.5rem;
}

.boton-secundario {
  display: block;
  width: 100%;
  padding: 0.65rem 1rem;
  margin-top: 0;
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio-chico);
  background: transparent;
  color: var(--azul);
  font-family: inherit;
  font-size: var(--t-sm);
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: all var(--transicion);
  letter-spacing: -0.01em;
}

.boton-secundario:hover {
  background: var(--azul-tenue);
  border-color: var(--azul-claro);
}

/* Comparador — página de entrada.

   Dos estados en la misma URL: elegir categoría y elegir productos. El
   segundo es el que carga el peso visual, porque es donde se decide. */

.comparador-encabezado {
  max-width: 46rem;
  margin: 0 0 var(--e-6);
}

.comparador-encabezado h1 { margin: 0 0 var(--e-2); }

.comparador-encabezado .apoyo {
  margin: 0;
  font-size: var(--t-md);
  color: var(--texto-suave);
}

.comparador-encabezado-compacto { margin-bottom: var(--e-5); }

.comparador-paso {
  margin: 0 0 var(--e-4);
  font-size: var(--t-md);
}

/* Paso 1 — categorías.

   Las tarjetas son las mismas de la Home (`.categoria-icono`): no hay un
   estilo propio que mantener en paralelo. Lo único que cambia es que las
   filas van parejas — con la cantidad de productos debajo del nombre, un
   nombre que envuelve a dos líneas dejaba su fila más alta que el resto. */

.grilla-categorias-pareja { grid-auto-rows: 1fr; }

/* Paso 2 — buscador */

.comparador-buscador {
  display: flex;
  gap: var(--e-3);
  margin: var(--e-5) 0 var(--e-4);
}

.comparador-buscador-campo {
  position: relative;
  flex: 1 1 auto;
  display: flex;
  align-items: center;
}

.comparador-buscador-campo svg {
  position: absolute;
  left: 0.85rem;
  color: var(--texto-suave);
  pointer-events: none;
}

.comparador-buscador-campo input {
  width: 100%;
  padding: 0.7rem 1rem 0.7rem 2.6rem;
  font: inherit;
  font-size: var(--t-sm);
  color: var(--texto);
  border: 1px solid var(--borde);
  border-radius: var(--radio-chico);
  background: #fff;
  transition: border-color var(--transicion), box-shadow var(--transicion);
}

.comparador-buscador-campo input:focus {
  outline: none;
  border-color: var(--azul-claro);
  box-shadow: 0 0 0 3px var(--azul-tenue);
}

.comparador-buscador .boton-secundario { width: auto; padding: 0.7rem 1.4rem; }

/* Paso 2 — grilla de productos elegibles.

   La casilla se oculta a la vista pero sigue existiendo: es lo que hace
   funcionar la selección sin JavaScript y lo que anuncia un lector de
   pantalla. El estado marcado lo dibuja el cuerpo de la tarjeta. */

.comparador-seleccion { margin: 0; }

/* Paginacion del selector. Va debajo de la grilla y arriba de la barra
   fija de comparar, con hueco propio: pegada al ultimo renglon de
   tarjetas se leia como una tarjeta mas. */
.comparador-paginacion {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--e-4);
  margin-top: var(--e-6);
  /* Deja aire por debajo para que `.barra-comparar`, que queda fija al
     pie, no tape el boton de pasar de pagina. */
  padding-bottom: var(--e-6);
}

.comparador-paginacion-cuenta {
  color: var(--texto-suave);
  font-size: var(--t--1);
  /* El numero de pagina no puede quedar entre los dos botones en una
     pantalla angosta: ahi la fila se parte y el orden de lectura seria
     «Anteriores / Siguiente / Pagina 2». */
  order: -1;
  flex-basis: 100%;
  text-align: center;
}

@media (min-width: 40rem) {
  .comparador-paginacion-cuenta { order: 0; flex-basis: auto; }
}

/* `grid-auto-rows: 1fr` empareja todas las tarjetas contra la más alta.
   Los nombres van de una a tres líneas («Trident Z5 RGB DDR5 64GB 6400MHz»
   contra «Redmi A3») y sin esto la grilla queda escalonada. Se emparejan
   las filas en vez de recortar el nombre a dos líneas: acá el final del
   nombre es lo que distingue una variante de otra —«256GB Deep Blue» de
   «256GB Silver»— y truncarlo volvería la grilla imposible de usar. */
.grilla-elegibles {
  display: grid;
  /* 14rem y no 12.5rem: acompaña a `.elegible-imagen` (12rem de alto) —
     con la columna angosta de antes, una foto más grande quedaba angosta
     y alta en vez de leerse como un cuadro. */
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  grid-auto-rows: 1fr;
  gap: var(--e-4);
}

/* `relative` para que la casilla, que va absoluta y oculta, quede anclada a
   su propia tarjeta. Sin esto su referencia es el bloque inicial de la
   página: hoy no se nota porque no lleva `top`/`left` y conserva su
   posición estática, pero cualquier offset futuro la mandaría a la otra
   punta y el foco de teclado saltaría con ella. */
.tarjeta-elegible { position: relative; display: block; cursor: pointer; }

.elegible-check {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.elegible-cuerpo {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
  height: 100%;
  padding: var(--e-4);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
  box-shadow: var(--sombra);
  transition: border-color var(--transicion), box-shadow var(--transicion),
              background var(--transicion);
}

.tarjeta-elegible:hover .elegible-cuerpo { border-color: #d5e1f3; }

.elegible-check:focus-visible ~ .elegible-cuerpo {
  outline: 2px solid var(--azul-claro);
  outline-offset: 2px;
}

.elegible-check:checked ~ .elegible-cuerpo {
  border-color: var(--azul);
  background: var(--fondo-tenue);
  box-shadow: 0 0 0 1px var(--azul), var(--sombra);
}

/* Con el máximo ya elegido, las tarjetas que faltan tildar se apagan en
   vez de quedar clickeables sin efecto: `comparador.js` las deshabilita
   (`elegible-check:disabled`) para que no se pueda seguir marcando más
   de las que el comparador realmente muestra lado a lado — antes se
   podían tildar todas, el aviso de "como máximo N" recién aparecía al
   apretar Comparar. Una ya marcada nunca se deshabilita: siempre tiene
   que poder destildarse para dejarle el lugar a otra. */
.elegible-check:disabled ~ .elegible-cuerpo {
  opacity: 0.5;
  box-shadow: none;
}

.tarjeta-elegible:has(.elegible-check:disabled) { cursor: not-allowed; }
.tarjeta-elegible:has(.elegible-check:disabled) .elegible-cuerpo { pointer-events: none; }
.tarjeta-elegible:has(.elegible-check:disabled):hover .elegible-cuerpo { border-color: var(--borde-suave); }

/* La marca de selección: círculo vacío en reposo, violeta con tilde al
   marcar. Es la única señal que no depende del color de fondo, así que es
   la que sostiene la lectura si el contraste falla. */
.elegible-marca-check {
  position: absolute;
  /* La foto también es posicionada y aparece después en el DOM. Sin una
     capa explícita podía pintarse por encima del círculo seleccionado y
     dejar visible apenas una medialuna del tilde. */
  z-index: 2;
  top: var(--e-3);
  right: var(--e-3);
  width: 1.35rem;
  height: 1.35rem;
  border: 2px solid var(--borde);
  border-radius: 50%;
  background: #fff;
  transition: border-color var(--transicion), background var(--transicion);
}

.elegible-check:checked ~ .elegible-cuerpo .elegible-marca-check {
  border-color: var(--azul);
  background: var(--azul) var(--icono-tilde) center / 0.8rem no-repeat;
}

.elegible-imagen {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Segunda vuelta: 9rem seguía leyéndose chica. 12rem más o menos
     empareja el alto de la foto con el ancho de la tarjeta (`.grilla-
     elegibles` la deja en ~14rem) — un cuadro casi cuadrado en vez de una
     franja, que es lo que de verdad hace que un celular se reconozca de
     un vistazo en esta grilla. */
  height: 12rem;
}

/* `.miniatura` (la imagen o el monograma, ver `_monograma_producto.html`)
   trae su propio `width/height: 4rem` fijo — pensado para usarse chica,
   suelta, en una fila de resultados. `max-width`/`max-height` a secas no
   le gana a un `width` explícito (no son la misma propiedad, así que ni
   compiten): por más que la caja de acá creciera, la imagen se quedaba en
   sus 4rem de siempre. Achica el punto: hay que pisar `width`/`height`
   con los mismos nombres para que esta imagen sí ocupe la caja. El
   monograma (el `span`, para cuando no hay foto) no lo necesita — ya se
   ve bien a su tamaño de siempre, y agrandar una inicial sola a 12rem se
   vería vacío. */
.elegible-imagen img {
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.elegible-texto {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}

.elegible-marca {
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--azul);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.elegible-modelo {
  font-size: var(--t-sm);
  font-weight: 500;
  line-height: 1.35;
}

/* Oculto por defecto: solo se ve en la vista Lista, más abajo. */
.elegible-specs { display: none; margin-top: 0.2rem; }

.elegible-spec {
  display: block;
  position: relative;
  padding-left: 0.85rem;
  font-size: var(--t-xs);
  line-height: 1.6;
  color: var(--texto-suave);
}

.elegible-spec::before {
  content: "";
  position: absolute;
  left: 0.15rem;
  top: 0.6em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--azul-claro);
}

/* --- Candidatos del comparador en mobile ---

   Hasta el 2026-10-24 la tarjeta pasaba a fila de lista en mobile (foto
   chica a la izquierda y specs). Cuando llegó el selector Cuadrícula /
   Lista, la grilla volvió a dos columnas pero esa fila siguió aplicando:
   foto y texto lado a lado en media pantalla, con el texto partido en
   una palabra por renglón (captura del operador, 2026-10-29). Ahora la
   fila es solo la vista Lista; en Cuadrícula la tarjeta es foto arriba,
   marca y modelo abajo, como en escritorio. */

/* Cuadrícula o lista (2026-10-24). Los radios son del formulario y se
   esconden: lo que se ve es el par de etiquetas, como un selector. */
.vista-elegibles {
  display: inline-flex;
  gap: 0.25rem;
  margin: 0 0 var(--e-4);
  padding: 0.25rem;
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio-chico);
  background: var(--fondo-suave);
}
.vista-radio { position: absolute; opacity: 0; pointer-events: none; }
.vista-elegibles label {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 2.25rem;
  padding: 0 0.85rem;
  border-radius: 8px;
  color: var(--texto-suave);
  font-size: var(--t-sm);
  font-weight: 500;
  cursor: pointer;
}
.vista-radio:checked + label { background: #fff; color: var(--azul); box-shadow: var(--sombra); }
.vista-radio:focus-visible + label { outline: 2px solid var(--azul); outline-offset: 2px; }

/* La lista: la fila de la búsqueda, foto chica a la izquierda y specs. */
.comparador-seleccion:has(#vista-lista:checked) .grilla-elegibles {
  grid-template-columns: 1fr;
  grid-auto-rows: auto;
  gap: var(--e-3);
}
.comparador-seleccion:has(#vista-lista:checked) .elegible-specs { display: block; }
.comparador-seleccion:has(#vista-lista:checked) .elegible-cuerpo {
  display: grid;
  grid-template-columns: 4.5rem 1fr;
  column-gap: 1rem;
  row-gap: 0;
  align-items: center;
  height: auto;
  padding: 0.85rem 1rem;
}
.comparador-seleccion:has(#vista-lista:checked) .elegible-imagen {
  grid-row: 1 / -1;
  width: 4.5rem;
  height: 4.5rem;
}
.comparador-seleccion:has(#vista-lista:checked) .elegible-texto { grid-column: 2; padding-right: 2.5rem; }
.comparador-seleccion:has(#vista-lista:checked) .elegible-marca-check { top: 50%; right: 1rem; transform: translateY(-50%); }

/* Barra de selección: pegada abajo mientras se recorre la grilla. */

.barra-comparar {
  position: sticky;
  bottom: 0;
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-3) var(--e-5);
  margin-top: var(--e-5);
  padding: var(--e-4) var(--e-5);
  border: 1px solid #dfe7f3;
  border-radius: var(--radio);
  background: rgba(255, 255, 255, .96);
  backdrop-filter: blur(8px);
  box-shadow: var(--sombra-alta);
}

.barra-comparar-estado {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  flex: 1 1 14rem;
  min-width: 0;
}

.barra-comparar-cuenta {
  font-size: var(--t-sm);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.barra-comparar-nombres {
  font-size: var(--t-xs);
  color: var(--texto-suave);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* En la misma fila que la cuenta y el botón, no en una propia: es una guía
   pasajera (falta un producto, sobran productos) y no justifica sumarle
   una tercera línea a una barra que está fija en pantalla. En anchos
   chicos el `flex-wrap` de la barra la baja sola. */
.barra-comparar-aviso {
  flex: 0 1 auto;
  margin: 0;
  font-size: var(--t-xs);
  color: var(--texto-suave);
  text-wrap: balance;
}

.barra-comparar-acciones {
  display: flex;
  align-items: center;
  gap: var(--e-4);
}

.barra-comparar-limpiar {
  font-size: var(--t-sm);
  color: var(--texto-suave);
}

.barra-comparar .boton-primario { white-space: nowrap; padding: 0.7rem 1.6rem; font-weight: 600; }

@media (max-width: 40rem) {
  .comparador-buscador { flex-wrap: wrap; }
  .comparador-buscador .boton-secundario { width: 100%; }
  /* Dos columnas fijas: con `auto-fill` y un mínimo de 10.5rem, según el
     margen del teléfono salían dos columnas o una sola tarjeta enorme. */
  .grilla-elegibles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--e-3); }
  .elegible-cuerpo { padding: var(--e-3); gap: var(--e-2); }
  .elegible-imagen { height: 7.5rem; }

  /* La barra está fija en pantalla, así que cada fila que suma es alto que
     le saca al listado para siempre. Apilada en tres filas se comía casi un
     quinto del viewport; la cuenta y el botón comparten la primera y solo
     el aviso —que aparece a veces— baja a una segunda. */
  .barra-comparar {
    padding: var(--e-3) var(--e-4);
    gap: var(--e-2) var(--e-3);
  }
  .barra-comparar-estado { flex: 1 1 7rem; }
  .barra-comparar-acciones { flex: 0 0 auto; }
  .barra-comparar-aviso { flex: 1 1 100%; order: 3; }

  /* `position: sticky; bottom: 0` pega la barra al borde del viewport —
     pero ese borde ahora lo ocupa `.nav-inferior` (fija, `z-index: 30`,
     por encima de esta barra). Sin este ajuste "Comparar" queda tapado
     detrás de la barra inferior durante todo el scroll, y solo se ve al
     llegar al final real del documento, donde ya no hay más contenido
     debajo tapándolo. Despegarla la misma altura que ya reserva `main`
     (mismo cálculo que su `padding-bottom`, arriba) la deja flotando
     justo encima del nav inferior, alcanzable en cualquier punto del
     scroll. */
  .barra-comparar {
    bottom: calc(4.5rem + env(safe-area-inset-bottom));
  }
}

/* `.panel-precio-mejor` ya no se usa en la ficha (la tienda pasó a
   `.panel-precio-tienda`, pegada al precio). La regla queda porque el
   nombre de clase sigue en otras plantillas que muestran el panel. */
.panel-precio-mejor {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin: var(--e-3) 0 0;
  font-size: var(--t-xs);
  color: var(--texto-suave);
}

.panel-precio h2 { margin-top: 0; font-size: var(--t-md); }
.panel-precio .vacio { color: var(--texto-suave); }

/* --- Listas curadas (2026-08-18) ---
   Los atajos temáticos de una categoría («más baratos», «más batería»)
   y la página propia de cada uno — `busqueda/listas.py`. Reusan el
   lenguaje de píldora que ya tienen las marcas y las subcategorías: son
   la misma clase de elemento (un salto de navegación), así que no
   estrenan un componente nuevo. */

.listas-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 0 0 var(--e-5);
}

.lista-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  /* 2.75rem de alto mínimo: el mismo piso táctil que el resto de las
     acciones del sitio. */
  min-height: 2.75rem;
  padding: 0.5rem 1.05rem;
  border: 1px solid var(--borde);
  border-radius: 999px;
  background: #fff;
  color: var(--texto);
  font-size: var(--t-sm);
  font-weight: 500;
  text-decoration: none;
  transition: border-color var(--transicion), background var(--transicion),
    color var(--transicion);
}

.lista-chip:hover {
  border-color: var(--azul);
  background: var(--azul-tenue);
  color: var(--azul);
}

/* El conteo no compite con el nombre de la lista: es el dato de apoyo. */
.lista-chip-cantidad {
  font-size: var(--t-xs);
  font-variant-numeric: tabular-nums;
  color: var(--texto-suave);
}

.lista-chip:hover .lista-chip-cantidad { color: inherit; }

.lista-encabezado {
  max-width: 44rem;
  margin: var(--e-5) 0 var(--e-6);
}

.lista-encabezado h1 {
  font-size: clamp(1.6rem, 3.4vw, 2.25rem);
  line-height: 1.15;
  margin: 0 0 var(--e-3);
}

/* La categoría, más liviana que el nombre de la lista: lo que distingue
   a esta página es el criterio, no la categoría (que ya viene dicha en
   la miga de pan). */
.lista-encabezado-categoria {
  font-weight: 400;
  color: var(--texto-suave);
}

.lista-nota { margin-top: var(--e-3); }

/* --- Seguí comparando (comparaciones sugeridas, 2026-08-18) ---
   Tarjetas de "A vs B" al pie del comparador. Mismo lenguaje sobrio que
   el resto del rediseño: borde tenue, sin fondo de color, la miniatura
   de cada producto y el par en una línea. */

.vs-sugeridas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: var(--e-4);
}

.vs-sugerida {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
  padding: var(--e-4);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: #fff;
  text-decoration: none;
  color: var(--texto);
  transition: border-color var(--transicion), box-shadow var(--transicion);
}

.vs-sugerida:hover {
  border-color: var(--borde);
  box-shadow: var(--sombra);
}

.vs-sugerida-par {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--e-3);
}

/* Caja cuadrada, igual criterio que el hero: es lo que empareja fotos de
   proporciones distintas (ver `.vs-hero-imagen`). */
.vs-sugerida-imagen {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 4.5rem;
  height: 4.5rem;
}

.vs-sugerida-imagen .miniatura {
  width: 100%;
  height: 100%;
  background: none;
  object-fit: contain;
}

.vs-sugerida-imagen .miniatura-monograma {
  width: 3rem;
  height: 3rem;
  font-size: var(--t-sm);
  background: var(--azul-tenue);
}

.vs-sugerida-vs {
  flex-shrink: 0;
  font-size: var(--t-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--texto-suave);
}

.vs-sugerida-nombres {
  font-size: var(--t-sm);
  font-weight: 600;
  line-height: 1.4;
  text-align: center;
}

.vs-sugerida-contra {
  font-weight: 400;
  color: var(--texto-suave);
}

.vs-sugerida-accion {
  align-self: center;
  padding: 0.35rem 1rem;
  border-radius: 999px;
  border: 1px solid var(--borde);
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--azul);
  transition: background var(--transicion), color var(--transicion),
    border-color var(--transicion);
}

.vs-sugerida:hover .vs-sugerida-accion {
  background: var(--azul);
  border-color: var(--azul);
  color: #fff;
}

/* --- Definición de cada métrica (glosario) ---
   `<details>` dentro de la celda de etiqueta de la ficha técnica. El
   disparador tiene que leerse como la etiqueta de siempre, no como un
   botón: lo único que lo distingue es el subrayado punteado, que es la
   convención de "acá hay una explicación" desde mucho antes de la web. */

.vs-glosario summary {
  list-style: none;
  cursor: help;
  text-decoration: underline dotted var(--borde);
  text-underline-offset: 3px;
}

.vs-glosario summary::-webkit-details-marker { display: none; }

.vs-glosario[open] summary {
  color: var(--azul);
  text-decoration-color: var(--azul);
}

.vs-glosario p {
  margin: 0.4rem 0 0;
  max-width: 22rem;
  font-size: var(--t-xs);
  font-weight: 400;
  line-height: 1.5;
  color: var(--texto-suave);
  /* La etiqueta de la fila va con `white-space: nowrap` para que no se
     parta en dos ("Almacena miento"); la definición sí tiene que
     envolver, así que lo revierte para su propio texto. */
  white-space: normal;
}

/* En mobile la columna de métrica mide ~103px: ahí adentro la definición
   quedaba en una tira de 87px de ancho, ilegible (medido en el
   navegador, 2026-08-18). Se saca del ancho de la celda y se apoya sobre
   la fila entera —que en mobile ocupa el viewport, porque la tabla entra
   completa sin scroll horizontal— con fondo propio para separarse de las
   filas que quedan debajo. 308px contra 87px. */
@media (max-width: 40rem) {
  .vs-tabla tbody tr { position: relative; }

  .vs-glosario[open] p {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 5;
    width: auto;
    max-width: none;
    margin: 0;
    padding: 0.6rem 0.7rem;
    border-radius: var(--radio-chico);
    background: var(--fondo-suave);
  }
}

/* --- Selección persistente para comparar (2026-08-18) ---
   El botón en cada tarjeta y la barra flotante que acompaña por todo el
   sitio. Sin JavaScript: son `<form>` con POST contra la sesión
   (`busqueda/seleccion.py`). */

/* El envoltorio pasa a ser el item de la grilla; la tarjeta lo llena. */
.tarjeta-envoltorio {
  position: relative;
  display: flex;
}

.tarjeta-envoltorio > .tarjeta {
  flex: 1;
  min-width: 0;
}

/* Visible también sin hover: comparar es una acción principal. */
.tarjeta-comparar {
  position: absolute;
  top: 0.55rem;
  right: 0.55rem;
  margin: 0;
}

.tarjeta-comparar-boton {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--borde);
  border-radius: 999px;
  background: rgba(255, 255, 255, .94);
  color: var(--texto-suave);
  font: inherit;
  font-size: var(--t-xs);
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  opacity: 1;
  transition: opacity var(--transicion), background var(--transicion),
    color var(--transicion), border-color var(--transicion);
}

.tarjeta-envoltorio:hover .tarjeta-comparar-boton,
.tarjeta-comparar-boton:focus-visible,
.tarjeta-comparar-boton.activo {
  opacity: 1;
}

.tarjeta-comparar-boton:hover {
  border-color: var(--azul);
  color: var(--azul);
}

.tarjeta-comparar-boton.activo {
  background: var(--verde-tenue);
  border-color: var(--verde);
  color: var(--verde);
}

/* En pantallas táctiles no hay hover: el botón tiene que estar visible
   siempre, o sería inalcanzable. */
@media (hover: none) {
  .tarjeta-comparar-boton { opacity: 1; }
}

/* En mobile, arriba a la derecha sobre la foto, como en escritorio y más
   chico, para no tapar media foto en una tarjeta de ~170px. La Home
   conserva el de antes (abajo a la izquierda, ver «Tarjetas de producto
   en mobile»). */
@media (max-width: 40rem) {
  :where(.pagina-inicio) .tarjeta-envoltorio .tarjeta-comparar {
    top: auto;
    right: auto;
    bottom: .9rem;
    left: .65rem;
  }
  :where(.pagina-inicio) .tarjeta-envoltorio .tarjeta-comparar-boton {
    font-size: .65rem;
    padding: .4rem .35rem;
  }
  :where(body:not(.pagina-inicio)) .tarjeta-envoltorio .tarjeta-comparar { top: 0.4rem; right: 0.4rem; }
  :where(body:not(.pagina-inicio)) .tarjeta-envoltorio .tarjeta-comparar-boton {
    font-size: .65rem;
    padding: .3rem .45rem;
  }
}

/* --- La barra flotante --- */

.barra-comparacion {
  position: fixed;
  left: 50%;
  bottom: var(--e-4);
  transform: translateX(-50%);
  z-index: 40;
  display: flex;
  align-items: center;
  gap: var(--e-5);
  width: min(60rem, calc(100vw - 2rem));
  padding: var(--e-3) var(--e-4);
  border: 1px solid var(--borde);
  border-radius: 999px;
  background: rgba(255, 255, 255, .96);
  backdrop-filter: blur(10px);
  box-shadow: var(--sombra-alta);
}

.barra-comparacion-items {
  display: flex;
  align-items: center;
  gap: var(--e-4);
  flex: 1;
  min-width: 0;
  overflow-x: auto;
}

.barra-comparacion-titulo {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-shrink: 0;
  font-size: var(--t-sm);
  font-weight: 700;
}

.barra-comparacion-cuenta {
  display: grid;
  place-items: center;
  min-width: 1.5rem;
  height: 1.5rem;
  padding: 0 0.35rem;
  border-radius: 999px;
  background: var(--azul);
  color: #fff;
  font-size: var(--t-xs);
  font-variant-numeric: tabular-nums;
}

.barra-comparacion-item {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-shrink: 0;
  padding: 0.2rem 0.2rem 0.2rem 0.35rem;
  border: 1px solid var(--borde-suave);
  border-radius: 999px;
}

.barra-comparacion-imagen {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  flex-shrink: 0;
}

.barra-comparacion-imagen .miniatura {
  width: 100%;
  height: 100%;
  background: none;
  object-fit: contain;
}

.barra-comparacion-imagen .miniatura-monograma {
  width: 1.6rem;
  height: 1.6rem;
  font-size: 0.6rem;
  background: var(--azul-tenue);
}

.barra-comparacion-nombre {
  max-width: 8rem;
  font-size: var(--t-xs);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.barra-comparacion-item form { margin: 0; }

.barra-comparacion-quitar {
  display: grid;
  place-items: center;
  width: 1.4rem;
  height: 1.4rem;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--texto-suave);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transicion), color var(--transicion);
}

.barra-comparacion-quitar:hover {
  background: var(--fondo-suave);
  color: var(--rojo);
}

.barra-comparacion-acciones {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  flex-shrink: 0;
}

.barra-comparacion-acciones form { margin: 0; }

.barra-comparacion-comparar {
  display: inline-flex;
  align-items: center;
  min-height: 2.5rem;
  padding: 0.5rem 1.25rem;
  border-radius: 999px;
  background: var(--azul);
  color: #fff;
  font-size: var(--t-sm);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--transicion);
}

.barra-comparacion-comparar:hover { background: var(--azul-claro); }

.barra-comparacion-falta {
  font-size: var(--t-xs);
  color: var(--texto-suave);
  white-space: nowrap;
}

.barra-comparacion-limpiar {
  padding: 0.3rem 0.5rem;
  border: 0;
  background: none;
  color: var(--texto-suave);
  font: inherit;
  font-size: var(--t-xs);
  text-decoration: underline;
  cursor: pointer;
}

.barra-comparacion-limpiar:hover { color: var(--rojo); }

@media (max-width: 40rem) {
  /* Sube por encima del nav inferior, que ya ocupa el pie de la
     pantalla. Sin esto una tapa a la otra. */
  .barra-comparacion {
    bottom: calc(4.5rem + env(safe-area-inset-bottom));
    gap: var(--e-3);
  }

  /* Acá se escondía cada producto seleccionado, porque con el ancho de
     un teléfono no entraba la fila. El costo era que no se podía ver ni
     sacar nada de la selección desde el teléfono. Ahora entran: la barra
     se pliega y la lista se apila al abrirla (bloque «La barra de
     comparación, plegable», al final del archivo). */
  .barra-comparacion-limpiar { padding: 0.3rem; }
}

/* ======================================================================
   MOVIMIENTO — respuesta al toque, transiciones de página y apertura
   de acordeones.
   ======================================================================

   El problema que resuelve: había 69 reglas `:hover` y ninguna `:active`.
   En un teléfono el hover no existe, así que tocar cualquier cosa no
   devolvía nada hasta que la página siguiente terminaba de cargar — la
   interfaz se sentía muerta justo en el momento en que la persona
   interactúa con ella, y este sitio es mobile-first.

   Criterio: el movimiento confirma lo que la persona hizo, nunca decora.
   Nada acá aparece, desaparece ni reordena contenido — solo responde.
   Quien pidió menos movimiento en su sistema no ve nada de esto: el
   interruptor global de `prefers-reduced-motion` (más arriba) ya apaga
   toda transición, y al final de este bloque se apagan además las
   transiciones de página, que ese interruptor no alcanza
   (DOCS/100-BRANDING.md §8).
*/

:root {
  /* La curva que `--transicion` ya usa en todo el sitio, suelta para
     poder combinarla con otras duraciones. */
  --curva: cubic-bezier(.2, .7, .3, 1);

  /* Presionar es rápido; soltar, más lento. Esa asimetría es lo que hace
     que un control se sienta físico sin necesidad de un rebote. */
  --transicion-presion: 90ms var(--curva);
  --transicion-suelta: 320ms var(--curva);

  /* Cuánto se hunde cada cosa al tocarla. Las superficies grandes se
     mueven menos: la misma escala que en un botón se ve exagerada en una
     tarjeta del ancho de la pantalla. */
  --presion-boton: .96;
  --presion-tarjeta: .985;
}

/* Una sola lista de transiciones para todo lo que responde al toque.
   Incluye propiedades que un elemento dado quizá nunca cambie
   —transicionar algo que no cambia no cuesta nada— y a cambio evita
   repetir la declaración con la combinación exacta de cada uno de los
   sesenta componentes que ya la traían. */
.boton-primario,
.boton-secundario,
.vs-boton-ofertas,
.tarjeta-comparar-boton,
.barra-comparacion-comparar,
.barra-comparacion-limpiar,
.barra-comparacion-quitar,
.carrusel-flecha,
.nav-icono,
.limpiar-filtros,
.enlace-flecha,
.buscador button,
.comparador-portada-buscador button,
.formulario-cuenta button,
.acciones-cuenta button,
.salir-cuenta button,
.favorito-flotante button,
.tarjeta,
.resultado,
.vs-cual-card,
.vs-sugerida,
.comparador-resultado,
.fila-tienda,
.lista-chip,
.marca-chip,
.marca,
.categoria-icono,
.galeria-miniatura,
.puntuacion-resumen,
.faceta-opcion,
.orden a,
.orden-busqueda a,
.paginacion a,
.ficha-navegacion a,
.enlace-tienda,
.categorias a {
  transition:
    background var(--transicion),
    color var(--transicion),
    border-color var(--transicion),
    box-shadow var(--transicion),
    opacity var(--transicion),
    transform var(--transicion),
    scale var(--transicion-suelta);

  /* El recuadro gris que dibuja el navegador al tocar aparecía tarde y
     con la forma equivocada (rectangular sobre esquinas redondeadas). Se
     saca porque acá abajo se da una respuesta propia, no para dejar el
     toque sin confirmación. */
  -webkit-tap-highlight-color: transparent;

  /* Sin esto el navegador espera ~300ms por si el toque era un doble
     toque para hacer zoom. Es buena parte de la sensación de lentitud en
     mobile, y no se pierde nada: el zoom con dos dedos sigue igual. */
  touch-action: manipulation;
}

/* --- La respuesta al toque -------------------------------------------

   Se usa la propiedad `scale` y no `transform: scale()` a propósito:
   varios de estos elementos ya usan `transform` para otra cosa (centrar
   con `translate(-50%)`, levantarse en hover) y escribir `transform` acá
   lo pisaría, rompiendo el posicionamiento. `scale` se compone con lo
   que ya haya, sin tocarlo. */
.boton-primario:active,
.boton-secundario:active,
.vs-boton-ofertas:active,
.tarjeta-comparar-boton:active,
.barra-comparacion-comparar:active,
.barra-comparacion-limpiar:active,
.barra-comparacion-quitar:active,
.carrusel-flecha:active,
.nav-icono:active,
.limpiar-filtros:active,
.buscador button:active,
.comparador-portada-buscador button:active,
.formulario-cuenta button:active,
.acciones-cuenta button:active,
.salir-cuenta button:active,
.favorito-flotante button:active,
.galeria-miniatura:active,
.marca-chip:active,
.lista-chip:active,
.categoria-icono:active {
  scale: var(--presion-boton);
  transition-duration: var(--transicion-presion);
}

.tarjeta:active,
.resultado:active,
.vs-cual-card:active,
.vs-sugerida:active,
.comparador-resultado:active,
.fila-tienda:active,
.marca:active,
.puntuacion-resumen:active,
.categorias a:active,
.enlace-tienda:active {
  scale: var(--presion-tarjeta);
  transition-duration: var(--transicion-presion);
}

/* Los de lista son texto sobre un fondo: encogerlos se lee como un error
   de renderizado, no como una respuesta. Se confirman con el mismo fondo
   que ya usan en hover — acá simplemente se les da también al tocar. */
.faceta-opcion:active,
/* La barra lateral pinta su propio `:hover` con más especificidad
   (`.sidebar-filtros .faceta-opcion:hover`), así que sin repetir el
   contexto acá el hover le ganaba al toque y esas opciones quedaban sin
   respuesta en desktop, donde el click también activa el hover. */
.sidebar-filtros .faceta-opcion:active,
.orden a:active,
.orden-busqueda a:active,
.paginacion a:active,
.ficha-navegacion a:active,
.nav-cabecera a:active,
.nav-pie a:active,
.menu-mas-lista a:active,
.sugerencias-lista a:active {
  background: var(--azul-tenue);
  transition-duration: var(--transicion-presion);
}

/* Un control deshabilitado no se hunde: se sentiría como que funcionó.
   `:disabled` solo no alcanza — varios de estos son `<a>`. */
button:disabled:active,
.boton-primario:disabled:active,
.boton-secundario:disabled:active,
.tarjeta-comparar-boton:disabled:active,
[aria-disabled="true"]:active {
  scale: 1;
}

/* --- Apertura de acordeones ------------------------------------------

   `<details>` abre de golpe por defecto. Animar su altura requiere que
   el navegador sepa interpolar `height: auto`, que es reciente; donde no
   se pueda, sigue abriendo de golpe igual que hasta ahora. */
@supports (interpolate-size: allow-keywords) and (transition-behavior: allow-discrete) {
  :root {
    interpolate-size: allow-keywords;
  }

  .vs-grupo::details-content,
  .vs-glosario::details-content {
    block-size: 0;
    overflow: clip;
    opacity: 0;
    transition:
      block-size var(--transicion),
      opacity var(--transicion),
      content-visibility var(--transicion) allow-discrete;
  }

  .vs-grupo[open]::details-content,
  .vs-glosario[open]::details-content {
    block-size: auto;
    opacity: 1;
  }

  /* `.acordeon` va aparte y solo en mobile. De 40.01rem para arriba está
     forzado a mostrarse siempre —los filtros de categoría no se pliegan
     en desktop, ver la regla de `@media (min-width: 40.01rem)` más
     arriba— y como este bloque viene después en el archivo, animar el
     pseudo-elemento sin acotar lo pisaba y dejaba la barra de filtros
     colapsada e invisible en desktop (verificado a 1280px). */
  @media (max-width: 40rem) {
    .acordeon::details-content {
      block-size: 0;
      overflow: clip;
      opacity: 0;
      transition:
        block-size var(--transicion),
        opacity var(--transicion),
        content-visibility var(--transicion) allow-discrete;
    }

    .acordeon[open]::details-content {
      block-size: auto;
      opacity: 1;
    }
  }
}

/* --- Transición entre páginas ----------------------------------------

   El sitio navega con enlaces normales, sin JavaScript
   (DOCS/110-SEO.md §4), así que cada click era un parpadeo en blanco.
   Esto lo reemplaza por un fundido corto sin cambiar una línea de HTML
   ni agregar un script: el navegador que no lo soporta navega como
   siempre. */
@view-transition {
  navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 220ms;
  animation-timing-function: var(--curva);
}

/* La cabecera y las barras fijas son las mismas en todas las páginas:
   fundirlas con el resto las hace parpadear sin motivo. Nombrarlas las
   deja quietas mientras el contenido cambia detrás. */
@supports (view-transition-name: none) {
  header.cabecera {
    view-transition-name: cabecera;
  }

  .nav-inferior {
    view-transition-name: nav-inferior;
  }

  .barra-comparacion {
    view-transition-name: barra-comparacion;
  }
}

/* El interruptor global de `prefers-reduced-motion` actúa sobre el
   `transition-duration` y el `animation-duration` de los elementos, pero
   no alcanza a las transiciones de página: son pseudo-elementos que `*`
   no selecciona. Se apagan en el origen. */
@media (prefers-reduced-motion: reduce) {
  @view-transition {
    navigation: none;
  }
}

/* --- La barra de comparación, plegable -------------------------------

   Referencia: el selector de versus.com (grabación del 2026-08-19). La
   píldora cuenta lo seleccionado y se abre en una lista donde se puede
   sacar producto por producto, con el botón Comparar al final.

   El reparto por ancho:

   - **Desktop**: exactamente como estaba, una fila. Se logra con
     `display: contents` en el `<details>`, en su contenido y en el
     cuerpo: esos tres dejan de generar caja y sus hijos vuelven a ser
     hijos directos del flex de `.barra-comparacion`, que es la
     estructura que el CSS de esta barra ya esperaba. Nada del layout
     viejo se reescribe.
   - **Mobile**: píldora que se despliega hacia abajo.

   Las dos reglas para forzar el desplegado en desktop son las mismas que
   usa `.acordeon` y por el mismo motivo: los navegadores que esconden un
   `<details>` cerrado poniendo `display: none` en sus hijos necesitan la
   primera, y los que lo envuelven en `::details-content` necesitan la
   segunda. */

.barra-comparacion-resumen {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  cursor: pointer;
  list-style: none;
}

.barra-comparacion-resumen::-webkit-details-marker { display: none; }

.barra-comparacion-chevron {
  width: 0.5rem;
  height: 0.5rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  /* Cerrado apunta hacia arriba: el panel crece hacia arriba desde una
     barra que vive abajo de la pantalla. */
  transform: rotate(-135deg);
  transition: transform var(--transicion);
}

.barra-comparacion-plegable[open] .barra-comparacion-chevron {
  transform: rotate(45deg);
}

@media (min-width: 40.01rem) {
  .barra-comparacion-plegable,
  .barra-comparacion-cuerpo {
    display: contents;
  }

  .barra-comparacion-plegable:not([open]) > *:not(summary) { display: contents; }

  .barra-comparacion-plegable::details-content {
    display: contents;
    content-visibility: visible;
  }

  /* En desktop no hay nada que plegar: el resumen es solo el título. */
  .barra-comparacion-resumen { cursor: default; }
  .barra-comparacion-chevron { display: none; }
}

@media (max-width: 40rem) {
  /* La píldora deja de ser una fila estirada y se ajusta a su contenido,
     como en la referencia. */
  .barra-comparacion {
    left: auto;
    right: var(--e-3);
    width: auto;
    max-width: calc(100vw - 1.5rem);
    transform: none;
    padding: 0;
    border-radius: var(--radio);
    overflow: hidden;
  }

  .barra-comparacion-resumen {
    justify-content: space-between;
    gap: var(--e-4);
    padding: var(--e-3) var(--e-4);
    min-height: 2.75rem;
  }

  .barra-comparacion-cuerpo {
    display: flex;
    flex-direction: column;
    gap: var(--e-3);
    padding: 0 var(--e-4) var(--e-4);
  }

  /* La lista se apila: en la fila horizontal los nombres quedaban
     cortados y había que arrastrar de costado para llegar al último. */
  .barra-comparacion-items {
    flex-direction: column;
    align-items: stretch;
    gap: var(--e-2);
    overflow-x: visible;
  }

  /* Vuelve a mostrarse lo que antes se escondía en mobile: es el motivo
     de todo este bloque. */
  .barra-comparacion-item {
    display: flex;
    justify-content: flex-start;
    gap: var(--e-3);
    padding: var(--e-2);
    border-radius: var(--radio-chico);
  }

  .barra-comparacion-nombre {
    flex: 1;
    max-width: none;
    white-space: normal;
  }

  /* Área de toque cómoda para la × de cada producto, que es la acción
     que esta pantalla viene a habilitar (DOCS/100-BRANDING.md §8). */
  .barra-comparacion-quitar {
    width: 2.25rem;
    height: 2.25rem;
  }

  .barra-comparacion-acciones {
    flex-direction: column;
    align-items: stretch;
    gap: var(--e-2);
  }

  .barra-comparacion-comparar {
    text-align: center;
  }
}

/* El despliegue.

   Se anima `grid-template-rows` de `0fr` a `1fr` y no la altura: son dos
   números, así que no hace falta que el navegador sepa interpolar
   `height: auto` (`interpolate-size`, que es reciente). Donde no haya
   soporte de nada de esto, el panel abre de golpe y funciona igual.

   `content-visibility` se declara en el estado abierto y NO se
   transiciona de forma discreta: transicionándolo, el contenido todavía
   no está renderizado cuando arranca la animación, así que la altura
   sale de cero y llega a cero. */
@media (max-width: 40rem) {
  .barra-comparacion-plegable::details-content {
    display: grid;
    grid-template-rows: 0fr;
    opacity: 0;
    transition:
      grid-template-rows var(--transicion),
      opacity var(--transicion);
  }

  .barra-comparacion-plegable[open]::details-content {
    grid-template-rows: 1fr;
    opacity: 1;
    content-visibility: visible;
  }

  /* Las dos hacen falta para que la fila de la grilla pueda valer cero:
     sin `min-height: 0` el contenido impone su altura mínima y no se
     encoge, y sin `overflow: hidden` se desborda mientras se abre. */
  .barra-comparacion-cuerpo {
    min-height: 0;
    overflow: hidden;
  }
}

/* Las secciones nombradas dentro de la frase del veredicto. Se subrayan
   con guiones y no con una línea llena para que no se lean como enlaces:
   son la etiqueta de una sección de la tabla de más abajo, no algo que
   lleve a otra página. El verde y el rojo repiten el código de color que
   ya usa la tabla, y nunca van solos — la palabra «salvo que» dice lo
   mismo sin depender del color (DOCS/100-BRANDING.md §8). */
.vs-veredicto-grupo {
  /* Es un enlace a la tabla que respalda esa sección. El subrayado
     punteado se eligió justamente para eso: marca que se puede tocar
     sin leerse como un enlace a otra página, que es lo que sugeriría
     el subrayado lleno. */
  padding: 0.05em 0.3em;
  border-radius: var(--radio-chico);
  background: var(--fondo-suave);
  color: inherit;
  text-decoration: underline dotted;
  text-underline-offset: 0.25em;
  transition: background var(--transicion), color var(--transicion);
}

.vs-veredicto-grupo:hover,
.vs-veredicto-grupo:focus-visible {
  text-decoration-style: solid;
}

.vs-veredicto-grupo.gana {
  color: var(--verde);
  background: var(--verde-tenue);
  text-decoration-color: var(--verde);
}

.vs-veredicto-grupo.cede {
  color: var(--texto-suave);
  text-decoration-color: var(--borde);
}

.vs-veredicto-grupo sup {
  font-size: 0.7em;
  font-variant-numeric: tabular-nums;
}

.vs-veredicto-ayuda {
  margin: var(--e-3) 0 0;
  font-size: var(--t-xs);
  color: var(--texto-suave);
}

/* --- Alineación de las columnas del hero del comparador --------------

   Cada columna es un flex independiente, así que la altura del nombre
   mandaba sobre todo lo de abajo: con cuatro productos, «iPhone 12 Mini»
   ocupa una línea y «iPhone 14 Plus 128GB (Recertificado)» dos o tres, y
   eso dejaba las fotos, las puntuaciones y los precios cada uno a una
   altura distinta. Se veía desprolijo justo en la parte que más se mira.

   Se probó `subgrid`, que sería la respuesta directa, y **no sirve acá**:
   la caja de la foto se dimensiona con `aspect-ratio` sobre un ancho
   porcentual, y eso no aporta altura al calcular las filas de un
   subgrid. La fila de la foto quedaba en 16px —el margen— con la imagen
   desbordándola (medido 2026-08-19).

   Así que se ataca lo único que de verdad varía: el alto del nombre. Se
   le reserva sitio para dos líneas siempre. Lo de abajo tiene la misma
   estructura en todas las columnas y las fotos ya son todas cuadradas
   (`productos/encuadre.py`), así que con el nombre parejo queda todo
   alineado sin depender de nada nuevo del navegador. */
.vs-hero-modelo {
  display: block;
  /* Dos líneas de `line-height: 1.1`. Un nombre de una línea reserva el
     mismo espacio que uno de dos; uno de tres crece, que es raro y
     preferible a cortarle el nombre al producto. */
  min-height: 2.2em;
}

/* El pie existe siempre, tenga contenido o no (ver la plantilla). Se
   alinea arriba, no abajo: con el nombre reservado a dos líneas y la
   línea de lanzamiento reservada en todas las columnas cuando alguna la
   tiene, lo de encima del precio mide igual en todas, y el precio queda
   a la misma altura aunque una columna agregue el precio original en
   pesos debajo. Alineado abajo, esa línea extra subía el precio de su
   columna (2026-09-30). */
.vs-hero-pie {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

.vs-hero-producto { height: 100%; }

/* Con cuatro columnas cada nombre tiene la mitad de ancho que con dos,
   pero el cuerpo era el mismo: por eso saltaba a tres líneas. Se baja el
   tamaño a medida que entran más productos, en vez de dejar que el texto
   decida el alto de la fila. */
.vs-hero[data-productos="3"] .vs-hero-nombre {
  font-size: clamp(1.05rem, 1.9vw, 1.5rem);
}

.vs-hero[data-productos="4"] .vs-hero-nombre {
  font-size: clamp(0.95rem, 1.5vw, 1.25rem);
}

/* --- Saltar desde el veredicto a la prueba ---------------------------

   Las secciones subrayadas del veredicto enlazan al grupo de la ficha
   técnica que las respalda. Pero los grupos arrancan cerrados y el
   navegador **no** abre un `<details>` cuando el destino del enlace es
   el `<details>` mismo: solo lo hace cuando el destino está adentro
   (probado en Chrome 148: `open` seguía en false tras el salto). Sin
   esto, tocar «pantalla» te dejaba mirando una sección plegada — la
   promesa de «ver la prueba» sin cumplir.

   Se fuerza el contenido visible con `:target`. Van dos reglas por el
   mismo motivo que el acordeón de más arriba: los navegadores que
   esconden un `<details>` cerrado con `display: none` en sus hijos
   necesitan la primera, y los que lo envuelven en `::details-content`
   necesitan la segunda. No se toca el atributo `open` —CSS no puede—,
   así que el chevron queda como está: el contenido se ve, que es lo que
   se vino a buscar, y tocando el encabezado se sigue plegando y
   desplegando como siempre. */
.vs-grupo:target > *:not(summary) {
  display: block;
}

.vs-grupo:target::details-content {
  content-visibility: visible;
  block-size: auto;
  opacity: 1;
  /* Sin transición, a propósito. Estas mismas propiedades se animan al
     plegar y desplegar el grupo a mano, y ahí el valor que manda durante
     la animación es el interpolado — con `content-visibility` animándose
     de forma discreta, el alto sale de un contenido todavía sin
     renderizar y se queda en cero (el mismo pozo que la barra de
     comparación, ver su bloque). Acá se llega por un salto de ancla, no
     por un gesto: mostrarlo de una es lo correcto y además no depende de
     que la animación termine bien. */
  transition: none;
}

/* Que se note cuál sección se acaba de abrir: si no, el salto deja al
   lector en medio de una tabla sin señal de por qué está ahí. */
.vs-grupo:target > .vs-grupo-resumen {
  background: var(--azul-tenue);
}

/* Los factores del Índice nombrados en el veredicto («disponibilidad»,
   «calidad del procesador»). No se subrayan como las secciones: esas
   llevan a una tabla, estos no van a ningún lado — su explicación está
   en el `title` y completa en la ficha de cada producto. */
.vs-veredicto-motivo {
  font-weight: 600;
  color: var(--texto);
}

/* El veredicto cuando empatan: una lista, no una frase larga. Con dos o
   tres productos parejos, meterlo todo en un párrafo obliga a releer
   para saber qué gana cada uno. */
.vs-empate-lista {
  margin: var(--e-4) 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
}

.vs-empate-lista li {
  padding: var(--e-3) var(--e-4);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio-chico);
  background: var(--fondo-suave);
}

.vs-empate-barato {
  color: var(--verde);
  font-weight: 600;
}

/* El aviso de que el que conviene no es el más potente. Va en el color
   del texto normal y no en rojo: no es un error ni una advertencia de
   peligro, es una precisión sobre en qué gana. */
.vs-veredicto-aviso {
  font-weight: 700;
}

/* Monograma en la cabecera de una marca sin logo oficial. Mismo tamaño
   que el logo real para que el encabezado no cambie de alto según la
   marca tenga o no imagen. */
.logo-marca-monograma {
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--radio-chico);
  background: var(--azul-tenue);
  color: var(--azul);
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1;
}

/* === Selector de moneda ================================================
   Un botón por moneda en la cabecera. Es un formulario común (sin JS),
   así que los botones se despintan para que lean como un control de
   opciones y no como dos acciones sueltas. */
.selector-moneda {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  background: var(--fondo-suave, rgba(0, 0, 0, .04));
  border-radius: 999px;
}

/* Botón de modo oscuro: mismo lenguaje que el selector de moneda (píldora
   tenue con borde), redondo porque lleva solo un ícono. 40px de lado y
   44 de área táctil por el margen negativo del formulario. */
.selector-tema { display: inline-flex; margin: 0; }
.tema-boton {
  display: inline-grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  color: var(--texto-suave);
  background: var(--fondo-suave);
  border: 1px solid var(--borde-suave);
  border-radius: 999px;
  cursor: pointer;
  transition: color var(--transicion), border-color var(--transicion);
}
.tema-boton:hover { color: var(--azul); border-color: var(--azul); }

.moneda-opcion {
  padding: 0.3rem 0.65rem;
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--texto-suave);
  background: none;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  transition: background var(--transicion-suelta) var(--curva),
              color var(--transicion-suelta) var(--curva);
}

.moneda-opcion:hover { color: var(--texto); }

.moneda-opcion.activa {
  color: var(--violeta, var(--azul));
  background: var(--superficie, #fff);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .08);
}

.moneda-opcion:active { scale: var(--presion-boton); }

/* Cada precio se escribe en las dos monedas y acá se decide cuál se ve,
   según `data-moneda` del <html>. Alternar un atributo es instantáneo:
   cambiar de moneda no vuelve a pedir la página.

   El valor del atributo lo pone el servidor con la moneda de la sesión,
   así que sin JavaScript se ve exactamente lo mismo. */
:root[data-moneda="USD"] .precio-en-uyu,
:root[data-moneda="UYU"] .precio-en-usd { display: none; }

/* El precio convertido no puede parecer el precio que va a cobrar la
   tienda: el «≈» avisa que es una conversión, y el original queda al
   lado, más chico. */
/* El «≈» acompaña al número, no compite con él: en el panel de la ficha
   el precio llega a 3rem y un signo del mismo cuerpo se leía como parte
   de la cifra. */
.precio-aprox {
  /* Con piso de 11 px: al lado de un precio chico, .62em daba 7 px. */
  font-size: max(.62em, .6875rem);
  font-weight: 400;
  letter-spacing: normal;
  opacity: .55;
  margin-right: .12em;
}

/* El precio original hereda el contexto de donde esté, y el panel de la
   ficha aprieta las letras (`letter-spacing: -.035em`) y usa cifras
   tabulares para que el número grande calce. Heredarlo dejaba «USD
   290,00» con las letras encimadas debajo del precio convertido, sin
   aire que lo separara. Acá se devuelve a texto normal. */
.precio-original {
  display: block;
  margin-top: .3rem;
  font-size: var(--t-sm);
  font-weight: 500;
  letter-spacing: normal;
  font-variant-numeric: normal;
  line-height: 1.35;
  color: var(--texto-suave);
}

/* En el panel de la ficha el precio es enorme y su original necesita más
   separación que en una tarjeta, donde ya está en cuerpo chico. */
.panel-precio-valor .precio-original {
  margin-top: .5rem;
  font-size: var(--t-base);
}

/* En una línea de texto («desde ≈ USD 137,39 · 1 tienda», las variantes
   de la ficha) el original va al lado entre paréntesis: como bloque partía
   esa fila en tres renglones mientras las demás ocupaban uno. */
.meta .precio-original {
  display: inline;
  margin: 0 0 0 .3em;
  font-size: inherit;
}
.meta .precio-original::before { content: "("; }
.meta .precio-original::after { content: ")"; }

/* Dentro de un botón (`Ir a la tienda · ≈ UYU 41.403`) el gris de texto
   suave sobre el azul no se leía (2026-10-16). Sigue en su renglón —en la
   misma línea no entra en el ancho del panel— pero con el color del botón. */
.boton-primario .precio-original {
  margin-top: .15rem;
  font-size: var(--t-sm);
  color: inherit;
  opacity: .85;
}

@media (max-width: 40rem) {
  /* En un teléfono la cabecera ya va justa de ancho: el selector queda,
     porque elegir moneda es justamente lo que más se necesita al
     comparar, pero apretado al mínimo legible. */
  .selector-moneda { margin-right: var(--e-2); }
  .moneda-opcion { padding: 0.3rem 0.5rem; }
}

/* === Cabecera: qué se comprime primero cuando no entra ==================
   Con la sesión iniciada la barra lleva el catálogo (Categorías, Marcas,
   Tiendas, Comparador), el buscador, el selector de moneda y cinco
   accesos de cuenta. No entra en una línea por debajo de ~78rem, y
   partida en dos filas se ve desarmada.

   El orden en que se cede espacio no es arbitrario: **primero se
   comprime lo secundario**. Los destinos del catálogo son para lo que la
   gente entra al sitio; Favoritos/Historial/Alertas son de la cuenta y
   su ícono ya es convencional. Por eso estas etiquetas se esconden antes
   de tocar nada del catálogo.

   Se repiten las reglas de `.oculto` en vez de `display: none`: el
   nombre sigue estando para un lector de pantalla, que es lo único que
   tiene para saber a dónde va ese enlace. No se puede reusar la clase
   porque se aplica en el HTML y acá depende del ancho. */
@media (max-width: 78rem) {
  .nav-cuenta .nav-icono-texto span {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  /* Sin texto al lado, el padding pensado para separar palabras deja los
     íconos flotando lejos entre sí. */
  .nav-cuenta .nav-icono-texto { padding: 0 0.35rem; }
}

/* Entre 40rem y 48rem la barra sigue sin entrar en una línea aun con el
   catálogo colapsado en ☰ y los accesos de cuenta en solo ícono: lo que
   queda ocupando lugar es el logotipo escrito, ~120px de los 720
   disponibles. Ahí se deja solo el isotipo — la lupa sigue siendo el
   enlace a la Home y sigue leyéndose como la marca.

   El nombre no se borra, se esconde a la vista: un lector de pantalla
   tiene que poder anunciar a dónde lleva ese enlace. Por debajo de 40rem
   esto deja de hacer falta, porque ahí Categorías/Favoritos/Perfil se van
   a la barra inferior (`.nav-duplica-mobile`). */
@media (max-width: 48rem) {
  .marca-texto {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
}

@media (max-width: 40rem) {
  /* Con la barra inferior en juego la cabecera vuelve a tener lugar. */
  .marca-texto {
    position: static;
    width: auto; height: auto;
    margin: 0;
    clip: auto;
  }
}

/* === Mis alertas =======================================================
   Una fila por alerta y no una tarjeta: lo que se sigue acá es un precio
   contra otro, y eso se lee mejor en una línea que en una grilla. La
   tarjeta de producto se usa en Favoritos, donde lo que importa es el
   producto; acá importa la diferencia. */
.lista-alertas {
  list-style: none;
  margin: var(--e-5) 0 0;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}

.alerta-fila {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-4);
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: var(--superficie, #fff);
  box-shadow: var(--sombra);
}

/* La que bajó se distingue por el borde, no por un fondo de color: el
   fondo compite con la foto del producto que está al lado. */
.alerta-fila.bajo { border-color: var(--azul); }

.alerta-producto {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex: 1 1 14rem;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.alerta-imagen {
  flex: 0 0 3rem;
  height: 3rem;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: var(--radio-chico);
  background: var(--fondo-suave);
}

.alerta-imagen img { max-width: 100%; max-height: 100%; }

.alerta-nombre {
  font-weight: 600;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

.alerta-precios {
  display: grid;
  gap: 0.1rem;
  flex: 0 1 auto;
  font-size: var(--t-sm);
}

.alerta-referencia { color: var(--texto-suave); }
.alerta-actual { font-weight: 600; }
.alerta-actual.sin-dato { font-weight: 400; color: var(--texto-suave); }

.alerta-estado {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-left: auto;
}

.alerta-señal {
  font-size: var(--t-xs);
  font-weight: 600;
  padding: 0.25rem 0.6rem;
  border-radius: 999px;
  color: var(--texto-suave);
  background: var(--fondo-suave);
}

.alerta-señal.baja { color: var(--azul); background: var(--azul-tenue); }

.alerta-cancelar {
  padding: 0.35rem 0.75rem;
  font-size: var(--t-xs);
  color: var(--texto-suave);
  background: none;
  border: 1px solid var(--borde);
  border-radius: 999px;
  cursor: pointer;
}

.alerta-cancelar:hover { color: var(--texto); border-color: var(--texto-suave); }

@media (max-width: 40rem) {
  /* En un teléfono la fila se apila; el estado deja de ir al extremo
     derecho porque ya no hay extremo derecho que valga. */
  .alerta-estado { margin-left: 0; width: 100%; justify-content: space-between; }
}

/* === Profundidad de la portada ======================================
 *
 * La home era un plano unico: una banda lavanda, el buscador y las
 * tarjetas, todo a la misma distancia. Se lee plana, y en una web que
 * quiere que la persona se quede a mirar eso importa.
 *
 * `DOCS/100-BRANDING.md` §8.1 dice que el movimiento responde a lo que
 * la persona hizo y no decora ni hace aparecer contenido. Esto lo
 * respeta con tres condiciones:
 *
 * 1. **Solo se mueven capas decorativas.** Ni un titulo, ni una
 *    tarjeta, ni un precio cambian de lugar: lo que deriva es un fondo
 *    que no dice nada, detras de todo (`z-index: -1`).
 * 2. **Responde al scroll**, que es algo que la persona hizo. No hay
 *    nada que se mueva solo.
 * 3. **No retrasa nada.** El contenido esta en su sitio final desde el
 *    primer pixel; si la animacion no corre, la pagina se ve igual que
 *    hoy.
 *
 * Se usa `animation-timeline: scroll()`, que es CSS puro: sin
 * JavaScript, sin escuchar el scroll y sin recalcular en cada frame
 * —que es lo que vuelve lento un parallax hecho a mano—. El navegador
 * que no lo soporte cae en el `@supports` y no ve ninguna diferencia.
 */

/* La capa que deriva. Va en `::after` para no tocar la banda de
   `::before`, que es la que da el color de fondo: si esa se moviera
   quedaria una franja sin pintar arriba. */
.pregunta::after {
  content: "";
  position: absolute;
  /* Sobresale de su caja a proposito: al desplazarse no puede dejar un
     borde vacio a la vista. */
  inset: -25% -10%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(28% 34% at 18% 22%, rgba(86, 135, 237, .16), transparent 70%),
    radial-gradient(24% 30% at 84% 30%, rgba(150, 180, 229, .14), transparent 70%);
}

@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .pregunta::after {
      animation: deriva-portada linear both;
      animation-timeline: scroll(root block);
      /* Termina a una pantalla de scroll: pasada la portada ya no hay
         nada que acompañar, y seguir moviendola gastaria pintura por
         algo que nadie ve. */
      animation-range: 0 100vh;
    }

    /* La banda de «¿Cómo funciona?» acompaña con la mitad de recorrido:
       la profundidad se nota cuando dos capas van a distinta velocidad,
       no cuando todas van a la misma. */
    .banner-como-funciona {
      position: relative;
      isolation: isolate;
    }

    .banner-como-funciona::before {
      content: "";
      position: absolute;
      inset: -30% -12%;
      z-index: -1;
      pointer-events: none;
      background:
        radial-gradient(30% 40% at 78% 24%, rgba(86, 135, 237, .10), transparent 72%);
      animation: deriva-secundaria linear both;
      animation-timeline: view(block);
      animation-range: entry 0% exit 100%;
    }
  }
}

@keyframes deriva-portada {
  /* 4,5rem sobre una pantalla de scroll: se percibe como profundidad,
     no como que algo se despega. Con mas, la capa se separa tanto del
     contenido que se lee como un error de renderizado. */
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(0, 4.5rem, 0); }
}

@keyframes deriva-secundaria {
  from { transform: translate3d(0, -2.5rem, 0); }
  to { transform: translate3d(0, 2.5rem, 0); }
}

/* === Vidriera de diferencias ========================================
 *
 * La Home tenia buscador, categorias y novedades: nada que mostrara que
 * el mismo producto vale distinto segun donde se compre, que es la
 * unica razon por la que alguien vuelve.
 *
 * Es una grilla y no un carrusel como Novedades: aca el valor esta en
 * ver varias diferencias juntas —cuatro o cinco de un vistazo dicen
 * «esto pasa siempre», una sola dice «encontraron un caso»—. Un
 * carrusel muestra de a una.
 */
.grilla-diferencias {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12.5rem, 1fr));
  gap: 0.9rem;
}

/* La diferencia va debajo del precio y en un tono aparte: el precio es
   lo que se paga y esto es cuanto se puede evitar pagar. Con el mismo
   color se leerian como dos precios del mismo producto. */
.tarjeta-diferencia {
  margin-top: 0.15rem;
  font-size: var(--t--1);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--verde);
}

@media (max-width: 40rem) {
  /* Dos columnas, como `.grilla` en un teléfono (ver «Tarjetas de
     producto en mobile: dos columnas»). En la Home la pisa `inicio.css`. */
  .grilla-diferencias { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.6rem; }
}

/* La salida de una ficha que no se puede comparar. Misma grilla que la
   vidriera de diferencias de la portada: son la misma clase de tarjeta
   —producto, precio y cuánto separa a las tiendas— y verse igual en los
   dos lugares es lo que hace que se entienda sin leer el título. */
.grilla-alternativas {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12.5rem, 1fr));
  gap: 0.9rem;
}

@media (max-width: 40rem) {
  .grilla-alternativas { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.6rem; }
}

/* --- Áreas de toque -------------------------------------------------

   `DOCS/100-BRANDING.md` §8 pide áreas de toque generosas en mobile, y
   el nav ya fija el número: 2.75rem (44px) de mínimo. Estos controles
   quedaban por debajo, medidos en el navegador a 390px:

     «+ Comparar» de cada tarjeta   26px de alto
     USD / UYU                      24px
     «Comparar» del buscador        35px

   El de las tarjetas es el que más importa: aparece una vez por
   producto —16 en una página de categoría— y es la acción con la que se
   arma una comparación, que es a lo que se viene al sitio.

   Solo bajo `pointer: coarse`, que es el dedo. Con un mouse la
   precisión ya alcanza y agrandar todo dejaría botones inflados sin
   motivo. */

@media (pointer: coarse) {
  /* Estos dos crecen de verdad: son botones sueltos, con lugar
     alrededor, y verse más grandes también los hace más obviamente
     tocables. */
  .boton-primario {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 2.75rem;
  }

  /* `flex` y no `inline-flex`: `.boton-secundario` es `display: block`
     con `width: 100%`, y ponerlo en línea lo achicaría al ancho de su
     texto en todos lados. `flex` centra vertical sin cambiar de nivel. */
  .boton-secundario {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 2.75rem;
  }

  /* Estos dos no: son píldoras compactas dentro de composiciones
     apretadas —una encima de la foto del producto, la otra un par de
     opciones pegadas— y agrandarlas cambiaría el diseño. Crece el área
     que recibe el toque, no la que se ve. */
  .tarjeta-comparar-boton,
  .moneda-opcion { position: relative; }

  .tarjeta-comparar-boton::after,
  .moneda-opcion::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 100%;
    height: 2.75rem;
  }
}

/* --- La salida de una búsqueda sin resultados ------------------------

   Antes la página terminaba en "todavía no tenemos ese producto": un
   aviso y nada más. Ahora abajo va la salida —quitar los filtros, o las
   categorías que sí tienen productos—, separada del aviso para que se
   lea como "y entonces qué", no como parte de la mala noticia. */
.salida-sin-resultados {
  margin-top: var(--e-6);
}

.salida-sin-resultados h2 {
  margin: 0 0 var(--e-4);
  font-size: var(--t-md);
  font-weight: 600;
  color: var(--texto-suave);
}

/* El enlace para soltar los filtros no ocupa el ancho entero como el
   resto de `.boton-secundario`: es una salida ofrecida, no la acción
   principal de la pantalla. */
.salida-sin-resultados .boton-secundario {
  display: inline-flex;
  width: auto;
}
/* --- Pasada de claridad y confianza (septiembre 2026) ----------------- */
.js .buscador-cabecera-wrap:not(.expandido) .buscador-cabecera-form {
  opacity: 0;
  pointer-events: none;
}

.js .buscador-cabecera-wrap:not(.js-listo) .buscador-cabecera-toggle {
  display: inline-flex;
}

.categoria-icono:not(:has(.categoria-accion)) {
  justify-content: center;
  min-height: 8.7rem;
}

.panel-precio-desactualizado {
  border-color: #e8c26a;
  background: linear-gradient(145deg, #fffdf7 0%, #fff8e7 100%);
}

.panel-precio-desactualizado .panel-precio-etiqueta,
.panel-precio-desactualizado .etiqueta-aviso { color: #805b08; }
.panel-precio-desactualizado .panel-precio-valor { color: #3e3523; }

.orden a,
.orden-busqueda a {
  min-height: 2.25rem;
  display: inline-flex;
  align-items: center;
  padding: .35rem .65rem;
  border-radius: 999px;
}

.orden a.actual,
.orden-busqueda a.actual { background: var(--azul-tenue); }
.orden-busqueda { flex-wrap: wrap; }

@media (min-width: 48.01rem) {
  .comparador-portada {
    min-height: 21rem;
    padding: clamp(2rem, 4vw, 3.5rem);
    gap: clamp(2rem, 4vw, 4rem);
  }
  .comparador-portada h1 { font-size: clamp(3.4rem, 6vw, 4.9rem); }
}

@media (max-width: 40rem) {
  .resultados-cabecera,
  .resultados-encabezado { align-items: stretch; }
  .orden,
  .orden-busqueda { gap: .4rem; }
  .orden-etiqueta { flex-basis: 100%; }
}

/* Cuando la categoría ya se apila, los filtros no deben ocupar una
   pantalla entera antes de mostrar el primer producto. */
@media (max-width: 48rem) {
  .sidebar-filtros:not([open]) > *:not(summary) { display: none; }
  .sidebar-filtros:not([open])::details-content {
    content-visibility: hidden;
    block-size: 0;
    overflow: hidden;
  }
  .sidebar-filtros summary { cursor: pointer; pointer-events: auto; }
  .sidebar-filtros summary::after { display: block; }
}

@media (min-width: 48.01rem) {
  .comparador-portada {
    min-height: 18rem;
    margin-bottom: var(--e-7);
    padding: clamp(1.75rem, 3vw, 2.75rem);
  }
  .comparador-portada h1 { font-size: clamp(3.2rem, 5vw, 4.35rem); }
  .comparador-portada-visual { min-height: 14rem; }
}

/* Directorios y guías: componentes compartidos de exploración. */
.directorio-cabecera { margin: 1.5rem 0 2rem; }
.directorio-etiqueta { display: block; color: var(--azul); font-size: .72rem; font-weight: 600; letter-spacing: .09em; text-transform: uppercase; margin-bottom: .75rem; }
.directorio-cabecera h1 { font-size: clamp(2.2rem, 4vw, 3.3rem); letter-spacing: -.045em; line-height: 1.15; }
.directorio-cabecera .apoyo { color: var(--texto-suave); margin: .75rem 0 0; max-width: 55ch; font-size: 1rem; }
.directorio-buscador { display: flex; align-items: center; gap: .8rem; padding: .5rem .6rem .5rem 1.1rem; background: #fff; border: 1px solid var(--borde-suave); border-radius: var(--radio); box-shadow: var(--sombra); }
.directorio-buscador svg { flex-shrink: 0; color: var(--texto-suave); }
.directorio-buscador input { width: 100%; min-width: 0; border: 0; padding: .65rem 0; font: inherit; color: var(--texto); background: transparent; }
.directorio-buscador:focus-within { outline: 2px solid var(--azul); outline-offset: 3px; }
.directorio-buscador button { border: 0; border-radius: 9px; min-height: 44px; padding: .6rem 1.2rem; background: var(--azul); color: #fff; font: inherit; font-size: .85rem; font-weight: 600; cursor: pointer; }
.directorio-buscador button:hover { background: var(--marca-inicio); }
.directorio-limpiar { display: inline-flex; align-items: center; min-height: 44px; gap: .75rem; font-size: .85rem; }
.directorio-conteo { margin: 1.75rem 0 1rem; color: var(--texto-suave); font-size: .85rem; }
.directorio-grilla { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1rem; }
.directorio-grilla-tiendas { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.directorio-tarjeta { display: flex; flex-direction: column; align-items: center; padding: 1.6rem 1.2rem 1rem; min-width: 0; text-align: center; color: var(--texto); text-decoration: none; border: 1px solid var(--borde-suave); border-radius: var(--radio); background: #fff; box-shadow: var(--sombra); transition: border-color var(--transicion), box-shadow var(--transicion); }
.directorio-tarjeta:hover { border-color: #b4c9eb; box-shadow: var(--sombra-alta); }
.directorio-logo { display: grid; place-items: center; width: 100%; height: 76px; margin-bottom: 1rem; }
.directorio-logo img.monograma-marca, .directorio-logo img.logo-tienda { width: 145px; height: 64px; max-width: 100%; max-height: 64px; object-fit: contain; border-radius: 0; }
.directorio-logo .monograma-marca-texto, .directorio-logo .logo-monograma { display: grid; place-items: center; width: 60px; height: 60px; font-size: 1.5rem; border-radius: 14px; }
.directorio-tarjeta h2 { font-size: 1rem; line-height: 1.4; overflow-wrap: anywhere; }
.directorio-cantidad { color: var(--texto-suave); font-size: .78rem; margin: .35rem 0 1.25rem; }
.directorio-accion { display: flex; width: 100%; justify-content: center; align-items: center; gap: .7rem; min-height: 44px; border-radius: 8px; background: var(--fondo-tenue); color: var(--azul); font-size: .8rem; font-weight: 600; margin-top: auto; }
.directorio-tarjeta:hover .directorio-accion { background: var(--azul-tenue); }
.directorio-vacio { grid-column: 1 / -1; padding: 3rem 1.5rem; text-align: center; background: var(--fondo-tenue); border-radius: var(--radio); }
.directorio-vacio h2 { font-size: 1.3rem; }
.directorio-vacio p { margin: .75rem 0 1.5rem; color: var(--texto-suave); }
.directorio-banner { display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; padding: 1.75rem 2rem; margin-top: 2.5rem; border: 1px solid var(--borde-suave); border-radius: var(--radio); background: var(--fondo-tenue); }
.directorio-banner h2 { font-size: 1.15rem; }
.directorio-banner p { font-size: .88rem; color: var(--texto-suave); margin: .5rem 0 0; }
.directorio-banner a { display: inline-flex; align-items: center; min-height: 44px; gap: .75rem; flex-shrink: 0; font-size: .85rem; font-weight: 600; text-decoration: none; }
.guias-grilla { display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: 1rem; }
.guia-tarjeta { position: relative; display: flex; flex-direction: column; padding: 2rem; min-width: 0; color: var(--texto); background: #f4f6fa; border: 1px solid var(--borde-suave); border-radius: 18px; text-decoration: none; transition: box-shadow var(--transicion); }
.guia-tarjeta:hover { box-shadow: var(--sombra-alta); }
.guia-numero { display: block; font-size: 3rem; line-height: 1; font-weight: 600; letter-spacing: -.08em; color: #5b6c86; margin-bottom: 2rem; }
.guia-tarjeta h3 { font-size: clamp(1.2rem, 2vw, 1.65rem); line-height: 1.25; letter-spacing: -.035em; }
.guia-tarjeta p { font-size: .87rem; line-height: 1.65; color: var(--texto-suave); margin: 1rem 0 1.75rem; }
.guia-enlace { display: flex; align-items: center; justify-content: space-between; gap: .75rem; min-height: 44px; margin-top: auto; font-size: .8rem; font-weight: 600; color: var(--azul); }
.guia-principal { background: #213756; border-color: #213756; color: #fff; }
.guia-principal .guia-numero { color: #7c8899; }
.guia-principal .directorio-etiqueta, .guia-principal .guia-enlace { color: #cbdcf4; }
.guia-principal p { color: #dce3ee; }
.guias-lectura { max-width: 760px; margin: 3.5rem auto 0; }
.guia-articulo { padding: 2rem 0 2.5rem; border-top: 1px solid var(--borde-suave); scroll-margin-top: 7rem; }
.guia-articulo h2 { font-size: clamp(1.5rem, 3vw, 2rem); line-height: 1.25; letter-spacing: -.03em; }
.guia-articulo p, .guia-articulo li { line-height: 1.8; color: var(--texto-suave); }
.guia-articulo p { margin: 1.2rem 0; }
.guia-articulo ol, .guia-articulo ul { padding-left: 1.35rem; margin: 1.5rem 0; }
.guia-articulo li { margin-bottom: 1rem; padding-left: .4rem; }
.guia-articulo strong { color: var(--texto); font-weight: 600; }
.error-codigo { display: block; color: var(--azul); font-size: 5rem; font-weight: 650; letter-spacing: -.07em; line-height: 1; margin-bottom: 1.5rem; }
.nav-cabecera a[aria-current="page"] { color: var(--azul); }
@media (max-width: 64rem) {
  .directorio-grilla { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .guias-grilla { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .guia-principal { grid-column: 1 / -1; }
}
@media (max-width: 40rem) {
  .directorio-grilla { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .7rem; }
  .directorio-tarjeta { padding: 1.2rem .75rem .75rem; }
  .directorio-logo { height: 60px; }
  .directorio-logo img.monograma-marca, .directorio-logo img.logo-tienda { width: 110px; height: 52px; }
  .directorio-tarjeta h2 { font-size: .88rem; }
  .directorio-cabecera { margin-bottom: 1.5rem; }
  .directorio-banner { align-items: start; flex-direction: column; padding: 1.5rem; gap: .75rem; }
  .guias-grilla { grid-template-columns: minmax(0, 1fr); }
  .guia-tarjeta { padding: 1.5rem; }
  .guia-numero { margin-bottom: 1.25rem; font-size: 2.5rem; }
  .guia-tarjeta h3 { font-size: 1.5rem; }
  .guias-lectura { margin-top: 2rem; }
}

/* Se muestra como parte del CTA de la navegación en la Home editorial. */
.nav-cta-flecha { display: none; }

/* Ordenar, en un teléfono: una sola fila que se desliza en vez de tres
   renglones de opciones que empujaban los resultados hacia abajo (búsqueda
   «redmi note 15», 375 px, 2026-10-02). Es la misma lista de enlaces; solo
   cambia cómo se acomoda. */
@media (max-width: 40rem) {
  .orden-busqueda,
  .orden {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .orden-busqueda::-webkit-scrollbar,
  .orden::-webkit-scrollbar { display: none; }
  .orden-busqueda > *,
  .orden > * { flex: none; white-space: nowrap; }
  /* Sin esto la fila que no se parte le imponía su ancho (745 px) a la
     columna de la grilla, y las tarjetas se salían de la pantalla. */
  .resultados,
  .resultados-categoria,
  .orden-busqueda,
  .orden { min-width: 0; }
  /* Cerrado, el contenido oculto del acordeón igual cuenta como hijo del
     flex y sumaba la separación (24 px de hueco bajo el título). */
  .sidebar-filtros:not([open]) { gap: 0; }
}

/* Migas en un teléfono: un solo renglón. El último tramo repite el nombre
   que el título ya dice, así que si no entra se corta con «…» en vez de
   ocupar un segundo renglón arriba de todo. */
@media (max-width: 40rem) {
  .miga {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-bottom: var(--e-2);
  }
}

/* Blancos de toque en un teléfono (medidos a 375 px, 2026-10-02): el
   selector USD/UYU de la cabecera medía 40×22 px y es de lo que más se
   toca; los enlaces del pie, 22 px; las migas, 18. Se agranda el área
   tocable con relleno, sin cambiar cómo se ven. */
@media (max-width: 40rem) {
  .moneda-opcion { min-height: 2rem; min-width: 2.75rem; }
  .nav-pie a { display: inline-flex; align-items: center; min-height: 2.75rem; }
  .miga a { display: inline-block; padding-block: .45rem; }
  .enlace-flecha { display: inline-flex; align-items: center; min-height: 2.75rem; }
  /* «Comparaciones frecuentes: A · B · C»: enlaces dentro de un párrafo,
     18 px de alto cada uno. Más interlineado y relleno vertical. */
  .comparar-rapido-frecuentes { line-height: 2.4; }
  .comparar-rapido-frecuentes a { padding-block: .5rem; }
}
