/* ============================================================
   TOKENS — se declaran una sola vez. Ni un hex suelto abajo.
   Espejo de resources/css/app.css (@theme de Tailwind 4).
   ============================================================ */
@font-face{
  font-family:'Jost';
  src:url('../fonts/jost-var.woff2') format('woff2');
  font-weight:400 600;
  font-style:normal;
  font-display:swap;
}
:root{
  --verde:#1A3C2A;
  --verde-hover:#14301F;
  --bronce:#C29A6E;
  --crema:#FAF3E1;
  --superficie:#E8D5BE;
  --texto:#404040;
  --exito:#2F6B4A;
  --error:#8C2F2F;

  --r-control:6px;
  --r-tarjeta:12px;
  --r-badge:999px;

  --sombra:0 1px 3px rgb(26 60 42 / 0.08);
  --ease:cubic-bezier(0.4,0,0.2,1);
  --ancho:1200px;

  /* Alto real de la cabecera. El hero se mete por debajo de ella con un margen
     negativo de este valor y recupera el mismo espacio con padding, asi el video
     sube por detras de la barra traslucida sin tapar el texto. 100px es el valor
     medido en escritorio (el monograma a 64px mas el relleno mas el filete de
     abajo); el JS del final lo reescribe con la medida real porque en movil la
     barra crece cuando la accion no cabe y al cambiar de idioma el menu cambia
     de ancho. Hay que retocarlo a mano cada vez que cambia el tamano del logo:
     si se queda viejo, el hero da un salto entre que pinta el CSS y corre el JS,
     y ademas las cajas de _gen/chk_hero.py dejan de coincidir. */
  --alto-cabecera:100px;

  /* Lo que hay encima del hero y le roba pantalla: la barra promocional y, en
     este mockup, la etiqueta de aviso. La cabecera no cuenta porque va montada
     encima del hero, no antes. Se resta de 100svh para que el video llegue
     justo al borde inferior de la pantalla en la primera vista. Lo mide el JS
     del final; 85px es el valor de arranque. */
  --alto-previo:85px;

  /* Ancho de la foto de la mano con el vial. De aqui sale tambien el hueco que
     el catalogo tiene que dejarle por arriba, asi que es una sola perilla: se
     toca esto y la mano y el hueco se mueven juntos. En 0 porque por debajo de
     960 la mano no se pone. */
  --mano:0px;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;
  background:var(--crema);
  color:var(--texto);
  font-family:'Jost',system-ui,-apple-system,'Segoe UI',sans-serif;
  font-weight:400;
  font-size:1rem;
  line-height:1.65;
  font-feature-settings:"ss01" 1;
}
img{max-width:100%;display:block}
a{color:inherit}
h1,h2,h3{margin:0;line-height:1.2;color:var(--verde)}
h1{font-weight:600;font-size:clamp(2rem,5vw,3.25rem);letter-spacing:-0.02em}
h2{font-weight:500;font-size:clamp(1.5rem,3vw,2.125rem);letter-spacing:-0.01em}
h3{font-weight:500;font-size:1.125rem}
p{margin:0}

.envoltura{max-width:var(--ancho);margin:0 auto;padding:0 20px}
/* Texto que solo existe para el lector de pantalla. No vale display:none: eso
   lo borra tambien para el lector, que es justo a quien va dirigido. */
.solo-lector{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;
}
/* La barra es pegajosa, asi que un salto a #ancla deja el borde del bloque
   debajo de ella y se come el rotulo. Con esto el bloque aterriza justo bajo la
   barra y su propio relleno hace el resto. */
.seccion{padding:72px 0;scroll-margin-top:var(--alto-cabecera)}
.seccion--ajustada{padding:56px 0}

/* ---- Botones -------------------------------------------------
   Un solo primario por pantalla visible. Todo lo demas es
   secundario o enlace de texto. El texto dice lo que pasa
   despues, nunca "Enviar" ni "Continuar".
   ------------------------------------------------------------ */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:48px;padding:0 28px;
  border:1px solid transparent;border-radius:var(--r-control);
  font-family:inherit;font-size:1rem;font-weight:500;
  text-decoration:none;cursor:pointer;
  transition:background-color 150ms var(--ease),color 150ms var(--ease),transform 150ms var(--ease);
}
.btn:active{transform:translateY(1px)}
.btn:focus-visible{outline:2px solid var(--bronce);outline-offset:2px}
.btn--primario{background:var(--verde);color:var(--crema)}
.btn--primario:hover{background:var(--verde-hover)}
.btn--sobre-verde{background:var(--crema);color:var(--verde)}
.btn--sobre-verde:hover{background:var(--superficie)}
.btn--fantasma{background:transparent;color:var(--verde);border-color:var(--verde)}
.btn--fantasma:hover{background:var(--verde);color:var(--crema)}
.btn--fantasma-claro{background:transparent;color:var(--crema);border-color:rgb(250 243 225 / 0.45)}
.btn--fantasma-claro:hover{background:rgb(250 243 225 / 0.12)}
.btn[disabled]{opacity:.55;cursor:not-allowed}
.btn[disabled]:active{transform:none}
.btn--bloque{width:100%}

.enlace-texto{
  color:var(--verde);font-weight:500;text-decoration:none;
  border-bottom:1px solid var(--bronce);padding-bottom:2px;
  transition:border-color 150ms var(--ease);
}
.enlace-texto:hover{border-color:var(--verde)}

/* ---- Badges --------------------------------------------------
   El bronce nunca es color de texto sobre crema por debajo de
   24px. Como fondo con texto crema encima, si.
   ------------------------------------------------------------ */
.badge{
  display:inline-flex;align-items:center;gap:6px;
  border-radius:var(--r-badge);
  padding:4px 12px;
  font-size:.8125rem;font-weight:500;line-height:1.4;
  white-space:nowrap;
}
.badge--coa{background:var(--verde);color:var(--crema)}
.badge--bronce{background:var(--bronce);color:#2A1F14}
.badge--suave{background:var(--superficie);color:var(--verde)}
.badge--agotado{background:transparent;color:var(--error);border:1px solid var(--error)}
.badge--stock{background:transparent;color:var(--exito);border:1px solid var(--exito)}

.rotulo{
  font-size:.75rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--verde);
}
.rotulo--claro{color:var(--bronce)}

/* ============================================================
   BARRA PROMOCIONAL  (bloque 1)
   ============================================================ */
.promo{background:var(--verde);color:var(--crema);text-align:center;font-size:.875rem}
.promo .envoltura{padding-top:10px;padding-bottom:10px}
.promo strong{color:var(--bronce);font-weight:600}

/* ============================================================
   CABECERA
   ============================================================ */
/* La cabecera flota sobre el hero: el video sube por detras de ella y la banda
   se ve al 70%. El blur no es adorno, es lo que sostiene la legibilidad cuando
   detras pasa el catalogo al hacer scroll; sin el, las fotos de producto se
   leen a traves de la barra y el menu se ensucia. Cuanta menos crema queda,
   mas trabaja: el texto de la barra es oscuro sobre claro, asi que lo que lo
   mata no es la luz que entra sino el detalle que entra con ella.
   --alto-cabecera lo mide el JS del final; 100px es solo el valor de arranque
   para que no haya salto antes de que corra. */
.cabecera{
  position:sticky;top:0;z-index:20;
  background:rgb(250 243 225 / 0.7);
  -webkit-backdrop-filter:blur(14px) saturate(1.4);
  backdrop-filter:blur(14px) saturate(1.4);
  border-bottom:1px solid rgb(232 213 190 / 0.55);
}
/* El padding vertical existe por el logo: sin el, el monograma toca arriba y
   abajo de la banda crema y se ve enjaulado. */
/* Los 20px laterales son los de .envoltura: esta clase va sobre el mismo div,
   asi que hay que repetirlos o el logo se pega al borde. */
.cabecera__fila{display:flex;align-items:center;gap:36px;min-height:68px;padding:16px 20px}
/* El conjunto de marca son dos piezas: el monograma y el logotipo. El nombre
   accesible lo pone el alt del monograma, que es el que esta siempre; el
   logotipo va con alt vacio porque dice exactamente lo mismo y, con los dos
   puestos, el lector de pantalla anunciaria la marca dos veces seguidas. */
.marca{
  display:flex;align-items:center;text-decoration:none;flex-shrink:0;
  gap:clamp(14px, 1.4vw, 18px);
}
.marca__icono{width:64px;height:auto}
/* El logotipo se mide por altura y no por ancho: la altura es lo que lo empareja
   con el monograma, y ademas su recorte esta pegado a la tinta (ver
   _gen/recorta_logotipo.py), asi que la altura CSS y la altura de las
   mayusculas son el mismo numero.
   Va en clamp y no en un tamano fijo porque es muy apaisado: cada punto de
   altura le suma casi siete de ancho, asi que en 960 —que es el ancho peor,
   porque es justo donde aparece el menu— un tamano fijo de escritorio partiria
   la barra. Bajando ahi al suelo del clamp entra con holgura, y como el cambio
   es gradual no se ve ningun escalon. */
.marca__letras{display:none;height:clamp(16px, 1.6vw, 20px);width:auto}
/* margin-left:auto en el menu ademas del de .cabecera__acciones: con los dos
   puestos, el hueco que sobra en la barra se reparte a partes iguales entre el
   logotipo y el conmutador de idioma, o sea que el menu queda centrado en ese
   hueco en vez de pegado a la marca. */
.nav{display:none;gap:24px;margin-left:auto}
.nav a{
  text-decoration:none;font-size:1.0625rem;color:var(--texto);
  padding:4px 0;border-bottom:2px solid transparent;
  transition:color 150ms var(--ease),border-color 150ms var(--ease);
}
.nav a:hover{color:var(--verde);border-color:var(--bronce)}
.cabecera__acciones{margin-left:auto;display:flex;align-items:center;gap:8px}

.idioma{display:inline-flex;border:1px solid var(--superficie);border-radius:var(--r-control);overflow:hidden}
.idioma button{
  min-height:44px;padding:0 14px;border:0;background:transparent;
  font-family:inherit;font-size:.8125rem;font-weight:500;color:var(--texto);cursor:pointer;
  transition:background-color 150ms var(--ease),color 150ms var(--ease);
}
.idioma button[aria-pressed="true"]{background:var(--verde);color:var(--crema)}
.idioma button:focus-visible{outline:2px solid var(--bronce);outline-offset:-2px}

.carrito{
  display:inline-flex;align-items:center;gap:8px;
  min-height:44px;padding:0 14px;
  border:1px solid var(--superficie);border-radius:var(--r-control);
  background:transparent;font-family:inherit;font-size:.9375rem;color:var(--verde);cursor:pointer;
  transition:border-color 150ms var(--ease);
}
.carrito:hover{border-color:var(--verde)}
.carrito__num{
  background:var(--verde);color:var(--crema);
  border-radius:var(--r-badge);min-width:20px;height:20px;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:.75rem;font-weight:600;padding:0 6px;
}

/* ============================================================
   HERO  (bloque 2) — un unico CTA primario
   ============================================================ */
/* El margen negativo mete el hero por debajo de la cabecera: sin el, el video
   arrancaria donde termina la barra y la barra traslucida no tendria nada que
   dejar ver. El padding de la envoltura devuelve el mismo alto para que el
   texto no quede tapado. */
/* El hero ocupa lo que queda de pantalla: 100svh menos las barras que van
   encima. Se usa svh y no vh ni dvh a proposito. En el movil, vh mide la
   pantalla con la barra del navegador escondida, asi que el hero sobresale y el
   ultimo renglon se va debajo del borde; dvh cambia de valor mientras se
   desplaza y el hero da un salto a media lectura. svh mide el caso mas
   apretado: no salta y no corta.
   Es min-height y no height porque en movil el texto ya mide mas que la
   pantalla y tiene que poder crecer.
   El suelo de 560px es para ventanas muy bajas (un portatil de 768 con las
   barras del navegador puestas): por debajo de eso el titular y el boton se
   apelotonan y es preferible que el hero pase de largo. */
.hero{
  position:relative;isolation:isolate;overflow:hidden;
  margin-top:calc(-1 * var(--alto-cabecera));
  padding-top:var(--alto-cabecera);
  min-height:max(560px, calc(100vh - var(--alto-previo)));
  min-height:max(560px, calc(100svh - var(--alto-previo)));
  display:grid;align-content:center;
  background:var(--verde);color:var(--crema);
}
/* Relleno simetrico: como el hero centra su contenido, un relleno desigual solo
   servia para empujar el texto hacia arriba y, en movil, para alargar 24px un
   bloque que ya se sale de pantalla. */
