/* ==========================================================================
   ZELQUO — Design tokens
   --------------------------------------------------------------------------
   Fuente de verdad: "ZELQUO — Manual de identidad digital", §03 Color,
   §04 Tipografía, §10 Motion y §13 Especificación para desarrollo.

   Aquí vive TODO el color, el radio, el espaciado y el movimiento del sitio.
   Ningún hexadecimal debe escribirse fuera de este bloque y de los dos de
   tema que le siguen: un color suelto en una regla es un color que no cambia
   al cambiar de tema y que nadie encuentra el día que haya que ajustarlo.

   Reparto que pide el manual: 60% superficies, 24% neutros y texto,
   14% azules de acción, 2% acento dorado. El azul eléctrico es SEÑAL DE
   ACCIÓN, no decoración: si aparece en todo, deja de significar nada.
   ========================================================================== */
:root{
  /* --- Superficies siempre oscuras (hero, pie, sidebar) --------------------
     No se invierten con el tema: son la cara "navy" de la marca y se ven
     igual en claro que en oscuro. Nunca negro puro. */
  --zq-bg-dark: #0A0F1C;      /* Azul noche */
  --zq-surface-dark: #101827; /* Carbón */
  --zq-surface-dark-2: #151F31; /* Pizarra */

  /* --- Azules de marca ---------------------------------------------------- */
  --zq-blue: #1565FF;         /* Azul eléctrico — acción */
  /* Los mismos azules en canales sueltos. Hacen falta porque rgba() no acepta
     un hexadecimal dentro de una variable, y sin ellos cada halo, cada borde
     translúcido y cada degradado del sitio vuelve a escribir el color a mano
     —que es justo lo que pasaba antes: 24 rgba() con el azul viejo incrustado
     que no se enteraron del cambio de marca. */
  --zq-blue-rgb: 21,101,255;
  --zq-blue-light-rgb: 77,178,255;
  /* El azul eléctrico da 4,84:1 contra blanco, así que cumple WCAG AA como
     fondo de botón con texto blanco y también como texto sobre fondo claro.
     Un solo azul sirve para las dos cosas; el ShopGo anterior necesitaba un
     tono aparte porque el suyo se quedaba en 3,65:1. */
  --zq-blue-strong: #1565FF;
  /* El hover NO aclara el fondo: cualquier azul más claro que #1565FF baja de
     4,5:1 contra el texto blanco del botón. La "subida de luminosidad" que
     pide el manual se consigue con el halo y la elevación (ver .btn-primary),
     que se ven más premium y no rompen el contraste. */
  --zq-blue-strong-hover: #0F52D6;
  --zq-blue-light: #4DB2FF;   /* Azul claro — acentos sobre oscuro */
  --zq-blue-soft: #8AB4FF;    /* Azul suave — texto de apoyo sobre oscuro */
  --zq-ice: #DCEBFF;
  /* #4DB2FF solo da 2,30:1 contra blanco: vale como acento SOBRE OSCURO y
     nunca como texto sobre fondo claro. Para eso está --zq-blue. */

  /* --- Neutros (tema claro; el bloque de tema oscuro los reescribe) -------- */
  --zq-text: #10131A;
  --zq-muted: #647083;
  --zq-border: #DDE3EC;
  --zq-surface: #EEF2F8;
  --zq-white: #FFFFFF;
  --zq-border-dark: rgba(255,255,255,.06);

  /* Superficies del tema. --zq-white queda reservado al texto sobre fondos
     que son oscuros en cualquier tema (hero, pie). */
  --zq-page: #F7F9FC;
  --zq-card: #FFFFFF;
  --zq-header-bg: rgba(247,249,252,.72);
  /* El recuadro de la foto es SIEMPRE blanco: las fotos de producto vienen
     recortadas sobre blanco y sobre gris o negro se ve el borde del recorte. */
  --zq-photo-bg: #FFFFFF;

  /* --- Semánticos --------------------------------------------------------- */
  --zq-success: #1F9D66;
  --zq-urgency: #D92D20;
  --zq-savings: #1565FF;  /* el descuento es información, no alarma */
  --zq-gold: #F5C542;     /* acento editorial — 2%, nunca color principal */

  /* --- Forma -------------------------------------------------------------- */
  --zq-radius-sm: 8px;
  --zq-radius-card: 16px;
  --zq-radius-button: 10px;
  --zq-radius-chip: 999px;
  --zq-radius-modal: 22px;

  --zq-shadow-card: 0 10px 30px rgba(10,15,28,.07);
  --zq-shadow-soft: 0 18px 50px rgba(0,0,0,.24);
  --zq-shadow-card-dark: 0 18px 50px rgba(0,0,0,.34);
  /* Halo azul del hover. Discreto a propósito: el manual pide 5% de efectos. */
  --zq-glow: 0 8px 26px rgba(21,101,255,.28);

  /* --- Espaciado (múltiplos de 4) ----------------------------------------- */
  --zq-space-1: 4px;
  --zq-space-2: 8px;
  --zq-space-3: 12px;
  --zq-space-4: 16px;
  --zq-space-5: 24px;
  --zq-space-6: 32px;
  --zq-space-7: 48px;
  --zq-space-8: 64px;
  --zq-space-9: 96px;

  --zq-max: 1280px;

  /* --- Tipografía ---------------------------------------------------------
     Satoshi es la de marca; Inter la cubre mientras carga y si Fontshare no
     responde. Las dos tienen métricas parecidas, así que el relevo no mueve
     el layout. Ninguna es propietaria: nada que licenciar. */
  --zq-font: 'Satoshi', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* --- Movimiento (manual §10) --------------------------------------------
     Tres duraciones y una curva. Todo lo que se mueva en el sitio sale de
     aquí; así el movimiento se siente de una sola pieza. */
  --zq-motion-fast: 180ms;   /* fade, hover, feedback inmediato */
  --zq-motion-base: 320ms;   /* entradas, deslizamientos, modales */
  --zq-motion-slow: 420ms;   /* transiciones entre vistas */
  --zq-ease: cubic-bezier(.22,1,.36,1);
  --zq-ease-out: cubic-bezier(.16,1,.3,1);
}

/* ==========================================================================
   Temas — claro, oscuro y "segun el sistema" (predeterminado)
   --------------------------------------------------------------------------
   Sin data-theme, manda el sistema operativo. Con data-theme="light" o "dark",
   manda la eleccion del usuario y el sistema se ignora. Por eso el bloque de
   prefers-color-scheme va acotado con :not([data-theme="light"]).

   El oscuro no es el claro invertido ni al revés: cada uno tiene su propia
   escala. El oscuro se construye por CAPAS de luminosidad (#0A0F1C → #101827
   → #151F31) con bordes de opacidad muy baja, nunca con líneas blancas.
   ========================================================================== */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --zq-text: #F7F9FC;
    --zq-muted: #AAB5C4;
    --zq-border: rgba(255,255,255,.07);
    --zq-surface: #151F31;
    --zq-page: #0A0F1C;
    --zq-card: #101827;
    --zq-header-bg: rgba(10,15,28,.72);
    --zq-shadow-card: var(--zq-shadow-card-dark);
    color-scheme: dark;
  }
}

:root[data-theme="dark"]{
  --zq-text: #F7F9FC;
  --zq-muted: #AAB5C4;
  --zq-border: rgba(255,255,255,.07);
  --zq-surface: #151F31;
  --zq-page: #0A0F1C;
  --zq-card: #101827;
  --zq-header-bg: rgba(10,15,28,.72);
  --zq-shadow-card: var(--zq-shadow-card-dark);
  color-scheme: dark;
}

:root[data-theme="light"]{ color-scheme: light; }

/* ==========================================================================
   Reset
   ========================================================================== */
*, *::before, *::after{ box-sizing: border-box; }
/* El atributo hidden gana a cualquier display. Sin esto, un componente con
   display:grid o flex sigue visible aunque el JS lo marque como oculto. */
[hidden]{ display: none !important; }
html{ scroll-behavior: smooth; }
body{
  margin: 0;
  font-family: var(--zq-font);
  color: var(--zq-text);
  background: var(--zq-page);
  -webkit-font-smoothing: antialiased;
  line-height: 1.5;
}
img{ max-width: 100%; display: block; }
a{ color: inherit; text-decoration: none; }
ul{ margin: 0; padding: 0; list-style: none; }
button{ font-family: inherit; cursor: pointer; }
h1,h2,h3,h4,p{ margin: 0; }
input{ font-family: inherit; }

@media (prefers-reduced-motion: reduce){
  *{ animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; }
}

/* Focus visibility — never remove keyboard focus */
/* El anillo usa el azul de marca, no el suave: #8AB4FF daba 2,09:1 contra
   blanco y WCAG 2.2 (criterio 1.4.11) pide 3:1 como mínimo para un indicador
   de foco. #1565FF da 4,84:1 sobre claro y 3,95:1 sobre el navy, así que
   cumple en los dos temas con un solo color. */
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, [tabindex]:focus-visible{
  outline: 2px solid var(--zq-blue);
  outline-offset: 2px;
  border-radius: 6px;
}
/* Sobre las superficies siempre oscuras el azul eléctrico se funde con el
   fondo: ahí manda el azul claro, que sobre el navy da 8,7:1. */
.hero :focus-visible,
.page-hero :focus-visible,
.newsletter :focus-visible,
.site-footer :focus-visible,
.sg-sidebar :focus-visible,
.mobile-nav :focus-visible{ outline-color: var(--zq-blue-light); }

/* ==========================================================================
   Layout helpers
   ========================================================================== */
.container{
  max-width: var(--zq-max);
  margin: 0 auto;
  padding: 0 var(--zq-space-5);
}
.editorial{ max-width: 780px; }

section{ padding: var(--zq-space-8) 0; }
.section-tight{ padding: var(--zq-space-7) 0; }

.section-head{
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--zq-space-4);
  margin-bottom: var(--zq-space-6);
  flex-wrap: wrap;
}
.section-head h2{ margin-bottom: var(--zq-space-2); }
.section-head p{ color: var(--zq-muted); font-size: 16px; max-width: 560px; }

.eyebrow{
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--zq-blue);
  margin-bottom: var(--zq-space-2);
}

/* ==========================================================================
   Typography scale
   ========================================================================== */
.display{ font-size: clamp(34px, 5vw, 60px); font-weight: 700; letter-spacing: -0.01em; line-height: 1.08; }
h1, .h1{ font-size: clamp(30px, 4vw, 44px); font-weight: 700; letter-spacing: -0.01em; line-height: 1.15; }
h2, .h2{ font-size: clamp(24px, 3vw, 30px); font-weight: 600; letter-spacing: -0.01em; line-height: 1.2; }
h3, .h3{ font-size: 19px; font-weight: 600; line-height: 1.3; }
.body-lg{ font-size: 18px; color: var(--zq-muted); }
.body{ font-size: 16px; }
.label{
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--zq-muted);
}
.muted{ color: var(--zq-muted); }

/* ==========================================================================
   Buttons
   ========================================================================== */
.btn{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--zq-space-2);
  height: 50px;
  padding: 0 var(--zq-space-5);
  border-radius: var(--zq-radius-button);
  font-size: 15px;
  font-weight: 600;
  border: 1px solid transparent;
  transition: transform var(--zq-motion-fast) var(--zq-ease),
              box-shadow var(--zq-motion-fast) var(--zq-ease),
              border-color var(--zq-motion-fast) var(--zq-ease),
              background var(--zq-motion-fast) var(--zq-ease),
              filter var(--zq-motion-fast) var(--zq-ease);
  white-space: nowrap;
}
/* `active` en todos los botones: el clic tiene que notarse antes de que
   llegue la respuesta del servidor. Es el feedback más barato que existe. */
.btn:active{ transform: scale(.98); }
.btn-primary{
  background: var(--zq-blue-strong);
  color: var(--zq-white);
}
/* El fondo NO se aclara al pasar el cursor. #1565FF con texto blanco da
   4,84:1 y cualquier azul más claro baja del 4,5:1 que exige WCAG AA, así que
   la "subida de luminosidad" que pide el manual se consigue con el halo y la
   elevación. Se ve más premium y nadie pierde legibilidad por el camino. */
.btn-primary:hover{
  box-shadow: var(--zq-glow);
  transform: translateY(-2px);
  filter: brightness(1.06);
}
.btn-secondary{
  background: transparent;
  border-color: var(--zq-border);
  color: var(--zq-text);
}
.btn-secondary:hover{
  border-color: var(--zq-blue);
  transform: translateY(-2px);
}
/* Terciario del manual: sin fondo ni borde salvo al pasar el cursor. Para
   acciones que acompañan a otra principal ("Ver todas", "Ver cómo funciona"). */
.btn-ghost{
  background: transparent;
  border-color: transparent;
  color: var(--zq-text);
}
.btn-ghost:hover{
  border-color: var(--zq-border);
  background: var(--zq-surface);
  color: var(--zq-blue);
}
.btn-block{ width: 100%; }
.btn-sm{ height: 40px; padding: 0 var(--zq-space-4); font-size: 14px; }
.btn-on-dark.btn-secondary{
  border-color: var(--zq-border-dark);
  color: var(--zq-white);
}

/* ==========================================================================
   Header
   ========================================================================== */
.site-header{
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--zq-header-bg);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--zq-border);
}
.site-header .container{
  display: flex;
  align-items: center;
  gap: var(--zq-space-5);
  height: 76px;
}
/* --- BrandLogo (js/brand.js) ---------------------------------------------
   Isotipo + wordmark + eslogan opcional. El manual (§02) pide 24 px mínimo
   para el isotipo en navegación y 112 px para el wordmark en escritorio; el
   tamaño de aquí abajo los cumple con margen. */
.zq-brand{
  display: inline-flex;
  align-items: center;
  gap: var(--zq-space-3);
  color: var(--zq-text);
  flex-shrink: 0;
}
.zq-brand-mark{
  flex: 0 0 34px;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
}
.zq-brand-mark img{ width: 34px; height: 34px; }
.zq-brand-text{ display: flex; flex-direction: column; line-height: 1.05; }
.zq-brand-wordmark{
  font-weight: 700;
  font-size: 20px;
  letter-spacing: .06em;
  /* El wordmark es una PALABRA, no una frase: sin esto, en un contenedor
     estrecho "ZELQUO" se partía en dos líneas bajo el isotipo. */
  white-space: nowrap;
}
.zq-brand-tagline{
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .02em;
  color: var(--zq-muted);
  margin-top: 3px;
  white-space: nowrap;
}
/* Sobre superficies siempre oscuras (hero, pie, sidebar, menú móvil) el
   eslogan necesita su propio gris: el --zq-muted del tema claro se pierde. */
.zq-brand-on-dark{ color: var(--zq-white); }
.zq-brand-on-dark .zq-brand-tagline{ color: var(--zq-blue-soft); }
.zq-brand-mark img{ transition: filter var(--zq-motion-base) var(--zq-ease); }
.zq-brand:hover .zq-brand-mark img{ filter: drop-shadow(0 0 12px rgba(21,101,255,.45)); }

