/* ============================================================
   components.css — componentes de Cotejo
   ============================================================ */

/* ---------- Etiquetas reutilizables ---------- */
.eyebrow {
  font-family: var(--ff-display);
  font-size: var(--fs--1);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-muted);
}

/* ---------- Aviso de modo demo ----------
   Tiene que ser imposible de ignorar: si no, se confunden datos de ejemplo
   con resultados reales. Pasó en la primera revisión. */
.demo-banner {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--accent-solid);
  color: var(--accent-ink);
  font-size: var(--fs--1);
  font-weight: 500;
  text-align: center;
  justify-content: center;
}
.demo-banner strong {
  font-family: var(--ff-display);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.demo-banner a {
  color: inherit;
  font-weight: 600;
  text-underline-offset: 3px;
}

/* ---------- Cabecera ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  /* Antes: color-mix(var(--bg) 88%, transparent) + blur -- semitransparente
     TODO el tiempo, no solo mientras hace scroll. En reposo (arriba de la
     pagina) eso pintaba con --bg (el tono MAS OSCURO del tema), mientras el
     resto de la pagina (body, el arranque del degradado del hero) usa
     --bg-elev (mas claro) -- el header se veia como un parche de otro
     color desde que cargaba, no solo al hacer scroll. Solido con
     --bg-elev siempre evita el mismatch en las dos situaciones. */
  background: var(--bg-elev);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease);
}
.site-header[data-stuck='true'] {
  border-bottom-color: var(--line);
}
/* El header es sticky y tapa el borde superior de la ventana en todo
   momento -- scrollIntoView({block:'start'}) no lo sabe, y alineaba el
   inicio de estas secciones justo detras de el (la pantalla de carga en
   #results quedaba parcialmente escondida, reportado 2026-08-26).
   --header-h la sincroniza app.js con la altura real del header (cambia
   por breakpoint/wrap). */
[data-hero], #results, .detail {
  scroll-margin-top: var(--header-h, 80px);
}
/* .site-header ya no lleva el padding-inline/centrado -- eso vive aqui.
   Antes .site-header ERA el contenido directo de un .wrap de PAGINA
   COMPLETA (header+main+footer juntos), asi que su fondo (background:
   var(--bg-elev), sticky) quedaba encajonado en esos 1180px con el fondo
   de la pagina asomando a los lados en cualquier pantalla mas ancha --
   no se veia como una barra fija de verdad. Reportado por el usuario
   2026-08-25. Ahora .site-header es full-bleed y .site-header__in centra
   el contenido adentro. NO reutiliza .wrap (max-width 1180px) a
   proposito: con el logo agrandado (2026-08-25) el header a 1180px de
   ancho de contenido no alcanzaba para logo+nav+boton en una sola fila,
   ni siquiera en monitores anchos (1180 es un ancho de CONTENIDO, no de
   pantalla -- ensanchar la ventana no ayudaba, medido en vivo). El
   header puede permitirse ser mas ancho que la columna de lectura del
   resto del sitio, es un patron normal. */
.site-header__in {
  display: flex;
  /* nowrap: el logo y las acciones (Iniciar sesión / Nueva búsqueda /
     tema) SIEMPRE van juntos en una fila -- nunca caen debajo del título.
     Si la .nav del medio no cabe, se recorta por la derecha (a <1360px ya
     está oculta y se usa el menú hamburguesa). */
  flex-wrap: nowrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3) var(--sp-4);
  padding-block: var(--sp-4);
  /* 1440px cabia sin encimar, pero dejaba tanto espacio entre logo y
     nav/boton que se veian "empujados a las esquinas" en monitores
     anchos -- reportado por el usuario 2026-08-26. 1300px es el minimo
     que sigue sin encimar (medido en vivo) y deja el contenido mas
     junto, no pegado a los bordes. */
  width: 100%;
  /* 1300 fue el minimo sin encimar cuando las acciones eran logo+nav+boton.
     Con "Iniciar sesion" (Clerk) sumado, a 1300 el header ya no cabia en
     una fila y las acciones se iban debajo del logo (reportado). 1360 deja
     margen para las 3 piezas + el boton de sesion, sin encimar. */
  max-width: 1360px;
  margin-inline: auto;
  padding-inline: var(--sp-5);
}
@media (min-width: 768px) { .site-header__in { padding-inline: var(--sp-6); } }

.theme-toggle {
  display: grid;
  place-items: center;
  width: 38px; height: 38px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  color: var(--fg-muted);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.theme-toggle:hover { color: var(--fg); border-color: var(--line-strong); }
.theme-toggle svg { width: 18px; height: 18px; }
:root[data-theme='light'] .theme-toggle .i-sun,
:root:not([data-theme='dark']) .theme-toggle .i-sun { display: none; }
:root[data-theme='dark'] .theme-toggle .i-moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .theme-toggle .i-sun { display: block; }
  :root:not([data-theme]) .theme-toggle .i-moon { display: none; }
}

/* ---------- Hero y buscador ----------
   Viven en base.css desde la portacion del mockup (hero expandido con
   kicker, chips y trust badges). Las reglas viejas de .hero / .searchbar
   se quitaron de aqui: este archivo carga DESPUES de base.css, asi que
   .hero y .hero h1 le ganaban por orden a la version nueva. .searchbar
   y .sub quedaron sin markup que las use. */

/* ---------- Chips ---------- */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  list-style: none;
  padding: 0;
  margin-top: var(--sp-4);
}
.chip {
  font-family: var(--ff-display);
  font-size: var(--fs--1);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  color: var(--fg-muted);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.chip:hover { color: var(--accent); border-color: var(--accent-solid); }

/* ---------- Franja de contexto ---------- */
.context {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  padding-block: var(--sp-5) var(--sp-4);
}
.context h2 {
  font-size: var(--fs-0);
  font-weight: 500;
  color: var(--fg-muted);
}
.context h2 strong { color: var(--fg); font-weight: 600; }

.source {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--ff-display);
  font-size: var(--fs--1);
  padding: var(--sp-1) var(--sp-3);
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  color: var(--fg-muted);
}
.source::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.source[data-kind='cache']   { color: var(--ok); }
.source[data-kind='live']    { color: var(--accent); }
.source[data-kind='catalog'] { color: var(--fg-muted); }

/* ---------- Acuse de requisitos ----------
   Portado de maqueta/mockup.css. Va en su propia linea dentro de .context,
   que es un flex row: sin flex-basis se metaria junto al conteo. */