.hero .envoltura{
  position:relative;z-index:2;
  display:grid;gap:40px;
  padding-top:32px;padding-bottom:32px;
}
.hero h1{color:var(--crema)}

/* El video ocupa el hero entero, no una caja: asi la escena respira de borde a
   borde y el texto se apoya encima. La legibilidad no depende de que el modelo
   haya dejado libre la izquierda (no siempre lo hace): la garantiza el velo. */
.hero__video{position:absolute;inset:0;z-index:0;background:var(--verde)}
.hero__video video,
.hero__video img{
  width:100%;height:100%;
  object-fit:cover;object-position:75% center;
  display:block;
}
/* Movil: el texto cae sobre el centro del cuadro, asi que el velo va de abajo
   hacia arriba y tapa parejo. En escritorio se vuelve horizontal (mas abajo). */
/* El velo no baja de 0.80 arriba ni con el fotograma mas soleado detras: medido
   sobre los 8 s del clip, ahi es donde el subtitulo de 18px se cae por debajo de
   4.5:1. En escritorio el texto ocupa media pantalla y el gradiente puede
   aflojar mucho antes (ver la consulta de 960px). */
.hero__velo{
  position:absolute;inset:0;z-index:1;
  background:
    linear-gradient(to top,rgb(20 48 31 / 0.97) 26%,rgb(20 48 31 / 0.88) 62%,rgb(20 48 31 / 0.80) 100%);
  /* El velo se retira de la franja que ocupa la cabecera. Esa franja no la ve
     nadie a pelo: o esta detras de la barra o ya subio fuera de pantalla, y el
     titular del hero empieza bastante mas abajo. Si el velo la cubriera, el
     video quedaria tapado justo donde se pidio verlo, y la barra al 70% no
     tendria mas que verde plano detras.
     Que el menu siga leyendose no depende del velo sino de la crema: al 70% el
     fondo puede mover el color un 30%, y con eso el peor fotograma de los seis
     deja el menu en 4.51:1 (chk_cabecera.py, 1280x720). Pasa AA por dos
     centesimas y ni una mas: 0.7 es el suelo de esta barra, con 0.6 el menu se
     cae. Si algun dia entra un clip mas claro hay que volver a medir antes de
     publicarlo, porque este margen no absorbe nada. */
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,
    rgb(0 0 0 / 0.35) calc(var(--alto-cabecera) * 0.72),#000 var(--alto-cabecera));
          mask-image:linear-gradient(to bottom,transparent 0,
    rgb(0 0 0 / 0.35) calc(var(--alto-cabecera) * 0.72),#000 var(--alto-cabecera));
}
/* El rotulo es bronce a 12px: sobre el verde plano da 4.7:1, pero sobre un
   fotograma con sol detras se hunde a 1.8:1. La placa lo devuelve a su fondo. */
.hero .rotulo--claro{
  /* inline-flex y no inline-block por la reserva de altura: en ventanas
     estrechas el rotulo mas largo se parte en dos lineas y el mas corto no, asi
     que el rotador le fija un min-height. Con inline-block el texto se quedaria
     pegado arriba y la placa verde con un hueco debajo; asi queda centrado. */
  display:inline-flex;
  align-items:center;
  padding:5px 12px;
  background:var(--verde);
  border-radius:var(--r-badge);
}
/* Rotacion entre escenas: solo opacidad, 600ms. Nada de scale ni parallax. */
.hero__escena{position:absolute;inset:0;opacity:0;transition:opacity 600ms var(--ease)}
.hero__escena[data-activa]{opacity:1}
/* Los puntos dicen cuantas escenas hay y dejan saltar a una: sin ellos el hero
   parece un video suelto y nadie descubre las otras cinco. */
.hero__puntos{
  position:absolute;z-index:3;right:20px;bottom:20px;
  display:flex;gap:10px;
}
.hero__punto{
  width:40px;height:4px;padding:0;
  border:0;border-radius:var(--r-badge);
  background:rgb(250 243 225 / 0.32);
  cursor:pointer;
  transition:background 150ms var(--ease);
}
.hero__punto[aria-current="true"]{background:var(--bronce)}
.hero__punto:hover{background:rgb(250 243 225 / 0.6)}
.hero__punto:focus-visible{outline:2px solid var(--crema);outline-offset:4px}
/* Flechas laterales. Nacen ocultas y las saca el hover del hero, que es lo que
   se pidio; el foco las saca tambien, porque si no quien navega con teclado
   tabula hasta un boton que no ve. En tactil no existen: no hay hover que las
   revele y los puntos ya dejan saltar de escena. */
.hero__flecha{
  position:absolute;z-index:4;top:50%;
  display:none;place-items:center;
  width:44px;height:44px;padding:0;margin-top:-22px;
  border:1px solid rgb(250 243 225 / 0.3);border-radius:50%;
  background:rgb(20 48 31 / 0.5);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  color:var(--crema);cursor:pointer;
  opacity:0;
  transition:opacity 220ms var(--ease),background 150ms var(--ease),
             border-color 150ms var(--ease);
}
.hero__flecha svg{
  width:20px;height:20px;fill:none;stroke:currentColor;
  stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;
}
.hero__flecha--izq{left:14px}
.hero__flecha--der{right:14px}
.hero__flecha:hover{background:rgb(20 48 31 / 0.78);border-color:var(--bronce)}
.hero__flecha:focus-visible{outline:2px solid var(--crema);outline-offset:3px}
@media (hover:hover) and (pointer:fine){
  .hero__flecha{display:grid}
  .hero:hover .hero__flecha,
  .hero__flecha:focus-visible{opacity:1}
}
/* Nombra el producto que se esta viendo y trae su lote: es lo que conecta la
   escena con el catalogo, si no el video es decoracion. La categoria no se
   repite aqui, la lleva el rotulo de arriba. Va sin linea propia porque justo
   encima .hero__pruebas ya pone una. */
/* 0.88 y no 0.82 como el resto del texto del hero: es la linea mas baja de la
   columna, donde el velo ya se ha aclarado, y al alargar los clips entro ahi el
   agua iluminada de calm. A 0.82 se quedaba en 4,45:1 y el minimo es 4,5. */
.hero__escena-rotulo{
  display:flex;flex-wrap:wrap;align-items:center;gap:10px;
  margin-top:16px;
  font-size:.9375rem;color:rgb(250 243 225 / 0.88);
}
.hero__escena-rotulo b{color:var(--crema);font-weight:600}
.hero__texto>*+*{margin-top:20px}
.hero__sub{font-size:1.125rem;line-height:1.6;color:rgb(250 243 225 / 0.82);max-width:52ch}
/* El rotulo, el titular y el subtitulo cambian con cada escena. Si el texto se
   sustituyera de golpe mientras el video se funde en 600ms pareceria un fallo,
   asi que se apaga, se cambia a oscuras y vuelve. El intercambio se hace en el
   punto muerto (ver el temporizador de ir()). */
.hero__copia{transition:opacity 260ms var(--ease),transform 260ms var(--ease)}
.hero__texto[data-cambiando] .hero__copia{opacity:0;transform:translateY(6px)}
.hero__acciones{display:flex;flex-direction:column;gap:12px;padding-top:8px}
/* 0.88 por lo mismo que el rotulo de abajo: esta en la parte baja de la
   columna, donde el velo ya se ha abierto, y la tirada nueva de metabolic trae
   el vial iluminado justo por detras. A 0.82 se quedaba en 4,37:1. */
.hero__pruebas{
  display:flex;flex-wrap:wrap;gap:8px 20px;
  padding-top:20px;margin-top:24px;
  border-top:1px solid rgb(250 243 225 / 0.18);
  font-size:.9375rem;color:rgb(250 243 225 / 0.88);
}
.hero__pruebas span{display:inline-flex;align-items:center;gap:8px}
.tic{color:var(--bronce);font-weight:600}


/* ============================================================
   TRIADA DE CONFIANZA  (bloque 3)
   ============================================================ */
/* position es para la mano del vial, que se cuelga del canto inferior. Y sin
   overflow:hidden a proposito: la mano tiene que poder salirse del bloque por
   abajo. Puede porque lo que hay debajo es crema tambien, asi que la costura de
   las dos secciones no existe. */
.triada{background:var(--crema);border-bottom:1px solid var(--superficie);position:relative}
.triada__rejilla{display:grid;gap:20px;margin-top:32px}
.confianza{
  background:transparent;
  border:1px solid var(--superficie);
  border-radius:var(--r-tarjeta);
  padding:24px;
}
/* El bronce va de FONDO con texto oscuro encima, nunca de color
   de texto sobre crema: a 12px daba 2.1:1 de contraste. */
.confianza__num{
  display:inline-flex;align-items:center;justify-content:center;
  width:32px;height:32px;margin-bottom:12px;
  background:var(--bronce);color:#2A1F14;
  border-radius:var(--r-control);
  font-size:.8125rem;font-weight:600;letter-spacing:.02em;
  font-variant-numeric:tabular-nums;
}
.confianza h3{margin-bottom:8px}
.confianza p{font-size:.9375rem}

/* LA MANO CON EL VIAL
   Entra por el borde derecho de la pagina y se apoya en el canto inferior de
   las tarjetas 02 y 03. Es la primera vez en toda la pagina que se ve el
   producto a escala humana, y cae justo donde se acaban las tres promesas y
   empieza el catalogo: firma las promesas y abre la puerta al catalogo.
   top se cuenta desde abajo del bloque: 56px es el relleno de .seccion--ajustada,
   o sea el canto inferior de las tarjetas, y los 28 de mas son el montaje. Son
   28 y no mas porque la tarjeta lleva 24 de relleno: hasta ahi se pisa el
   canto, y a partir de ahi se empezaria a pisar el texto. */
.mano-vial{
  position:absolute;right:0;
  top:calc(100% - 56px - 28px);
  width:var(--mano);height:auto;
  /* Decorativa: no debe robar el clic a nada de lo que tape, ni salir al
     seleccionar texto con el raton. */
  pointer-events:none;user-select:none;
  display:none;
}

/* ============================================================
   CATEGORIAS  (bloque 4)
   ============================================================ */
/* En movil sigue siendo lo de siempre: titulo arriba y cuadricula debajo. El
   reparto en dos columnas —texto a la izquierda, fila de tarjetas metiendose
   bajo el brazo por la derecha— solo tiene sentido con sitio para las dos
   cosas, asi que vive entero en el bloque de 960. */
.catalogo-home{display:grid;gap:28px}
/* La copia del juego de tarjetas existe solo para que el desfile no tenga
   costura. Donde no hay desfile no pinta nada, y en el movil doblaria la
   cuadricula: fuera por defecto, dentro solo con .catalogo-home--desfile.
   Doble clase a proposito: .categoria trae su propio display:block y esta
   escrita mas abajo, asi que con una sola ganaria ella y los clones saldrian
   en la cuadricula del movil. */
.categoria.categoria--clon{display:none}
/* El titular parte por la coma y no por donde caiga: "22 compuestos" y "26
   presentaciones" son dos cuentas distintas y se leen mejor una debajo de otra.
   Van en dos <span> y no con un <br> porque el cambio de idioma escribe
   textContent, y un nodo bilingue con hijos dentro se los comeria. */
.catalogo-home__titular span{display:block}
.catalogo-home__texto p{margin-top:14px;max-width:46ch}
.catalogo-home__texto .btn{margin-top:22px}
.catalogo-home__pista{min-width:0}
/* Las flechas mueven una fila horizontal: sin fila, no pintan nada. */
.pista__mando{display:none;gap:10px;margin-top:28px}
.pista__flecha{
  width:44px;height:44px;
  /* Para el ancla del .solo-lector, que va absoluto. */
  position:relative;
  display:grid;place-items:center;
  background:transparent;color:var(--verde);
  border:1px solid var(--superficie);border-radius:50%;
  font-family:inherit;font-size:1.5rem;line-height:1;cursor:pointer;
  transition:background 150ms var(--ease),border-color 150ms var(--ease),opacity 150ms var(--ease);
}
.pista__flecha:hover{background:var(--crema);border-color:var(--bronce)}
.pista__flecha[disabled]{opacity:.3;cursor:default}
.pista__flecha[disabled]:hover{background:transparent;border-color:var(--superficie)}

.categorias__rejilla{display:grid;gap:16px;margin-top:32px;grid-template-columns:repeat(2,1fr)}
.categoria{
  position:relative;display:block;text-decoration:none;
  border-radius:var(--r-tarjeta);overflow:hidden;
  background:var(--verde);
}
/* El velo de la tarjeta que queda detras del brazo. Quien decide cual es
   sitio.js, que mide la silueta contra la caja de cada tarjeta.
   Va en un ::after y no bajando la opacidad de la tarjeta entera porque lo que
   se busca es que la foto siga ahi, vista a traves de algo: al 70% de crema la
   tarjeta se apaga hasta casi el fondo pero no desaparece, que es como se lee
   "esto esta detras" y no "esto no esta". */
.categoria::after{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:var(--crema);opacity:0;
  transition:opacity 260ms var(--ease);
}
.categoria--tapada::after{opacity:.7}
/* Sin pointer-events porque a este nivel ya no es un enlace sino la textura que
   se ve tras la mano. */
.categoria--tapada{pointer-events:none}
/* El desenfoque va solo en la foto, no en la tarjeta: si se difumina el
   conjunto tambien se difumina el velo y el canto redondeado se emborrona. */
.categoria--tapada .categoria__foto{filter:blur(2px)}
/* Mismo trato que las tarjetas de producto: entra la persona, el vial espera
   debajo. Se quito el scale(1.03) de antes porque escalar dos fotos mientras
   se funden entre si deja el cruce sucio; el cambio de imagen ya es el gesto. */
/* Las dos son clases sueltas a proposito. Con `.categoria img` el selector
   pesaba mas que `.categoria__vial` y le imponia width:100%, asi que en movil
   la miniatura salia del tamano de la tarjeta entera. */
.categoria__foto{
  display:block;width:100%;height:auto;aspect-ratio:1/1;object-fit:cover;
  transition:filter 260ms var(--ease);
}
.categoria__vial{
  position:absolute;inset:0;width:100%;height:100%;
  /* La foto del vial es cuadrada y la tarjeta ya no lo es: sin esto el 100x100%
     la estira y el frasco sale ovalado al pasar el raton. */
  object-fit:cover;object-position:center;
  opacity:0;transition:opacity 150ms var(--ease);
}
.categoria:focus-visible{outline:2px solid var(--verde);outline-offset:3px}
.categoria__capa{
  position:absolute;inset:auto 0 0 0;z-index:1;
  padding:16px;
  background:linear-gradient(to top,rgb(20 48 31 / 0.94),rgb(20 48 31 / 0));
  color:var(--crema);
}
/* La pista va arriba a la derecha: abajo ya vive el nombre de la categoria. */
.categoria__pista{
  position:absolute;top:12px;right:12px;z-index:1;
  padding:5px 10px;
  background:rgb(250 243 225 / 0.94);color:var(--verde);
  border-radius:var(--r-badge);
  font-size:.75rem;font-weight:500;letter-spacing:.01em;
  transition:opacity 150ms var(--ease);
  pointer-events:none;
}
@media (hover:hover) and (pointer:fine){
  .categoria:hover .categoria__vial,
  .categoria:focus-within .categoria__vial{opacity:1}
  .categoria:hover .categoria__pista,
  .categoria:focus-within .categoria__pista{opacity:0}
}
/* Sin raton no hay hover. En la tarjeta de producto el frasco se queda de
   miniatura porque ahi se decide la compra; aqui no: la tarjeta de categoria
   solo enruta al catalogo, y a 160px el rotulo ya ocupa dos tercios del alto,
   asi que una miniatura encima le caeria sobre el texto. */
@media (hover:none){
  .categoria__pista,
  .categoria__vial{display:none}
}
.categoria__capa strong{display:block;font-weight:500;font-size:1rem;line-height:1.3}
.categoria__capa small{font-size:.8125rem;color:rgb(250 243 225 / 0.72)}

/* ============================================================
   MAS VENDIDOS  (bloque 5)
   ============================================================ */
/* Los mas vendidos van sobre banda verde oscuro. Es el unico bloque oscuro
   entre categorias y COA, que van los dos sobre crema: el contraste marca el
   escaparate y de paso es lo que hace que el ADN se vea, porque un filamento de
   luz sobre arena no existe y sobre verde profundo si.
   position + overflow son para la helice: el filamento se sale del bloque por
   las dos puntas y aqui es donde se corta. isolation es para la mezcla del
   video: sin el, atravesaria hasta el fondo de la pagina en vez de pararse en
   esta banda. */
#vendidos{background:var(--verde);position:relative;overflow:hidden;isolation:isolate}
#vendidos > .envoltura{position:relative;z-index:1}
/* Sobre verde, el verde de los titulos desaparece. Mismo reparto que en el
   cierre: rotulo en bronce, titular en crema. */
#vendidos h2{color:var(--crema)}
#vendidos > .envoltura > .rotulo{color:var(--bronce)}
#vendidos .enlace-texto{color:var(--crema)}
#vendidos .enlace-texto:hover{color:var(--bronce)}

/* EL ADN DE FONDO
   Es el mismo clip del hero de marioka, recoloreado a la marca sin tocar el
   archivo. El original es una helice cian encendida sobre azul casi negro.
   Sobre banda oscura no hay que invertir nada: la cadena solo cambia el tono.
     brightness+contrast   hunde el azul del fondo hasta negro puro y saca la hebra
     hue-rotate            lleva el cian al bronce
     saturate+brightness   lo baja de neon a bronce de marca
   Y encima lighten, que es el maximo por canal: donde el video es mas oscuro
   que la banda pasa la banda, o sea en todo el rectangulo menos el filamento.
   El rectangulo del video desaparece y solo queda la helice.
   lighten y no screen a proposito: con screen el filamento se lleva por delante
   el verde del fondo y el bronce se ensucia (salia #acaa75 en vez de #c29a6e);
   con el maximo, el color que pone el filtro es el que se ve.
   Los numeros salen de una busqueda contra cuatro colores medidos en el clip
   (fondo #000916, nucleo #4ac2ee, halo #1e6e96, hebra tenue #285a78), con el
   halo pesando mas que el nucleo: es la mayor parte de lo que se ve.
     fondo  -> #000000   (desaparece: la banda gana el maximo)
     nucleo -> #a99f82   (bronce de marca #c29a6e)
     halo   -> #767751
   Si se cambia el clip hay que volver a medir: esta calibrado contra ESTE
   video, no es una formula general. Hoja de prueba en _gen/prueba_adn.py.

   La capa no lleva transform ni will-change, y es a proposito: cualquiera de
   los dos crea un contexto de apilado, y la mezcla se para ahi en vez de llegar
   a la banda. Eso es lo que dejaba el rectangulo del video a la vista. Por eso
   el giro, el desplazamiento del parallax y el tramo van todos en el mismo
   transform, sobre el propio video, y el parallax viaja por --desliz, que se
   hereda sin apilar nada. */
.helice{position:absolute;inset:0;overflow:hidden;pointer-events:none;display:none}
/* Dos copias en fila, la segunda del reves. Una sola no vale: con object-fit
   cover el video se escala por el alto, asi que estirar un clip de 900 px a la
   diagonal del bloque multiplica la hebra por dos y sale un churro gordo en vez
   de una helice. Partiendola en dos, cada copia va casi a escala 1.
   El espejo es lo que hace invisible la union: la copia de arriba entra en el
   corte por el mismo sitio por el que sale la de abajo, asi que el filamento no
   da el salto que daria repitiendo el clip tal cual. */
.helice video{
  position:absolute;left:50%;top:50%;
  width:var(--grosor,300px);height:calc(var(--largo,204%) / 2);
  object-fit:cover;display:block;
  filter:brightness(1.4) contrast(2.25) hue-rotate(-128deg) saturate(.3) brightness(.75);
  mix-blend-mode:lighten;
  opacity:var(--fuerza,1);
  transform:translate(-50%,-50%) translate3d(0,var(--desliz,0px),0)
            rotate(var(--giro,59deg)) translateY(var(--tramo)) scaleY(var(--espejo,1));
}
.helice video:first-of-type{--tramo:-50%}
.helice video:last-of-type{--tramo:50%;--espejo:-1}
/* La foto de la tarjeta va sobre --verde, que ahora es tambien el color de la
   banda: sin borde, la mitad de arriba de la tarjeta se funde con el fondo y se
   pierden las esquinas. El bronce rebajado dibuja el canto sobre el verde
   (queda un #656647) y casi no se nota sobre la crema del cuerpo. */
#vendidos .producto{border-color:rgb(194 154 110 / 0.45)}
.productos__rejilla{display:grid;gap:20px;margin-top:32px}
.producto{
  display:flex;flex-direction:column;
  background:var(--crema);
  border:1px solid var(--superficie);
  border-radius:var(--r-tarjeta);
  overflow:hidden;
  /* Cada tarjeta es destino de enlace: el boton del hero salta a la ficha de la
     escena que se este viendo. Sin esto la tarjeta aterriza debajo de la barra
     pegajosa, que mide --alto-cabecera; los 16px de mas son para que no quede
     lamiendo el borde. */
  scroll-margin-top:calc(var(--alto-cabecera) + 16px);
  transition:box-shadow 150ms var(--ease),border-color 150ms var(--ease);
}
.producto:hover{box-shadow:var(--sombra);border-color:var(--bronce)}
/* Dos fotos apiladas: primero la persona, el vial debajo esperando el raton.
   La de beneficio vende el porque; la del vial confirma el que. */
.producto__img{position:relative;background:var(--verde);overflow:hidden}
/* height:auto es obligatorio: el atributo height="400" del HTML es una pista de
   presentacion, y mientras la altura no sea auto el navegador ignora aspect-ratio
   y deja la foto estirada a 400px de alto. */
.producto__foto{display:block;width:100%;height:auto;aspect-ratio:1/1;object-fit:cover}
.producto__foto--vial{
  position:absolute;inset:0;height:100%;
  opacity:0;transition:opacity 150ms var(--ease);
}
/* Solo opacity, nunca transform ni filtros: la tarjeta ya gasta su unica sombra. */
@media (hover:hover) and (pointer:fine){
  .producto:hover .producto__foto--vial,
  .producto:focus-within .producto__foto--vial{opacity:1}
  .producto:hover .producto__pista,
  .producto:focus-within .producto__pista{opacity:0}
}
.producto__pista{
  position:absolute;right:12px;bottom:12px;
  padding:5px 10px;
  background:rgb(250 243 225 / 0.94);color:var(--verde);
  border-radius:var(--r-badge);
  font-size:.75rem;font-weight:500;letter-spacing:.01em;
  transition:opacity 150ms var(--ease);
  pointer-events:none;
}
/* Sin raton no hay hover que valga: el vial se queda visible en miniatura,
   porque nadie paga $99 sin ver el frasco. */
@media (hover:none){
  .producto__pista{display:none}
  .producto__foto--vial{
    inset:auto 12px 12px auto;
    width:76px;height:76px;
    opacity:1;
    border-radius:var(--r-control);
    border:2px solid var(--crema);
  }
}
.producto__cinta{position:absolute;top:12px;left:12px;display:flex;gap:6px;z-index:1}
.producto__cuerpo{padding:20px;display:flex;flex-direction:column;flex:1;gap:12px}
.producto__nombre{font-size:1.0625rem;font-weight:500;color:var(--verde);line-height:1.3}
.producto__cat{font-size:.8125rem;color:var(--texto);opacity:.8}
.producto__precio{
  font-size:1.375rem;font-weight:600;color:var(--verde);
  display:flex;align-items:baseline;gap:10px;
}
.producto__tachado{
  font-size:1rem;font-weight:400;color:var(--texto);
  text-decoration:line-through;opacity:.65;
}
/* El badge de COA va ENCIMA del boton de compra, nunca debajo.
   Es la evidencia que desarma la duda. */
.producto__coa{
  display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  padding:10px 12px;
  background:var(--superficie);
  border-radius:var(--r-control);
  font-size:.8125rem;
}
.producto__lote{font-weight:600;color:var(--verde);font-variant-numeric:tabular-nums}
.producto__pie{margin-top:auto;display:flex;flex-direction:column;gap:8px}
.producto__nota{font-size:.75rem;color:var(--texto);opacity:.75;text-align:center}
.producto__desvio{
  font-size:.8125rem;text-align:center;
  padding-top:4px;
}

/* ============================================================
   COMO LEER UN COA  (bloque 6)
   ============================================================ */
/* Arena, la misma banda del cierre. Son los dos bloques que piden lo mismo -
   "mira el COA antes que el precio" - asi que comparten fondo y el ojo los
   empareja aunque esten separados por el FAQ.
   Sin color propio: hereda el del body, que ya es el texto normal de la pagina. */
.coa{background:var(--superficie)}
.coa__intro{max-width:60ch;margin-top:12px}
.coa__pasos{display:grid;gap:20px;margin-top:36px}
.coa__paso{
  /* Sobre arena el bronce al 32% es invisible; al 55% queda un pelo mas oscuro
     que el fondo, que es justo lo que hace .confianza con superficie sobre crema. */
  border:1px solid rgb(194 154 110 / 0.55);
  border-radius:var(--r-tarjeta);
  padding:24px;
}
/* Mismo criterio que .confianza__num: sobre banda clara el bronce va de FONDO
   con texto oscuro encima, nunca de tinta (1.8:1 sobre arena). De paso el numero
   deja de gritar mas que el titulo del paso, que es lo que hay que leer. */
.coa__paso strong{
  display:inline-flex;align-items:center;justify-content:center;
  width:36px;height:36px;margin-bottom:12px;
  background:var(--bronce);color:#2A1F14;
  border-radius:var(--r-control);
  font-size:.875rem;font-weight:600;letter-spacing:.02em;
  font-variant-numeric:tabular-nums;
}
.coa__paso h3{margin-bottom:8px}
.coa__paso p{font-size:.9375rem}
.coa__cierre{margin-top:32px;display:flex;flex-wrap:wrap;gap:12px;align-items:center}

/* ============================================================
   FAQ  (bloque 7)
   ============================================================ */
.faq__lista{margin-top:32px;border-top:1px solid var(--superficie)}
.faq details{border-bottom:1px solid var(--superficie)}
.faq summary{
  cursor:pointer;list-style:none;
  padding:20px 40px 20px 0;position:relative;
  font-size:1.0625rem;font-weight:500;color:var(--verde);
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{
  content:"+";position:absolute;right:8px;top:50%;transform:translateY(-50%);
  font-size:1.5rem;font-weight:400;color:var(--verde);line-height:1;
}
.faq details[open] summary::after{content:"\2212"}
.faq summary:focus-visible{outline:2px solid var(--bronce);outline-offset:2px}
.faq__cuerpo{padding:0 0 20px;max-width:70ch;font-size:.9375rem}

/* ============================================================
   CTA FINAL  (bloque 8)
   ============================================================ */
/* Verde de marca: es la ultima parada antes del pie y la unica banda oscura de
   esta mitad de la pagina, asi que corta el hilo de la lectura y deja el boton
   solo delante del ojo. */
/* position + overflow + isolation, igual que en mas vendidos y por lo mismo: el
   video se sale del bloque por arriba y por abajo y aqui es donde se corta, y
   sin isolation la mezcla atravesaria hasta el fondo de la pagina en vez de
   pararse en esta banda. */
.cierre{background:var(--verde);color:var(--crema);position:relative;overflow:hidden;isolation:isolate}
.cierre > .envoltura{position:relative;z-index:1}
.cierre h2{color:var(--crema)}
.cierre__caja{text-align:center;max-width:60ch;margin:0 auto}
.cierre__caja p{margin-top:12px;color:rgb(250 243 225 / 0.82)}
.cierre__acciones{margin-top:28px;display:flex;flex-direction:column;gap:12px;align-items:center}

/* LAS MOLECULAS DE FONDO
   Mismo montaje que el ADN de mas vendidos: mezcla lighten sobre banda verde,
   asi que solo sobrevive lo que es mas claro que la banda y el rectangulo del
   video desaparece. Lo que cambia es de donde sale el negro. El ADN venia ya
   encendido sobre azul casi negro y el filtro solo le cambiaba el tono; el
   render que mando la clienta es justo al reves, cintas grises sobre gris
   claro, y con lighten un fondo claro gana en TODO el rectangulo y deja la
   banda gris. Por eso el recoloreado a fondo casi negro y cintas de bronce se
   pide en la imagen antes de animarla (_gen/gen_moleculas.py) y no se intenta
   con un filtro aqui: un filtro no sabe distinguir el fondo de las cintas.
   Como el negro ya viene puesto, el filtro de aqui no tiene que fabricar
   ninguno; solo baja el brillo para que las cintas no se coman la banda y deje
   encendidos los cantos, que es lo unico que se quiere ver.
   Un solo video y sin geometria, al reves que la helice: el render ya es 16:9 y
   ya fluye de abajo a la izquierda a arriba a la derecha, asi que object-fit
   cover lo encaja solo en cualquier ancho. La unica cuenta es el margen de
   arriba y abajo, que tiene que ser mayor que el recorrido del parallax
   (--desliz llega a 110px) o asomaria el corte al deslizarse.
   La cadena de filtros:
     contrast(4.6)   hunde el cuerpo del gel hasta negro y deja arriba solo los
                     cantos encendidos. Es lo que baja la banda del 40% pintado
                     al 20%, que es lo que pinta el ADN. Sin esto el render
                     entero se ve, el verde desaparece y el parrafo queda
                     cruzado de moleculas.
     sepia(1)        el render trae una cinta de gel gris, y un gris no se
                     arregla con hue-rotate ni con saturate porque no tiene tono
                     del que tirar. La matriz de sepia lleva todo al marron,
                     gris incluido. (En el ADN se descarto justo por esto, pero
                     alli la mezcla era multiply y hacia falta un blanco limpio;
                     aqui, con lighten, ensuciar es lo que se busca.)
     saturate(1.6)   abre ese marron hasta el bronce de marca.
     brightness(.29) baja el conjunto para que solo lo encendido gane el maximo.
   Calibrado contra tres fotogramas del clip (1 s, 6,5 s y 11 s) en
   _gen/prueba_moleculas.py. Si se cambia el clip hay que volver a pasar la
   hoja: esta ajustado contra ESTE video. */
.moleculas{position:absolute;inset:0;overflow:hidden;pointer-events:none;display:none}
.moleculas video{
  position:absolute;left:0;top:-160px;
  width:100%;height:calc(100% + 320px);
  object-fit:cover;display:block;
  filter:contrast(4.6) sepia(1) saturate(1.6) brightness(.29);
  mix-blend-mode:lighten;
  transform:translate3d(0,var(--desliz,0px),0);
}
/* Sin --fuerza, al reves que la helice: alli la opacidad es el mando para bajar
   el filamento cuando el bloque crece de alto. Aqui el brillo ya lo reparte el
   velo pixel a pixel — fuerte por los lados, nulo detras del texto — y una
   opacidad global encima solo apagaria tambien los lados. */
/* EL VELO
   Abre un hueco de verde limpio en el centro, que es por donde va la columna de
   texto (topada en 60ch, unos 640 de los 1425 px del bloque). Sin el, el
   parrafo se lee sobre cadenas de moleculas.
   Va como capa verde POR ENCIMA del video, y no como mask-image sobre la capa,
   por dos razones: una mascara en .moleculas crearia un contexto de apilado y
   la mezcla se pararia ahi (el mismo fallo que documenta el ADN), y una
   mascara sobre el propio video se moveria con el parallax, o sea el hueco se
   desplazaria dejando el texto fuera. Pintado aparte, el hueco se queda quieto.
   Verde opaco a transparente es, sobre esta banda, exactamente lo mismo que
   bajarle la opacidad al video pixel a pixel — que es como esta simulado en la
   hoja de prueba. El segundo color va escrito y no con var(): interpolar hacia
   la palabra transparent es interpolar hacia negro transparente, y en el camino
   el verde se apaga. */
.cierre::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(ellipse 31% 48% at 50% 50%,
             var(--verde) 55%, rgb(26 60 42 / 0) 100%);
}

/* ============================================================
   PIE
   ============================================================ */
/* Pie sobre crema: es el fondo del arte del logo, asi que el logo se apoya
   directo, sin placa ni recorte visible. El bloque .cierre que va justo
   encima es --superficie (arena), asi que el corte se ve sin borde. */
.pie{background:var(--crema);color:var(--texto);font-size:.9375rem}
.pie .envoltura{padding-top:56px;padding-bottom:32px}
.pie__rejilla{display:grid;gap:32px}
.pie h3{color:var(--verde);font-size:.9375rem;font-weight:600;letter-spacing:.06em;text-transform:uppercase;margin-bottom:14px}
.pie ul{list-style:none;margin:0;padding:0;display:grid;gap:8px}
.pie a{text-decoration:none;transition:color 150ms var(--ease)}
.pie a:hover{color:var(--verde)}
.pie__marca img{width:180px;height:auto;margin-bottom:14px}
.pie__legal{
  margin-top:40px;padding-top:24px;
  border-top:1px solid var(--superficie);
  font-size:.8125rem;line-height:1.6;
  display:grid;gap:12px;
}
/* El aviso legal iba en bronce, que sobre crema da 3.4:1 y aqui mide 13px.
   Verde: el aviso obligatorio es lo ultimo que puede quedar a medio leer. */
.pie__legal strong{color:var(--verde);font-weight:600}

/* ============================================================
   PAGINAS INTERIORES
   ============================================================ */
/* Cabezal de pagina. Es el sustituto del hero en todo lo que no es la home:
   banda verde, una sola idea y la ruta de vuelta. Verde y no crema porque la
   cabecera es translucida y necesita algo detras que la separe del contenido;
   sobre crema la barra flota sobre un fondo del mismo color y se pierde. */
.pagina{
  background:var(--verde);color:var(--crema);
  /* Sube por detras de la cabecera, igual que el hero, para que la banda empiece
     arriba del todo y no quede un filo crema entre la barra y el verde. */
  margin-top:calc(var(--alto-cabecera) * -1);
  padding-top:calc(var(--alto-cabecera) + 48px);
  padding-bottom:48px;
}
.pagina h1{color:var(--crema);font-size:clamp(1.75rem,4vw,2.75rem)}
.pagina__lead{
  margin-top:16px;max-width:62ch;
  font-size:1.0625rem;line-height:1.6;color:rgb(250 243 225 / 0.82);
}
/* Migas: la ruta de vuelta. Va antes del rotulo porque lo primero que necesita
   quien cae aqui desde el pie es saber de donde cuelga esto. */
.migas{font-size:.8125rem;margin-bottom:14px;color:rgb(250 243 225 / 0.7)}
.migas a{color:rgb(250 243 225 / 0.7);text-decoration:none;border-bottom:1px solid transparent}
.migas a:hover{color:var(--crema);border-bottom-color:var(--bronce)}
.migas span{margin:0 8px}
/* Dato suelto del cabezal (precio desde, numero de compuestos, fecha de la
   version del documento). Bronce sobre verde da 4.7:1, asi que aqui si vale. */
.pagina__datos{
  margin-top:24px;display:flex;flex-wrap:wrap;gap:10px 28px;
  font-size:.9375rem;color:rgb(250 243 225 / 0.82);
}
.pagina__datos b{color:var(--bronce);font-weight:600}

/* ---- Cuerpo de texto largo ------------------------------------------------
   Solo para documentos: legales, guias y politicas. Un ancho de 68ch y un
   ritmo vertical unico, para no ir poniendo margenes a mano en cada pagina. */
.prosa{max-width:68ch}
.prosa>*+*{margin-top:18px}
.prosa h2{font-size:1.375rem;margin-top:44px}
.prosa h2:first-child{margin-top:0}
.prosa h3{margin-top:30px}
.prosa ul,.prosa ol{margin-left:0;padding-left:22px;display:grid;gap:10px}
.prosa li{padding-left:2px}
.prosa li::marker{color:var(--bronce)}
.prosa strong{color:var(--verde);font-weight:600}
/* El :not(.btn) no es adorno. Un enlace dentro de la prosa es mas especifico
   que .btn--primario, asi que sin el, el boton del final salia con el texto en
   verde sobre el fondo verde -invisible- y con la raya de bronce del enlace
   debajo. Excluyendolo, el boton se pinta con sus propias reglas. */
.prosa a:not(.btn){color:var(--verde);font-weight:500;border-bottom:1px solid var(--bronce);text-decoration:none}
.prosa a:not(.btn):hover{border-bottom-color:var(--verde)}
/* Fecha de version del documento. Va arriba y en pequeno: es dato de archivo,
   no de lectura. */
.prosa__version{
  font-size:.8125rem;color:#6B6B6B;
  padding-bottom:18px;border-bottom:1px solid var(--superficie);
}

/* Caja de aviso dentro del texto. La variante --fuerte es para lo que no puede
   pasar desapercibido (el aviso de uso en investigacion). */
.nota{
  border-left:3px solid var(--bronce);
  background:var(--superficie);
  border-radius:0 var(--r-tarjeta) var(--r-tarjeta) 0;
  padding:20px 24px;font-size:.9375rem;
}
.nota>*+*{margin-top:10px}
.nota__titulo{
  display:block;font-size:.75rem;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--verde);margin-bottom:8px;
}
.nota--fuerte{background:var(--verde);color:rgb(250 243 225 / 0.86);border-left-color:var(--bronce)}
.nota--fuerte .nota__titulo{color:var(--bronce)}
.nota--fuerte strong{color:var(--crema)}