.main-nav{
  display: flex;
  align-items: center;
  gap: var(--zq-space-5);
  margin-left: var(--zq-space-4);
}
.main-nav a{
  font-size: 15px;
  font-weight: 500;
  color: var(--zq-text);
  padding: var(--zq-space-2) 0;
  border-bottom: 2px solid transparent;
  transition: color 160ms var(--zq-ease), border-color 160ms var(--zq-ease);
}
.main-nav a:hover, .main-nav a.active{
  color: var(--zq-blue);
  border-color: var(--zq-blue);
}

.header-search{
  flex: 1;
  max-width: 380px;
  margin-left: auto;
  position: relative;
}
.header-search input{
  width: 100%;
  height: 44px;
  border-radius: var(--zq-radius-chip);
  border: 1px solid var(--zq-border);
  background: var(--zq-surface);
  padding: 0 var(--zq-space-4) 0 40px;
  font-size: 14px;
  color: var(--zq-text);
  transition: border-color 160ms var(--zq-ease), background 160ms var(--zq-ease);
}
.header-search input:focus{
  outline: none;
  border-color: var(--zq-blue);
  background: var(--zq-card);
}
.header-search svg{
  position: absolute;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--zq-muted);
}

.header-actions{
  display: flex;
  align-items: center;
  gap: var(--zq-space-3);
  flex-shrink: 0;
  margin-left: auto;
}
.icon-btn{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: 12px;
  border: 1px solid var(--zq-border);
  background: var(--zq-card);
  color: var(--zq-text);
  transition: border-color 160ms var(--zq-ease), transform 160ms var(--zq-ease);
}
.icon-btn:hover{ border-color: var(--zq-blue); transform: translateY(-2px); }

.nav-toggle{
  display: flex;
  align-items: center;
  gap: 8px;
  height: 42px;
  padding: 0 var(--zq-space-4) 0 var(--zq-space-3);
  border-radius: 12px;
  border: 1px solid var(--zq-border);
  background: var(--zq-card);
  color: var(--zq-text);
  font-size: 14px;
  font-weight: 600;
  font-family: var(--zq-font);
  flex-shrink: 0;
  transition: border-color 160ms var(--zq-ease), color 160ms var(--zq-ease);
}
.nav-toggle:hover{ border-color: var(--zq-blue); color: var(--zq-blue); }

/* ==========================================================================
   Hero
   ========================================================================== */
/* El hero es la cara "navy" de la marca: no cambia con el tema. Tres capas de
   luz azul sobre azul noche, ninguna encima del texto. La de ::after es la
   única que se mueve con el scroll (--zq-parallax, js/motion.js): 32px como
   mucho, y solo el fondo. Mover el titular lo haría "nadar". */
.hero{
  position: relative;
  --zq-parallax: 0px;
  background: linear-gradient(180deg, var(--zq-bg-dark) 0%, var(--zq-surface-dark) 100%);
  color: var(--zq-white);
  overflow: hidden;
  padding: var(--zq-space-9) 0 var(--zq-space-8);
}
.hero::before,
.hero::after{
  content: "";
  position: absolute;
  inset: -10% -5%;
  pointer-events: none;
}
.hero::before{
  background: radial-gradient(1100px 520px at 78% -6%, rgba(var(--zq-blue-light-rgb),.24), transparent 62%);
}
.hero::after{
  background: radial-gradient(680px 340px at 8% 104%, rgba(var(--zq-blue-rgb),.30), transparent 68%);
  /* translate3d (y no translateY) manda la capa a la GPU: cada paso del
     parallax es una composición, no un repintado del hero entero.
     Sin `will-change`: dejarlo puesto de forma permanente reserva una textura
     del tamaño del hero durante toda la vida de la página, y esto se mueve
     como mucho unos segundos al principio del scroll. */
  transform: translate3d(0, var(--zq-parallax), 0);
}
.hero .container{
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: var(--zq-space-8);
  align-items: center;
}
.hero-copy .eyebrow{
  color: var(--zq-blue-soft);
  background: rgba(var(--zq-blue-light-rgb),.10);
  border: 1px solid rgba(var(--zq-blue-light-rgb),.20);
  border-radius: var(--zq-radius-chip);
  padding: 6px var(--zq-space-3);
  margin-bottom: var(--zq-space-5);
}
.hero-copy h1{
  color: var(--zq-white);
  font-size: clamp(38px, 5.2vw, 64px);
  line-height: 1.06;
  letter-spacing: -0.02em;
  margin-bottom: var(--zq-space-4);
}
/* La segunda línea del titular ES la marca: se lleva el azul claro, que sobre
   el navy da 8,7:1. El azul eléctrico aquí quedaría casi negro sobre negro. */
.hero-accent{ color: var(--zq-blue-light); }
.hero-copy p{
  color: rgba(255,255,255,.74);
  font-size: 17px;
  max-width: 500px;
  margin-bottom: var(--zq-space-6);
}

/* El buscador es uno de los elementos principales de la home (manual §13):
   píldora ancha, icono a la izquierda y botón dentro del propio contenedor. */
.hero-search{
  display: flex;
  align-items: center;
  gap: var(--zq-space-2);
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.10);
  padding: var(--zq-space-2);
  padding-left: var(--zq-space-4);
  border-radius: var(--zq-radius-chip);
  max-width: 540px;
  margin-bottom: var(--zq-space-5);
  transition: border-color var(--zq-motion-fast) var(--zq-ease), background var(--zq-motion-fast) var(--zq-ease);
}
.hero-search:focus-within{
  border-color: rgba(var(--zq-blue-light-rgb),.55);
  background: rgba(255,255,255,.08);
}
.hero-search > svg{ color: rgba(255,255,255,.5); flex-shrink: 0; }
.hero-search input{
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  color: var(--zq-white);
  padding: 0 var(--zq-space-2);
  font-size: 15px;
}
.hero-search input::placeholder{ color: rgba(255,255,255,.5); }
.hero-search input:focus{ outline: none; }
/* El contenedor es una píldora: el botón interior comparte el mismo radio y
   una altura que deja el mismo margen arriba, abajo y a la derecha. */
.hero-search .btn{
  border-radius: var(--zq-radius-chip);
  height: 44px;
  padding: 0 var(--zq-space-5);
  flex-shrink: 0;
}
/* El botón lleva icono y texto. En escritorio se lee "Buscar"; en móvil el
   texto se oculta y queda el icono, porque con la palabra dentro el campo se
   quedaba en 150px y el marcador de posición se cortaba por la mitad. El
   texto sigue en el DOM: es el nombre accesible del botón. */
.hero-search-ico{ display: none; }

/* Dos intenciones, dos botones: mirar ofertas o entender qué es esto. */
.hero-actions{ display: flex; gap: var(--zq-space-3); flex-wrap: wrap; }
.hero-actions .btn-ghost{
  color: var(--zq-white);
  border-color: rgba(255,255,255,.18);
}
.hero-actions .btn-ghost:hover{
  border-color: rgba(var(--zq-blue-light-rgb),.6);
  background: rgba(255,255,255,.06);
  color: var(--zq-white);
}

/* ==========================================================================
   Trust bar (manual §14) — cuatro hechos comprobables bajo el hero
   ========================================================================== */
.trust-bar{ padding: 0; margin-top: calc(var(--zq-space-7) * -1); position: relative; z-index: 2; }
.trust-bar-grid{
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--zq-space-1);
  background: var(--zq-card);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
  box-shadow: var(--zq-shadow-card);
  padding: var(--zq-space-5);
  overflow: hidden;
}
/* Alineadas ARRIBA, no centradas. Con `center`, cada celda se centraba por su
   cuenta: en cuanto un subtítulo se iba a dos líneas, su título subía 9px y
   los cuatro dejaban de compartir línea. Alineando arriba, los títulos quedan
   siempre a la misma altura parta lo que parta —otro idioma, otra anchura— y
   deja de depender de que el texto quepa justo. */
.trust-bar-grid li{
  display: flex;
  align-items: flex-start;
  gap: var(--zq-space-3);
  padding: 0 var(--zq-space-4);
  min-width: 0;
}
/* Separadores entre columnas, no alrededor: un borde en cada `li` dejaría una
   línea suelta al final de la fila. */
.trust-bar-grid li + li{ border-left: 1px solid var(--zq-border); }
.trust-bar-ico{
  flex: 0 0 40px;
  width: 40px; height: 40px;
  border-radius: 11px;
  background: rgba(var(--zq-blue-rgb),.10);
  color: var(--zq-blue);
  display: grid;
  place-items: center;
  /* Con las celdas alineadas arriba, el cuadro del icono (40px) empieza en el
     mismo punto que el título (19px de línea). Bajarlo 2px lo deja ópticamente
     a la altura del par título + subtítulo en vez de pegado al borde. */
  margin-top: 2px;
}
.trust-bar-ico svg{ width: 20px; height: 20px; }
.trust-bar-grid strong{ display: block; font-size: 14.5px; font-weight: 600; }
/* El `:not()` NO es cosmético. El icono también es un <span>, y este selector
   —una clase más un tipo, (0,1,1)— gana por especificidad a `.trust-bar-ico`,
   que es solo una clase (0,1,0). Sin la exclusión, el subtítulo le imponía al
   icono `display: block` (matando su `place-items: center`, así que el glifo
   se iba a la esquina superior izquierda de su cuadro, con 20px de hueco a la
   derecha y otros 20 debajo) y `color: var(--zq-muted)`, que lo dejaba gris en
   vez del azul de marca. */
.trust-bar-grid span:not(.trust-bar-ico){
  display: block;
  font-size: 12.5px;
  color: var(--zq-muted);
  /* Reparte el texto entre las líneas en vez de dejar una línea llena y otra
     con una palabra suelta, que es como quedaba "publicarlo". */
  text-wrap: pretty;
}

/* --------------------------------------------------------------------------
   Carrusel del hero — un producto por panel, avanzando solo cada 8s.
   Marcado en renderHeroDeals (js/main.js), comportamiento en js/carousel.js.
   -------------------------------------------------------------------------- */
.hero-visual{
  position: relative;
  min-width: 0;
}

/* La ventana recorta; la pista se desplaza dentro. `overflow:hidden` es lo que
   hace que solo se vea un panel aunque los cinco estén en el DOM. */
.zq-carousel-viewport{
  overflow: hidden;
  border-radius: var(--zq-radius-modal);
}
.zq-carousel-track{
  display: flex;
  /* Cada panel ocupa la ventana entera: `translate3d(-N*100%)` deja el panel N
     exactamente encuadrado, sin cálculos de píxeles ni medir nada. */
  transition: transform 420ms var(--zq-ease);
}
.hero-slide{
  flex: 0 0 100%;
  min-width: 0;
  display: block;
  color: var(--zq-white);
}

/* --- El escenario: aquí es donde desaparece el fondo blanco ----------------
   Las fotos de Amazon vienen sobre blanco puro. Con el escenario en un tono
   claro y la imagen en `multiply`, el blanco de la foto se multiplica por el
   del escenario y desaparece; lo que no es blanco —el producto— se queda. Así
   se ve recortado SIN tocar ni una imagen: nada que descargar, nada que
   editar, nada que rehospedar y nada que se desincronice cuando el catálogo
   cambie de productos destacados.

   `isolation: isolate` es imprescindible: sin él, `multiply` mezclaría con
   todo lo que hay detrás —el navy del hero— y el producto saldría negro. */
.hero-slide-stage{
  position: relative;
  isolation: isolate;
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  padding: var(--zq-space-6);
  border-radius: var(--zq-radius-modal);
  /* Dos capas: la sombra de apoyo encima del degradado del escenario.
     Va en el `background` y no en un `::after`, porque dentro de un
     `isolation: isolate` un pseudo-elemento con `z-index: -1` cae por detrás
     del fondo del propio escenario y no se ve nunca; y sin z-index negativo
     caería por delante de la foto. Como capa de fondo queda donde tiene que
     estar: sobre el escenario y bajo el producto.

     Además el `multiply` de la foto la multiplica también con esta sombra, así
     que el blanco de la imagen la deja pasar y parece que el producto apoya. */
  background:
    radial-gradient(30% 6% at 50% 88%, rgba(10,15,28,.22), transparent 70%),
    radial-gradient(70% 60% at 50% 38%, #FFFFFF 0%, #F4F7FB 55%, #E8EEF7 100%);
}
/* `width/height: 100%` + `object-fit: contain`, y NO `max-width/max-height`.
   Con los `max-*`, el alto disponible dependía del contenido y el contenido
   dependía del alto: el navegador rompía el bucle usando el tamaño natural de
   la foto —1500px— y el panel se comía la pantalla entera. Así el que manda es
   el `aspect-ratio` del escenario y la foto se ajusta dentro sin deformarse. */
.hero-slide-stage img{
  width: 100%;
  height: 100%;
  /* `min-height: 0` es lo que hace que el `aspect-ratio` del escenario mande
     de verdad. Un hijo de rejilla trae `min-height: auto`, que para una imagen
     equivale a su alto natural: con una foto de 1000x1830 el escenario se
     estiraba a 898px de alto y se comía la pantalla, ignorando el 4:3. */
  min-height: 0;
  min-width: 0;
  object-fit: contain;
  mix-blend-mode: multiply;
  transition: transform var(--zq-motion-slow) var(--zq-ease);
}
.hero-slide:hover .hero-slide-stage img{ transform: scale(1.03); }
.hero-slide-sinfoto{ font-size: 56px; }

.hero-slide-dto{
  position: absolute;
  top: var(--zq-space-4);
  left: var(--zq-space-4);
  /* La insignia NO se multiplica: es interfaz, no fotografía. Sin esto el azul
     sólido se fundía con el escenario y quedaba lavado. */
  mix-blend-mode: normal;
}

/* --- Datos del producto, ya sobre el navy del hero ----------------------- */
.hero-slide-info{
  display: grid;
  gap: 2px;
  padding: var(--zq-space-4) var(--zq-space-2) 0;
}
.hero-slide-brand{
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--zq-blue-soft);
}
.hero-slide-name{
  font-size: 16px;
  font-weight: 600;
  color: var(--zq-white);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* Alto fijo de dos líneas: si no, un nombre corto y uno largo dan paneles de
     distinta altura y el carrusel “salta” en cada cambio. */
  min-height: 2.6em;
}
.hero-slide-price{ display: flex; align-items: baseline; gap: var(--zq-space-2); }
.hero-slide-price .now{ color: var(--zq-blue-light); font-weight: 700; font-size: 22px; }
.hero-slide-price .was{ color: rgba(255,255,255,.45); text-decoration: line-through; font-size: 14px; }

/* --- Controles ------------------------------------------------------------ */
.zq-carousel-ui{
  display: flex;
  align-items: center;
  gap: var(--zq-space-3);
  margin-top: var(--zq-space-4);
  padding: 0 var(--zq-space-2);
}
.zq-carousel-dots{ display: flex; gap: var(--zq-space-2); }
.zq-carousel-dot{
  width: 26px;
  height: 4px;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: rgba(255,255,255,.22);
  transition: background var(--zq-motion-fast) var(--zq-ease), width var(--zq-motion-base) var(--zq-ease);
  position: relative;
}
/* El punto mide 4px de alto pero el área que responde al dedo llega a 44:
   WCAG 2.5.8 y el manual §12. */