.requisitos {
  flex-basis: 100%;
  background: var(--accent-wash);
  border-radius: var(--r-md);
  padding: var(--sp-4) var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.requisitos__tit {
  font-size: .74rem;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
}
.requisitos__lista {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  list-style: none;
  padding: 0;
  margin: 0;
}
.req {
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  padding: var(--sp-2) var(--sp-4);
  font-size: .88rem;
  font-weight: 600;
}
.req strong { font-variant-numeric: tabular-nums; }
.requisitos__nota { font-size: .84rem; color: var(--fg-muted); }

/* ---------- Cumple / no cumple / sin dato ----------
   Los tres estados son distintos a proposito: "sin dato" no es "no
   cumple". Casi siempre la tienda no publica el spec, y afirmar que no
   cumple seria falso. */
.cumples {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
/* Declarar `display` en un elemento que tambien usa [hidden] obliga a
   apagarlo explicitamente: si no, la mayoria de las busquedas (las que no
   traen requisito numerico) dejarian un item de flex vacio sumando un gap
   de mas dentro de .meta. */
.cumples[hidden],
.requisitos[hidden] { display: none; }
.cumple {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: .78rem;
  font-weight: 700;
  padding: 2px var(--sp-3);
  border-radius: var(--r-pill);
  border: 1px solid currentColor;
}
.cumple::before { font-weight: 800; }
.cumple--si  { color: var(--ok); }
.cumple--si::before  { content: '\2713'; }
.cumple--no  { color: var(--bad); }
.cumple--no::before  { content: '\2715'; }
.cumple--nd  { color: var(--fg-faint); }
.cumple--nd::before  { content: '\2014'; }

/* ---------- Veredicto ---------- */
.verdict {
  position: relative;
  padding: var(--sp-5) var(--sp-5) var(--sp-5) var(--sp-6);
  background: var(--bg-elev);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-1);
  overflow: hidden;
}
.verdict::before {
  content: '';
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 4px;
  background: var(--verdict-accent-solid);
}
.verdict .eyebrow { color: var(--verdict-accent); margin-bottom: var(--sp-3); }
.verdict p {
  font-family: var(--ff-verdict);
  font-size: clamp(1.15rem, 2.6vw, 1.5rem);
  line-height: 1.45;
  letter-spacing: -0.01em;
  max-width: var(--measure);
}

/* Veredicto reusado en la pagina de coleccion: mismo componente, con
   margen propio y el titulo (h1 ya vive en .acuse) como eyebrow. */
.coleccion__verdict { margin: var(--sp-6) 0; }
.coleccion__verdict .verdict__body {
  font-family: var(--ff-verdict);
  font-size: clamp(1.15rem, 2.6vw, 1.5rem);
  line-height: 1.5;
  letter-spacing: -0.01em;
  max-width: var(--measure);
}
.coleccion__verdict .verdict__body p { margin: 0 0 var(--sp-3); }
.coleccion__verdict .verdict__body p:last-child { margin-bottom: 0; }
.coleccion__verdict .verdict__body ul,
.coleccion__verdict .verdict__body ol { margin: var(--sp-3) 0; padding-left: 1.3em; }
.coleccion__verdict .verdict__body li { margin-bottom: var(--sp-2); }

.coleccion__curada {
  font-family: var(--ff-display); font-size: .82rem; color: var(--fg-faint);
  display: flex; align-items: center; gap: 6px;
}
.coleccion__curada::before { content: '\2726'; color: var(--verdict-accent); }

.info-zoom { border: 0; padding: 0; background: transparent; max-width: 92vw; max-height: 92vh; }
.info-zoom::backdrop { background: rgba(4, 12, 15, .86); }
.info-zoom img { display: block; max-width: 92vw; max-height: 92vh; border-radius: var(--r-lg); }

/* ---------- Tarjeta de producto ---------- */
.pcard {
  position: relative;
  display: grid;
  gap: var(--sp-4);
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--sp-4);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.pcard:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-2);
  border-color: var(--line-strong);
}
.pcard:has(a:focus-visible) { border-color: var(--accent-solid); }

/* El enlace del título cubre la tarjeta, sin perder semántica ni teclado */
.pcard .title a::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
}
.pcard .title a { text-decoration: none; }
.pcard .title a:hover { text-decoration: underline; text-underline-offset: 3px; }

.pcard .thumb {
  width: 100%;
  aspect-ratio: 1;
  object-fit: contain;
  background: var(--bg-sunken);
  border-radius: var(--r-md);
  padding: var(--sp-2);
}
.pcard .title {
  font-size: var(--fs-0);
  font-weight: 500;
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.pcard .meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  font-size: var(--fs--1);
  color: var(--fg-muted);
}
.pcard .why {
  font-size: var(--fs--1);
  line-height: 1.5;
  color: var(--fg-muted);
  border-left: 2px solid var(--accent-wash);
  padding-left: var(--sp-3);
}
.pcard .price {
  font-family: var(--ff-mono);
  font-size: var(--fs-1);
  font-weight: 500;
  white-space: nowrap;
}
.pcard .price s {
  display: block;
  font-size: var(--fs--1);
  color: var(--fg-muted);
  font-weight: 400;
}

/* OJO: .rank/.pcard NO se usan en ningun HTML real de este proyecto --
   el medallon de posicion real es .rango/.rango--1 en base.css, sobre
   .ganador/.tarjeta. Este bloque vivio aqui muerto un rato (edit que no
   aplicaba a nada, encontrado y corregido 2026-08-21) -- si vuelves a
   ver ".rank" en un diff, es sospechoso, no lo repitas. */

/* ---------- La ganadora ---------- */
.winner {
  border-color: color-mix(in srgb, var(--accent-solid) 45%, var(--line));
  box-shadow: var(--shadow-1), 0 0 0 1px var(--accent-wash);
  padding: var(--sp-5);
}
.winner .thumb { max-width: 260px; }
.winner .title { font-size: var(--fs-2); font-family: var(--ff-display); -webkit-line-clamp: 3; line-clamp: 3; }
.winner .price { font-size: var(--fs-3); }
.winner .why {
  font-size: var(--fs-0);
  color: var(--fg);
  border-left-color: var(--accent-solid);
}
@media (min-width: 768px) {
  .winner { grid-template-columns: 260px 1fr; align-items: start; }
  .winner .body { display: grid; gap: var(--sp-4); }
}