/* Indice de saltos de los documentos largos. Un legal sin indice se abandona en
   el primer scroll: el que entra viene a por UNA respuesta, no a leerlo entero. */
.indice{
  border:1px solid var(--superficie);border-radius:var(--r-tarjeta);
  padding:20px 24px;background:var(--crema);
}
.indice ol{list-style:none;margin:0;padding:0;display:grid;gap:8px;counter-reset:i}
.indice li{counter-increment:i}
.indice a{
  text-decoration:none;color:var(--texto);font-size:.9375rem;
  border-bottom:1px solid transparent;transition:color 150ms var(--ease);
}
.indice a::before{
  content:counter(i,decimal-leading-zero);
  color:var(--bronce);font-weight:600;margin-right:10px;
  font-variant-numeric:tabular-nums;
}
.indice a:hover{color:var(--verde)}

/* ---- Rejilla de tarjetas de apoyo (pasos, garantias, metodos de pago) ------
   Es la misma tarjeta de .coa__paso pero suelta, para poder usarla fuera de
   aquel bloque sin arrastrar su contenedor. */
.tarjetas{display:grid;gap:20px;margin-top:32px}
.tarjeta{
  border:1px solid var(--superficie);border-radius:var(--r-tarjeta);
  padding:24px;background:var(--crema);
}
.tarjeta h3{margin-bottom:8px}
.tarjeta p{font-size:.9375rem}
.tarjeta__num{
  display:inline-flex;align-items:center;justify-content:center;
  width:36px;height:36px;margin-bottom:12px;
  background:var(--bronce);color:#2A1F14;border-radius:var(--r-control);
  font-size:.875rem;font-weight:600;letter-spacing:.02em;
  font-variant-numeric:tabular-nums;
}