.zq-carousel-dot::before{
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 100%; height: 44px;
  min-width: 44px;
  transform: translate(-50%, -50%);
}
.zq-carousel-dot:hover{ background: rgba(255,255,255,.45); }
.zq-carousel-dot.is-active{ background: var(--zq-blue-light); width: 40px; }

.zq-carousel-count{
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .08em;
  color: rgba(255,255,255,.5);
  font-variant-numeric: tabular-nums;
}
.zq-carousel-toggle{
  margin-left: auto;
  width: 34px; height: 34px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,.14);
  background: rgba(255,255,255,.05);
  color: rgba(255,255,255,.75);
  transition: color var(--zq-motion-fast) var(--zq-ease), border-color var(--zq-motion-fast) var(--zq-ease);
}
.zq-carousel-toggle svg{ width: 14px; height: 14px; }
.zq-carousel-toggle:hover{ color: var(--zq-white); border-color: rgba(var(--zq-blue-light-rgb),.6); }

/* Sin animación de desplazamiento con reduced-motion: el panel simplemente
   cambia. Y como el carrusel tampoco avanza solo en ese modo, el botón de
   pausa no tiene nada que pausar: se esconde en vez de mentir. */
@media (prefers-reduced-motion: reduce){
  .zq-carousel-track{ transition: none; }
  .hero-slide-stage img{ transition: none; }
}
.zq-carousel.is-reducido .zq-carousel-toggle{ display: none; }
/* ==========================================================================
   Offer cards
   ========================================================================== */
.offers-grid{
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--zq-space-5);
}
.offer-card{
  background: var(--zq-card);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: transform 200ms var(--zq-ease), box-shadow 200ms var(--zq-ease), border-color 200ms var(--zq-ease);
}
.offer-card:hover{
  transform: translateY(-4px);
  box-shadow: var(--zq-glow);
  border-color: rgba(var(--zq-blue-rgb),.45);
}
.offer-media{
  position: relative;
  aspect-ratio: 4/3;
  background: var(--zq-photo-bg);
  /* Las fotos de producto vienen sobre blanco. Sin esta línea, en tema oscuro
     el recuadro blanco parecía un agujero recortado en la tarjeta. */
  border-bottom: 1px solid var(--zq-border);
  /* Contiene el zoom de la foto: sin esto se sale por encima de la insignia
     de descuento y por debajo del borde de la tarjeta. */
  overflow: hidden;
}
/* Zoom muy contenido (1.03, el manual pide 1.02-1.04): la foto respira, el
   encuadre no cambia y el producto sigue siendo el protagonista. */
.offer-media-link img{ transition: transform 220ms var(--zq-ease); }
.offer-card:hover .offer-media-link img{ transform: scale(1.03); }
/* En pantallas táctiles no hay cursor: el hover se queda "pegado" tras tocar
   la tarjeta y la foto se queda ampliada. Se limita a punteros de verdad. */
@media (hover: none){
  .offer-card:hover{ transform: none; box-shadow: none; }
  .offer-card:hover .offer-media-link img{ transform: none; }
}
.offer-media-link{
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 46px;
}
.offer-media-link img{
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: var(--zq-space-4);
}
.offer-badges{
  position: absolute;
  top: var(--zq-space-3);
  left: var(--zq-space-3);
  display: flex;
  gap: var(--zq-space-2);
}
.chip{
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 var(--zq-space-3);
  border-radius: var(--zq-radius-chip);
  font-size: 12px;
  font-weight: 600;
}
/* Píldora azul sólida con texto blanco, como en el manual (§07). El azul
   eléctrico sobre blanco da 4,84:1, así que cumple AA sin necesidad del tono
   profundo que hacía falta cuando la insignia era azul sobre azul hielo. */
.chip-savings{ background: var(--zq-blue); color: var(--zq-white); }
/* Marca y etiquetas editoriales van sobre la FOTO, que puede ser de cualquier
   color: fondo oscuro casi opaco para que se lean sobre una foto clara y
   sobre una oscura sin depender de cuál toque.

   Aquí había un `backdrop-filter: blur(8px)` para que quedara de cristal. Se
   quitó: hay una insignia por tarjeta y veinte tarjetas por pantalla, así que
   eran veinte capas de desenfoque compuestas en cada fotograma del scroll —el
   navegador ni siquiera llegaba a terminar un cuadro estable. El desenfoque de
   verdad se queda donde aporta y solo hay uno: el header (manual §38, "evitar
   blur excesivo"). */
.chip-editorial{
  background: rgba(10,15,28,.82);
  color: var(--zq-white);
}
.chip-urgency{ background: #FDECEA; color: var(--zq-urgency); }
/* Producto sin compra disponible: sigue en el catálogo, con la ficha y el
   precio intactos, pero señalado y sin botón de compra hasta que vuelva
   a haber stock. Se apaga la foto, nunca se oculta la tarjeta. */
.chip-unavailable{ background: var(--zq-surface); color: var(--zq-muted); border: 1px solid var(--zq-border); }
.product-card-unavailable .offer-media img{ opacity: .55; filter: grayscale(.35); }
.product-card-unavailable .offer-price-now{ color: var(--zq-muted); }
.btn-unavailable{ opacity: .75; }
/* Botón de copiar el enlace de afiliado en el panel de administración. */
.link-copy{
  border: 1px solid var(--zq-border);
  background: var(--zq-card);
  color: var(--zq-muted);
  border-radius: 6px;
  cursor: pointer;
  font-size: 12px;
  line-height: 1;
  padding: 3px 5px;
  margin-left: 4px;
}
.link-copy:hover{ color: var(--zq-blue); border-color: var(--zq-blue); }

/* Panel de administración: estado de publicación de un vistazo.
   Solo los productos 'active' se ven en la tienda. */
.estado-pill{
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}
.estado-activo{ color: var(--zq-success); }
.estado-inactivo{ color: var(--zq-muted); }
tr.fila-inactiva > td{ opacity: .72; }
tr.fila-inactiva > td:first-child{ opacity: 1; }
.fav-btn{
  position: absolute;
  top: var(--zq-space-3);
  right: var(--zq-space-3);
  width: 34px; height: 34px;
  border-radius: 50%;
  background: rgba(255,255,255,.92);
  border: 1px solid var(--zq-border);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--zq-muted);
  transition: color var(--zq-motion-fast) var(--zq-ease),
              border-color var(--zq-motion-fast) var(--zq-ease),
              transform var(--zq-motion-fast) var(--zq-ease),
              box-shadow var(--zq-motion-fast) var(--zq-ease);
}
.fav-btn:hover, .fav-btn.active{ color: var(--zq-blue); border-color: var(--zq-blue); }
.fav-btn.active svg{ fill: var(--zq-blue); }
/* Microinteracción del corazón (manual §21 / prompt §21): un pulso de 200ms
   —dentro de los 160-220 que pide— con relleno y un halo mínimo. Nada de
   rebotes: el favorito se guarda, no se celebra. */
.fav-btn:hover{ transform: scale(1.08); }
.fav-btn:active{ transform: scale(.94); }
.fav-btn.active{ box-shadow: 0 0 0 4px rgba(var(--zq-blue-rgb),.12); }
/* El círculo mide 34px por diseño —a 44 taparía media foto—, pero el área que
   responde al dedo llega a 44x44 con una capa invisible por encima. Es lo que
   piden el manual §12 y WCAG 2.5.8, y no cuesta un solo píxel visible. */
.fav-btn::before{
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 44px; height: 44px;
  transform: translate(-50%, -50%);
}
.fav-btn.active svg{ animation: zq-fav-pulse 200ms var(--zq-ease); }
@keyframes zq-fav-pulse{
  0%{ transform: scale(.8); }
  60%{ transform: scale(1.12); }
  100%{ transform: scale(1); }
}

.offer-body{
  padding: var(--zq-space-4);
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1;
}
/* Una sola línea. Rutas largas como "Afeitado y depilación · Afeitadoras
   eléctricas" se iban a dos y esa tarjeta crecía 18px; como la rejilla estira
   toda la fila, una sola descolocaba los precios de las otras tres. El texto
   completo sigue disponible en el `title`. */
.offer-store{
  font-size: 12px;
  color: var(--zq-muted);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.offer-name{
  font-size: 15px;
  font-weight: 600;
  color: var(--zq-text);
  line-height: 1.35;
  min-height: 2.7em;
}
.offer-price-row{
  display: flex;
  align-items: baseline;
  gap: var(--zq-space-2);
  margin-top: 4px;
}
.offer-price-now{ font-size: 20px; font-weight: 700; color: var(--zq-blue); }
.offer-price-was{ font-size: 14px; color: var(--zq-muted); text-decoration: line-through; }
.offer-meta{
  font-size: 12px;
  color: var(--zq-muted);
  margin-top: 2px;
}
.offer-meta.out-of-stock{ color: var(--zq-urgency); }
.offer-cta{
  height: 44px;
  border-radius: var(--zq-radius-button);
  background: var(--zq-blue-strong);
  color: var(--zq-white);
  font-size: 14px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: background 160ms var(--zq-ease), transform 160ms var(--zq-ease);
}
.offer-cta:hover{ background: var(--zq-blue-strong-hover); transform: translateY(-1px); }
.offer-cta.alt{
  background: transparent;
  border: 1px solid var(--zq-border);
  color: var(--zq-text);
}
/* `margin-top:auto` empuja los botones al pie de la tarjeta: con o sin
   especificaciones, con o sin marketplace, la fila de acciones de las cuatro
   tarjetas de una fila queda a la misma altura. */
.offer-actions-row{
  display: flex;
  gap: var(--zq-space-2);
  margin-top: auto;
  padding-top: var(--zq-space-3);
}
.offer-actions-row .offer-cta{ flex: 1; }
.compare-btn{
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: var(--zq-radius-button);
  border: 1px solid var(--zq-border);
  background: var(--zq-card);
  color: var(--zq-muted);
  font-size: 16px;
  transition: border-color 160ms var(--zq-ease), color 160ms var(--zq-ease), background 160ms var(--zq-ease);
}
/* El icono era el carácter "⇄". Satoshi no lo tiene, así que el navegador lo
   sustituía por la primera fuente que sí, y en algunos casos ni eso: se veía
   como dos letras sueltas. Ahora es un SVG y se ve igual en cualquier
   dispositivo, tenga las fuentes que tenga. */
.compare-btn{ display: inline-grid; place-items: center; }
.compare-btn svg{ width: 18px; height: 18px; }
.compare-btn:hover{ border-color: var(--zq-blue); color: var(--zq-blue); }
.compare-btn.active{ background: var(--zq-blue-strong); border-color: var(--zq-blue-strong); color: var(--zq-white); }

/* ==========================================================================
   Categories
   ========================================================================== */
/* Tres columnas, no seis: el manual pide "tarjetas visuales grandes" y un
   máximo de 4-6 por bloque. A seis por fila cada tarjeta se quedaba en 190px
   y no cabía más que un emoji y una palabra.

   Los iconos son SVG de un mismo juego —mismo trazo, misma caja— y todos van
   del mismo azul. Un color distinto por categoría es la solución fácil y es
   exactamente lo que el manual descarta: seis acentos compitiendo destruyen
   la sensación de sistema. */
.category-grid{
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--zq-space-4);
}
.category-card{
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--zq-space-4);
  background: var(--zq-card);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
  padding: var(--zq-space-5);
  overflow: hidden;
  transition: transform var(--zq-motion-fast) var(--zq-ease),
              border-color var(--zq-motion-fast) var(--zq-ease),
              box-shadow var(--zq-motion-fast) var(--zq-ease);
}
/* El halo azul es una capa aparte y no un `background` que cambia: así se
   funde con opacidad —barato para la GPU— en vez de repintar el fondo. */
.category-card::before{
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(420px 180px at 100% 0%, rgba(var(--zq-blue-rgb),.10), transparent 70%);
  opacity: 0;
  transition: opacity var(--zq-motion-base) var(--zq-ease);
  pointer-events: none;
}
.category-card:hover{
  transform: translateY(-4px);
  border-color: rgba(var(--zq-blue-rgb),.45);
  box-shadow: var(--zq-glow);
}
.category-card:hover::before{ opacity: 1; }
/* Sin nada publicado todavía: se atenúa en vez de prometer un escaparate
   que al entrar está vacío. Sigue siendo pulsable —el catálogo puede crecer
   entre una carga y otra— pero no compite con las que sí tienen productos. */
.category-card.is-empty{ opacity: .5; }
.category-card.is-empty:hover{ opacity: 1; }

.category-ico{
  flex: 0 0 52px;
  width: 52px; height: 52px;
  border-radius: 14px;
  background: rgba(var(--zq-blue-rgb),.10);
  color: var(--zq-blue);
  display: grid;
  place-items: center;
  transition: background var(--zq-motion-fast) var(--zq-ease);
}
.category-ico svg{ width: 24px; height: 24px; }
.category-card:hover .category-ico{ background: rgba(var(--zq-blue-rgb),.18); }

.category-body{ display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.category-card .name{ font-size: 17px; font-weight: 600; color: var(--zq-text); }
.category-card .desc{ font-size: 13.5px; color: var(--zq-muted); }
.category-card .count{ font-size: 12px; color: var(--zq-blue); font-weight: 600; margin-top: 4px; }
.category-go{
  margin-left: auto;
  color: var(--zq-muted);
  font-size: 18px;
  transition: transform var(--zq-motion-fast) var(--zq-ease), color var(--zq-motion-fast) var(--zq-ease);
}
.category-card:hover .category-go{ transform: translateX(4px); color: var(--zq-blue); }

/* ==========================================================================
   Editorial tabs
   ========================================================================== */
.tab-bar{
  display: flex;
  gap: var(--zq-space-2);
  flex-wrap: wrap;
}
.tab-btn{
  height: 40px;
  padding: 0 var(--zq-space-4);
  border-radius: var(--zq-radius-chip);
  border: 1px solid var(--zq-border);
  background: var(--zq-card);
  font-size: 14px;
  font-weight: 500;
  color: var(--zq-muted);
  transition: all 160ms var(--zq-ease);
}
.tab-btn:hover{ border-color: var(--zq-blue); color: var(--zq-text); }
.tab-btn.active{ background: var(--zq-blue-strong); border-color: var(--zq-blue-strong); color: var(--zq-white); }

/* ==========================================================================
   Trust section
   ========================================================================== */
.trust-section{
  background: var(--zq-surface);
}
.trust-grid{
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--zq-space-5);
}
.trust-card{
  background: var(--zq-card);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
  padding: var(--zq-space-5);
}
.trust-card .icon{
  width: 44px; height: 44px;
  border-radius: 12px;
  background: var(--zq-ice);
  color: var(--zq-blue);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--zq-space-4);
}
.trust-card h3{ margin-bottom: var(--zq-space-2); }
.trust-card p{ color: var(--zq-muted); font-size: 14.5px; }