/* ---------- Rejilla de alternativas ---------- */
.alts {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: 1fr;
  list-style: none;
  padding: 0;
}
@media (min-width: 560px) { .alts { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .alts { grid-template-columns: repeat(4, 1fr); } }

/* ---------- Insignia de tienda ---------- */
.badge {
  font-family: var(--ff-display);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 500;
  padding: 3px var(--sp-2);
  border-radius: var(--r-sm);
  white-space: nowrap;
}
.badge[data-store='mercadolibre'] { background: var(--store-ml-badge-bg); color: var(--store-ml-badge-fg); }
.badge[data-store='amazon']       { background: var(--store-az-badge-bg); color: var(--store-az-badge-fg); }

/* ---------- Calificación ---------- */
.rating { display: inline-flex; align-items: center; gap: var(--sp-1); white-space: nowrap; }
.rating .star { color: var(--accent); }
.rating .out-of-range {
  color: var(--bad);
  cursor: help;
  border-bottom: 1px dotted currentColor;
}

/* ---------- Tabla comparativa ---------- */
.compare-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--bg-elev);
  -webkit-overflow-scrolling: touch;
}
table.compare {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs--1);
  min-width: 640px;
}
table.compare th,
table.compare td {
  padding: var(--sp-3);
  text-align: left;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}
table.compare thead th {
  font-family: var(--ff-display);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--fg-muted);
  background: var(--bg-sunken);
  font-weight: 500;
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 2;
}
table.compare tbody tr:last-child th,
table.compare tbody tr:last-child td { border-bottom: none; }
table.compare tbody tr:hover td,
table.compare tbody tr:hover th { background: color-mix(in srgb, var(--accent-solid) 5%, transparent); }

/* Primera columna fija: el producto, para no perder de vista qué se compara */
table.compare th[scope='row'] {
  position: sticky;
  inset-inline-start: 0;
  z-index: 1;
  background: var(--bg-elev);
  min-width: 220px;
  max-width: 280px;
  font-weight: 500;
  border-inline-end: 1px solid var(--line);
}
table.compare tbody tr:hover th[scope='row'] {
  background: color-mix(in srgb, var(--accent-solid) 5%, var(--bg-elev));
}
table.compare th[scope='row'] .cell-product {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
table.compare th[scope='row'] img {
  width: 36px; height: 36px;
  object-fit: contain;
  border-radius: var(--r-sm);
  background: var(--bg-sunken);
  flex-shrink: 0;
}
table.compare th[scope='row'] span {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.3;
}
table.compare td.num { font-family: var(--ff-mono); white-space: nowrap; }
table.compare td.best {
  color: var(--accent);
  font-weight: 600;
}
table.compare td.best::after {
  content: ' ●';
  font-size: 0.6em;
  vertical-align: middle;
}

/* ---------- Esqueletos ---------- */
@keyframes shimmer { to { background-position-x: -200%; } }
.sk {
  border-radius: var(--r-sm);
  background: linear-gradient(90deg,
    var(--bg-sunken) 0%,
    color-mix(in srgb, var(--bg-sunken) 60%, var(--fg-faint)) 50%,
    var(--bg-sunken) 100%);
  background-size: 200% 100%;
  animation: shimmer 1.4s linear infinite;
}
.sk-thumb { width: 100%; aspect-ratio: 1; border-radius: var(--r-md); }
.sk-line { height: 0.75rem; }
.sk-line.short { width: 45%; }
.sk-line.mid { width: 70%; }

/* ---------- Progreso de búsqueda ---------- */
.loader {
  position: relative;
  padding: var(--sp-6) var(--sp-5) var(--sp-5);
  border: 1.5px solid var(--line);
  border-radius: var(--r-xl);
  background: var(--bg-elev);
  overflow: hidden;
  transition: border-color .4s ease, box-shadow .4s ease;
}
.loader.is-complete {
  animation: loader-pop .55s cubic-bezier(.34,1.56,.64,1);
  border-color: var(--accent);
  box-shadow: 0 20px 60px rgba(184,86,9,.18), 0 0 0 3px var(--accent-wash);
}
@keyframes loader-pop {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.02); }
  100% { transform: scale(1); }
}

.loader__confetti { position: absolute; inset: 0; pointer-events: none; }
.loader__confetti span {
  position: absolute; top: 50%; left: 50%;
  width: 7px; height: 7px; border-radius: 2px;
  background: var(--accent);
  opacity: 0;
  transform: translate(-50%, -50%);
}
.loader.is-complete .loader__confetti span {
  /* 1.6s (antes .9s "se sentia un parpadeo"): sube, se queda visible, y
     recien al final cae y se desvanece. */
  animation: loader-confetti 1.6s cubic-bezier(.15,.75,.3,1) forwards;
  animation-delay: var(--d, 0s);
}
@keyframes loader-confetti {
  0%   { opacity: 0; transform: translate(-50%, -50%) rotate(0deg); }
  12%  { opacity: 1; }
  55%  { opacity: 1; transform: translate(calc(-50% + var(--x, 0px) * .8), calc(-50% + var(--y, -60px) * .8)) rotate(calc(var(--r, 90deg) * .6)); }
  100% { opacity: 0; transform: translate(calc(-50% + var(--x, 0px)), calc(-50% + var(--y, -60px) + 26px)) rotate(var(--r, 90deg)); }
}

/* ---------- stepper: 4 nodos conectados ---------- */
.loader__stepper {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  align-items: start;
  margin-bottom: var(--sp-5);
  position: relative;
}
.loader__stepper::before {
  content: "";
  position: absolute;
  top: 1.65rem;
  left: 12.5%;
  right: 12.5%;
  height: 2px;
  background: var(--line);
}
.loader__track {
  position: absolute;
  top: 1.65rem;
  left: 12.5%;
  height: 2px;
  background: var(--accent);
  width: 0%;
  transition: width .6s cubic-bezier(.4,0,.2,1);
}
.loader__step {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
}
.loader__node {
  width: 3.3rem; height: 3.3rem;
  border-radius: 50%;
  background: var(--bg);
  border: 2px solid var(--line);
  display: grid; place-items: center;
  color: var(--fg-faint);
  transition: border-color .4s ease, color .4s ease, background .4s ease;
}
.loader__node svg { width: 1.5rem; height: 1.5rem; }
.loader__label {
  font-family: var(--ff-display); font-size: .66rem; font-weight: 600;
  color: var(--fg-faint); text-align: center; line-height: 1.25;
  max-width: 6rem;
  transition: color .4s ease;
}
.loader__step.is-done .loader__node { border-color: var(--accent); background: var(--accent); color: var(--accent-ink); }
.loader__step.is-active .loader__node {
  border-color: var(--accent); color: var(--accent); background: var(--accent-wash);
  animation: loader-pulse 1.6s ease-in-out infinite;
}
.loader__step.is-active .loader__label, .loader__step.is-done .loader__label { color: var(--fg); }
.loader__step[data-loader-step='1'].is-active .loader__node { color: var(--store-az); border-color: var(--store-az); }
.loader__step[data-loader-step='1'].is-done .loader__node {
  background: linear-gradient(90deg, var(--store-ml) 50%, var(--store-az) 50%); border-color: transparent; color: var(--accent-ink);
}
@keyframes loader-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--accent-wash); }
  50% { box-shadow: 0 0 0 8px transparent; }
}