/* ---- Lista de precios de categoria ----------------------------------------
   Tabla y no tarjetas: quien llega a una categoria de peptidos compara
   presentacion y precio en columna, y en tarjetas eso obliga a ir y volver con
   la vista. En movil cada fila se apila y las etiquetas salen de data-rotulo. */
.precios{width:100%;border-collapse:collapse;margin-top:28px;font-size:.9375rem}
.precios caption{text-align:left;padding-bottom:14px;color:#6B6B6B;font-size:.875rem}
.precios th{
  text-align:left;font-weight:600;color:var(--verde);
  font-size:.75rem;letter-spacing:.1em;text-transform:uppercase;
  padding:0 16px 12px 0;border-bottom:1px solid var(--superficie);
}
.precios td{padding:16px 16px 16px 0;border-bottom:1px solid var(--superficie);vertical-align:top}
.precios tr:last-child td{border-bottom:0}
.precios__nombre{font-weight:500;color:var(--verde)}
.precios__detalle{display:block;font-size:.8125rem;color:#6B6B6B;margin-top:3px}
.precios__precio{font-weight:600;color:var(--verde);font-variant-numeric:tabular-nums;white-space:nowrap}
.precios th:last-child,.precios td:last-child{text-align:right;padding-right:0}

/* ---- Paso a otras categorias ---------------------------------------------- */
.otras{display:grid;gap:12px;margin-top:32px}
.otras a{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:16px 20px;text-decoration:none;
  border:1px solid var(--superficie);border-radius:var(--r-tarjeta);
  background:var(--crema);color:var(--verde);font-weight:500;
  transition:border-color 150ms var(--ease),transform 150ms var(--ease);
}
.otras a:hover{border-color:var(--bronce)}
.otras small{color:#6B6B6B;font-weight:400}

/* ---- Pie de pagina interior: siempre una salida ---------------------------
   Ninguna interior termina en un punto muerto. El bloque .cierre de la home se
   reutiliza tal cual; esto solo es la version corta para documentos. */
.salida{
  margin-top:48px;padding-top:28px;border-top:1px solid var(--superficie);
  display:flex;flex-wrap:wrap;gap:12px;align-items:center;
}
.salida p{font-size:.9375rem;color:#6B6B6B}

/* ============================================================
   ESCALADO — movil primero
   ============================================================ */
@media (min-width:640px){
  /* Por debajo de aqui el logotipo no cabe: la barra solo tiene sitio para el
     monograma, el idioma y el carrito. Se queda el monograma, que es la pieza
     que aguanta sola. */
  .marca__letras{display:block}
  .hero__acciones{flex-direction:row;align-items:center}
  .hero__acciones .btn{width:auto}
  .triada__rejilla{grid-template-columns:repeat(3,1fr)}
  .categorias__rejilla{grid-template-columns:repeat(3,1fr)}
  .productos__rejilla{grid-template-columns:repeat(2,1fr)}
  /* El ADN entra aqui y no antes. En movil el bloque mide 375x2836: la diagonal
     es casi tres pantallas, el clip habria que estirarlo x3 y del filamento
     solo se veria un trozo del nucleo, gordo y borroso. Y de paso el telefono
     se ahorra 2,8 MB y un decodificador. Con dos columnas el bloque ya es
     ancho y el dibujo se lee. */
  .helice{display:block}
  /* Con lighten la opacidad es solo el brillo del filamento: baje lo que baje,
     el rectangulo sigue sin verse, porque el maximo por canal ya deja pasar la
     banda entera. Aqui va algo por debajo del tope porque el bloque queda alto y
     el ADN cruza por detras de dos filas de tarjetas. */
  .helice video{--fuerza:.85}
  .coa__pasos{grid-template-columns:repeat(2,1fr)}
  /* Mismo corte que el ADN y por la misma cuenta: en el movil esta banda es la
     ultima parada antes del pie y no compensa bajarse un video para adornarla.
     Sin el, se queda en verde liso, que es como estaba. */
  .moleculas{display:block}
  .cierre__acciones{flex-direction:row;justify-content:center}
  .cierre__acciones .btn{width:auto}
  .pie__rejilla{grid-template-columns:repeat(2,1fr)}
  /* Interiores */
  .tarjetas{grid-template-columns:repeat(2,1fr)}
  .otras{grid-template-columns:repeat(2,1fr)}
}
@media (min-width:960px){
  .nav{display:flex}
  /* Interiores: cuatro pasos en fila, como los del COA en la home. */
  .tarjetas--4{grid-template-columns:repeat(4,1fr)}
  .tarjetas--3{grid-template-columns:repeat(3,1fr)}
  .otras{grid-template-columns:repeat(3,1fr)}
  /* El documento y su indice, uno al lado del otro. El indice se queda pegado
     al hacer scroll: en un legal de 2.000 palabras es la unica forma de que
     siga sirviendo despues del primer salto. */
  .doc{display:grid;grid-template-columns:1fr 260px;gap:56px;align-items:start}
  .doc>.indice{position:sticky;top:calc(var(--alto-cabecera) + 20px);order:2}
  .doc>.prosa{order:1}
  /* La segunda columna queda vacia a proposito: es el hueco por donde se ve la
     escena. El texto vive en la primera y el velo se vuelve horizontal para que
     el lado derecho del video llegue limpio. */
  /* Sin min-height propio: el alto lo pone ahora .hero con 100svh, y si la
     envoltura tambien lo pidiera, en pantallas bajas ganaria ella y el hero se
     saldria de cuadro. */
  .hero .envoltura{
    grid-template-columns:1.05fr 0.95fr;align-items:center;
    padding-top:56px;padding-bottom:56px;gap:56px;
    /* Canal para la flecha izquierda (14px de margen + 44 de boton + aire).
       Por encima de 1328px de ventana el margen de la envoltura ya lo da hecho
       y esto se queda en los 20px de siempre, asi que la maqueta ancha —la que
       miden los comprobadores de contraste— no se mueve ni un pixel. Por
       debajo, el texto se aparta lo justo en vez de comerse la flecha. */
    padding-left:max(20px, calc(84px - (100vw - var(--ancho)) / 2));
  }
  /* La parada del 56% cae justo donde termina el texto (llega al 50% del ancho),
     asi que es la que decide si se lee. Estaba en 0.62, calibrado con un solo
     clip oscuro; con los seis del rotador manda el peor y tres traen mucha luz
     dorada ahi. 0.66 es el valor mas ligero que deja pasar AA en los seis (ver
     _gen/calibra_velo.py): subirlo mas taparia video sin necesidad. */
  .hero__velo{
    background:linear-gradient(to right,
      rgb(20 48 31 / 0.97) 0%,
      rgb(20 48 31 / 0.93) 34%,
      rgb(20 48 31 / 0.66) 56%,
      rgb(20 48 31 / 0.22) 78%,
      rgb(20 48 31 / 0.05) 100%);
  }
  .hero__video video,
  .hero__video img{object-position:center}
  /* La mano solo cuando las tres tarjetas ya estan en fila: en columna el brazo
     cruzaria la tarjeta entera de lado a lado.
     La foto ocupa la mitad derecha de la pagina. Dicho asi suena a capricho pero
     es lo que resuelve el encaje: como las tarjetas son tres, la del medio
     siempre monta a caballo del centro, asi que el canto izquierdo de la foto
     cae dentro de la 02 a cualquier ancho, sin tener que perseguirla con
     numeros. (Sale de calc(50vw - 20px) y no de 50vw porque a la derecha de la
     pagina hay barra de scroll: son los ~15px que se lleva, mas holgura.)
     El tope de 900 es para que en pantallas muy anchas el brazo deje de crecer.
     A partir de ~1840px el canto se corre a la derecha del centro y hacia los
     2150 pasa a montar la 03 en vez de la 02: sigue cumpliendo el encargo y no
     se come media pagina. */
  :root{
    --mano:min(calc(50vw - 20px), 900px);
    /* Lo que el antebrazo cuelga POR DEBAJO de donde empezaria el catalogo, y
       que por tanto hay que abrirle. 0.473 es donde toca fondo la silueta, no el
       borde de abajo del fichero: la foto lleva transparencia y el brazo sale
       por la derecha, asi que el punto mas bajo cae en x=1044 a 665px de los
       1408 de ancho. Lo mide _gen/perfil_mano.py; si se recorta otra vez la
       foto, hay que volver a correrlo. 256 es el aire que ya existe entre el
       canto de arriba de la foto y la primera fila de tarjetas.
       Sin esto el brazo cae encima de las dos tarjetas de categoria de la
       derecha: son enlaces, y taparlos con un adorno es tirar clics a la
       basura. */
    --hueco-mano:max(0px, calc(var(--mano) * 0.473 - 256px));
  }
  .mano-vial{display:block}
  /* El hueco se lo come el catalogo por arriba, no la triada por abajo: asi la
     mano queda pegada a las tarjetas que tiene que tocar y el aire sobra por el
     lado donde no molesta. Y se le descuenta al scroll-margin para que los
     enlaces "Ver el catalogo" sigan aterrizando en el rotulo y no en el aire.
     Esto vale de 960 a 1199, donde el catalogo sigue en cuadricula. De 1200
     para arriba el bloque se parte en dos columnas y el brazo pasa a taparlas
     a proposito: alli se le quita el hueco. */
  #categorias{
    padding-top:calc(72px + var(--hueco-mano));
    scroll-margin-top:calc(var(--alto-cabecera) - var(--hueco-mano));
  }
  .productos__rejilla{grid-template-columns:repeat(4,1fr)}
  /* Una sola fila de tarjetas: el bloque queda apaisado, el ADN cruza casi todo
     por aire libre y aqui si se le deja a tope. */
  .helice video{--fuerza:1}
  .coa__pasos{grid-template-columns:repeat(4,1fr)}
  .pie__rejilla{grid-template-columns:1.4fr 1fr 1fr 1fr}
}
/* ============================================================
   EL CATALOGO DE LA HOME, EN DOS COLUMNAS (desde 1200)
   ============================================================
   Texto a la izquierda, fila de tarjetas a la derecha y el brazo del vial
   cayendo sobre las ultimas. Aqui si se le deja tapar: el degradado de nitidez
   es lo que hace leer la fila como algo que sigue POR DETRAS de la foto, en vez
   de chocar con ella. Cual se apaga lo decide sitio.js midiendo la silueta.
   Desde 1200 y no desde 960 porque mas abajo la columna de texto se come media
   pista: quedarian dos tarjetas a la vista y las dos debajo del brazo. */
@media (min-width:1200px){
  /* El hueco existia para que el brazo NO tocase las tarjetas. Ahora se busca
     justo lo contrario, asi que se devuelve el aire normal. */
  #categorias{padding-top:72px;scroll-margin-top:var(--alto-cabecera)}
  /* Sin esto gana la tarjeta: .categoria es position:relative y va despues en
     el documento, asi que a igualdad de z-index pinta encima. Y tiene que ser 3
     y no 2, que es lo que lleva el velo del ::after: a igualdad tambien ganaria
     el velo, y el brazo saldria lavado justo por donde tiene que verse entero.
     Orden de arriba abajo: brazo (3) > velo (2) > rotulo y chapa (1) > foto. */
  .mano-vial{z-index:3}
  .catalogo-home{
    grid-template-columns:clamp(300px,26%,360px) minmax(0,1fr);
    column-gap:56px;align-items:center;
  }
  /* SIN DESFILE. Es el suelo del que parte todo: si el JS no llega a arrancar, o
     el sistema pide menos movimiento, la fila se queda quieta y se arrastra con
     las flechas. Las seis familias siguen siendo alcanzables. */
  .catalogo-home__pista{
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x proximity;
    /* Las flechas ya hacen de barra; la del navegador solo cortaria la fila. */
    scrollbar-width:none;
    /* Aire para que el aro de foco de una tarjeta no salga cortado por el borde
       del contenedor de scroll. */
    padding:6px 0;
  }
  .catalogo-home__pista::-webkit-scrollbar{display:none}
  /* Tres a la vista, ni una mas. La tarjeta se calcula contra el ancho de la
     pista en vez de fijarla en pixeles, asi que el reparto aguanta igual de
     1200 a una pantalla de 4K: siempre tres enteras y la cuarta ya fuera. Las
     otras tres estan a la derecha, que es donde cae el brazo. (32 son los dos
     huecos de 16 que quedan entre las tres.) */
  .categorias__rejilla{
    grid-template-columns:repeat(6, calc((100% - 32px) / 3));
    margin-top:0;
  }
  .categoria{scroll-snap-align:start}
  /* Retrato, como en la referencia. En cuadrado la fila queda baja y ancha y el
     brazo la cruza de lado a lado en vez de caer sobre ella. */
  .categoria__foto{aspect-ratio:.64}
  .pista__mando{display:flex}

  /* CON DESFILE. La fila cruza sola de derecha a izquierda y no para nunca. Las
     seis tarjetas van dos veces (las clona js/sitio.js) y el recorrido es
     exactamente la mitad del total: al cerrar el ciclo la copia esta donde
     estaba el original, asi que la costura no se ve y el salto al volver a
     empezar tampoco.
     Aqui solo esta la maqueta. El movimiento lo escribe sitio.js en el transform
     de la fila, no una animacion de CSS, porque una animacion gana al transform
     de JS y las flechas se quedarian sin nada que empujar.
     El ancho de tarjeta tambien lo escribe el JS en --tarjeta en vez de
     calcularlo aqui porque la fila mide max-content: un porcentaje se estaria
     midiendo contra si mismo. */
  .catalogo-home--desfile .catalogo-home__pista{
    /* clip y no hidden: hidden crea un contenedor de scroll, y al tabular a una
       tarjeta el navegador lo desplazaria por dentro para enseñarla, peleandose
       con el transform. clip recorta igual pero no se puede desplazar. */
    overflow:hidden;overflow:clip;
    scroll-snap-type:none;
  }
  .catalogo-home--desfile .categorias__rejilla{
    display:flex;width:max-content;
    /* El gap de la cuadricula tiene que irse: flex tambien lo aplica, y sumado
       al margen daba doce bloques con once huecos otra vez. Es justo el medio
       hueco que descuadraba la vuelta. */
    gap:0;
    /* La fila cambia de transform en cada fotograma desde JS. Sin avisar, el
       navegador no sabe que esto es una animacion y repinta las doce tarjetas
       con sus fotos una y otra vez; avisando, se la lleva a su propia capa y el
       movimiento le sale gratis. */
    will-change:transform;
  }
  .catalogo-home--desfile .categoria{
    flex:0 0 var(--tarjeta,260px);
    /* El hueco va de margen y no de gap: con gap, doce tarjetas dejan once
       huecos y la mitad del total cae media rendija corrida, que es un tiron
       visible en cada vuelta. Con margen son doce bloques iguales y la mitad
       cae limpia. */
    margin-right:16px;
    scroll-snap-align:none;
  }
  .catalogo-home--desfile .categoria.categoria--clon{display:block}
  /* Las pausas —raton encima, foco dentro, seccion fuera de pantalla— las lleva
     sitio.js dejando de avanzar, que es donde vive ahora el movimiento. */
}
/* Misma franja en la que la envoltura abre el canal para la flecha izquierda:
   ahi el texto se corre 24px a la derecha, o sea hacia donde el velo pesa menos,
   y el subtitulo se queda en 4.26:1 contra los 4.5 que pide AA. 0.70 es el valor
   mas ligero que devuelve las cinco cajas por encima del minimo con los seis
   clips (calibra_velo.py, vista "portatil 1280x720"). Por encima de 1328 no hace
   falta y se queda en 0.66, que tapa menos video. */
@media (min-width:960px) and (max-width:1327px){
  .hero__velo{
    background:linear-gradient(to right,
      rgb(20 48 31 / 0.97) 0%,
      rgb(20 48 31 / 0.93) 34%,
      rgb(20 48 31 / 0.70) 56%,
      rgb(20 48 31 / 0.22) 78%,
      rgb(20 48 31 / 0.05) 100%);
  }
}
/* Portatiles bajos. El texto del hero mide 585px y por encima de el van la
   promo y la cabecera: hacen falta 804px de ventana para que quepa. En un
   portatil de 1366x768 la ventana se queda en unos 660 y el hero asomaba 84px
   por debajo del borde, justo lo contrario de lo que se pidio.
   Se recorta el aire antes que la letra: primero el relleno de la envoltura
   (que ademas no se ve, porque el hero centra su contenido y solo cuenta cuando
   no cabe), luego el ritmo vertical, y solo al final el titular, de 52 a 46px.
   Debajo de unos 640px de ventana vuelve a no caber y el hero crece: por ahi
   ya no hay nada que recortar sin dejar el titular en nada. */
@media (min-width:960px) and (max-height:820px){
  .hero .envoltura{padding-top:32px;padding-bottom:32px}
  .hero__texto>*+*{margin-top:16px}
  .hero__pruebas{padding-top:12px}
  .hero h1{font-size:2.875rem}
}
/* En movil el CTA primario ocupa el ancho completo. */
@media (max-width:639px){
  .hero__acciones .btn,.cierre__acciones .btn{width:100%}
  /* Ritmo vertical mas corto solo aqui. Son cinco huecos entre los bloques del
     hero, asi que bajar de 20 a 16 recorta 20px: lo justo para que en un
     telefono de 812px de alto el hero entero quepa en la primera pantalla en
     vez de asomar por debajo. En escritorio sobra sitio y se queda en 20. */
  .hero__texto>*+*{margin-top:16px}
  /* La lista de precios deja de ser tabla y pasa a fichas apiladas: tres
     columnas en 375px dejan el nombre del compuesto partido en cuatro renglones.
     La cabecera se esconde y cada celda se anuncia sola con data-rotulo. */
  .precios thead{display:none}
  .precios,.precios tbody,.precios tr,.precios td{display:block;width:100%}
  .precios tr{
    border:1px solid var(--superficie);border-radius:var(--r-tarjeta);
    padding:16px 18px;margin-bottom:12px;background:var(--crema);
  }
  .precios td{border:0;padding:0}
  .precios td+td{margin-top:10px}
  .precios td[data-rotulo]::before{
    content:attr(data-rotulo);
    display:block;font-size:.6875rem;font-weight:600;letter-spacing:.1em;
    text-transform:uppercase;color:#6B6B6B;margin-bottom:3px;
  }
  /* El rotulo es un atributo, y el conmutador de idioma solo cambia textContent:
     con uno solo, la ficha en espanol seguia diciendo COMPOUND / SIZE / PRICE.
     Se resuelve aqui y no en el guion porque el guion ya escribe lang en <html>,
     asi que el CSS tiene todo lo que necesita para elegir. */
  html[lang="es"] .precios td[data-rotulo-es]::before{content:attr(data-rotulo-es)}
  .precios td:last-child{text-align:left}
}

/* Sin animacion para quien la desactivo. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }
  /* El video no es una animacion CSS, asi que la regla de arriba no lo toca: se
     para desde el guion, que ademas apaga el parallax y el acelerado por
     scroll. Queda el fotograma quieto, que es dibujo, no movimiento. */
}

/* ============================================================
   FICHA DE PRODUCTO, CATALOGO Y CHECKOUT
   ============================================================
   Todo lo que hay debajo lo estampa _gen/fichas.py: 22 fichas, la rejilla
   filtrable y el checkout. Se escribe al final del archivo a proposito, para
   que las tres pantallas nuevas puedan pisar reglas de la home (el ancho de
   .productos__rejilla dentro del catalogo, por ejemplo) sin tocar el bloque
   original ni subir la especificidad con !important. */

/* Los tres bloques que arrancan escondidos -carrito vacio, "no hay resultados",
   mapa que no cargo- llevan el atributo hidden y ademas display propio. Sin
   esto el display gana y el bloque se ve igual. */
[hidden]{display:none !important}

/* ---- Ficha: la rejilla ---------------------------------------------------
   Movil: foto, luego decision. Escritorio: la foto se queda pegada mientras el
   lado derecho corre, porque la columna de compra es larga (precio, dosis, COA,
   plazo y el acordeon) y quien baja a leer el certificado no deberia perder de
   vista lo que esta comprando. */
.pagina--ficha{padding-bottom:28px}
.ficha{padding:36px 0 8px}
.ficha__rejilla{display:grid;gap:32px}
.ficha__info{min-width:0}

/* ---- Galeria: beneficio primero, vial despues ----------------------------
   El mismo orden que las tarjetas de la home. La primera foto dice para que se
   estudia; la segunda ensena el frasco que llega a la puerta. Las dos van
   apiladas en el mismo marco y solo cambia la opacidad: sin saltos de alto. */
.galeria__marco{
  position:relative;
  background:var(--verde);
  border:1px solid var(--superficie);
  border-radius:var(--r-tarjeta);
  overflow:hidden;
}
.galeria__vista{position:relative;aspect-ratio:1/1}
/* height:auto por lo mismo que .producto__foto: con el height="720" del HTML
   puesto, el navegador ignora aspect-ratio y estira la foto. */
.galeria__vista img{
  position:absolute;inset:0;
  width:100%;height:100%;object-fit:cover;
  opacity:0;transition:opacity 200ms var(--ease);
}
.galeria__vista img.activa{opacity:1}
.galeria__flecha{
  position:absolute;top:50%;transform:translateY(-50%);
  width:40px;height:40px;
  display:grid;place-items:center;
  background:rgb(250 243 225 / 0.92);color:var(--verde);
  border:none;border-radius:50%;
  font-size:1.5rem;line-height:1;cursor:pointer;
  transition:background 150ms var(--ease);
}
.galeria__flecha:hover{background:var(--crema)}
.galeria__flecha:focus-visible{outline:2px solid var(--bronce);outline-offset:2px}
.galeria__flecha--izq{left:12px}
.galeria__flecha--der{right:12px}
.galeria__cinta{position:absolute;top:14px;left:14px;display:flex;gap:6px;z-index:1}
/* El sello de pureza va sobre la foto y no debajo: es lo primero que mira
   quien compra material de referencia, antes incluso que el precio. */
.galeria__sello{
  position:absolute;right:14px;bottom:14px;z-index:1;
  display:flex;flex-direction:column;align-items:center;
  padding:10px 14px;
  background:rgb(250 243 225 / 0.94);
  border-radius:var(--r-control);
  line-height:1.2;text-align:center;
  pointer-events:none;
}
.galeria__sello b{font-size:1.125rem;font-weight:600;color:var(--verde)}
.galeria__sello span{font-size:.6875rem;letter-spacing:.08em;text-transform:uppercase;color:var(--bronce)}
.galeria__sello small{font-size:.6875rem;color:var(--texto);opacity:.8;margin-top:2px}
.galeria__minis{display:flex;gap:10px;margin-top:12px}
.galeria__minis button{
  width:72px;height:72px;padding:0;
  background:var(--verde);
  border:2px solid var(--superficie);
  border-radius:var(--r-control);
  overflow:hidden;cursor:pointer;
  transition:border-color 150ms var(--ease);
}
.galeria__minis button:hover{border-color:var(--bronce)}
.galeria__minis button.activa{border-color:var(--verde)}
.galeria__minis img{display:block;width:100%;height:100%;object-fit:cover}

/* ---- Ficha: cabecera de texto ------------------------------------------- */
.estrellas{color:var(--bronce);letter-spacing:.08em}
.estrellas--mini{letter-spacing:0}
.ficha__estrellas{display:flex;flex-wrap:wrap;align-items:center;gap:8px;font-size:.875rem}
.ficha__estrellas b{color:var(--verde);font-weight:600}
.ficha__estrellas a{color:var(--texto);text-decoration:underline;text-underline-offset:3px}
.ficha h1{font-size:clamp(1.75rem,4vw,2.5rem);color:var(--verde);margin-top:8px;line-height:1.15}
/* La linea tecnica: quimico, familia, pureza y COA. Es la frase que separa a
   quien vende material trazable de quien vende un frasco. */
.ficha__pipe{margin-top:8px;font-size:.875rem;color:var(--texto);opacity:.85}
.ficha__desc{margin-top:16px;max-width:60ch;font-size:1rem}
.chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:18px}
.chips span{
  padding:6px 12px;
  background:var(--superficie);
  border-radius:var(--r-badge);
  font-size:.8125rem;color:var(--verde);
}

/* ---- Ficha: el bloque de compra -----------------------------------------
   Una caja sola, con borde, para que se lea como el sitio donde se decide.
   Orden deliberado: precio, oferta, dosis, CERTIFICADO, y solo entonces el
   boton. El COA queda siempre justo encima del boton, igual que en las
   tarjetas de la home. */
.compra{
  margin-top:24px;padding:22px;
  background:var(--crema);
  border:1px solid var(--superficie);
  border-radius:var(--r-tarjeta);
}
.compra__precio{display:flex;align-items:baseline;gap:10px}
.compra__precio b{font-size:2rem;font-weight:600;color:var(--verde);line-height:1}
.compra__oferta{
  margin-top:8px;font-size:.9375rem;color:var(--exito);
  display:flex;flex-wrap:wrap;align-items:baseline;gap:6px;
}
.compra__oferta b{font-weight:600}
.ficha__tamano{margin-top:10px;font-size:.9375rem}
.ficha__tamano b{color:var(--verde);font-weight:600}
.ficha__tamano span{opacity:.8}

/* Presentaciones: radios de verdad debajo, tarjeta visible encima. El input
   sigue en el DOM (teclado, lector de pantalla, :checked), solo que no se ve. */
.presentaciones{border:none;padding:0;margin:20px 0 0}
.presentaciones legend{
  padding:0;margin-bottom:10px;
  font-size:.75rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--bronce);font-weight:500;
}
.presentaciones__grupo{display:grid;grid-template-columns:repeat(auto-fit,minmax(104px,1fr));gap:10px}
.presentaciones__opcion{
  position:relative;
  display:flex;flex-direction:column;gap:2px;
  padding:12px;
  background:var(--crema);
  border:1.5px solid var(--superficie);
  border-radius:var(--r-control);
  cursor:pointer;
  transition:border-color 150ms var(--ease),background 150ms var(--ease);
}
.presentaciones__opcion:hover{border-color:var(--bronce)}
.presentaciones__opcion input{position:absolute;opacity:0;width:0;height:0}
.presentaciones__opcion:focus-within{outline:2px solid var(--bronce);outline-offset:2px}
.presentaciones__opcion.activa{border-color:var(--verde);background:var(--superficie)}
.presentaciones__dosis{font-weight:600;color:var(--verde)}
.presentaciones__precio{font-size:.875rem;color:var(--texto)}