.disclosure-banner{
  display: flex;
  align-items: flex-start;
  gap: var(--zq-space-3);
  background: var(--zq-ice);
  border: 1px solid rgba(var(--zq-blue-rgb),.18);
  border-radius: var(--zq-radius-card);
  padding: var(--zq-space-5);
  margin-top: var(--zq-space-6);
}
.disclosure-banner svg{ color: var(--zq-blue); flex-shrink: 0; margin-top: 2px; }
/* Color fijo, no --zq-text: el fondo del banner es azul claro en ambos temas
   y en oscuro el texto claro sobre azul claro quedaba ilegible. */
.disclosure-banner p{ font-size: 14.5px; color: var(--zq-bg-dark); }
.disclosure-banner a{ color: var(--zq-blue); font-weight: 600; }

/* ==========================================================================
   Newsletter
   ========================================================================== */
.newsletter{
  background: linear-gradient(135deg, var(--zq-bg-dark), var(--zq-surface-dark));
  color: var(--zq-white);
  border-radius: var(--zq-radius-modal);
  padding: var(--zq-space-7);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--zq-space-6);
  flex-wrap: wrap;
}
.newsletter-copy{ max-width: 480px; }
.newsletter-copy .eyebrow{ color: var(--zq-blue-soft); }
.newsletter-copy h2{ color: var(--zq-white); margin-bottom: var(--zq-space-2); }
.newsletter-copy p{ color: rgba(255,255,255,.68); font-size: 15px; }
.newsletter-form{
  display: flex;
  gap: var(--zq-space-3);
  flex: 1;
  min-width: 280px;
  max-width: 440px;
}
.newsletter-form input{
  flex: 1;
  min-width: 0;
  height: 50px;
  border-radius: var(--zq-radius-button);
  border: 1px solid var(--zq-border-dark);
  background: rgba(255,255,255,.06);
  color: var(--zq-white);
  padding: 0 var(--zq-space-4);
  font-size: 14px;
}
.newsletter-form input::placeholder{ color: rgba(255,255,255,.5); }
.newsletter-form input:focus{ outline: none; border-color: var(--zq-blue-soft); }
.form-note{ font-size: 12.5px; color: rgba(255,255,255,.5); margin-top: var(--zq-space-2); }
.form-success{ font-size: 14px; color: var(--zq-blue-soft); margin-top: var(--zq-space-2); display: none; }
.form-success.show{ display: block; }

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer{
  background: var(--zq-bg-dark);
  color: rgba(255,255,255,.7);
  padding: var(--zq-space-8) 0 var(--zq-space-5);
}
.footer-top{
  display: grid;
  /* Cinco bloques desde que el pie sigue la estructura del manual §42:
     marca + Explorar, Ayuda, Mi cuenta y Legal. Con las cuatro columnas de
     antes, "Legal" caía a una segunda fila debajo de la marca. */
  grid-template-columns: minmax(0, 1.5fr) repeat(4, minmax(0, 1fr));
  gap: var(--zq-space-6);
  padding-bottom: var(--zq-space-7);
  border-bottom: 1px solid var(--zq-border-dark);
}
.footer-brand .zq-brand{ margin-bottom: var(--zq-space-4); }
.footer-brand p{ font-size: 14px; color: rgba(255,255,255,.55); max-width: 300px; margin-bottom: var(--zq-space-4); }
.footer-social{ display: flex; gap: var(--zq-space-2); }
.footer-social a{
  width: 38px; height: 38px;
  border-radius: 10px;
  border: 1px solid var(--zq-border-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color 160ms var(--zq-ease), color 160ms var(--zq-ease);
}
.footer-social a:hover{ border-color: var(--zq-blue-soft); color: var(--zq-blue-soft); }
.footer-col h4{
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: rgba(255,255,255,.9);
  margin-bottom: var(--zq-space-4);
}
.footer-col ul{ display: grid; gap: var(--zq-space-3); }
.footer-col a{ font-size: 14px; color: rgba(255,255,255,.6); transition: color 160ms var(--zq-ease); }
.footer-col a:hover{ color: var(--zq-blue-soft); }
.footer-bottom{
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: var(--zq-space-5);
  flex-wrap: wrap;
  gap: var(--zq-space-3);
}
.footer-bottom p{ font-size: 13px; color: rgba(255,255,255,.45); }
.footer-disclosure{ font-size: 13px; color: rgba(255,255,255,.45); max-width: 640px; }

/* ==========================================================================
   Filters (ofertas.html)
   ========================================================================== */
.filters-bar{
  display: flex;
  align-items: center;
  gap: var(--zq-space-3);
  flex-wrap: wrap;
  margin-bottom: var(--zq-space-6);
  padding: var(--zq-space-4);
  background: var(--zq-surface);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
}
.filters-bar select, .filters-bar .search-mini input{
  height: 42px;
  border-radius: 12px;
  border: 1px solid var(--zq-border);
  background: var(--zq-card);
  padding: 0 var(--zq-space-3);
  cursor: pointer;
  font-size: 14px;
  color: var(--zq-text);
}
.search-mini{ position: relative; flex: 1 1 220px; min-width: 0; }
/* Mas especifico que la regla de .filters-bar, para reservar el hueco del icono. */
.filters-bar .search-mini input, .search-mini input{ width: 100%; padding-left: 40px; cursor: text; }
.search-mini svg{ position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--zq-muted); pointer-events: none; }
.results-count{ font-size: 13px; color: var(--zq-muted); margin-left: auto; }

/* Estados vacíos y de error (manual §33-34).
   Ocupan TODA la rejilla, no una celda: dentro de un `grid` de cuatro
   columnas, un aviso sin `grid-column` se metía en la primera columna y salía
   una tira de texto de 300px de ancho en el borde izquierdo.
   Nunca se deja una pantalla en blanco y nunca se enseña el error técnico:
   siempre hay una frase que explica qué pasó y una salida a la que ir. */
.empty-state{
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--zq-space-3);
  text-align: center;
  padding: var(--zq-space-8) var(--zq-space-5);
  border: 1px dashed var(--zq-border);
  border-radius: var(--zq-radius-card);
  background: var(--zq-surface);
  color: var(--zq-muted);
  font-size: 15px;
}
.empty-state p{ max-width: 46ch; }
.empty-state a{ color: var(--zq-blue); font-weight: 600; }
.empty-state .empty-ico{
  width: 48px; height: 48px;
  border-radius: 14px;
  background: var(--zq-card);
  border: 1px solid var(--zq-border);
  color: var(--zq-blue);
  display: grid;
  place-items: center;
}
.empty-state .empty-ico svg{ width: 22px; height: 22px; }
.empty-state strong{ color: var(--zq-text); font-size: 17px; font-weight: 600; }

/* ==========================================================================
   Simple content pages
   ========================================================================== */
/* La cabecera de las páginas interiores es el mismo navy del hero con un solo
   halo en vez de dos: mismo idioma visual, menos peso, porque aquí lo que
   importa es lo que hay debajo. */
.page-hero{
  position: relative;
  background: linear-gradient(180deg, var(--zq-bg-dark), var(--zq-surface-dark));
  color: var(--zq-white);
  padding: var(--zq-space-8) 0 var(--zq-space-7);
  overflow: hidden;
}
.page-hero::before{
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(760px 320px at 88% -20%, rgba(var(--zq-blue-light-rgb),.20), transparent 65%);
  pointer-events: none;
}
.page-hero .container{ position: relative; z-index: 1; }
.page-hero .eyebrow{ color: var(--zq-blue-soft); }
.page-hero h1{ color: var(--zq-white); }
.page-hero p{ color: rgba(255,255,255,.7); max-width: 620px; margin-top: var(--zq-space-3); }

.content-block{ max-width: 780px; }
.content-block h2{ margin-top: var(--zq-space-7); margin-bottom: var(--zq-space-3); }
.content-block h2:first-child{ margin-top: 0; }
.content-block p{ color: var(--zq-muted); margin-bottom: var(--zq-space-3); }
.content-block ul{ display: grid; gap: var(--zq-space-2); margin-bottom: var(--zq-space-3); }
.content-block li{ color: var(--zq-muted); padding-left: var(--zq-space-4); position: relative; }
.content-block li::before{
  content: "";
  position: absolute;
  left: 0; top: 10px;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--zq-blue);
}

.method-steps{ display: grid; gap: var(--zq-space-4); }
.method-step{
  display: flex;
  gap: var(--zq-space-4);
  padding: var(--zq-space-5);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
}
.method-step .num{
  width: 36px; height: 36px;
  border-radius: 10px;
  background: var(--zq-ice);
  color: var(--zq-blue);
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 1023px){
  .offers-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Dos columnas, no tres: la tarjeta de categoría es horizontal (icono +
     texto + flecha) y por debajo de 340px de ancho el microcopy se parte. */
  .category-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* La barra de confianza pasa a 2x2. Los separadores verticales se rehacen:
     con cuatro en fila el borde iba en `li + li`, y en rejilla eso deja una
     línea colgando a la izquierda de la segunda fila. */
  .trust-bar{ margin-top: calc(var(--zq-space-6) * -1); }
  .trust-bar-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--zq-space-4); }
  .trust-bar-grid li + li{ border-left: none; }
  .trust-bar-grid li{ padding: 0; }
  .compare-pitch .container{ grid-template-columns: minmax(0, 1fr); gap: var(--zq-space-6); padding: var(--zq-space-6); }
  .trust-grid{ grid-template-columns: minmax(0, 1fr); }
  .footer-top{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero .container{ grid-template-columns: minmax(0, 1fr); }
  /* En una sola columna el titular manda. Con `order:-1` el bloque de fotos
     subía al principio y quien llegaba desde el móvil se encontraba 96px de
     hueco, una sudadera, y el titular —lo que explica qué es esto— por debajo
     del borde de la pantalla. */
  .hero{ padding: var(--zq-space-7) 0 var(--zq-space-7); }
  .hero .container{ gap: var(--zq-space-6); }
  /* A una sola columna, el carrusel no debe estirarse a todo el ancho: a
     1023px un panel 4:3 mediría 700px de alto y taparía el resto de la home. */
  .hero-visual{ max-width: 520px; width: 100%; margin: 0 auto; }
  .main-nav{ display: none; }
  .header-search{ display: none; }
}

@media (max-width: 639px){
  section{ padding: var(--zq-space-7) 0; }
  .offers-grid{ grid-template-columns: minmax(0, 1fr); }
  .category-grid{ grid-template-columns: minmax(0, 1fr); }
  .trust-bar-grid{ grid-template-columns: minmax(0, 1fr); padding: var(--zq-space-4); }

  /* Hero en móvil (manual §12 y prompt §36): menos aire, titular algo menor y
     los dos CTA a lo ancho, que es lo que se puede pulsar con el pulgar. */
  .hero{ padding: var(--zq-space-6) 0 var(--zq-space-7); }
  .hero-copy h1{ font-size: clamp(32px, 9vw, 40px); }
  .hero-copy p{ font-size: 16px; }
  .hero-actions{ flex-direction: column; align-items: stretch; }
  .hero-actions .btn{ width: 100%; }

  /* El buscador ocupa prácticamente todo el ancho y el botón pasa a icono: con
     la palabra "Buscar" dentro solo quedaban 150px para el campo y el
     marcador de posición se cortaba a la mitad. El icono decorativo de la
     izquierda desaparece porque el botón ya dice lo mismo. */
  .hero-search{ padding-left: var(--zq-space-3); max-width: none; }
  .hero-search > svg{ display: none; }
  .hero-search .btn{ width: 44px; padding: 0; }
  .hero-search-ico{ display: block; }
  /* Se oculta A LA VISTA, no al lector de pantalla. Con `display:none` el
     texto sale del árbol de accesibilidad y el botón se queda sin nombre: en
     móvil sería un botón azul que no se anuncia como nada. */
  .hero-search-txt{
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* El carrusel no puede llevarse media pantalla antes de la primera sección:
     el escenario pasa de 4:3 a algo más bajo y el producto sigue entero. */
  .hero-slide-stage{ aspect-ratio: 16 / 11; padding: var(--zq-space-5); }
  .hero-slide-name{ font-size: 15px; }
  .hero-slide-price .now{ font-size: 20px; }
  .footer-top{ grid-template-columns: minmax(0, 1fr); }
  .newsletter{ flex-direction: column; align-items: stretch; }
  .newsletter-form{ max-width: none; flex-direction: column; }
  .newsletter-form input{ min-width: 0; }
  .offer-cta{ width: 100%; }
  .site-header .container{ height: 68px; gap: var(--zq-space-2); }
  .header-actions{ gap: var(--zq-space-2); }
  .header-actions .icon-btn{ display: none; }
  .btn-sm{ padding: 0 var(--zq-space-3); }
  .filters-bar{ flex-direction: column; align-items: stretch; }
  .filters-bar select{ width: 100%; }
  /* En columna, `flex: 1 1 220px` pasa a fijar el ALTO del contenedor: la caja
     medía 220px y el icono, centrado al 50%, quedaba muy por debajo del campo. */
  .filters-bar .search-mini{ flex: 0 0 auto; width: 100%; }
  .results-count{ margin-left: 0; }
}

/* Mobile nav drawer */
.mobile-nav{
  position: fixed;
  inset: 0;
  background: var(--zq-bg-dark);
  z-index: 100;
  display: none;
  flex-direction: column;
  padding: var(--zq-space-5);
  color: var(--zq-white);
}
.mobile-nav.open{ display: flex; }
.mobile-nav-head{
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--zq-space-6);
}
.mobile-nav a{
  font-size: 20px;
  font-weight: 600;
  padding: var(--zq-space-3) 0;
  border-bottom: 1px solid var(--zq-border-dark);
}
.mobile-nav .close-btn{
  width: 42px; height: 42px;
  border-radius: 12px;
  border: 1px solid var(--zq-border-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--zq-white);
}
.mobile-nav-auth{
  margin-top: auto;
  padding-top: var(--zq-space-5);
  display: grid;
  gap: var(--zq-space-2);
}
.mobile-nav-auth a, .mobile-nav-auth button{
  font-size: 16px;
  font-weight: 600;
  color: var(--zq-white);
  text-align: left;
  background: rgba(255,255,255,.06);
  border: 1px solid var(--zq-border-dark);
  border-radius: 12px;
  padding: var(--zq-space-3) var(--zq-space-4);
}
.mobile-nav-auth a.primary{
  background: var(--zq-blue-strong);
  border-color: var(--zq-blue);
  text-align: center;
}

/* ==========================================================================
   Auth slot / avatar (header)
   ========================================================================== */
.auth-slot{ display: flex; align-items: center; gap: var(--zq-space-2); }
.avatar-menu{ position: relative; }
.avatar-btn{
  width: 42px; height: 42px;
  border-radius: 50%;
  border: none;
  background: transparent;
  padding: 0;
}
.avatar-circle{
  width: 42px; height: 42px;
  border-radius: 50%;
  background: var(--zq-blue);
  color: var(--zq-white);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 15px;
}
/* El ancho lo manda el conmutador de tema, que es el elemento más ancho del
   menú: sus tres botones (Claro / Oscuro / Sistema) miden 278px juntos y no
   pueden encogerse sin recortar las etiquetas. Con los 240px de antes, la
   columna del grid se estiraba a 302px —un grid coge como mínimo el
   `min-content` de su contenido— y como el fondo y el borde se pintan sobre
   la caja de 240, TODAS las filas sobresalían 71px por la derecha: el
   resaltado al pasar el cursor y las líneas separadoras se salían del panel.

   `grid-template-columns: minmax(0, 1fr)` es el cinturón de seguridad: fija
   el mínimo de la columna en 0, así que aunque mañana entre aquí algo más
   ancho, se ajustará en vez de desbordar el recuadro. */