/* ---------- barra + porcentaje ---------- */
.loader__meter { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.loader__meter-track { flex: 1; height: 8px; border-radius: var(--r-pill); background: var(--line); overflow: hidden; }
.loader__meter-fill {
  height: 100%; width: 0%;
  background: linear-gradient(90deg, var(--store-ml), var(--accent) 60%, var(--store-az));
  border-radius: var(--r-pill);
  transition: width .6s cubic-bezier(.4,0,.2,1);
}
.loader__pct {
  font-family: var(--ff-mono); font-variant-numeric: tabular-nums;
  font-size: .85rem; font-weight: 700; color: var(--accent);
  min-width: 3ch; text-align: right;
}

.loader__phaserow { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3); }
.loader__phase { font-family: var(--ff-display); font-weight: 600; font-size: .95rem; color: var(--fg); }
.loader__elapsed { font-family: var(--ff-mono); font-variant-numeric: tabular-nums; font-size: .8rem; color: var(--fg-muted); white-space: nowrap; }

.loader__note {
  font-size: var(--fs--1); color: var(--fg-muted); text-align: center;
  margin: var(--sp-4) 0 0; opacity: 0; transition: opacity .5s ease; line-height: 1.5;
}
.loader__note.is-shown { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .loader.is-complete { animation: none; }
  .loader.is-complete .loader__confetti span { animation: none; }
  .loader__step.is-active .loader__node { animation: none; }
  .loader__track, .loader__meter-fill { transition: none; }
}

/* ---------- Estados (error / vacío) ---------- */
.state {
  display: grid;
  gap: var(--sp-4);
  justify-items: start;
  padding: var(--sp-6);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--bg-elev);
}
.state h3 { font-family: var(--ff-display); font-size: var(--fs-2); }
.state p { color: var(--fg-muted); max-width: var(--measure); }
.state[data-tone='error'] { border-inline-start: 3px solid var(--bad); }

/* ---------- Chips de intención (búsqueda ambigua y corta) ----------
   Misma caja que .state (mismo peso visual: reemplaza los resultados
   mientras el usuario elige), con sus propios chips + "Otro" + skip. */
.intent {
  display: grid;
  gap: var(--sp-4);
  justify-items: start;
  padding: var(--sp-6);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--bg-elev);
}
.intent h3 { font-family: var(--ff-display); font-size: var(--fs-2); margin: 0; }
.intent__hint { color: var(--fg-muted); margin: 0; max-width: var(--measure); }
.intent__chips { margin-top: 0; }
.intent__chips .chip { cursor: pointer; background: var(--bg-elev); }
.intent__otro {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  width: 100%;
  max-width: 26rem;
}
.intent__otro input {
  flex: 1 1 12rem;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--fg);
  font-family: var(--ff-sans);
  font-size: var(--fs--1);
}
.intent__otro input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.intent__skip {
  font-family: var(--ff-display);
  font-size: var(--fs--1);
  color: var(--fg-muted);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.intent__skip:hover { color: var(--accent); }

/* ---------- Panel de filtros (Fase 2, calidad de busqueda) ----------
   <details> nativo -- abre/cierra sin JS, mismo criterio de bajo costo
   que ya usan las FAQ del home. */
.filtros {
  margin-block: var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--bg-elev);
  padding: var(--sp-4) var(--sp-5);
}
.filtros summary {
  cursor: pointer;
  font-family: var(--ff-display);
  font-weight: 600;
  font-size: var(--fs--1);
  list-style: none;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
.filtros summary::-webkit-details-marker { display: none; }
.filtros summary::after {
  content: "▸";
  font-size: .75em;
  transition: transform .15s var(--ease);
}
.filtros[open] summary::after { transform: rotate(90deg); }
.filtros__form { margin-top: var(--sp-4); display: grid; gap: var(--sp-4); }
.filtros__row { display: flex; flex-wrap: wrap; gap: var(--sp-4); }
.filtros__row--check { gap: var(--sp-5); }
.filtros__campo {
  display: grid;
  gap: var(--sp-1);
  font-size: var(--fs--1);
  color: var(--fg-muted);
  flex: 1 1 9rem;
}
.filtros__campo input, .filtros__campo select {
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--fg);
  font-family: var(--ff-sans);
  font-size: var(--fs--1);
}
.filtros__campo input:focus-visible, .filtros__campo select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.filtros__check {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs--1);
  color: var(--fg);
  cursor: pointer;
}
.filtros__actions { display: flex; gap: var(--sp-3); flex-wrap: wrap; }

/* Botón de rescate "ver todo en Amazon, ya filtrado" -- discreto, no
   compite con la tarjeta ganadora ni con "ver mas". */
.rescate {
  text-align: center;
  margin-block: var(--sp-6) 0;
}
.rescate a {
  color: var(--fg-muted);
  font-family: var(--ff-display);
  font-size: var(--fs--1);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.rescate a:hover { color: var(--accent); }

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-5);
  border-radius: var(--r-pill);
  font-weight: 600;
  font-size: var(--fs--1);
  border: 1px solid var(--line-strong);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.btn:hover { border-color: var(--accent-solid); color: var(--accent); }
/* "Ver más" (y cualquier boton que se deshabilite mientras carga) solo
   cambiaba el texto -- mismo color/cursor que uno clickeable normal, se
   sentia como si no hubiera pasado nada. Reportado por el usuario
   2026-08-25. */
.btn:disabled { opacity: 0.55; cursor: wait; }
.btn:disabled:hover { border-color: var(--line-strong); color: inherit; }
.btn-primary {
  background: var(--accent-solid);
  color: var(--accent-ink);
  border-color: var(--accent-solid);
}
.btn-primary:hover { filter: brightness(1.08); color: var(--accent-ink); }
.btn-buy {
  justify-content: center;
  width: 100%;
  padding-block: var(--sp-4);
  font-size: var(--fs-0);
  text-decoration: none;
}

/* ---------- Detalle ---------- */
.detail { padding-block: var(--sp-5); }
.detail .back {
  font-family: var(--ff-display);
  font-size: var(--fs--1);
  color: var(--fg-muted);
  margin-bottom: var(--sp-5);
  display: inline-flex;
  gap: var(--sp-2);
}
.detail .back:hover { color: var(--accent); }