.ficha__coa{
  display:flex;flex-wrap:wrap;align-items:center;gap:10px;
  margin-top:20px;padding:12px 14px;
  background:var(--superficie);
  border-radius:var(--r-control);
  font-size:.8125rem;
}
.ficha__coa__texto{display:flex;flex-direction:column;line-height:1.35}
.ficha__coa a{margin-left:auto;color:var(--verde);text-decoration:underline;text-underline-offset:3px}
/* El numero de lote cambia con la dosis elegida: tabular para que no baile. */
.lote-vivo{color:var(--verde);font-weight:600;font-variant-numeric:tabular-nums}

.cantidad{
  display:inline-flex;align-items:center;
  border:1px solid var(--superficie);
  border-radius:var(--r-control);
  background:var(--crema);overflow:hidden;
}
.cantidad button{
  width:40px;height:44px;
  background:none;border:none;cursor:pointer;
  font-size:1.0625rem;color:var(--verde);
  transition:background 150ms var(--ease);
}
.cantidad button:hover{background:var(--superficie)}
.cantidad input,.cantidad>span{
  width:44px;height:44px;
  border:none;background:none;
  text-align:center;font:inherit;font-weight:600;color:var(--verde);
  display:grid;place-items:center;
}
.cantidad input::-webkit-outer-spin-button,
.cantidad input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.cantidad input[type=number]{-moz-appearance:textfield;appearance:textfield}
.cantidad--mini button{width:28px;height:28px;font-size:.875rem}
.cantidad--mini>span{width:30px;height:28px;font-size:.8125rem}