.dropdown-menu{
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  /* 312 y no 296: con el ancho justo, la caja del texto queda 0,02px por
     debajo de lo que mide la etiqueta —el navegador redondea hacia abajo— y eso
     basta para que "Sistema" salga como "Siste…". Se deja holgura de verdad. */
  width: 312px;
  max-width: calc(100vw - var(--zq-space-5));
  background: var(--zq-card);
  border: 1px solid var(--zq-border);
  border-radius: 16px;
  box-shadow: var(--zq-shadow-card);
  padding: var(--zq-space-2);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  z-index: 60;
}
/* En el móvil el avatar no está pegado al borde —comparte sitio con el botón
   Menú— así que un panel anclado a su derecha con 312px de ancho se salía 63px
   por la IZQUIERDA de la pantalla. Aquí deja de colgar del avatar y se ancla a
   la ventana, con el mismo margen por los dos lados. */
@media (max-width: 639px){
  .dropdown-menu{
    position: fixed;
    top: 76px;
    right: var(--zq-space-3);
    left: var(--zq-space-3);
    width: auto;
    max-width: none;
  }
}

.dropdown-user{
  padding: var(--zq-space-3) var(--zq-space-3) var(--zq-space-2);
  border-bottom: 1px solid var(--zq-border);
  margin-bottom: var(--zq-space-2);
  display: grid;
}
.dropdown-user strong{ font-size: 14px; }
/* Un correo largo es una sola palabra sin puntos de corte: sin esto empujaría
   el ancho del panel igual que hacía el conmutador. */
.dropdown-user span{
  font-size: 12.5px;
  color: var(--zq-muted);
  overflow-wrap: anywhere;
}
/* Hijos DIRECTOS, no cualquier descendiente. El conmutador de tema vive
   dentro de este menú, así que `.dropdown-menu button` alcanzaba también a sus
   tres botones y les imponía `width: 100%`: con eso, `flex-basis: auto` se
   resolvía a "todos iguales" y "Sistema" se recortaba mientras a "Claro" le
   sobraba sitio. También les metía el color rojo de Cerrar sesión, que solo se
   salvaba porque `.theme-switch button` viene más abajo en el archivo. */
.dropdown-menu > a, .dropdown-menu > button{
  display: block;
  width: 100%;
  text-align: left;
  padding: var(--zq-space-2) var(--zq-space-3);
  border-radius: 10px;
  font-size: 14px;
  font-weight: 500;
  color: var(--zq-text);
  background: none;
  border: none;
}
.dropdown-menu > a:hover, .dropdown-menu > button:hover{ background: var(--zq-surface); color: var(--zq-blue); }
.dropdown-menu > button{ color: var(--zq-urgency); }
/* Los botones de un flex no bajan de su `min-content` a menos que se les
   permita: en una pantalla estrecha, donde el panel se acota a la ventana,
   esto deja que se repartan el hueco y recorten la etiqueta en vez de
   desbordar el menú otra vez. */
/* La regla base es `flex: 1`, que reparte el ancho en tres partes IGUALES sin
   mirar cuánto ocupa cada etiqueta: "Claro" sobraba de espacio mientras
   "Sistema" se cortaba por menos de un píxel. Con `1 1 auto` cada botón parte
   de su propio texto y solo se reparten el sobrante, así que ninguna etiqueta
   se recorta y la fila se adapta sola si el idioma cambia.
   `min-width: 0` sigue siendo la red de seguridad: en una pantalla muy
   estrecha se recortan con puntos suspensivos en vez de desbordar el panel. */
.dropdown-theme .theme-switch button{
  flex: 1 1 auto;
  min-width: 0;
  /* Los 12px de costado que usa el conmutador en el menú móvil y en el
     sidebar, donde tiene el ancho de la pantalla, no caben aquí: son 24px por
     botón contra un panel de 296. Con 8 entran las tres etiquetas enteras. */
  padding: 0 var(--zq-space-2);
}
.dropdown-theme .theme-switch button span{ overflow: hidden; text-overflow: ellipsis; }

/* ==========================================================================
   Auth pages (login / registro)
   ========================================================================== */
.auth-section{
  min-height: 60vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--zq-space-8) var(--zq-space-5);
}
.auth-card{
  width: 100%;
  max-width: 420px;
  background: var(--zq-card);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
  box-shadow: var(--zq-shadow-card);
  padding: var(--zq-space-7);
}
.auth-switch{ margin-top: var(--zq-space-5); font-size: 14px; color: var(--zq-muted); text-align: center; }
.auth-switch a{ color: var(--zq-blue); font-weight: 600; }

.field{ display: grid; gap: 6px; margin-bottom: var(--zq-space-4); }
.field label{ font-size: 13px; font-weight: 600; color: var(--zq-text); }
.field input, .field select{
  height: 46px;
  border-radius: 12px;
  border: 1px solid var(--zq-border);
  padding: 0 var(--zq-space-4);
  font-size: 14.5px;
  font-family: var(--zq-font);
  color: var(--zq-text);
  background: var(--zq-card);
}
.field input:focus, .field select:focus{ outline: none; border-color: var(--zq-blue); }
.field input:disabled{ background: var(--zq-surface); color: var(--zq-muted); }
.field-hint{ font-size: 12.5px; color: var(--zq-muted); }

/* Campo de contraseña con botón de mostrar/ocultar (js/password-toggle.js).
   El input reserva a la derecha el hueco del botón para que el texto no pase
   por debajo del ojo, incluso con una contraseña larga. */
.password-field{ position: relative; display: block; }
.password-field input{ width: 100%; padding-right: 46px; }
.password-toggle{
  position: absolute;
  top: 0;
  right: 0;
  width: 44px;
  height: 46px;
  display: grid;
  place-items: center;
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  color: var(--zq-muted);
  border-radius: 0 12px 12px 0;
}
.password-toggle svg{ width: 20px; height: 20px; }
.password-toggle:hover{ color: var(--zq-text); }
.password-toggle:focus-visible{ outline: 2px solid var(--zq-blue); outline-offset: -2px; }
.password-toggle[aria-pressed="true"]{ color: var(--zq-blue); }
.form-error{ font-size: 13.5px; color: var(--zq-urgency); min-height: 0; margin: 0 0 var(--zq-space-3); }
.form-error:empty{ display: none; }
.stacked-form{ max-width: 440px; }

/* ==========================================================================
   Panel de usuario (cuenta.html)
   ========================================================================== */
.account-layout{
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: var(--zq-space-7);
  align-items: start;
}
.account-nav{
  display: grid;
  gap: 4px;
  position: sticky;
  top: 96px;
}
.account-tab{
  text-align: left;
  padding: var(--zq-space-3) var(--zq-space-4);
  border-radius: 12px;
  border: none;
  background: none;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--zq-muted);
}
.account-tab:hover{ background: var(--zq-surface); color: var(--zq-text); }
.account-tab.active{ background: var(--zq-ice); color: var(--zq-blue); font-weight: 600; }
.account-content{ min-width: 0; }
.account-panel h2{ margin-bottom: var(--zq-space-5); }

.checkbox-grid{ display: flex; flex-wrap: wrap; gap: var(--zq-space-2); margin-top: 6px; }
.checkbox-pill{
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: var(--zq-space-2) var(--zq-space-4);
  border-radius: var(--zq-radius-chip);
  border: 1px solid var(--zq-border);
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
}
.checkbox-pill:has(input:checked){ border-color: var(--zq-blue); background: var(--zq-ice); color: var(--zq-blue); }

.switch-row{ display: flex; align-items: center; gap: var(--zq-space-3); font-size: 14.5px; margin-bottom: var(--zq-space-3); cursor: pointer; }
.radio-row{ display: flex; gap: var(--zq-space-5); margin-top: 6px; font-size: 14.5px; }
.radio-row label{ display: flex; align-items: center; gap: 6px; cursor: pointer; }

.alert-row{
  display: flex;
  align-items: center;
  gap: var(--zq-space-4);
  padding: var(--zq-space-4);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
  margin-bottom: var(--zq-space-3);
}
.alert-row-media{
  width: 48px; height: 48px;
  border-radius: 12px;
  background: var(--zq-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  flex-shrink: 0;
}
.alert-row-info{ display: grid; gap: 2px; flex: 1; min-width: 0; }
.alert-row-info a{ font-size: 14.5px; font-weight: 600; color: var(--zq-text); }
.alert-row-info a:hover{ color: var(--zq-blue); }
.alert-row-info span{ font-size: 12.5px; }
.alert-row-target{ text-align: right; font-size: 12.5px; color: var(--zq-muted); }
.alert-row-target strong{ display: block; font-size: 15px; color: var(--zq-text); }

/* ==========================================================================
   Producto (detalle)
   ========================================================================== */
.product-detail{
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
  gap: var(--zq-space-7);
}
.product-media{
  aspect-ratio: 1/1;
  background: var(--zq-photo-bg);
  border-radius: var(--zq-radius-card);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 96px;
  position: relative;
}
.product-media .offer-badges{ position: absolute; top: var(--zq-space-4); left: var(--zq-space-4); display: flex; gap: var(--zq-space-2); }
.product-media img{
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: var(--zq-space-6);
  border-radius: var(--zq-radius-card);
}
.product-info{ display: flex; flex-direction: column; }
.product-price-row{ display: flex; align-items: baseline; gap: var(--zq-space-3); margin: var(--zq-space-3) 0 4px; }
.product-price-now{ font-size: 34px; font-weight: 700; color: var(--zq-blue); }
.product-actions{ display: flex; align-items: center; gap: var(--zq-space-3); margin-top: var(--zq-space-5); flex-wrap: wrap; }
.fav-btn.large{ position: static; width: 50px; height: 50px; }
.disclosure-inline{ font-size: 13px; color: var(--zq-muted); margin-top: var(--zq-space-4); max-width: 480px; }

.alert-form-card{
  margin-top: var(--zq-space-6);
  padding: var(--zq-space-5);
  background: var(--zq-surface);
  border-radius: var(--zq-radius-card);
  max-width: 460px;
}
.alert-form-card h3{ margin-bottom: 4px; }
.alert-form-card p{ margin-bottom: var(--zq-space-4); }
.alert-form-card form{ display: flex; gap: var(--zq-space-3); }
.alert-form-card input{
  flex: 1;
  min-width: 0;
  height: 46px;
  border-radius: 12px;
  border: 1px solid var(--zq-border);
  padding: 0 var(--zq-space-4);
  font-size: 14.5px;
  font-family: var(--zq-font);
}
.alert-form-card input:focus{ outline: none; border-color: var(--zq-blue); }
.alert-form-card .form-success, .alert-form-card .form-error{ margin-top: var(--zq-space-3); }

.price-chart-card{
  background: var(--zq-card);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
  padding: var(--zq-space-5);
}
#price-chart{ width: 100%; height: 220px; display: block; }
.price-chart-labels{
  display: flex;
  justify-content: space-between;
  margin-top: var(--zq-space-3);
  font-size: 12.5px;
  color: var(--zq-muted);
}
.price-chart-minmax{ font-weight: 600; color: var(--zq-text); }

/* ==========================================================================
   Comparador
   ========================================================================== */
.table-scroll{ overflow-x: auto; border: 1px solid var(--zq-border); border-radius: var(--zq-radius-card); }
.compare-table{ width: 100%; border-collapse: collapse; min-width: 640px; }
.compare-table th, .compare-table td{ padding: var(--zq-space-4); text-align: left; border-bottom: 1px solid var(--zq-border); font-size: 14px; }
.compare-table thead th{ background: var(--zq-surface); vertical-align: top; position: relative; min-width: 160px; }
.compare-table tbody th{ color: var(--zq-muted); font-weight: 600; font-size: 13px; white-space: nowrap; background: var(--zq-card); }
.compare-media{ font-size: 32px; margin: var(--zq-space-2) 0; }
.compare-media img{ width: 100%; max-width: 140px; height: 90px; object-fit: contain; }
.compare-remove{
  position: absolute;
  top: var(--zq-space-2);
  right: var(--zq-space-2);
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 1px solid var(--zq-border);
  background: var(--zq-card);
  color: var(--zq-muted);
  font-size: 12px;
}
.compare-table thead th a{ font-weight: 600; color: var(--zq-text); }
.compare-price{ font-weight: 700; font-size: 16px; }
.compare-price.best{ color: var(--zq-blue); }
.compare-price .chip{ display: block; width: max-content; margin-top: 6px; }

/* ==========================================================================
   Bandeja flotante del comparador
   ========================================================================== */
.compare-tray{
  position: fixed;
  left: 50%;
  bottom: var(--zq-space-5);
  transform: translateX(-50%);
  z-index: 70;
  background: var(--zq-bg-dark);
  color: var(--zq-white);
  border-radius: var(--zq-radius-chip);
  padding: var(--zq-space-3) var(--zq-space-3) var(--zq-space-3) var(--zq-space-5);
  display: flex;
  align-items: center;
  gap: var(--zq-space-4);
  box-shadow: 0 16px 40px rgba(8,17,31,.35);
  font-size: 14px;
}
.compare-tray-actions{ display: flex; gap: var(--zq-space-2); }

/* ==========================================================================
   Catálogo de productos (Misión 1: cámaras Mirrorless)
   ========================================================================== */
/* El resumen ocupa SIEMPRE dos líneas: ni una ni tres.
   Con `min-height` solo, un resumen largo se iba a tres líneas y esa tarjeta
   crecía; como la rejilla estira toda la fila, una sola tarjeta desalineaba
   los precios y los botones de las otras tres. Recortado a dos, todas las
   tarjetas miden lo mismo y los precios caen sobre la misma línea. */
.product-highlight{
  font-size: 13.5px;
  color: var(--zq-muted);
  line-height: 1.4;
  margin: 2px 0;
  min-height: 2.8em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Una sola línea, sin envolver: dos productos de la misma fila con distinto
   número de datos dejaban los botones a alturas distintas. */
/* Línea de tienda y disponibilidad. El manual (§07) la pone entre lo que la
   tarjeta debe responder "rápidamente": dónde compro. Por eso el nombre de la
   tienda va en peso medio y con el color del texto, no en gris de nota al pie
   como el resto de la línea. */
.product-mini-specs{
  font-size: 12.5px;
  color: var(--zq-muted);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.product-mini-specs span:first-of-type{ color: var(--zq-text); font-weight: 500; }
.editorial-highlight{ font-size: 16px; color: var(--zq-muted); margin: 4px 0 var(--zq-space-3); max-width: 480px; }

.ideal-for-card{
  margin-top: var(--zq-space-5);
  padding: var(--zq-space-4) var(--zq-space-5);
  background: var(--zq-ice);
  border-radius: 14px;
  font-size: 14px;
  max-width: 480px;
  /* Color fijo, no --zq-text: el fondo es azul claro en ambos temas y en
     oscuro el texto claro sobre azul claro quedaba ilegible (contraste 1,01).
     Misma regla que .disclosure-banner p. */
  color: var(--zq-bg-dark);
}
.ideal-for-card strong{ color: var(--zq-blue); }

.spec-table{ width: 100%; border-collapse: collapse; min-width: 480px; }
.spec-table tr{ border-bottom: 1px solid var(--zq-border); }
.spec-table th, .spec-table td{ padding: var(--zq-space-3) var(--zq-space-4); text-align: left; font-size: 14px; }
.spec-table th{ width: 45%; color: var(--zq-muted); font-weight: 500; }
.spec-table td{ font-weight: 600; }

.pros-cons-grid{ display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--zq-space-5); }
.pros-card, .cons-card{ padding: var(--zq-space-5); border-radius: var(--zq-radius-card); border: 1px solid var(--zq-border); }
.pros-card{ background: rgba(34,160,107,.06); }
.cons-card{ background: rgba(217,45,32,.05); }
.pros-card h3{ color: var(--zq-success); margin-bottom: var(--zq-space-3); }
.cons-card h3{ color: var(--zq-urgency); margin-bottom: var(--zq-space-3); }
.pros-card ul, .cons-card ul{ display: grid; gap: var(--zq-space-2); }
.pros-card li, .cons-card li{ font-size: 14px; padding-left: var(--zq-space-4); position: relative; color: var(--zq-text); }
.pros-card li::before{ content: "✓"; position: absolute; left: 0; color: var(--zq-success); font-weight: 700; }
.cons-card li::before{ content: "–"; position: absolute; left: 0; color: var(--zq-urgency); font-weight: 700; }

@media (max-width: 639px){
  .pros-cons-grid{ grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 1023px){
  .product-detail{ grid-template-columns: minmax(0, 1fr); }
  .product-media{ aspect-ratio: 16/9; font-size: 72px; }
  .account-layout{ grid-template-columns: minmax(0, 1fr); }
  .account-nav{ position: static; display: flex; overflow-x: auto; gap: var(--zq-space-2); padding-bottom: 4px; }
  .account-tab{ white-space: nowrap; }
}

@media (max-width: 639px){
  .auth-card{ padding: var(--zq-space-5); }
  .alert-form-card form{ flex-direction: column; }
  .compare-tray{ flex-direction: column; align-items: stretch; text-align: center; left: var(--zq-space-4); right: var(--zq-space-4); bottom: var(--zq-space-4); transform: none; }
  .alert-row{ flex-wrap: wrap; }
  .alert-row-target{ text-align: left; }
}

/* ==========================================================================
   Selector internacional (país · idioma · marketplace)
   ========================================================================== */
.intl-selector{ position: relative; }
.intl-btn{
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 40px;
  padding: 0 var(--zq-space-3);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-chip);
  background: var(--zq-card);
  color: var(--zq-text);
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.intl-btn:hover{ border-color: rgba(var(--zq-blue-rgb),.35); background: var(--zq-surface); }
.intl-btn-label{ max-width: 190px; overflow: hidden; text-overflow: ellipsis; }

.intl-panel{
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 80;
  width: min(320px, calc(100vw - 32px));
  padding: var(--zq-space-4);
  display: grid;
  gap: var(--zq-space-3);
  background: var(--zq-card);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
  box-shadow: var(--zq-shadow-card);
}
.intl-panel[hidden]{ display: none; }
.intl-field{ display: grid; gap: 6px; }
.intl-field > span{ font-size: 12px; font-weight: 600; color: var(--zq-muted); }
.intl-field select{
  width: 100%;
  height: 40px;
  padding: 0 var(--zq-space-3);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-button);
  background: var(--zq-card);
  color: var(--zq-text);
  font-size: 14px;
}
.intl-apply{ width: 100%; justify-content: center; }

/* Dentro del menú móvil el panel va siempre desplegado y a ancho completo. */
.mobile-nav-intl{ margin: var(--zq-space-4) 0; }
.mobile-nav-intl .intl-btn{ width: 100%; justify-content: center; }
.mobile-nav-intl .intl-panel{ position: static; width: 100%; margin-top: var(--zq-space-3); box-shadow: none; }

@media (max-width: 1023px){
  /* Por debajo de 1024 el selector de país vive en el menú lateral: en el
     header no cabe sin apretar el resto de los controles. */
  .header-actions #intl-selector-mount{ display: none; }
}

/* Insignia del marketplace en tarjetas y fichas */
.marketplace-badge{
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: var(--zq-muted);
  white-space: nowrap;
}
.price-approx{ font-size: 12px; color: var(--zq-muted); }

/* Soporte de escritura de derecha a izquierda (árabe) */
[dir="rtl"] .intl-panel{ right: auto; left: 0; }
[dir="rtl"] .offer-badges{ left: auto; right: var(--zq-space-3); }
[dir="rtl"] .fav-btn{ right: auto; left: var(--zq-space-3); }


/* ==========================================================================
   Selector de tema (claro / oscuro / sistema)
   ========================================================================== */
.theme-switch{
  display: flex;
  gap: 4px;
  padding: 4px;
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-chip);
  background: var(--zq-surface);
}
.theme-switch button{
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 34px;
  padding: 0 var(--zq-space-3);
  border: none;
  border-radius: var(--zq-radius-chip);
  background: transparent;
  color: var(--zq-muted);
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
}
.theme-switch button[aria-pressed="true"]{
  background: var(--zq-card);
  color: var(--zq-text);
  font-weight: 600;
  box-shadow: 0 1px 3px rgba(8,17,31,.12);
}

.dropdown-theme{
  padding: var(--zq-space-2) var(--zq-space-3) var(--zq-space-3);
  border-top: 1px solid var(--zq-border);
  margin-top: var(--zq-space-2);
}
.dropdown-theme > span{
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--zq-muted);
  margin-bottom: var(--zq-space-2);
}