/* Detalle = MISMO diseño que la tarjeta ganadora (2026-09). .detail-card
   solo agrega la capa fina sobre .ganador (base.css): mismos 2 columnas,
   misma foto (más grande aquí), mismos componentes. Ver template
   data-tpl="detail" y renderDetail() -> fillCard() en render.js. */
@media (min-width: 820px) {
  .detail-card { grid-template-columns: 380px 1fr; }
}
.detail-card .ganador__foto img { max-height: 440px; }
/* Zoom "lupa": la imagen crece y sigue al cursor DENTRO de su marco. El
   contenedor la recorta; transform-origin lo mueve render.js con el
   mouse. Solo en dispositivos con hover real. */
.detail-card .ganador__foto.zoom-box { overflow: hidden; cursor: zoom-in; }
.detail-card .ganador__foto.zoom-box img { transition: transform .18s var(--ease); }
.detail-card .ganador__foto.zoom-box.is-zooming img { transform: scale(2.2); }
@media (prefers-reduced-motion: reduce) {
  .detail-card .ganador__foto.zoom-box.is-zooming img { transition: none; }
}

.detail-card .detail-specs { margin-top: var(--sp-4); }
.detail-card .detail-specs .eyebrow { margin-bottom: var(--sp-2); display: block; }
.detail-card .detail-specs .specs { border-top: none; }
.detail-card .detail-reviews .eyebrow { margin-bottom: var(--sp-2); display: block; }
.detail-card .detail-reviews .reviews-citas { margin-top: var(--sp-2); }

/* Galeria de miniaturas (2026-08-27): la tienda ya trae hasta 6 fotos por
   producto, se pagan y se tiraban -- solo se pintaba la primera. Clic en
   una miniatura cambia data-img, no navega a ningun lado. */
.detail-gallery {
  display: flex;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
  flex-wrap: wrap;
}
.detail-gallery__thumb {
  width: 56px;
  height: 56px;
  border-radius: var(--r-sm);
  border: 1.5px solid var(--line);
  background: var(--bg-sunken);
  padding: 2px;
  overflow: hidden;
  flex: none;
  cursor: pointer;
  transition: border-color var(--dur) var(--ease);
}
.detail-gallery__thumb:hover { border-color: var(--line-strong); }
.detail-gallery__thumb[aria-current='true'] { border-color: var(--accent); }
.detail-gallery__thumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
/* Chips de variantes (2026-08-27): informativo -- "tambien existe en estos
   colores", no son botones de compra (no tenemos esas variantes como
   productos propios en catalogo, seria prometer algo que no se puede
   cumplir con un clic). */
.detail-variantes {
  font-size: var(--fs--1);
  color: var(--fg-muted);
}
.detail-variantes__label { font-weight: 600; margin-right: var(--sp-2); }
.detail-variantes__chip {
  display: inline-block;
  background: var(--bg-sunken);
  border-radius: var(--r-sm);
  padding: 2px var(--sp-2);
  margin: 2px 4px 2px 0;
}
/* Pros/contras tintados (2026-08-25, "un claro distintivo para que el
   usuario los vea mas rapido") -- ahora en .prosycontras, el componente
   compartido entre la tarjeta ganadora y el detalle (2026-09), asi los
   dos se ven igual. color-mix() en vez de rgba fijo para seguir el tema. */
.prosycontras > div {
  padding: var(--sp-4);
  border-radius: var(--r-md);
  border: 1px solid transparent;
}
.prosycontras > div:first-child {
  background: color-mix(in srgb, var(--ok) 8%, transparent);
  border-color: color-mix(in srgb, var(--ok) 25%, transparent);
}
.prosycontras > div:last-child {
  background: color-mix(in srgb, var(--bad) 8%, transparent);
  border-color: color-mix(in srgb, var(--bad) 25%, transparent);
}

/* ---------- Destacados / recientes ---------- */
.tiles {
  display: grid;
  gap: var(--sp-3);
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  list-style: none;
  padding: 0;
}

/* ---------- Disclosure y pie ---------- */
.site-footer {
  padding-block: var(--sp-6) var(--sp-7);
  color: var(--fg-muted);
  font-size: var(--fs--1);
}

/* ---------- Secciones ---------- */
.section { padding-block: var(--sp-5); }
.section > .eyebrow { margin-bottom: var(--sp-4); }

/* ============================================================
   COLECCIONES CURADAS (Fase C) — sección propia.
   colecciones.html (índice) y coleccion.html (detalle), ver
   assets/js/colecciones.js, assets/js/coleccion.js, render.js.
   Reusan clases ya existentes en este archivo/base.css para las
   tarjetas y la rejilla (.fcard/.pgrid, .alternativas/.tarjeta,
   .acuse, .state) -- lo único que faltaba es esto: .sec__head (en
   base.css) solo pone tamaño de título a un h2, pensado para
   secciones dentro de index.html que nunca traen su propio h1 de
   página. Aquí el h1 SÍ es el título real de la página.
   ============================================================ */
.sec__head h1 { font-size: clamp(1.8rem, 3.6vw, 2.6rem); margin-block: var(--sp-3); }

/* Infografía a lo ancho, arriba (junto con nombre + reseña, antes de los
   productos -- coleccion.html). Es solo una imagen -- se ve igual en claro
   y oscuro. No debe desbordar horizontalmente: max-width 100%. */
.coleccion__info { margin: var(--sp-5) 0 var(--sp-7); }
.coleccion__info img {
  display: block;
  width: 100%;
  max-width: 100%;
  height: auto;
  border-radius: var(--r-md);
  cursor: zoom-in;
}
.coleccion__info figcaption {
  margin-top: var(--sp-2); font-size: .8rem; color: var(--fg-faint);
  font-family: var(--ff-display);
}

/* Reseña del dueño (coleccion.html, .acuse [data-desc]) -- HTML simple
   (negritas/bullets) escrito en el editor del panel, ver
   collection_pipeline._sanitize_rich_text. */
.coleccion__resena p { margin: 0 0 var(--sp-3); }
.coleccion__resena p:last-child { margin-bottom: 0; }
.coleccion__resena ul, .coleccion__resena ol { margin: var(--sp-2) 0; padding-left: 1.4em; }
.coleccion__resena li { margin-bottom: var(--sp-1); }
.coleccion__resena b, .coleccion__resena strong { color: var(--fg); }