.compra__fila{display:flex;gap:12px;margin-top:20px}
.compra__fila .btn{flex:1}
.compra .btn--bloque{margin-top:10px}
.compra__confianza{
  display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  margin-top:16px;font-size:.8125rem;color:var(--texto);
}
.compra__confianza a{color:var(--verde);text-decoration:underline;text-underline-offset:3px}
.compra__ruo{
  margin-top:14px;padding-top:14px;
  border-top:1px solid var(--superficie);
  font-size:.6875rem;letter-spacing:.06em;text-align:center;
}
.compra__ruo strong{color:var(--verde);font-weight:500}
.compra__desvio{margin-top:10px;font-size:.8125rem;text-align:center;opacity:.85}
.compra .btn[disabled]{opacity:.5;cursor:not-allowed}

/* ---- Plazo: las tres fechas ---------------------------------------------
   Las escribe el guion en dias habiles de verdad. Ver la fecha concreta -no
   "2-4 dias"- es lo que quita la ultima duda antes de pulsar. */
.plazo{
  list-style:none;
  display:grid;grid-template-columns:repeat(3,1fr);gap:0;
  margin-top:20px;padding:16px;
  background:var(--superficie);
  border-radius:var(--r-tarjeta);
  text-align:center;
}
.plazo li{position:relative;padding:0 6px;display:flex;flex-direction:column;gap:2px}
/* La linea que une los tres pasos: se dibuja desde el hueco, no con un borde,
   para que no cuelgue por fuera del primero ni del ultimo. */