/* Dentro del menú móvil, que es siempre oscuro, el conmutador se adapta. */
.mobile-nav-theme{ margin: var(--zq-space-4) 0; }
.mobile-nav-theme > span{
  display: block;
  font-size: 13px;
  color: rgba(255,255,255,.6);
  margin-bottom: var(--zq-space-2);
}
.mobile-nav-theme .theme-switch{
  background: rgba(255,255,255,.06);
  border-color: var(--zq-border-dark);
}
.mobile-nav-theme .theme-switch button{ color: rgba(255,255,255,.65); }
.mobile-nav-theme .theme-switch button[aria-pressed="true"]{
  background: rgba(255,255,255,.14);
  color: var(--zq-white);
  box-shadow: none;
}

/* ==========================================================================
   Sidebar lateral (escritorio >= 1024px)
   --------------------------------------------------------------------------
   Rail de iconos de 76px que se despliega a 296px al pasar el cursor por el
   logo. Se expande SOBRE el contenido: el body solo reserva el ancho del rail,
   asi que abrirlo no mueve la pagina. Es oscuro en los dos temas: forma parte
   de la identidad de marca, igual que el hero y el pie.
   ========================================================================== */
:root{
  --zq-rail: 76px;
  --zq-rail-open: 304px;
  /* 12px = el mismo hueco superior que deja el buscador dentro del header,
     así el borde de arriba del sidebar y el del campo arrancan a la misma
     altura y las dos cajas se leen como una sola línea. */
  --zq-side-gap: 12px;
  --zq-side-ease: cubic-bezier(.22, 1, .36, 1);
  --zq-side-line: rgba(var(--zq-blue-light-rgb),.10);
  --zq-side-dim: rgba(220,238,255,.62);
  --zq-side-danger: #FF6B6B;
}

.sg-sidebar{ display: none; }

@media (min-width: 1024px){
  /* Solo se reserva el rail. La parte desplegada flota sobre el contenido.
     El doble hueco deja el mismo aire a la derecha del rail que el que hay
     sobre el sidebar, para que el marco se lea parejo por los cuatro lados. */
  body.has-sg-sidebar{ padding-left: calc(var(--zq-rail) + var(--zq-side-gap) * 2); }

  .sg-sidebar{
    position: fixed;
    top: var(--zq-side-gap);
    left: var(--zq-side-gap);
    z-index: 90;
    display: flex;
    flex-direction: column;
    width: var(--zq-rail);
    height: calc(100vh - var(--zq-side-gap) * 2);
    /* Relleno igual por los cuatro lados. Antes el de arriba era 0 para que el
       centro de la fila del logo coincidiera con el del buscador del header;
       con el eslogan debajo del wordmark esa fila creció, la coincidencia dejó
       de existir igualmente y lo único que quedaba era un logo pegado al borde
       superior con 12px de aire por debajo. Se renuncia a esa alineación —que
       nadie llegaba a percibir, con el buscador tan lejos a la derecha— a
       cambio de que el marco respire lo mismo arriba que abajo.

       A los lados, 12 de relleno + 1 de borde propio + 1 de borde del item +
       10 del item dejan el icono centrado a 38px, mitad exacta del rail. */
    padding: 12px;
    border-radius: 22px;
    border: 1px solid var(--zq-side-line);
    background: linear-gradient(180deg, #070B12 0%, #0A0F1C 100%);
    box-shadow: 0 18px 50px rgba(0,0,0,.28);
    color: var(--zq-ice);
    /* visible para que los tooltips del modo plegado no queden recortados */
    overflow: visible;
    transition: width 240ms var(--zq-side-ease), box-shadow 240ms var(--zq-side-ease);
  }
  .sg-sidebar.is-open{
    width: var(--zq-rail-open);
    box-shadow: 0 24px 64px rgba(0,0,0,.42);
  }

  /* --- Logo: enlace a Inicio, y disparador de la apertura por hover/foco --- */
  .sg-side-brand{
    display: flex;
    align-items: center;
    gap: 12px;
    height: 44px;          /* igual que el campo de búsqueda del header */
    flex: 0 0 44px;
    margin-bottom: 12px;
    padding: 0 10px;
    /* borde invisible: alinea el isotipo con los iconos, que sí llevan uno */
    border: 1px solid transparent;
    color: var(--zq-white);
    font-weight: 700;
    font-size: 19px;
    white-space: nowrap;
    border-radius: 14px;
  }
  .sg-side-brand .zq-brand-mark{
    flex: 0 0 28px;
    width: 28px;
    height: 28px;
  }
  .sg-side-brand .zq-brand-mark img{ width: 28px; height: 28px; }
  /* El texto de la marca solo existe con el rail desplegado: plegado hay 76px
     de ancho y el wordmark no cabe, pero se anima en vez de aparecer de golpe. */
  .sg-side-brand .zq-brand-text{
    opacity: 0;
    transform: translateX(-6px);
    transition: opacity var(--zq-motion-fast) var(--zq-side-ease), transform 240ms var(--zq-side-ease);
  }
  .sg-sidebar.is-open .sg-side-brand .zq-brand-text{ opacity: 1; transform: none; }
  .sg-side-brand:hover .zq-brand-mark img{ filter: drop-shadow(0 0 12px rgba(77,178,255,.55)); }

  /* --- Cuerpo desplazable --------------------------------------------- */
  .sg-side-scroll{
    flex: 1;
    min-height: 0;
    overflow: visible;
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .sg-sidebar.is-open .sg-side-scroll{
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: thin;
    scrollbar-color: rgba(var(--zq-blue-light-rgb),.25) transparent;
  }
  .sg-sidebar.is-open .sg-side-scroll::-webkit-scrollbar{ width: 6px; }
  .sg-sidebar.is-open .sg-side-scroll::-webkit-scrollbar-thumb{
    background: rgba(var(--zq-blue-light-rgb),.22);
    border-radius: 999px;
  }

  /* --- Grupos: separador discreto en plegado, rotulo en desplegado ----- */
  .sg-side-group{ display: flex; flex-direction: column; gap: 2px; }
  .sg-side-group + .sg-side-group{
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--zq-side-line);
  }
  .sg-side-legend{
    height: 0;
    margin: 0;
    padding: 0 10px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: rgba(220,238,255,.42);
    opacity: 0;
    overflow: hidden;
    transition: opacity 160ms var(--zq-side-ease), height 200ms var(--zq-side-ease), margin 200ms var(--zq-side-ease);
  }
  .sg-sidebar.is-open .sg-side-legend{ height: 16px; margin-bottom: 8px; opacity: 1; }
  .sg-side-legend-inline{ padding: 0; }
  .sg-sidebar.is-open .sg-side-legend-inline{ margin-bottom: 0; }

  /* --- Opcion --------------------------------------------------------- */
  .sg-side-item{
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
    height: 44px;          /* mismo módulo que el buscador y la fila del logo */
    padding: 0 10px;
    border: 1px solid transparent;
    border-radius: 14px;
    background: transparent;
    color: var(--zq-side-dim);
    font-family: var(--zq-font);
    font-size: 14.5px;
    font-weight: 500;
    text-align: left;
    white-space: nowrap;
    width: 100%;
    transition: background 180ms var(--zq-side-ease), color 180ms var(--zq-side-ease),
                border-color 180ms var(--zq-side-ease), box-shadow 180ms var(--zq-side-ease);
  }
  .sg-side-ico{
    flex: 0 0 28px;
    width: 28px;
    height: 28px;
    display: grid;
    place-items: center;
    transition: transform 180ms var(--zq-side-ease), color 180ms var(--zq-side-ease);
  }
  .sg-side-ico svg{ width: 20px; height: 20px; }
  .sg-side-label{
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    opacity: 0;
    transform: translateX(-6px);
    transition: opacity 160ms var(--zq-side-ease), transform 240ms var(--zq-side-ease);
  }
  .sg-side-chevron{
    opacity: 0;
    font-size: 18px;
    line-height: 1;
    color: rgba(220,238,255,.35);
    transition: opacity 160ms var(--zq-side-ease);
  }
  .sg-sidebar.is-open .sg-side-label{ opacity: 1; transform: none; }
  .sg-sidebar.is-open .sg-side-chevron{ opacity: 1; }

  .sg-side-item:hover{
    background: rgba(var(--zq-blue-rgb),.12);
    border-color: rgba(var(--zq-blue-light-rgb),.18);
    color: var(--zq-white);
  }
  .sg-side-item:hover .sg-side-ico{ color: var(--zq-blue-soft); transform: translateX(1px); }
  .sg-side-item:focus-visible{ outline-offset: -2px; }

  .sg-side-item.is-active{
    background: linear-gradient(135deg, var(--zq-blue) 0%, var(--zq-blue-light) 100%);
    border-color: rgba(220,238,255,.30);
    color: var(--zq-white);
    font-weight: 600;
    box-shadow: 0 0 20px rgba(var(--zq-blue-rgb),.20);
  }
  .sg-side-item.is-active .sg-side-ico,
  .sg-side-item.is-active .sg-side-chevron{ color: var(--zq-white); }
  .sg-side-item-accent{ color: var(--zq-blue-soft); }

  /* --- Tooltip del modo plegado --------------------------------------- */
  .sg-sidebar:not(.is-open) .sg-side-item::after,
  .sg-sidebar:not(.is-open) .sg-side-field::after{
    content: attr(data-tip);
    position: absolute;
    left: calc(100% + 8px);
    top: 50%;
    transform: translateY(-50%) translateX(-4px);
    padding: 7px 11px;
    border-radius: 10px;
    border: 1px solid var(--zq-side-line);
    background: #101827;
    color: var(--zq-white);
    font-size: 13px;
    font-weight: 500;
    white-space: nowrap;
    box-shadow: 0 12px 30px rgba(0,0,0,.35);
    opacity: 0;
    pointer-events: none;
    transition: opacity 140ms var(--zq-side-ease), transform 180ms var(--zq-side-ease);
  }
  .sg-sidebar:not(.is-open) .sg-side-item:hover::after,
  .sg-sidebar:not(.is-open) .sg-side-item:focus-visible::after,
  .sg-sidebar:not(.is-open) .sg-side-field:hover::after{
    opacity: 1;
    transform: translateY(-50%) translateX(0);
  }

  /* --- Preferencias: pais/idioma y apariencia -------------------------- */
  .sg-side-field{
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 8px 10px;
    border-radius: 14px;
    color: var(--zq-side-dim);
  }
  .sg-side-field > .sg-side-ico{ height: 30px; }
  .sg-side-field-body{ display: none; flex: 1; min-width: 0; }
  .sg-sidebar.is-open .sg-side-field-body{ display: block; }
  .sg-sidebar:not(.is-open) .sg-side-field:hover .sg-side-ico{ color: var(--zq-blue-soft); }

  /* Apariencia: el icono y el rótulo van en una fila y el conmutador debajo,
     a todo el ancho. En columna junto al icono solo quedaban 210px para un
     control que necesita 274 y "Sistema" se salía del sidebar. */
  .sg-side-field-theme{ display: block; }
  .sg-side-field-head{ display: flex; align-items: center; gap: 12px; }
  .sg-sidebar.is-open .sg-side-field-theme .sg-side-field-body{ margin-top: 10px; }

  /* Selector internacional: pill oscura y panel en flujo, sin recortes. */
  .sg-sidebar .intl-btn{
    width: 100%;
    height: 38px;
    justify-content: flex-start;
    background: rgba(255,255,255,.05);
    border-color: var(--zq-side-line);
    color: var(--zq-ice);
    border-radius: 12px;
  }
  .sg-sidebar .intl-btn:hover{
    background: rgba(var(--zq-blue-rgb),.14);
    border-color: rgba(var(--zq-blue-light-rgb),.28);
  }
  .sg-sidebar .intl-btn-label{ max-width: none; }
  .sg-sidebar .intl-panel{
    position: static;
    width: 100%;
    margin-top: 10px;
    padding: 12px;
    background: rgba(255,255,255,.04);
    border-color: var(--zq-side-line);
    box-shadow: none;
  }
  .sg-sidebar .intl-field > span{ color: rgba(220,238,255,.5); }
  .sg-sidebar .intl-field select{
    background: rgba(8,17,31,.85);
    border-color: var(--zq-side-line);
    color: var(--zq-ice);
  }

  /* Conmutador de apariencia: segmented control azul. */
  .sg-sidebar .theme-switch{
    width: 100%;
    background: rgba(255,255,255,.05);
    border-color: var(--zq-side-line);
  }
  .sg-sidebar .theme-switch button{
    flex: 1 1 0;
    min-width: 0;          /* sin esto el nowrap impone el ancho y desborda */
    justify-content: center;
    gap: 4px;
    height: 32px;
    padding: 0 4px;
    font-size: 12px;
    color: rgba(220,238,255,.6);
  }
  .sg-sidebar .theme-switch button span{
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .sg-sidebar .theme-switch button:hover{ color: var(--zq-white); }
  .sg-sidebar .theme-switch button[aria-pressed="true"]{
    background: rgba(var(--zq-blue-rgb),.22);
    border: 1px solid rgba(var(--zq-blue-light-rgb),.45);
    color: var(--zq-blue-soft);
    box-shadow: 0 0 14px rgba(var(--zq-blue-rgb),.18);
  }

  /* --- Cerrar sesion: accion destructiva, discreta --------------------- */
  .sg-side-foot:not(:empty){
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--zq-side-line);
  }
  .sg-side-logout{ color: var(--zq-side-danger); }
  .sg-side-logout .sg-side-ico{ color: var(--zq-side-danger); }
  .sg-side-logout:hover{
    background: rgba(255,107,107,.12);
    border-color: rgba(255,107,107,.28);
    color: var(--zq-side-danger);
  }
  .sg-side-logout:hover .sg-side-ico{ color: var(--zq-side-danger); }

  /* --- Header: lo que se muda al sidebar deja de duplicarse ------------
     Marca, navegación y botón Menú viven en el sidebar y aquí sobran. La
     CUENTA no: con todo esto oculto, el header quedaba como una barra vacía
     con un buscador flotando en medio, y quien llegaba por primera vez no
     tenía ningún sitio visible donde iniciar sesión —había que descubrir que
     el rail de iconos se despliega al pasar el cursor—. El acceso a la cuenta
     y el selector de país se quedan a la derecha, que es donde se buscan. */
  .has-sg-sidebar .site-header .zq-brand,
  .has-sg-sidebar .site-header .main-nav,
  .has-sg-sidebar .site-header .nav-toggle{ display: none; }

  /* El buscador se centra sobre el ANCHO ÚTIL, no sobre la ventana: con
     `margin:0 auto` el rail de la izquierda lo empujaba y quedaba visiblemente
     descentrado respecto al contenido de debajo. */
  /* Rejilla de tres columnas con los laterales iguales: así el buscador
     queda centrado de verdad sobre el contenido, y no desplazado por lo ancho
     que sea el bloque de la cuenta, que es lo que pasaba con `margin:auto`
     dentro de un flex. */
  .has-sg-sidebar .site-header .container{
    display: grid;
    grid-template-columns: 1fr minmax(0, 520px) 1fr;
    align-items: center;
    height: 68px;
  }
  .has-sg-sidebar .site-header .header-search{
    grid-column: 2;
    max-width: none;
    margin: 0;
  }
  .has-sg-sidebar .site-header .header-actions{
    grid-column: 3;
    margin-left: auto;
  }
}

/* ==========================================================================
   Comparador de productos (COMPARATOR_POLICY.md)
   --------------------------------------------------------------------------
   Una sola hoja para todas las categorias: la tabla la ordena el perfil que
   devuelve la API, no el CSS. En escritorio los productos son columnas; por
   debajo de 900px las columnas se estrechan y la tabla se desplaza en
   horizontal dentro de su contenedor, sin que la pagina se mueva (§105, §106).
   ========================================================================== */

.cmp-aviso{
  padding: var(--zq-space-3) var(--zq-space-4);
  margin-bottom: var(--zq-space-4);
  border: 1px solid rgba(var(--zq-blue-rgb),.22);
  border-radius: var(--zq-radius-button);
  background: rgba(var(--zq-blue-rgb),.07);
  color: var(--zq-text);
  font-size: 14px;
}

/* --- cabecera con los productos ---------------------------------------- */
.cmp-head-actions{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--zq-space-3);
  margin-bottom: var(--zq-space-4);
  flex-wrap: wrap;
}
.cmp-count{ font-size: 13px; color: var(--zq-muted); font-weight: 600; }