/* ---------- Sesión (Clerk) + picker de intereses ---------- */
/* El bloque de acciones (auth + "Nueva busqueda" + toggle) va anclado a
   la derecha por el space-between del padre: cuando Clerk carga async y
   llena [data-auth-area], el grupo crece hacia la IZQUIERDA, no empuja a
   sus hermanos. justify-content:flex-end alinea el avatar/boton dentro
   del hueco. (Un min-width de reserva aqui hacia que el header no
   cupiera en una fila y envolviera las acciones debajo del logo.) */
.auth-area { display: flex; align-items: center; justify-content: flex-end; }

.intereses-dialog {
  /* El reset global "* { margin: 0; }" (base.css) le gana al centrado
     automatico que el navegador le da a <dialog> via "margin: auto" en
     su hoja de estilos de usuario -- sin esto, showModal() lo deja
     pegado arriba a la izquierda en vez de centrado. Se reafirma aqui
     a mano, funciona igual en mobile porque no depende de conocer el
     alto del contenido. */
  position: fixed;
  inset: 0;
  margin: auto;
  border: none;
  border-radius: var(--r-lg);
  padding: var(--sp-6);
  max-width: 480px;
  width: min(90vw, 480px);
  max-height: min(85vh, 640px);
  overflow-y: auto;
  background: var(--bg-elev);
  color: var(--fg);
  box-shadow: var(--shadow-3);
}
.intereses-dialog::backdrop { background: rgba(0, 0, 0, 0.5); }
.intereses-lista {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-2);
  list-style: none;
  padding: 0;
  margin: var(--sp-4) 0;
}
.intereses-item {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs--1);
}
.intereses-item:has(input:disabled) { opacity: 0.4; }
.intereses-error { color: var(--bad); font-size: var(--fs--1); }
.intereses-acciones { display: flex; gap: var(--sp-3); margin-top: var(--sp-4); }

/* CTA de cierre de la pagina de coleccion -- banda oscura, misma
   familia que .band-dark del sistema. */
.coleccion-cta {
  margin: var(--sp-7) 0 var(--sp-5);
  /* --band-dark (no --band-dark-2): en tema oscuro --band-dark-2 es
     identico a --bg y la banda desaparecia. --band-dark coincide con el
     footer y queda un escalon por encima del fondo; el borde la delimita
     en los dos temas. */
  background: var(--band-dark);
  border: 1px solid var(--line-strong);
  color: var(--band-dark-fg);
  border-radius: var(--r-xl);
  padding: var(--sp-6);
  text-align: center;
}
.coleccion-cta h2 {
  font-family: var(--ff-display); font-size: clamp(1.3rem, 3vw, 1.6rem);
  margin: 0 0 var(--sp-3);
}
.coleccion-cta p {
  color: var(--band-dark-fg-muted); max-width: 52ch; margin: 0 auto var(--sp-4);
}
/* justify-content: center -- sin sesion el form es un solo boton y sin
   esto quedaba pegado a la izquierda de la caja de 520px (reportado
   2026-09-07). Con sesion (input flex:1 + boton) no cambia nada: el
   input se estira y no queda espacio libre que repartir. */
.coleccion-cta__form { display: flex; justify-content: center; gap: var(--sp-3); max-width: 520px; margin: 0 auto; flex-wrap: wrap; }
.coleccion-cta__form input {
  flex: 1; min-width: 200px; border: 1px solid var(--line-strong);
  background: rgba(255, 255, 255, .06); color: var(--band-dark-fg);
  border-radius: var(--r-pill); padding: 11px 16px; font: inherit;
}
.coleccion-cta__form input::placeholder { color: var(--band-dark-fg-muted); }
.coleccion-cta__hint { font-size: .78rem; color: var(--band-dark-fg-muted); margin-top: var(--sp-3); }
.coleccion-cta__ok { font-family: var(--ff-display); font-weight: 600; }
.coleccion-cta__ok span { color: var(--band-dark-ok); }

/* ============================================================
   Cupones bancarios + tarjetas Cashback+ (cupones.html)
   spec: docs/superpowers/specs/2026-09-03-cupones-bancarios-design.md
   ============================================================ */

.cupones__intro { color: var(--fg-muted); max-width: 60ch; margin-top: var(--sp-3); }

.cupones__filtros { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: var(--sp-5) 0; }
.cupones__filtros .chip { background: var(--bg-elev); cursor: pointer; border-color: var(--line-strong); }
.cupones__filtros .chip[aria-pressed="true"] {
  background: var(--accent-solid); color: var(--accent-ink); border-color: var(--accent-solid);
}

.cupones__grid {
  list-style: none; padding: 0; margin: 0; display: grid; gap: var(--sp-4);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
}
.cupones__grid > li { display: flex; }
.cupones__disc { margin-top: var(--sp-6); font-size: var(--fs--1); color: var(--fg-faint); max-width: 72ch; }

/* ---------- una tarjeta ---------- */
.coupon {
  /* --bank = color de marca del banco, lo setea cupones.js inline por
     tarjeta (dato de contenido, ver marcaBanco()). Aquí solo se lee. */
  --bank: var(--fg);
  display: flex; flex-direction: column; width: 100%; height: 100%; min-height: 25rem;
  background: var(--bg-elev); border: 1px solid var(--line);
  border-radius: var(--r-md); overflow: hidden; box-shadow: var(--shadow-1);
  font-family: var(--ff-sans);
}
.coupon__gancho {
  position: relative;
  padding: var(--sp-4) var(--sp-4) var(--sp-3); border-bottom: 1px dashed var(--line-strong);
  background: linear-gradient(160deg, color-mix(in srgb, var(--bank) 12%, var(--bg-elev)), var(--bg-elev));
}
.coupon__bankdot {
  flex: none; width: 26px; height: 26px; border-radius: var(--r-sm);
  background: var(--bank); color: #fff; display: grid; place-items: center;
  font-family: var(--ff-display); font-weight: 700; font-size: .72rem; letter-spacing: -.02em;
}
/* Piso de altura (no tope): el contenido crece libre, nada se recorta.
   La alineación de la franja/botón/fecha la da el grid (tarjetas de la
   misma fila, misma altura) + .coupon__btm anclado al fondo. */
.coupon__bankrow { min-height: 1.5rem; }
.coupon__benef { min-height: 2.7rem; }
/* reserva 2 renglones aunque solo use 1 -> el gancho mide igual en todas
   las tarjetas y la línea punteada queda al mismo nivel. */