.plazo li+li::before{
  content:"";position:absolute;left:0;top:9px;
  width:1px;height:calc(100% - 12px);
  background:rgb(64 64 64 / 0.18);
}
.plazo__paso{font-size:.6875rem;letter-spacing:.08em;text-transform:uppercase;color:var(--bronce)}
.plazo b{font-size:.9375rem;font-weight:600;color:var(--verde)}
.plazo small{font-size:.6875rem;color:var(--texto);opacity:.8}

/* ---- Acordeon de la ficha ------------------------------------------------
   Hereda .faq de la home. Solo cambia que aqui el cuerpo lleva parrafos
   sueltos en vez de una linea, y que el bloque arranca separado del plazo. */
.ficha__acordeon{margin-top:32px}
.faq__cuerpo p+p{margin-top:12px}
.faq__cuerpo a{color:var(--verde);text-decoration:underline;text-underline-offset:3px}

/* ---- Resena verificada --------------------------------------------------- */
.resena{
  max-width:760px;margin:0 auto;padding:28px;
  background:var(--crema);
  border:1px solid var(--superficie);
  border-left:3px solid var(--bronce);
  border-radius:var(--r-tarjeta);
  text-align:center;
}
.resena blockquote{margin-top:12px;font-size:1.0625rem;line-height:1.6;color:var(--verde)}
.resena figcaption{margin-top:14px;font-size:.8125rem;color:var(--texto);opacity:.85}
.resena figcaption b{color:var(--verde);font-weight:600;opacity:1}

/* ---- Filas de seis: relacionados y mas vendidos --------------------------
   La misma pareja de fotos que la tarjeta grande, en pequeno. Movil dos por
   fila, tres a los 640 y las seis completas a los 960. */
.rejilla-mini{display:grid;grid-template-columns:repeat(2,1fr);gap:14px;margin-top:28px}
.mini{
  display:flex;flex-direction:column;gap:6px;
  text-decoration:none;color:inherit;
  border:1px solid transparent;border-radius:var(--r-tarjeta);
  padding:8px;
  transition:border-color 150ms var(--ease),background 150ms var(--ease);
}
.mini:hover{border-color:var(--superficie);background:var(--crema)}
.mini__img{
  position:relative;display:block;
  aspect-ratio:1/1;overflow:hidden;
  background:var(--verde);border-radius:var(--r-control);
}
.mini__img img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.mini__vial{opacity:0;transition:opacity 150ms var(--ease)}
@media (hover:hover) and (pointer:fine){
  .mini:hover .mini__vial,.mini:focus-visible .mini__vial{opacity:1}
}
.mini__agotado{
  position:absolute;left:8px;top:8px;z-index:1;
  padding:3px 8px;border-radius:var(--r-badge);
  background:rgb(250 243 225 / 0.94);color:var(--verde);
  font-size:.6875rem;font-weight:500;
}
.mini__nombre{font-size:.875rem;font-weight:500;color:var(--verde);line-height:1.3;margin-top:4px}
.mini__precio b{font-size:.9375rem;font-weight:600;color:var(--verde)}
.mini__nota{font-size:.75rem;color:var(--texto);opacity:.8}

/* ============================================================
   CATALOGO
   ============================================================ */
.catalogo{display:grid;gap:28px}
.catalogo__cuerpo{min-width:0}

.filtros{
  align-self:start;
  padding:20px;
  background:var(--crema);
  border:1px solid var(--superficie);
  border-radius:var(--r-tarjeta);
}
.filtros__grupo+.filtros__grupo{margin-top:22px;padding-top:22px;border-top:1px solid var(--superficie)}
.filtros__grupo h3{
  font-size:.75rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--bronce);font-weight:500;margin-bottom:10px;
}
.filtros__grupo label{
  display:flex;align-items:center;gap:10px;
  padding:5px 0;font-size:.9375rem;cursor:pointer;
}
.filtros__grupo label span{flex:1;color:var(--texto)}
.filtros__grupo label small{color:var(--texto);opacity:.6;font-variant-numeric:tabular-nums}
.filtros__grupo input[type=checkbox]{width:16px;height:16px;accent-color:var(--verde);cursor:pointer}
.filtros__precio{
  display:flex;justify-content:space-between;
  margin-top:8px;font-size:.875rem;font-weight:600;color:var(--verde);
  font-variant-numeric:tabular-nums;
}
.filtros__limpiar{margin-top:22px}

/* Los cuatro grupos de filtros miden mas de 700px: en movil empujaban el primer
   producto casi dos pantallas hacia abajo. Ahi van cerrados detras del boton y
   solo se abren si el visitante los pide. La regla vive en un max-width para no
   tener que deshacerla despues en escritorio, donde el boton no existe y los
   filtros se ven siempre. El `~ *` alcanza a los grupos y al "Limpiar todo"
   porque el boton es el primer hijo del aside. */
.filtros__abrir{display:none}
@media (max-width:959px){
  .filtros__abrir{
    display:flex;align-items:center;justify-content:space-between;gap:12px;
    width:100%;padding:4px 0;background:none;border:0;cursor:pointer;
    font-family:inherit;font-size:1rem;font-weight:600;color:var(--verde);
  }
  .filtros__abrir::after{
    content:"+";font-size:1.25rem;font-weight:400;line-height:1;
    color:var(--bronce);transition:transform .2s var(--ease);
  }
  .filtros__abrir[aria-expanded="true"]::after{content:"\2212"}
  .filtros__abrir[aria-expanded="true"]{margin-bottom:18px}
  .filtros__abrir[aria-expanded="false"] ~ *{display:none}
}

/* Rango de dos manecillas. Son dos <input type=range> montados uno encima del
   otro: el carril no recibe raton (pointer-events:none) y solo las manecillas
   lo recuperan, que es lo que deja agarrar la de abajo cuando se cruzan. */