.cmp-cols{
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  gap: var(--zq-space-4);
}
.cmp-col{
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: var(--zq-space-4);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
  background: var(--zq-card);
}
.cmp-remove{
  position: absolute;
  top: 8px;
  right: 8px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid var(--zq-border);
  background: var(--zq-card);
  color: var(--zq-muted);
  font-size: 13px;
  line-height: 1;
  display: grid;
  place-items: center;
  transition: color 160ms var(--zq-ease), border-color 160ms var(--zq-ease);
}
.cmp-remove:hover{ color: var(--zq-urgency); border-color: var(--zq-urgency); }

.cmp-media{
  display: grid;
  place-items: center;
  height: 132px;
  margin-bottom: var(--zq-space-2);
  border-radius: 12px;
  /* Las fotos vienen recortadas sobre blanco: sobre gris se ve el recorte. */
  background: var(--zq-photo-bg);
  font-size: 30px;
}
/* Proporciones intactas: nunca se deforma para cuadrar columnas (§110). */
.cmp-media img{ max-height: 118px; width: auto; object-fit: contain; }

.cmp-type{ font-size: 12px; color: var(--zq-muted); font-weight: 600; }
.cmp-name{
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  /* El nombre largo no rompe la columna: se corta a dos lineas y el title
     conserva el nombre completo (§109). */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.cmp-rating{ font-size: 13px; color: var(--zq-savings); font-weight: 600; }
.cmp-rating span{ color: var(--zq-muted); font-weight: 500; }

.cmp-price{ display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-top: 2px; }
.cmp-price strong{ font-size: 20px; font-weight: 700; }
.cmp-was{ font-size: 13px; color: var(--zq-muted); text-decoration: line-through; }

.cmp-flag{
  align-self: flex-start;
  padding: 3px 9px;
  border-radius: var(--zq-radius-chip);
  background: rgba(34,160,107,.12);
  border: 1px solid rgba(34,160,107,.30);
  color: var(--zq-success);
  font-size: 11.5px;
  font-weight: 600;
}

/* El estado no se transmite solo con color: siempre lleva texto (§174). */
.cmp-stock{ font-size: 13px; font-weight: 600; }
.cmp-stock.in{ color: var(--zq-success); }
.cmp-stock.out{ color: var(--zq-urgency); }

.cmp-col .offer-cta{ margin-top: auto; }
.cmp-col .offer-cta.disabled{
  background: var(--zq-surface);
  color: var(--zq-muted);
  border: 1px solid var(--zq-border);
  cursor: not-allowed;
  text-align: center;
}

/* --- diferencias clave -------------------------------------------------- */
.cmp-key{ margin-top: var(--zq-space-6); }
.cmp-key h2{ margin-bottom: var(--zq-space-4); }
.cmp-key-grid{
  display: grid;
  grid-template-columns: minmax(140px, 200px) repeat(var(--cols), minmax(0, 1fr));
  gap: 1px;
  background: var(--zq-border);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
  overflow: hidden;
}
.cmp-key-head, .cmp-key-label, .cmp-key-cell{
  background: var(--zq-card);
  padding: var(--zq-space-3) var(--zq-space-4);
  font-size: 14px;
}
.cmp-key-head{ font-weight: 600; font-size: 13px; }
.cmp-key-label{ color: var(--zq-muted); font-weight: 600; font-size: 13px; }
.cmp-key-cell.favorable{ color: var(--zq-success); font-weight: 600; }

/* El triangulo acompaña al color, para no depender solo de el (§175). */
.cmp-mark{ margin-left: 5px; font-size: 10px; }

/* --- tabla de especificaciones ------------------------------------------ */
.cmp-specs{ margin-top: var(--zq-space-6); }
.cmp-specs-head{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--zq-space-4);
  margin-bottom: var(--zq-space-4);
  flex-wrap: wrap;
}
.cmp-toggle{
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: var(--zq-muted);
  cursor: pointer;
}
.cmp-toggle input{ width: 16px; height: 16px; accent-color: var(--zq-blue); cursor: pointer; }

.cmp-table{ width: 100%; border-collapse: collapse; }
.cmp-table th, .cmp-table td{
  padding: var(--zq-space-3) var(--zq-space-4);
  text-align: left;
  font-size: 14px;
  border-bottom: 1px solid var(--zq-border);
  vertical-align: top;
}
.cmp-table thead th{
  font-size: 13px;
  font-weight: 600;
  color: var(--zq-text);
  background: var(--zq-card);
  /* Cabecera fija: el nombre y la columna siguen visibles en tablas largas (§39). */
  position: sticky;
  top: 0;
  z-index: 2;
}
.cmp-table tbody th{ color: var(--zq-muted); font-weight: 500; width: 26%; }
.cmp-table tr.cmp-section th{
  background: var(--zq-surface);
  color: var(--zq-text);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.cmp-table td.favorable{ color: var(--zq-success); font-weight: 600; }
.cmp-table tr.cmp-equal td, .cmp-table tr.cmp-equal th{ color: var(--zq-muted); }
.cmp-null{ color: var(--zq-muted); font-style: italic; }
.cmp-vacio{ color: var(--zq-muted); font-size: 14px; padding: var(--zq-space-4) 0; }

/* --- pros / contras / ideal para ---------------------------------------- */
.cmp-editorial{ margin-top: var(--zq-space-6); }
.cmp-editorial h2{ margin-bottom: var(--zq-space-4); }
.cmp-editorial-grid{
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  gap: var(--zq-space-4);
}
.cmp-editorial-col{
  padding: var(--zq-space-4);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
  background: var(--zq-card);
}
.cmp-editorial-col h3{ font-size: 14px; margin-bottom: var(--zq-space-3); }
.cmp-pros, .cmp-cons{ display: grid; gap: 6px; margin-bottom: var(--zq-space-3); }
.cmp-pros li, .cmp-cons li{ font-size: 13.5px; padding-left: 20px; position: relative; line-height: 1.45; }
.cmp-pros li::before{ content: "+"; position: absolute; left: 4px; color: var(--zq-success); font-weight: 700; }
.cmp-cons li::before{ content: "−"; position: absolute; left: 4px; color: var(--zq-urgency); font-weight: 700; }
.cmp-ideal{ font-size: 13.5px; color: var(--zq-muted); }
.cmp-ideal strong{ color: var(--zq-blue); }

/* --- aviso de seleccion -------------------------------------------------- */
.compare-notice{
  position: fixed;
  left: 50%;
  bottom: 96px;
  transform: translate(-50%, 12px);
  z-index: 95;
  display: flex;
  align-items: center;
  gap: var(--zq-space-3);
  max-width: min(560px, calc(100vw - 32px));
  padding: var(--zq-space-3) var(--zq-space-4);
  border-radius: var(--zq-radius-button);
  border: 1px solid var(--zq-border-dark);
  background: var(--zq-surface-dark);
  color: var(--zq-white);
  font-size: 14px;
  box-shadow: 0 18px 44px rgba(0,0,0,.32);
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms var(--zq-ease), transform 220ms var(--zq-ease);
}
.compare-notice.visible{ opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.compare-notice button{
  flex-shrink: 0;
  padding: 6px 12px;
  border-radius: 10px;
  border: 1px solid rgba(var(--zq-blue-light-rgb),.45);
  background: rgba(var(--zq-blue-rgb),.18);
  color: var(--zq-blue-soft);
  font-family: var(--zq-font);
  font-size: 13px;
  font-weight: 600;
}
.compare-notice button:hover{ background: rgba(var(--zq-blue-rgb),.3); color: var(--zq-white); }

/* --- responsive --------------------------------------------------------- */
@media (max-width: 900px){
  /* Cuatro columnas diminutas son ilegibles: se fija un ancho minimo y se
     desplaza en horizontal solo el bloque, no la pagina (§106, §107). */
  .cmp-cols, .cmp-editorial-grid{
    grid-auto-flow: column;
    grid-auto-columns: minmax(210px, 1fr);
    grid-template-columns: none;
    overflow-x: auto;
    padding-bottom: var(--zq-space-2);
    scroll-snap-type: x mandatory;
  }
  .cmp-col, .cmp-editorial-col{ scroll-snap-align: start; }
  .cmp-key-grid{
    grid-template-columns: minmax(112px, 40%) repeat(var(--cols), minmax(112px, 1fr));
    overflow-x: auto;
  }
  .cmp-table{ min-width: 560px; }
  .cmp-table tbody th{ width: auto; min-width: 132px; }
  .compare-notice{ bottom: 120px; }
}

/* ==========================================================================
   Componentes añadidos en la revisión general
   --------------------------------------------------------------------------
   Todo lo de aquí abajo apoya cambios de esta pasada: la entrada a la cuenta
   desde el header de escritorio, la ruta de navegación y la ficha técnica por
   secciones de la ficha de producto, y la tienda en el comparador.
   ========================================================================== */

/* --- Acceso a la cuenta desde el header (solo escritorio) --------------- */
/* Por debajo de 1024px estos dos botones ya están en el menú lateral, y aquí
   apretarían el buscador contra el botón Menú. */
.auth-cta{ display: none; }
@media (min-width: 1024px){
  .auth-cta{ display: inline-flex; }
}

/* --- Ruta de navegación (ficha de producto) ---------------------------- */
.breadcrumb{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--zq-muted);
  margin-bottom: var(--zq-space-4);
}
.breadcrumb a{ color: var(--zq-muted); }
.breadcrumb a:hover{ color: var(--zq-blue); }
.breadcrumb [aria-current="page"]{ color: var(--zq-text); font-weight: 600; }
.breadcrumb-sep{ color: var(--zq-border); }

/* --- Ficha técnica por secciones --------------------------------------- */
/* La ficha ya no es una lista plana de veinte filas de cámara: son las
   secciones que define el perfil de comparación del producto, así que un
   ratón enseña "Sensor y precisión" y una maleta "Capacidad y medidas". */
.spec-group + .spec-group{ margin-top: var(--zq-space-5); }
.spec-group-title{
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--zq-muted);
  margin-bottom: var(--zq-space-3);
}
/* Sin `min-width` fijo: una tabla de dos columnas no necesita 480px y en
   móvil obligaba a desplazar en horizontal para leer dos palabras. */