.coupon__sub { min-height: 2.9em; margin-top: var(--sp-1); }
.coupon__bankrow { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-2); }
.coupon__bank { font-family: var(--ff-display); font-weight: 600; font-size: var(--fs-0); }
.coupon__store {
  margin-left: auto; font-family: var(--ff-display); font-weight: 700; font-size: .6rem;
  letter-spacing: .05em; text-transform: uppercase; padding: .18rem .42rem;
  border-radius: var(--r-sm); white-space: nowrap;
}
.coupon__store[data-s="amazon"]       { background: var(--store-az-badge-bg); color: var(--store-az-badge-fg); }
.coupon__store[data-s="mercadolibre"] { background: var(--store-ml-badge-bg); color: var(--store-ml-badge-fg); }
.coupon__store[data-s="ambas"]        { background: var(--bg-sunken); color: var(--fg-muted); border: 1px solid var(--line); }
.coupon__store[data-s="cb"]           { background: color-mix(in srgb, var(--ok) 16%, transparent); color: var(--ok); border: 1px solid color-mix(in srgb, var(--ok) 34%, transparent); }

.coupon__benef { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap; }
.coupon__num { font-family: var(--ff-display); font-weight: 700; line-height: 1; font-size: var(--fs-4); color: var(--bank); letter-spacing: -.03em; }
.coupon__unit { font-family: var(--ff-display); font-weight: 600; font-size: var(--fs-0); color: var(--fg); }
.coupon__msi {
  font-family: var(--ff-display); font-weight: 600; font-size: .62rem; letter-spacing: .03em;
  text-transform: uppercase; align-self: center; padding: .15rem .4rem; border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--bank) 16%, transparent); color: var(--bank);
}
.coupon__sub { font-size: var(--fs-0); color: var(--fg-muted); margin-top: var(--sp-2); line-height: 1.4; }

.coupon__cuerpo { padding: var(--sp-3) var(--sp-4) var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-3); flex: 1; }
/* Piso, no tope: los datos se ven completos, se envuelven si hacen falta. */
.coupon__lineas { display: flex; flex-direction: column; gap: var(--sp-2); min-height: 4.4rem; }
.coupon__linea { display: flex; gap: var(--sp-2); font-size: var(--fs-0); color: var(--fg); align-items: flex-start; line-height: 1.4; }
.coupon__ci { flex: none; line-height: 1.4; color: var(--fg-faint); }

/* margin-top:auto -> la franja/bono, la vigencia y el botón se anclan al
   fondo; el hueco sobrante queda arriba, así el botón alinea entre
   tarjetas de una fila aunque tengan distinto contenido. */
.coupon__btm { margin-top: auto; display: flex; flex-direction: column; gap: var(--sp-3); }

.coupon__reveal {
  position: relative; display: flex; align-items: center; justify-content: center;
  min-height: 46px; overflow: hidden; border: 1.5px dashed var(--line-strong);
  border-radius: var(--r-sm); background: var(--bg-sunken);
  font-family: var(--ff-mono); font-weight: 700; font-size: var(--fs-0); letter-spacing: .06em; color: var(--fg);
  text-align: center; padding: 0 var(--sp-2);
}
.coupon__reveal--info {
  border-style: solid; border-color: var(--line);
  font-family: var(--ff-sans); font-weight: 400; font-size: var(--fs-0);
  letter-spacing: 0; color: var(--fg-muted);
}
.coupon__code { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.coupon__reveal--bono { border-color: color-mix(in srgb, var(--bank) 45%, var(--line-strong)); }
.coupon__code { transition: transform .3s var(--ease); }
.coupon__reveal.is-open .coupon__code { animation: coupon-pop .5s cubic-bezier(.2, 1.3, .35, 1); }
@keyframes coupon-pop { 0% { transform: scale(.7); opacity: 0; } 55% { transform: scale(1.08); } 100% { transform: scale(1); opacity: 1; } }
.coupon__copied {
  position: absolute; right: 10px; opacity: 0; font-family: var(--ff-sans);
  font-size: .66rem; font-weight: 700; color: var(--ok); transition: opacity .3s .2s var(--ease);
}
.coupon__reveal.is-open .coupon__copied { opacity: 1; }
.coupon__cover {
  position: absolute; inset: 0; border: 0; cursor: pointer; z-index: 2;
  display: flex; align-items: center; justify-content: center; gap: .4rem;
  font-family: var(--ff-display); font-weight: 600; font-size: var(--fs--1); color: var(--bank);
  background: repeating-linear-gradient(45deg,
    color-mix(in srgb, var(--bank) 7%, var(--bg-elev)), color-mix(in srgb, var(--bank) 7%, var(--bg-elev)) 7px,
    color-mix(in srgb, var(--bank) 16%, var(--bg-elev)) 7px, color-mix(in srgb, var(--bank) 16%, var(--bg-elev)) 14px);
  transition: transform .45s cubic-bezier(.6, -0.1, .3, 1), opacity .4s;
}
.coupon__cover::before { content: "\1F3AB"; }
.coupon__reveal--bono .coupon__cover::before { content: ""; }
.coupon__reveal.is-open .coupon__cover { transform: translateX(-108%) rotate(-2deg); opacity: 0; pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
  .coupon__reveal.is-open .coupon__cover { transform: none; transition: opacity .15s; }
  .coupon__reveal.is-open .coupon__code { animation: none; }
}

.coupon__bono {
  min-height: 46px; display: flex; align-items: center; justify-content: center; text-align: center;
  border: 1.5px solid color-mix(in srgb, var(--bank) 35%, var(--line)); border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--bank) 8%, var(--bg-sunken));
  padding: var(--sp-2) var(--sp-3); font-size: var(--fs--1); font-weight: 500;
}

/* Tema oscuro: los colores de marca (navy BBVA, negro Klar/Plata) se
   pierden sobre el fondo oscuro. Se mezclan hacia el --fg claro para que
   el número y la tapa sigan legibles sin dejar de tener tinte de marca.
   El dot gana un borde para no desaparecer. */
:root:not([data-theme="light"]) .coupon__num,
:root:not([data-theme="light"]) .coupon__cover,
:root[data-theme="dark"] .coupon__num,
:root[data-theme="dark"] .coupon__cover {
  color: color-mix(in srgb, var(--bank) 45%, var(--fg));
}
:root:not([data-theme="light"]) .coupon__bankdot,
:root[data-theme="dark"] .coupon__bankdot {
  box-shadow: 0 0 0 1px var(--line-strong);
}