.rango{position:relative;height:30px}
.rango__riel,.rango__lleno{position:absolute;top:13px;height:4px;border-radius:2px}
.rango__riel{left:0;right:0;background:var(--superficie)}
.rango__lleno{background:var(--bronce)}
.rango input[type=range]{
  position:absolute;top:0;left:0;
  width:100%;height:30px;margin:0;
  -webkit-appearance:none;appearance:none;
  background:transparent;pointer-events:none;
}
.rango input[type=range]:focus-visible{outline:2px solid var(--bronce);outline-offset:4px}
.rango input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;pointer-events:auto;
  width:18px;height:18px;border-radius:50%;
  background:var(--crema);border:2px solid var(--verde);
  cursor:pointer;box-shadow:var(--sombra);
}
.rango input[type=range]::-moz-range-thumb{
  pointer-events:auto;
  width:14px;height:14px;border-radius:50%;
  background:var(--crema);border:2px solid var(--verde);cursor:pointer;
}

.catalogo__barra{
  display:flex;flex-wrap:wrap;gap:12px;
  align-items:center;justify-content:space-between;
}
.catalogo__cuenta{font-size:.875rem;color:var(--texto)}
.catalogo__cuenta b{color:var(--verde);font-weight:600;font-variant-numeric:tabular-nums}
.catalogo__orden{display:flex;align-items:center;gap:8px;font-size:.875rem}
select.orden{
  padding:9px 12px;
  border:1px solid var(--superficie);border-radius:var(--r-control);
  background:var(--crema);color:var(--verde);font:inherit;font-size:.875rem;
  cursor:pointer;
}
select.orden:focus-visible{outline:2px solid var(--bronce);outline-offset:2px}

.chips-activos{display:flex;flex-wrap:wrap;gap:8px}
.chips-activos:not(:empty){margin-top:14px}
.chip{
  display:inline-flex;align-items:center;gap:6px;
  padding:5px 12px;
  background:var(--superficie);color:var(--verde);
  border:none;border-radius:var(--r-badge);
  font:inherit;font-size:.8125rem;cursor:pointer;
}
.chip::after{content:"\00d7";opacity:.6}
.chip:hover{background:var(--bronce);color:var(--crema)}
.chip--limpiar{background:none;border:1px solid var(--superficie);text-decoration:underline;text-underline-offset:3px}
.chip--limpiar::after{content:none}

/* La tarjeta del catalogo saca el pie fuera del cuerpo para que los botones de
   todas las tarjetas de una fila queden a la misma altura. Hay que devolverle
   el relleno que traia de dentro. */
.catalogo .productos__rejilla{scroll-margin-top:calc(var(--alto-cabecera) + 16px)}
.catalogo .producto>.producto__pie{padding:0 20px 20px;gap:10px;align-items:center}
a.producto__img{display:block}
.producto__nombre a{color:inherit;text-decoration:none}
.producto__nombre a:hover{color:var(--bronce)}
.producto__resena{font-size:.8125rem;color:var(--texto)}
.producto__desde{font-size:.8125rem;font-weight:400;color:var(--texto);opacity:.75}
.catalogo__vacio{
  display:block;
  margin-top:36px;padding:36px;
  background:var(--crema);border:1px dashed var(--superficie);
  border-radius:var(--r-tarjeta);text-align:center;color:var(--texto);
}
.paginacion{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin-top:32px}
.paginacion:empty{display:none}
.paginacion button{
  min-width:40px;height:40px;padding:0 12px;
  background:var(--crema);color:var(--verde);
  border:1px solid var(--superficie);border-radius:var(--r-control);
  font:inherit;font-weight:500;cursor:pointer;
  transition:border-color 150ms var(--ease),background 150ms var(--ease);
}
.paginacion button:hover{border-color:var(--bronce)}
.paginacion button.activa{background:var(--verde);color:var(--crema);border-color:var(--verde)}

/* Banda de garantias. Va debajo de la rejilla porque quien llega ahi ya vio
   los precios: lo que le falta es saber que pasa despues de pagar. */
.franja{
  display:grid;gap:18px;
  margin-top:40px;padding:24px;
  background:var(--verde);border-radius:var(--r-tarjeta);
}
.franja div{display:flex;flex-direction:column;gap:4px}
.franja b{color:var(--bronce);font-weight:600;font-size:.9375rem}
.franja span{color:rgb(250 243 225 / 0.82);font-size:.8125rem;line-height:1.5}

/* ============================================================
   CHECKOUT
   ============================================================ */
.checkout{display:grid;gap:28px;align-items:start}
.checkout__vacia{
  display:block;
  padding:48px 24px;text-align:center;
  background:var(--crema);border:1px dashed var(--superficie);
  border-radius:var(--r-tarjeta);
}
.checkout__vacia h2{color:var(--verde)}
.checkout__vacia p{margin:10px 0 20px;color:var(--texto)}
.checkout__form h2,.resumen h2{font-size:1.25rem;color:var(--verde)}
.checkout__sub{margin-top:6px;margin-bottom:20px;font-size:.875rem;color:var(--texto);opacity:.85}

.campo{display:block}
.campo+.campo{margin-top:16px}
.campo>span{
  display:block;margin-bottom:6px;
  font-size:.8125rem;font-weight:500;color:var(--verde);
}
.campo input,.campo textarea{
  width:100%;padding:12px 14px;
  border:1px solid var(--superficie);border-radius:var(--r-control);
  background:var(--crema);color:var(--texto);
  font:inherit;font-size:1rem;
  transition:border-color 150ms var(--ease);
}
.campo input:focus,.campo textarea:focus{outline:none;border-color:var(--verde)}
.campo textarea{resize:vertical;min-height:88px}
.campo__nota{display:block;margin-top:5px;font-size:.75rem;color:var(--texto);opacity:.7}
/* El error se marca al intentar enviar, nunca mientras se escribe. */
.campo--mal input,.campo--mal textarea{border-color:var(--error)}
.campo--mal>span{color:var(--error)}

/* El mapa es ayuda, no requisito: si Leaflet no baja, el guion esconde el
   bloque entero y el pedido sale igual con la direccion escrita. */
.mapa-bloque{
  margin-top:24px;padding:18px;
  background:var(--crema);border:1px solid var(--superficie);
  border-radius:var(--r-tarjeta);
}
.mapa-bloque__cabeza{display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:space-between}
.mapa-bloque__cabeza b{color:var(--verde);font-size:.9375rem}
.mapa-estado{margin-top:10px;font-size:.8125rem;color:var(--texto);opacity:.85}
#mapa{
  height:280px;margin-top:12px;
  border-radius:var(--r-control);
  background:var(--superficie);
  z-index:0; /* debajo de la barra pegajosa: Leaflet monta sus paneles en 400 */
}
.mapa-nota{margin-top:10px;font-size:.75rem;color:var(--texto);opacity:.7}

/* ---- Resumen del pedido -------------------------------------------------- */
.resumen{
  align-self:start;
  padding:22px;
  background:var(--crema);
  border:1px solid var(--superficie);
  border-radius:var(--r-tarjeta);
}
.resumen__lista{margin-top:16px}
.resumen__item{
  display:flex;gap:12px;align-items:flex-start;
  padding:14px 0;border-bottom:1px solid var(--superficie);
}
.resumen__item:first-child{padding-top:0}
.resumen__foto{
  flex:0 0 auto;width:60px;height:60px;
  border-radius:var(--r-control);overflow:hidden;background:var(--verde);
}
.resumen__foto img{display:block;width:100%;height:100%;object-fit:cover}
.resumen__datos{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px;align-items:flex-start}
.resumen__nombre{font-size:.9375rem;font-weight:500;color:var(--verde);text-decoration:none;line-height:1.3}
.resumen__nombre:hover{color:var(--bronce)}
.resumen__lote{font-size:.75rem;color:var(--texto);opacity:.7;font-variant-numeric:tabular-nums}
.resumen__lado{display:flex;flex-direction:column;align-items:flex-end;gap:6px}
.resumen__lado b{font-weight:600;color:var(--verde);font-variant-numeric:tabular-nums}
.resumen__quita{
  background:none;border:none;cursor:pointer;
  font-size:1.125rem;line-height:1;color:var(--texto);opacity:.5;
  transition:opacity 150ms var(--ease),color 150ms var(--ease);
}
.resumen__quita:hover{opacity:1;color:var(--error)}

.cupon{display:flex;gap:8px;margin-top:18px}
.cupon input{
  flex:1;min-width:0;padding:10px 12px;
  border:1px solid var(--superficie);border-radius:var(--r-control);
  background:var(--crema);font:inherit;font-size:.875rem;
  text-transform:uppercase;letter-spacing:.04em;
}
.cupon input:focus{outline:none;border-color:var(--verde)}
.promo-msj{margin-top:8px;font-size:.8125rem}
.promo-msj--ok{color:var(--exito)}
.promo-msj--mal{color:var(--error)}

.resumen__filas{margin-top:18px;padding-top:16px;border-top:1px solid var(--superficie)}
.resumen__filas>p{display:flex;justify-content:space-between;gap:12px;font-size:.9375rem;padding:5px 0}
.resumen__filas b{font-variant-numeric:tabular-nums;color:var(--verde)}
.resumen__descuento{color:var(--exito)}
.resumen__descuento b{color:var(--exito)}
.resumen__nota-envio{
  display:block;
  font-size:.75rem;color:var(--texto);opacity:.7;padding-top:0;
}
.resumen__total{
  margin-top:10px;padding-top:12px;
  border-top:1px solid var(--superficie);
  font-size:1.0625rem;font-weight:600;color:var(--verde);
}
.resumen__total b{font-size:1.375rem}
.resumen__confirmar{margin-top:18px}
.resumen__ok{
  display:block;
  margin-top:16px;padding:16px;
  background:var(--superficie);border-radius:var(--r-control);
  text-align:center;
}
.resumen__ok b{color:var(--verde)}
.resumen__ok p{margin-top:6px;font-size:.8125rem;color:var(--texto)}
.resumen__ok__num{font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:.04em}
.resumen__ok__enlace{margin-top:12px}
.resumen__nota{margin-top:14px;font-size:.75rem;color:var(--texto);opacity:.75;line-height:1.5}
.resumen__sellos{list-style:none;margin-top:16px;padding-top:14px;border-top:1px solid var(--superficie)}
.resumen__sellos li{position:relative;padding-left:22px;font-size:.8125rem;color:var(--texto)}
.resumen__sellos li+li{margin-top:8px}
.resumen__sellos li::before{
  content:"\2713";position:absolute;left:0;top:0;
  color:var(--exito);font-weight:600;
}

/* Acuse del boton de anadir: 1,6 segundos en verde y vuelve. Sin esto, en una
   rejilla de doce tarjetas nadie sabe si el clic entro. Lleva !important
   porque pisa a .btn--primario y a .btn--fantasma, que ya traen los tres
   valores puestos por su propia clase. */
.btn--hecho{background:var(--exito) !important;border-color:var(--exito) !important;color:var(--crema) !important}
.carrito__num--lleno{background:var(--bronce);color:var(--verde)}

@media (min-width:640px){
  .rejilla-mini{grid-template-columns:repeat(3,1fr)}
  .franja{grid-template-columns:repeat(2,1fr);gap:24px}
  .plazo{padding:18px 22px}
}

@media (min-width:960px){
  .ficha{padding:44px 0 8px}
  .ficha__rejilla{grid-template-columns:minmax(0,1.02fr) minmax(0,1fr);gap:48px}
  /* La foto acompana toda la columna de decision. align-self:start es lo que
     impide que el grid la estire y anule el sticky. */
  .galeria{position:sticky;top:calc(var(--alto-cabecera) + 20px);align-self:start}
  .rejilla-mini{grid-template-columns:repeat(6,1fr);gap:16px}
  .franja{grid-template-columns:repeat(4,1fr)}
  .catalogo{grid-template-columns:262px minmax(0,1fr);gap:36px}
  .filtros{position:sticky;top:calc(var(--alto-cabecera) + 20px)}
  /* Tres y no cuatro: el aside ya se llevo 262px de los 1200. Va despues del
     bloque de la home a proposito: misma especificidad, gana la ultima. */
  .catalogo .productos__rejilla{grid-template-columns:repeat(3,1fr)}
  .checkout{grid-template-columns:minmax(0,1fr) 372px;gap:40px}
  .resumen{position:sticky;top:calc(var(--alto-cabecera) + 20px)}
}