.spec-table{ min-width: 0; }
.spec-table tr:last-child{ border-bottom: none; }

/* --- Tienda del producto en el comparador ------------------------------ */
.cmp-market{ margin: 2px 0 4px; }

/* --- Franja de confianza del hero -------------------------------------- */
/* La columna de texto del hero es estrecha: con tres elementos en fila el
   tercero saltaba solo a una segunda línea y la franja quedaba coja, con un
   hueco enorme a la derecha. En rejilla de dos columnas caen ordenados, con
   los tres alineados por la izquierda en lugar de repartidos al azar.
   (Separadores verticales, no: al envolverse quedaba una barra suelta
   abriendo la segunda línea.) */
.hero-trust{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, max-content));
  gap: var(--zq-space-3) var(--zq-space-5);
}
.hero-trust li{ min-width: 0; }

/* ==========================================================================
   Favoritos, alertas e historial sobre productos
   --------------------------------------------------------------------------
   El corazón existía solo en las tarjetas de "oferta", que lo llevaban con un
   fill en línea que el JS iba cambiando. Las tarjetas de producto lo pintan
   desde CSS, así que el estado por defecto tiene que declararse aquí: sin
   `fill: none`, un SVG se rellena de negro y el corazón sale macizo siempre.
   ========================================================================== */
.fav-btn svg{ fill: none; transition: fill 160ms var(--zq-ease); }
.fav-btn[aria-pressed="true"] svg,
.fav-btn.active svg{ fill: var(--zq-blue); }
.fav-btn:disabled{ opacity: .6; cursor: progress; }
/* Sobre la foto blanca del producto el círculo necesita separarse del fondo. */
.product-card .fav-btn{ background: rgba(255,255,255,.94); color: #5A6472; }
.product-card .fav-btn:hover,
.product-card .fav-btn.active{ color: var(--zq-blue); }

/* Estado "en seguimiento" de una alerta: gris tranquilo, no una insignia de
   oferta. Antes iba con un `style` en línea dentro de la plantilla. */
.chip-seguimiento{
  background: var(--zq-surface);
  color: var(--zq-muted);
  border: 1px solid var(--zq-border);
}

/* La fila de alerta ahora puede llevar la foto real del producto, no solo un
   emoji: la imagen se ajusta al hueco sin deformarse. */
.alert-row-media{ overflow: hidden; background: var(--zq-photo-bg); }
.alert-row-media img{ width: 100%; height: 100%; object-fit: contain; padding: 4px; }

/* Etiqueta solo para lectores de pantalla: el campo de precio objetivo lleva
   su placeholder a la vista, pero un placeholder no es una etiqueta. */
.sr-only{
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.alert-form-card .field-hint{ margin-top: var(--zq-space-2); display: block; }

/* ==========================================================================
   MOTION SYSTEM (manual §10 · js/motion.js)
   --------------------------------------------------------------------------
   Aquí vive el CÓMO se mueve todo. El JavaScript solo decide CUÁNDO añadir
   una clase; la animación la hace el compositor con `transform` y `opacity`,
   que son las dos únicas propiedades que no obligan al navegador a recalcular
   el layout en cada fotograma.
   ========================================================================== */

/* --- Transiciones entre páginas ------------------------------------------
   Las hace el navegador, no nosotros. Sin interceptar clics, sin router y
   sin riesgo de dejar el sitio sin navegación si algo falla: donde no hay
   soporte, se navega como toda la vida. */
@view-transition{ navigation: auto; }

::view-transition-old(root){ animation: zq-fade-out 180ms var(--zq-ease) both; }
::view-transition-new(root){ animation: zq-page-in var(--zq-motion-base) var(--zq-ease) both; }

/* Sin View Transitions, el fundido de entrada lo pone esta clase (la añade
   js/motion.js). Con ellas, el navegador ya lo hace y un segundo fundido
   encima daría un doble parpadeo. */
.zq-sin-view-transitions body{ animation: zq-page-in var(--zq-motion-base) var(--zq-ease) both; }

@keyframes zq-page-in{
  from{ opacity: 0; transform: translateY(8px); }
  to{ opacity: 1; transform: none; }
}
@keyframes zq-fade-out{
  from{ opacity: 1; }
  to{ opacity: 0; }
}

/* --- Scroll reveal --------------------------------------------------------
   Estado inicial + estado final. El retraso escalonado lo inyecta el JS como
   `transition-delay` en línea, para que cada grupo lleve su propio contador. */
/* Acotado a `.zq-js`, que theme.js pone en el <head> antes de pintar. Sin
   esa guarda, un fallo de JavaScript —o un bloqueador de scripts— dejaba la
   página entera invisible: `[data-reveal]` nace con opacity 0 y quien la
   quita es precisamente el script que no llegó a ejecutarse. */
.zq-js [data-reveal]{
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--zq-motion-base) var(--zq-ease),
              transform var(--zq-motion-base) var(--zq-ease);
}
.zq-js [data-reveal].is-in{ opacity: 1; transform: none; }

/* --- Actualización de precio ---------------------------------------------
   "Nunca animar precio con rebotes o destellos agresivos" (manual §10). Un
   resalte de fondo que entra y sale: dice "esto cambió" sin mover un píxel
   de la página, así que nada de lo que hay debajo salta. */
.zq-price-changed{
  animation: zq-price-highlight 1.2s var(--zq-ease);
  border-radius: 6px;
}
@keyframes zq-price-highlight{
  0%{ background: rgba(var(--zq-blue-rgb),.22); }
  100%{ background: transparent; }
}

/* --- Reduced motion -------------------------------------------------------
   No es una preferencia estética: hay quien la activa porque el movimiento le
   provoca náuseas o mareo. Con ella, el contenido nace visible (si no,
   `[data-reveal]` lo dejaría invisible para siempre al no animarse nunca) y
   no queda parallax, ni escalonado, ni transiciones entre páginas. */
@media (prefers-reduced-motion: reduce){
  .zq-js [data-reveal]{ opacity: 1; transform: none; transition: none; }
  .zq-sin-view-transitions body{ animation: none; }
  ::view-transition-old(root),
  ::view-transition-new(root){ animation: none; }
  .hero::after{ transform: none !important; }
  .fav-btn.active svg{ animation: none; }
  .zq-price-changed{ animation: none; }
}

/* ==========================================================================
   TOASTS (js/toast.js · manual §32)
   --------------------------------------------------------------------------
   Escritorio abajo a la derecha, móvil abajo al centro y a lo ancho.
   ========================================================================== */
.zq-toasts{
  position: fixed;
  right: var(--zq-space-5);
  bottom: var(--zq-space-5);
  z-index: 200;
  display: flex;
  flex-direction: column;
  gap: var(--zq-space-2);
  align-items: flex-end;
  /* El contenedor ocupa toda la esquina pero no debe tapar lo que hay debajo:
     solo los toasts reciben clics. */
  pointer-events: none;
}
.zq-toast{
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: var(--zq-space-3);
  max-width: min(420px, calc(100vw - var(--zq-space-6)));
  padding: var(--zq-space-3) var(--zq-space-4);
  border-radius: var(--zq-radius-button);
  background: var(--zq-card);
  border: 1px solid var(--zq-border);
  box-shadow: var(--zq-shadow-soft);
  color: var(--zq-text);
  font-size: 14.5px;
  opacity: 0;
  transform: translateY(12px) scale(.97);
  transition: opacity var(--zq-motion-fast) var(--zq-ease),
              transform var(--zq-motion-base) var(--zq-ease);
}
.zq-toast.is-in{ opacity: 1; transform: none; }
.zq-toast-ico{ flex: 0 0 20px; width: 20px; height: 20px; }
.zq-toast-ico svg{ width: 20px; height: 20px; }
.zq-toast-exito .zq-toast-ico{ color: var(--zq-success); }
.zq-toast-error .zq-toast-ico{ color: var(--zq-urgency); }
.zq-toast-info .zq-toast-ico{ color: var(--zq-blue); }
.zq-toast-msg{ flex: 1; min-width: 0; }
.zq-toast-accion{
  flex-shrink: 0;
  background: transparent;
  border: 1px solid var(--zq-border);
  border-radius: 8px;
  color: var(--zq-blue);
  font-size: 13px;
  font-weight: 600;
  padding: 6px var(--zq-space-3);
  transition: border-color var(--zq-motion-fast) var(--zq-ease), background var(--zq-motion-fast) var(--zq-ease);
}
.zq-toast-accion:hover{ border-color: var(--zq-blue); background: rgba(var(--zq-blue-rgb),.08); }
.zq-toast-cerrar{
  flex-shrink: 0;
  width: 28px; height: 28px;
  display: grid;
  place-items: center;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: var(--zq-muted);
}
.zq-toast-cerrar svg{ width: 15px; height: 15px; }
.zq-toast-cerrar:hover{ color: var(--zq-text); background: var(--zq-surface); }

@media (max-width: 640px){
  /* Móvil: abajo y centrado, a lo ancho. Por encima de la barra del
     navegador, que en iOS se come los últimos píxeles de la ventana. */
  .zq-toasts{
    left: var(--zq-space-4);
    right: var(--zq-space-4);
    bottom: calc(var(--zq-space-4) + env(safe-area-inset-bottom, 0px));
    align-items: stretch;
  }
  .zq-toast{ max-width: none; }
}

@media (prefers-reduced-motion: reduce){
  .zq-toast{ transition: opacity 100ms linear; transform: none; }
  .zq-toast.is-in{ transform: none; }
}

/* ==========================================================================
   SKELETONS (manual §10: "skeleton → contenido, sin flash")
   --------------------------------------------------------------------------
   Reproducen el layout REAL de la tarjeta —foto 4:3, marca, título, precio,
   botón—, no un rectángulo genérico: así el contenido no da un salto al
   llegar. Sin spinner: un spinner dice "espera", un skeleton dice "esto es lo
   que va a aparecer y dónde va a estar".
   ========================================================================== */
.skeleton-card{
  background: var(--zq-card);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.skeleton-media{ aspect-ratio: 4/3; border-bottom: 1px solid var(--zq-border); }
.skeleton-body{
  padding: var(--zq-space-4);
  display: flex;
  flex-direction: column;
  gap: var(--zq-space-2);
  flex: 1;
}
.skeleton-line{ height: 12px; border-radius: 6px; }
.skeleton-line.w-40{ width: 40%; }
.skeleton-line.w-90{ width: 90%; }
.skeleton-line.w-60{ width: 60%; }
.skeleton-line.tall{ height: 20px; }
.skeleton-cta{ height: 44px; border-radius: var(--zq-radius-button); margin-top: auto; }

.skeleton-media, .skeleton-line, .skeleton-cta{
  background: linear-gradient(
    100deg,
    var(--zq-surface) 30%,
    rgba(var(--zq-blue-light-rgb),.10) 50%,
    var(--zq-surface) 70%
  );
  background-size: 300% 100%;
  animation: zq-shimmer 1.6s ease-in-out infinite;
}
@keyframes zq-shimmer{
  from{ background-position: 150% 0; }
  to{ background-position: -50% 0; }
}
@media (prefers-reduced-motion: reduce){
  .skeleton-media, .skeleton-line, .skeleton-cta{ animation: none; background: var(--zq-surface); }
}

/* ==========================================================================
   COMPARA ANTES DE COMPRAR (home)
   ========================================================================== */
.compare-pitch .container{
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--zq-space-8);
  align-items: center;
  background: var(--zq-surface);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-modal);
  padding: var(--zq-space-8);
}
.compare-pitch-copy h2{ margin-bottom: var(--zq-space-3); }
.compare-pitch-copy p{ color: var(--zq-muted); margin-bottom: var(--zq-space-5); max-width: 46ch; }
.compare-pitch-steps{ display: flex; flex-direction: column; gap: var(--zq-space-4); }
.compare-pitch-steps li{
  display: flex;
  align-items: flex-start;
  gap: var(--zq-space-4);
  background: var(--zq-card);
  border: 1px solid var(--zq-border);
  border-radius: var(--zq-radius-card);
  padding: var(--zq-space-4) var(--zq-space-5);
}
.step-n{
  flex: 0 0 32px;
  width: 32px; height: 32px;
  border-radius: 10px;
  background: rgba(var(--zq-blue-rgb),.10);
  color: var(--zq-blue);
  font-weight: 700;
  font-size: 14px;
  display: grid;
  place-items: center;
}
.compare-pitch-steps strong{ display: block; font-size: 15px; margin-bottom: 2px; }
/* Mismo `:not()` y por el mismo motivo que en la barra de confianza: el número
   del paso es un <span>, y `.compare-pitch-steps span` (0,1,1) le ganaba a
   `.step-n` (0,1,0). El resultado era un "1" gris y pequeño pegado a la
   esquina de su cuadro, en vez de un número azul y centrado. */
.compare-pitch-steps span:not(.step-n){ display: block; font-size: 13.5px; color: var(--zq-muted); }