.coupon__vig { display: flex; align-items: center; gap: var(--sp-2); font-family: var(--ff-mono); font-size: .72rem; color: var(--fg-faint); }
.coupon__pip { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.coupon__vig.is-urgent { color: var(--bad); font-weight: 700; }
.coupon__vig.is-soon { color: var(--warn); font-weight: 700; }
.coupon__vig.is-ok .coupon__pip { background: var(--ok); }

.coupon__foot { display: flex; flex-direction: column; gap: var(--sp-2); padding-top: var(--sp-1); }
.coupon__cta {
  display: block; text-align: center; text-decoration: none; padding: var(--sp-3);
  border-radius: var(--r-sm); background: var(--accent-solid); color: var(--accent-ink);
  font-family: var(--ff-display); font-weight: 600; font-size: var(--fs--1);
}
.coupon__cta:hover { filter: brightness(1.05); }
/* Una sola línea siempre -> el botón alinea entre tarjetas. El link
   "Detalles en [banco]" (secundario, el banco ya sale en el botón)
   se recorta con … si no cabe; verif y ¿Sirvió? nunca se pierden. */
.coupon__meta { display: flex; flex-wrap: nowrap; align-items: center; gap: var(--sp-2); font-size: .72rem; color: var(--fg-faint); min-height: 1.5rem; }
.coupon__terms { color: var(--fg-muted); text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1 1 auto; min-width: 2.5rem; }
.coupon__terms:hover { color: var(--accent); }
.coupon__verif { white-space: nowrap; flex: none; }
.coupon__report { display: flex; align-items: center; gap: .25rem; margin-left: auto; flex: none; }
.coupon__vote {
  border: 1px solid var(--line); background: var(--bg-elev); cursor: pointer;
  border-radius: var(--r-sm); padding: .1rem .34rem; font-size: .82rem; line-height: 1;
}
.coupon__vote:hover:not(:disabled) { border-color: var(--accent-solid); }
.coupon__vote.is-on { border-color: var(--ok); background: color-mix(in srgb, var(--ok) 14%, transparent); }
.coupon__vote:disabled { cursor: default; opacity: .55; }

/* ---------- bloque del home "Promos bancarias vigentes" ---------- */
.home-coupons { margin-top: var(--sp-7); }
.home-coupons__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-4); margin-bottom: var(--sp-4); }
.home-coupons__head h2 { font-family: var(--ff-display); font-size: var(--fs-2); margin: 0; }
.home-coupons__all { font-family: var(--ff-display); font-size: var(--fs--1); color: var(--accent); text-decoration: none; white-space: nowrap; }
.home-coupons__all:hover { text-decoration: underline; }
.home-coupons__row {
  list-style: none; padding: 0; margin: 0; display: grid; gap: var(--sp-4);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
}
.home-coupons__row > li { display: flex; }

/* versión chica de la tarjeta de cupones -- misma forma y colores */
.coupon--mini {
  min-height: 0; text-decoration: none; cursor: pointer;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.coupon--mini:hover { border-color: var(--bank); transform: translateY(-2px); box-shadow: var(--shadow-2); }
.coupon--mini .coupon__gancho { border-bottom: 0; padding: var(--sp-4); }
.coupon--mini .coupon__num { font-size: var(--fs-3); }
/* En el home las 3 tarjetas van lado a lado: para que el monto, la
   sub-línea y el pie queden ALINEADOS entre tarjetas aunque el nombre del
   banco tenga largo distinto ("Santander" vs "Tarjeta Mercado Pago"), se
   reserva altura fija por fila y se limita el nombre a 2 líneas. Sin esto
   se veían desfasados (reportado 2026-09-07). */
.coupon--mini .coupon__bankrow { min-height: 2.9rem; align-items: flex-start; }
.coupon--mini .coupon__bank {
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden; line-height: 1.2;
}
.coupon--mini .coupon__benef { min-height: 2.4rem; }
.coupon--mini .coupon__sub { min-height: 0; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.coupon__mini-cta {
  margin-top: auto; padding: var(--sp-3) var(--sp-4);
  font-family: var(--ff-display); font-weight: 600; font-size: var(--fs--1); color: var(--accent);
  border-top: 1px dashed var(--line-strong);
}

/* ---------- chip de cupón en la tarjeta ganadora ---------- */
.coupon-chip { margin-top: var(--sp-3); display: flex; flex-direction: column; gap: var(--sp-2); }
.coupon-chip__btn {
  display: flex; align-items: center; gap: var(--sp-2); width: 100%; cursor: pointer;
  padding: var(--sp-3); border-radius: var(--r-md); text-align: left;
  border: 1.5px dashed color-mix(in srgb, var(--ml) 50%, var(--line-strong));
  background: color-mix(in srgb, var(--store-ml-wash) 70%, var(--bg-elev));
  font-family: var(--ff-sans); font-size: var(--fs--1); color: var(--fg);
}
.coupon-chip.is-open .coupon-chip__btn {
  border-style: solid; border-color: color-mix(in srgb, var(--ok) 45%, transparent);
  background: color-mix(in srgb, var(--ok) 12%, var(--bg-elev));
}
.coupon-chip__tag { flex: none; width: 24px; height: 24px; border-radius: var(--r-sm); display: grid; place-items: center; background: var(--ml); color: #000; font-size: .8rem; }
.coupon-chip.is-open .coupon-chip__tag { background: var(--ok); color: #fff; }
.coupon-chip__txt { flex: 1; min-width: 0; }
.coupon-chip.is-open .coupon-chip__txt strong { font-family: var(--ff-mono); letter-spacing: .06em; }
.coupon-chip__accion { flex: none; font-family: var(--ff-display); font-weight: 600; color: var(--accent); }
.coupon-chip.is-open .coupon-chip__accion { color: var(--ok); }
.coupon-chip__todas { font-size: var(--fs--1); color: var(--fg-muted); text-decoration: none; align-self: flex-start; }
.coupon-chip__todas:hover { color: var(--accent); }

/* ---------- barra de confirmación (abajo, fija) ---------- */
.coupon-bar {
  position: fixed; left: 50%; bottom: var(--sp-4); z-index: 60;
  transform: translate(-50%, 140%); transition: transform .3s var(--ease);
  display: flex; align-items: center; gap: var(--sp-3);
  max-width: min(560px, calc(100vw - 2 * var(--sp-4)));
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-pill);
  background: var(--band-dark); color: var(--band-dark-fg);
  box-shadow: var(--shadow-2); font-size: var(--fs--1);
}
.coupon-bar.is-in { transform: translate(-50%, 0); }
.coupon-bar__msg { flex: 1; min-width: 0; }
.coupon-bar__msg b { font-family: var(--ff-mono); letter-spacing: .06em; color: #fff; }
.coupon-bar__x { flex: none; border: 0; background: transparent; color: var(--band-dark-fg-muted); cursor: pointer; font-size: 1rem; line-height: 1; }
.coupon-bar__x:hover { color: var(--band-dark-fg); }
@media (prefers-reduced-motion: reduce) { .coupon-bar { transition: none; } }
