/* ==========================================================================
   The Lab Room · piezas comunes
   Lo que comparten la portada, la ficha de producto y los listados de tienda:
   paleta, retícula, botones, encabezados de sección, tarjeta de producto y
   las animaciones de aparición. Sale de la maqueta que validó la clienta.
   Se carga solo en nuestras plantillas, nunca encima del tema.
   ========================================================================== */

:root{
  /* Fondo B, confirmado por Monica en la videollamada del 13 de agosto: la
     pagina en blanco y el gris de la foto convertido en la baldosa de la
     tarjeta. Antes: --bone #F3EDE3, --bone-2 #ECE4D6, --line .14 */
  --bone:#FFFFFF; --bone-2:#F2F2F0; --ink:#1B1A17; --ink-soft:#3A382F;
  /* El verde del pie. Antes era el eucalipto #8A9A82. Ver design-system.css. */
  --eucalyptus:#CCD5C6; --verde-texto:#5B6B55;
  --amber:#C79A5B; --clay:#C2876A;
  --card:#F2F2F0; --line:rgba(27,26,23,.11);
  /* Y los mismos con el prefijo `tlr-`, que es como los pide `chrome.css`, la
     hoja del encabezado y el pie, que sí se carga en las plantillas propias.
     `design-system.css` las define pero NO se carga aquí: la plantilla barre
     todo lo ajeno y trae su CSS completo. Antes las ponía `fondos.css`, que iba
     encolada en todo el sitio; al borrarla el encabezado se volvió hueso, por el
     `var(--tlr-bone, #F3EDE3)` de chrome.css. Comprobado leyendo el color
     calculado, no a ojo. */
  --tlr-bone:#FFFFFF; --tlr-card:#F2F2F0; --tlr-linea:#E9E7E3;
  --tlr-ink:#1B1A17; --tlr-ink-soft:#3A382F;
  --tlr-eucalyptus:#CCD5C6; --tlr-verde-texto:#5B6B55;
  /* 18 oct: tokens de la tipografía A, los mismos de design-system.css, que aquí
     no se carga. Sin --tlr-sans en esta hoja, con la pila de Archivo escrita. */
  --tlr-t-cuerpo:300 14.5px/1.75 'Archivo',system-ui,sans-serif;
  --tlr-t-etiqueta:600 11.5px/1.3 'Archivo',system-ui,sans-serif;
  --tlr-t-etiqueta-ls:.16em;
  --tlr-t-titulo-peso:300;
  --serif:'Zodiak',Georgia,serif; --sans:'Archivo',system-ui,sans-serif;
  --pad:clamp(1.25rem,5vw,6rem);
  --maxw:1500px;
}
*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
body{background:var(--bone);color:var(--ink);font-family:var(--sans);font-size:16px;line-height:1.6;overflow-x:hidden}
img{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
::selection{background:var(--ink);color:var(--bone)}

.wrap{max-width:var(--maxw);margin:0 auto;padding-inline:var(--pad)}
.serif{font-family:var(--serif)}
.eyebrow{font-size:.72rem;letter-spacing:.22em;text-transform:uppercase;font-weight:500;color:var(--ink-soft)}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}

/* ---------- botones ----------
   El boton principal va en eucalipto con la letra en tinta, decision de Dani
   del 11 de agosto: Monica se quejo de que la web volvia al beige y al negro y
   pidio el verde. El texto NO puede ir en hueso: sobre eucalipto mide 2,57:1 y
   no se lee. En tinta mide 5,82:1 y pasa AA. */
.btn{display:inline-flex;align-items:center;gap:.7rem;font-family:var(--sans);font-size:.78rem;letter-spacing:.14em;text-transform:uppercase;font-weight:600;padding:1.05rem 1.9rem;border-radius:999px;border:1px solid var(--eucalyptus);background:var(--eucalyptus);color:var(--ink);cursor:pointer;transition:transform .5s cubic-bezier(.22,1,.36,1),background .35s,color .35s;will-change:transform}
.btn .arrow{transition:transform .45s cubic-bezier(.22,1,.36,1)}
.btn:hover .arrow{transform:translateX(5px)}
.btn--ghost{background:transparent;color:var(--ink)}
.btn--ghost:hover{background:var(--eucalyptus);color:var(--ink);border-color:var(--eucalyptus)}
.btn--light{background:var(--bone);color:var(--ink);border-color:var(--bone)}
.btn--light:hover{background:transparent;color:var(--bone)}
.btn--ghost-light{background:transparent;color:var(--bone);border-color:rgba(243,237,227,.55)}
.btn--ghost-light:hover{background:var(--bone);color:var(--ink);border-color:var(--bone)}

/* Al pasar el raton se invierte: tinta con la letra en hueso. Antes iba al
   reves, y ahora que el reposo ya es verde ese hover no se veria. */
.btn:hover,button.btn:hover,form button[type="submit"]:hover{background:var(--ink);border-color:var(--ink);color:var(--bone)}
.btn--light:hover,.btn--ghost-light:hover{background:var(--bone);border-color:var(--bone);color:var(--ink)}

/* ---------- encabezado de seccion ---------- */
/* ESCALA Y AIRE, 28 de agosto. Dani: "no es nada impresionante, quiero algo muy
   top". Lo que separaba esta portada de la referencia no era el movimiento: era
   que todo iba al mismo tamaño y con el mismo hueco, y una página con un solo
   ritmo se lee plana por bien hecha que esté.

   Se tocan dos cosas y nada más: el tamaño de los titulares de sección y el
   aire entre secciones. Ni colores, ni tipografías, ni maqueta. */
.sec{padding-block:clamp(4.5rem,9vw,9rem)}
.sec-head{display:flex;justify-content:space-between;align-items:flex-end;gap:2rem;margin-bottom:clamp(2.4rem,4.6vw,4rem)}
/* De 3,4 a 4,6 rem en pantalla grande. El titular es lo primero que dice si una
   tienda es cara o es un catálogo, y a 3,4 competía de tú a tú con el nombre de
   los productos. El mínimo sube poco (2,1 -> 2,4) a propósito: en un móvil de
   390 px, "Los más deseados" a 2,8 se parte en tres líneas. */
.sec-head h2{font-family:var(--serif);font-weight:400;font-size:clamp(2.4rem,5.2vw,4.6rem);line-height:1;letter-spacing:-.018em}
.sec-head a{font-size:.78rem;letter-spacing:.13em;text-transform:uppercase;font-weight:600;white-space:nowrap;border-bottom:1px solid var(--ink);padding-bottom:.3rem}

/* ---------- tarjeta de producto ---------- */
/* `min-width:0` en los hijos, 7 de septiembre: sin ella, el ancho mínimo por
   defecto de una celda de grid es el de su contenido ("min-content"), y basta
   UN hijo con una palabra o frase larga sin partir (la tarjeta promocional
   nueva, en este caso) para que ESA columna entera se ensanche más que 1fr y
   arrastre a todas las demás celdas de la misma columna, en todas las filas
   -así se desbordaba la tienda a 390px, y el hijo culpable ni tenía que
   estar en la fila visible-. Medido en el navegador: sin esto, la 2ª columna
   llegaba a 298px con la 1ª en 146px, cuando ambas debían ser iguales. */
.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(1rem,1.6vw,1.6rem)}
.grid>*{min-width:0}

/* ---------- hilera cortada por el borde ----------
   Patron de omorovicza.eu: la hilera de la portada desborda a proposito y la
   ultima tarjeta queda partida por el borde, que es como se ve que hay mas
   catalogo. La rejilla de cuatro cerraba en seco y parecia que eso era todo.

   El desbordamiento vive DENTRO de `.rail`, nunca en el cuerpo: se sale por la
   derecha exactamente `var(--pad)`, que es el propio relleno de `.wrap`, asi
   que no puede pasarse del ancho de la ventana ni sacar barra lateral. Nada de
   `50vw - 50%`, que en Windows cuenta la barra de desplazamiento y desborda.

   El listado de tienda NO lleva esto y sigue en rejilla: alli el catalogo esta
   entero y paginado, no hay nada mas que insinuar. */
.rail{
  display:grid;grid-auto-flow:column;
  grid-auto-columns:clamp(240px,21vw,310px);
  gap:clamp(1rem,1.6vw,1.6rem);
  overflow-x:auto;overscroll-behavior-x:contain;
  scroll-snap-type:x proximity;
  margin-right:calc(-1 * var(--pad));
  padding-right:var(--pad);
  /* sitio para que la sombra del :focus y el corazon no se corten arriba */
  padding-block:2px;
  scrollbar-width:none;-ms-overflow-style:none;
}
.rail::-webkit-scrollbar{display:none}
.rail>.card{scroll-snap-align:start}

/* ---------- las flechas de la hilera ----------
   Sin ellas la tarjeta cortada es un callejon sin salida con raton: se ve
   partida y no hay nada que pulsar. Con el dedo se arrastra, pero Monica mira
   desde el ordenador y ya dijo "a mi me cuesta mucho ver asi las cosas".
   La barra de desplazamiento va oculta a proposito, asi que la senal tiene que
   ser esta. Se esconden en los extremos, para que no inviten a nada. */
.rail-caja{position:relative}
.rail-flecha{
  position:absolute;top:calc(50% - 3.2rem);transform:translateY(-50%);z-index:3;
  width:44px;height:44px;border-radius:50%;border:1px solid var(--line);
  background:var(--bone);color:var(--ink);cursor:pointer;
  display:grid;place-items:center;
  transition:opacity .3s,background .3s,border-color .3s,color .3s,visibility .3s;
  box-shadow:0 2px 12px rgba(27,26,23,.10);
}
.rail-flecha:hover{background:var(--ink);border-color:var(--ink);color:var(--bone)}
.rail-flecha[disabled]{opacity:0;visibility:hidden;pointer-events:none}
.rail-flecha--antes{left:-14px}
.rail-flecha--despues{right:-14px}
.rail-flecha svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.6}
@media (hover:none){
  /* Con el dedo se arrastra y las flechas solo estorban. */
  .rail-flecha{display:none}
}
/* Las tarjetas de la hilera SI se desvelan una a una desde el 1 de septiembre
   (oportunidad 1 del pase de animaciones). Antes se forzaban todas a opacidad 1
   de golpe, y el motivo era un defecto real y no una eleccion: el observador
   por defecto mira el VIEWPORT del navegador, y las tarjetas que quedan fuera
   por la derecha del propio `.rail{overflow-x:auto}` (la 5ª y la 6ª, las que
   dan pie al "carrito cortado") no cruzan nunca ese viewport si nadie arrastra
   el carril, asi que su interseccion no se dispara jamas y se quedarian en
   opacidad 0 para siempre. Medido con Playwright: de 47 `.reveal` de la
   portada, exactamente 1 se quedaba sin `.in` tras un recorrido vertical
   completo, y era la 6ª tarjeta del carril (x=1699, fuera del viewport de
   1440). La hipotesis del mapa (rootMargin del -8% en el fondo de pagina) no
   era la causa: es el recorte horizontal del propio carril.
   El arreglo no esta aqui, esta en el JS de cada plantilla que usa `.rail`:
   cuando el CONTENEDOR `.rail` gana `.in`, revela el a sus tarjetas
   directamente, sin depender de que cada una cruce el viewport por su cuenta.
   Aqui solo hace falta que las tarjetas dejen de estar siempre visibles y
   vuelvan al sistema `.reveal`/`.in` normal, que ya trae el escalon de
   transition-delay. */
@media (max-width:640px){
  /* En movil se mantienen las dos por pantalla que ya estaban aprobadas. */
  .rail{grid-auto-columns:44vw;gap:1rem}
}
/* La tarjeta entera es la baldosa desde el 11 de septiembre, no solo la foto:
   foto cuadrada arriba, cuerpo en medio y barra de compra al pie, todo sobre el
   mismo gris y con un solo radio. Es la estructura de la tarjeta compacta de
   omorovicza.eu que eligió Dani (Context/research/omorovicza-tarjeta-20260911/),
   traducida a nuestros colores y tipos. `flex` en columna para que la barra
   quede pegada al pie aunque la rejilla estire la tarjeta al alto de la fila. */
/* 17 de septiembre. Mónica, tres vídeos del 16 y un mensaje escrito: "Nombre
   fuera", "el nombre está fuera de la foto como en mi página web ahora", "esto
   está ahí metido en el medio y eso no me gusta nada".
   El nombre YA estaba fuera de la foto en el maquetado. Lo que lo metía dentro
   era que `.card` llevaba el MISMO gris que `.card-media`, así que foto y texto
   se leían como una sola caja. Sus tres referencias (Irene Forte, Crown Affair
   y su web actual) dejan la foto sola y el texto sobre el fondo de la página.
   La baldosa gris se queda SOLO en la foto. */
.card{position:relative;cursor:pointer;background:transparent;border-radius:0;overflow:visible;display:flex;flex-direction:column}
.card-media{border-radius:3px}
/* Cuadrada como la referencia (antes 4/5). El packshot antiguo va a `contain`
   con relleno y trae el mismo gris de fondo, así que en cuadrado no aparece
   ningún recuadro; solo cambia cuánto aire hay a los lados. */
.card-media{position:relative;background:var(--card);height:0;padding-bottom:125%;overflow:hidden;transition:background .5s ease}
/* 5 de octubre de 2026. Mónica, 4 oct: "esto ya te lo dije, no me gusta la foto
   en cuadrado, me gusta en rectangular". Revierte el cuadrado del 11 de
   septiembre y vuelve a vertical, 4:5 (padding-bottom:125%). Se elige 4:5 y no
   algo más alto porque las fotos de la tienda son 600x728 y 760x943 (0,82 y
   0,81 de ancho/alto, o sea 4:4,9): con 4:5 el recorte de las fotos que van a
   `cover` es de un 1-3 %, y es la proporción de su web actual y de las
   referencias (omorovicza, crown affair). Va con `padding-bottom` y `height:0`,
   NO con `aspect-ratio`: ver la memoria aspect-ratio-con-min-height-ensancha.
   Las fotos van en `.card-shot` (absoluto, inset:0), así que su `height:100%`
   sigue resolviendo. `min-width:0` en los hijos del carril, igual que en
   `.grid>*`. */
.rail>*{min-width:0}
/* Un gris un punto mas oscuro y no var(--bone-2), que en B es el mismo gris de
   reposo: el boton dejaria de responder al raton sin que se viera en una captura. */
/* El fondo de la caja NO cambia al pasar el ratón. Antes iba a #EBE9E5, más
   oscuro que el fondo de los propios packshots (242,242,240): la foto quedaba
   dibujada como un rectángulo claro dentro de la caja, que es el "recuadro
   blanco" que se veía al hacer hover. Se queda en `--card`, el mismo tono que
   traen las fotos de estudio, y así la foto y la caja son una sola superficie. */
/* Sin sombra: `drop-shadow` la dibuja alrededor del RECTANGULO de la imagen y no
   del producto, porque la foto trae su fondo opaco. Con la baldosa gris detras
   salia una caja dentro de otra. Medido en pantalla antes de quitarla. */

/* `--tlr-card-zoom` lo pone `tlr_zoom_tarjeta()` en el PHP, y sube el suelo de
   la escala por volumen de 0,29 a 0,55 sin tocar el techo. El porqué está
   entero en el comentario de esa función.

   OJO CON EL HOVER: el zoom de la tarjeta y el del ratón son el mismo
   `transform`, así que el segundo PISA al primero. Escrito como estaba antes
   (`transform:scale(1.045)` a secas), pasar el ratón por encima devolvía la
   foto a su tamaño pequeño de golpe, que es peor que no hacer nada. Los dos
   van multiplicados, y por eso el hover nombra la variable también. */
/* 12 sep, proporción real: la escala parte de la BASE de la caja (origen
   50% 100%) y `--tlr-card-dy` desplaza la foto para que la base del producto
   caiga en la misma línea en todas las tarjetas. Los dos números los pone
   `tlr_proporcion_tarjeta()` (piezas.php); sin ellos, 1 y 0, como antes. */
.card-media img{width:100%;height:100%;object-fit:contain;padding:8% 12% 7%;filter:none;
  transform-origin:50% 100%;
  /* 17 de septiembre. Mónica, 16 sep: "creo que es importante que el producto
     se vea bien". El multiplicador NO sustituye al sistema de proporción del
     12 de septiembre, lo escala entero: así el bote de 18 cm sigue siendo más
     alto que el sérum de 10,5 en la misma medida que antes. Poner 1 aquí lo
     devuelve todo a como estaba. */
  transform:translateY(var(--tlr-card-dy,0%)) scale(calc(var(--tlr-card-zoom,1) * var(--tlr-card-escala,1)));
  transition:transform .8s cubic-bezier(.22,1,.36,1)}
.card:hover .card-media img{transform:translateY(var(--tlr-card-dy,0%)) scale(calc(var(--tlr-card-zoom,1) * var(--tlr-card-escala,1) * 1.045))}
/* 17 de septiembre: 1,05 y no el 1,07 del plan. Medido en píxeles sobre las
   dos tiendas (ES y EN) a 1440 y a 390: con 1,07, a 390 las fotos de ambiente
   (Pack Ritual de Rosas, Tulum Sunset, Wax Brow Pencil...) llegaban a 1-2 px del
   borde de arriba de la baldosa, antes a 13. Con 1,05 ninguna toca el borde. */
.grid .card-media img{--tlr-card-escala:1.05}
/* 18 de septiembre. Mónica, vídeo del 17: "fotos más grandes en general de
   producto, porque se ven muy pequeñas y el producto no se aprecia como
   debería, y más centradas". Es SOLO la hilera de la portada: la tienda se
   queda en el 1,05 que se midió ayer, y por eso son dos reglas y no una.
   1,30 y no más, medido en píxeles con el mismo método de la tienda
   (.planning/verif/p18-rail.js) en las dos portadas y a 1440 y 390: con 1,40
   tampoco se recorta nadie, pero los dos sérums llegan a 7-8 px del borde de
   arriba y se van descentrados hacia arriba (8 px arriba contra 47 abajo);
   con 1,30 el producto crece un 30 % y esos mismos sérums quedan centrados
   (32 arriba contra 40 abajo a 1440). La holgura mínima medida es de 17 px de
   171 a 390. Poner 1 aquí devuelve la hilera a como estaba.
   NO se toca `--tlr-card-dy`: la línea de base común sale de la proporción
   real del 12 de septiembre, y centrar tarjeta a tarjeta la rompería. El
   escalado ya sube el producto solo, porque el origen es la base. */
.rail .card-media img{--tlr-card-escala:1.30}

/* ---------- las fotos nuevas, reencuadradas ----------
   Un packshot antiguo se pinta a `contain` con relleno porque su fondo es el
   mismo gris de la caja. Una foto reencuadrada trae SU PROPIO fondo, y a
   `contain` se queda flotando con márgenes grises alrededor, que es el mismo
   fallo que ya nos costó una vuelta el 18 con las segundas fotos.

   VA AQUÍ ABAJO Y NO ANTES, Y ESO ES EL ARREGLO. La primera versión la puse
   encima de `.card-media img` y no hizo nada: `.card-media--nueva img` y
   `.card-media img` pesan lo MISMO en especificidad (una clase más un
   elemento), así que decide el orden y ganaba la de abajo. Medido en el
   navegador: seguía en `contain` con 24 px de relleno. Es exactamente el error
   contra el que avisa el comentario de `.card-shot__alt`, y lo repetí igual.

   El hover nombra las dos reglas porque `transform` es una sola propiedad y la
   de arriba la pisaría. */
.card-media--nueva img{object-fit:cover;padding:0;transform:none}
.card:hover .card-media--nueva img{transform:scale(1.045)}

/* La segunda foto va dentro de la misma caja y tiene que crecer igual, o al
   pasar el ratón el producto pega un salto de tamaño al cambiar de foto.

   DEFECTO encontrado y arreglado el 7 de septiembre por la tarde: el fundido
   de .7s de `.card-shot__alt` (más abajo) nunca llegaba a pintarse. `transition`
   es una sola propiedad y el navegador la resuelve entera por especificidad,
   no mezcla lo de una regla con lo de otra: `.card-media img` (elemento + una
   clase) pesa más que `.card-shot__alt` sola (una clase), así que su
   `transition:transform .8s` ganaba SIEMPRE, y con ella su lista de
   propiedades — solo `transform` — se comía también a `opacity`, que se
   quedaba sin transición ninguna. Medido en capturas fotograma a fotograma:
   la foto nueva ya estaba a opacidad 1 a los 120ms, un corte, no un fundido.
   La transición vive aquí ahora, en la regla que YA gana por especificidad
   (elemento + dos clases), y así de paso gobierna el fundido de la propia
   `opacity` además del tamaño. */
/* 13 de septiembre: la foto del hover YA NO hereda el zoom del producto.
   Va a `object-fit:cover` (regla de más abajo), o sea que llena la baldosa
   sola. Escalarla por el zoom del producto sobraba, y desde que el zoom es
   por altura real (12 de septiembre) la mitad de los productos tienen zoom
   MENOR que 1: la foto encogía por debajo de la baldosa y dejaba un marco de
   fondo alrededor. Se veía en la tarjeta del Wonder Balm (zoom 0,769).
   La transición se queda AQUÍ y no se toca: esta regla es la que gana por
   especificidad y con ella viaja el fundido de `opacity` (ver el comentario
   del 7 de septiembre, arriba). Solo cambia `transform`. */
.card-media img.card-shot__alt{transform:none;transform-origin:50% 50%;
  transition:opacity .7s cubic-bezier(.22,1,.36,1),transform .9s cubic-bezier(.22,1,.36,1)}
.card:hover .card-media img.card-shot__alt{transform:scale(1.045)}

/* La segunda foto puede ser nuestra sin que la principal lo sea (ampliación
   del 7 de septiembre): un producto con su packshot de galería de siempre
   como principal, con zoom por volumen o sin él, puede llevar una segunda
   foto real ya encuadrada. `.card-shot__alt--nueva` pesa una clase más que
   la regla de arriba (elemento + dos clases contra elemento + una), así que
   gana sin `!important` y sin importar el orden. */
.card-media img.card-shot__alt.card-shot__alt--nueva{transform:none}
.card:hover .card-media img.card-shot__alt.card-shot__alt--nueva{transform:scale(1.045)}
/* Antetitulo de reclamo, patron de omorovicza.eu: versalita pequena arriba a la
   izquierda DENTRO de la foto y sin pastilla. Sustituye a `.card-tag`, que era
   una pastilla verde y competia con la propia foto. Las pastillas siguen siendo
   el lenguaje de los BOTONES, que es lo que Dani aprobo el 13 de agosto. */
.card-eyebrow{position:absolute;top:.9rem;left:.95rem;z-index:2;font-size:.6rem;letter-spacing:.18em;text-transform:uppercase;font-weight:600;color:var(--ink-soft)}
/* 21 de septiembre. Dani: "en móvil el MÁS VENDIDO queda por encima del
   producto y no queda bien". Lo provocó el 1,30 del 18: en la baldosa de 171 px
   el gotero de los dos sérums sube hasta la etiqueta. Medido en píxeles con
   .planning/verif/p21-piezas.js (producto = distinto del gris 242,242,240,
   tolerancia 10, dentro del rectángulo de la etiqueta), ES y EN, a 390 y 375:
   con 1,30 la etiqueta pisa 135-164 px de producto en Beauty Boost y Calming.
   Mónica pidió el producto GRANDE, así que se pierde lo mínimo y se combina
   con acercar la etiqueta a la esquina (sigue en una línea, como siempre):
     solo escala: 1,26 pisa; 1,22 pisa a 375; 1,18 queda a 3,9 px.
     escala + esquina: 1,26 pisa a 375; 1,22 queda a 2,7 px, pegado;
     1,20 queda a 5,7 px a 375 y 8,1 a 390, sin pisar en ninguna tarjeta.
   1,20: el producto de la hilera sigue un 20 % por encima de su tamaño base y
   pierde un 7,7 % respecto al 1,30 (el sérum, 130 -> 120 px de alto a 390).
   SOLO móvil: a 1440 la etiqueta queda a 38-123 px del producto con el 1,30,
   medido, así que el ordenador no se toca. */
@media (max-width:640px){
  .rail .card-media img{--tlr-card-escala:1.20}
  .rail .card-eyebrow{top:.6rem;left:.65rem}
}
/* El fondo iba a fuego en hueso, igual que la cabecera fija, así que con B se
   quedaba beige encima de la baldosa gris. Ahora sigue a `--bone`. */
/* `overflow:hidden` añadido el 7 de septiembre al enganchar YITH. NO es el
   arreglo del desbordamiento horizontal a 390px de ese mismo día: se
   sospechó primero de la etiqueta de texto de YITH ("Añadir a la lista de
   deseos", oculta por `clip` en la línea de abajo) y se descartó midiendo
   en el navegador — su caja ya vive dentro de los 34px del círculo y no
   llegaba a salir de él. La causa real fue de la retícula (`min-width:0`
   en `.grid>*`, ver más abajo). Esto se deja igual como cinturón de
   seguridad: nada que YITH meta ahí dentro se sale de un círculo de 34px. */
.card-fav{position:absolute;top:.7rem;right:.7rem;z-index:2;width:34px;height:34px;border-radius:50%;background:rgba(255,255,255,.85);background:color-mix(in srgb,var(--bone) 85%,transparent);display:grid;place-items:center;opacity:0;transform:translateY(-4px);transition:.4s;border:0;cursor:pointer;overflow:hidden}
.card:hover .card-fav{opacity:1;transform:none}
/* Enganchado a YITH de verdad, 7 de septiembre (ver `piezas.php`): dentro del
   círculo ya no hay un carácter Unicode suelto, hay el botón real de YITH,
   con su propio SVG y una etiqueta de texto que aquí sobra —el círculo ya
   dice lo que hace por su posición y su icono, poner además "Añadir a la
   lista de deseos" desbordaría un círculo de 34px—. Medido en el navegador
   antes de escribir esto, no adivinado. */
.card-fav .yith-wcwl-add-to-wishlist-button{display:grid;place-items:center;width:100%;height:100%;color:var(--ink);text-decoration:none}
.card-fav .yith-wcwl-add-to-wishlist-button__label{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}
.card-fav .yith-wcwl-icon-svg{width:16px;height:16px}
/* Mientras YITH comprueba si ya está en la lista (su clase `--loading`), que
   se quede el contorno del corazón en vez de lo que traiga YITH por defecto
   para ese estado: sin su hoja de estilos (barrida en las páginas propias,
   igual que el resto de lo ajeno) ese estado no tiene look propio y se
   quedaría en blanco. */
.card-fav .yith-wcwl-add-to-wishlist-button--loading{opacity:1}
/* La barra de compra, 11 de septiembre. Sustituye al botón pastilla que
   flotaba ENCIMA de la foto (absoluto, oculto hasta el hover en escritorio).
   Mónica: "queda fatal", "tapa la foto", "a lo mejor estuviera debajo". Ahora
   es el pie de la tarjeta a todo el ancho, precio a la izquierda y "Añadir" a
   la derecha, como la barra "€250 | ADD" de omorovicza.eu (40 px, dorada con
   blanco allí; aquí eucalipto con tinta, que es el lenguaje de botones
   aprobado el 13 de agosto, y al pasar el ratón se vuelve tinta como el resto
   de botones). Siempre visible, también en escritorio: no hay nada que
   descubrir con el ratón. `margin-top:auto` la empuja al pie cuando la
   rejilla estira la tarjeta al alto de su fila. */
.card-add{margin-top:auto;display:flex;justify-content:space-between;align-items:center;gap:.6rem;
  padding:.85rem 1rem;background:var(--eucalyptus);color:var(--ink);text-decoration:none;
  font-family:var(--sans);font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;font-weight:600;
  transition:background .35s,color .35s}
.card-add:hover{background:var(--ink);color:var(--bone)}
/* 17 de septiembre: sin la baldosa gris detrás, la barra ya no la recorta el
   radio de `.card` y se quedaba con esquinas vivas debajo de una foto con
   esquinas redondeadas. Mismo radio que la foto. */
.card-add{border-radius:3px}
/* El precio más grande que la acción, 11 de septiembre a las 12:35: con el mismo
   cuerpo de .72rem en mayúsculas que "Añadir", Mónica y Melissa: "el precio
   está enano, aquí no lo ve nadie". En la referencia van iguales (14 px), pero
   la suya es una barra de 40 px con texto blanco sobre dorado; aquí el
   eucalipto con tinta pide más cuerpo. Sin mayúsculas ni espaciado ancho, que
   en cifras solo restan. */
.card-add__precio{white-space:nowrap;font-size:1rem;letter-spacing:.02em;text-transform:none;font-weight:500}
/* Agotado (15 oct): la misma barra, apagada y sin reacción al ratón. */
.card-add--agotado,.card-add--agotado:hover{background:var(--card);color:var(--ink-soft);cursor:default}
.card-info{padding:.85rem .1rem 1rem}
/* Dos lineas de hueco reservadas: la raya de debajo solo sirve de algo si cae a
   la misma altura en toda la hilera, y los nombres van de una linea a tres. Con
   los nombres de una linea la raya se subia y la fila quedaba a escalones. */
/* El nombre tenía SUELO pero no TECHO, y ese era el fallo que se veía en móvil.

   Medido a 390 px: el libro de Mónica se llama "Aprende A Quererte. Un Mapa
   Para Transformarte Por Dentro y Por Fuera" y ocupaba **cinco líneas, 130 px**,
   mientras el Apricot ocupaba dos, 43 px. La rejilla estira las dos tarjetas de
   una fila al alto de la más larga, así que la primera fila medía 460 px y las
   siguientes 373 y 395: filas de tres alturas distintas y un hueco enorme
   debajo del Apricot.

   Con dos por fila el fallo salta a la vista; con cuatro se diluye, y por eso
   no se veía en escritorio.

   Techo de dos líneas, igual que la frase de beneficio lleva el suyo de tres.
   El nombre completo está en la ficha, que es donde importa. */
/* 5 de octubre de 2026. Mónica, 4 oct: nombres en MAYÚSCULAS ("CALENDULA EYEBROW
   ELIXIR 15ML", palo seco, como su web actual), "los títulos un poco más
   pequeños y más unidos a las estrellas, precio, etc.". Revierte el serif de
   1,18 rem. Se pasa al palo seco del sistema (Archivo) y no se deja Zodiak en
   versales: es lo que ella enseña, el resto de la tarjeta (tamaño, frase,
   barra) ya es Archivo, y una serif de contraste en mayúsculas con espaciado
   sale pesada en 167 px de ancho. `text-transform` y no el texto: el título
   de la base de datos no se toca. 0,8 rem con 0,05 em de espaciado y peso 500:
   en mayúsculas el mismo cuerpo se lee más grande, y por eso baja de 1,18 a 0,8.
   Las dos líneas de hueco se quedan (la raya de debajo cae a la misma altura
   en toda la hilera), pero el nombre se apoya ABAJO de ese hueco, pegado a la
   raya; el aire sobrante queda entre la foto y el nombre. El techo de dos
   líneas va en el enlace, porque el `h3` ahora es flex. */
.card-name{font-family:var(--sans);font-size:.8rem;font-weight:500;letter-spacing:.05em;text-transform:uppercase;margin:0 0 .3rem;line-height:1.3;
  min-height:2.6em;display:flex;flex-direction:column;justify-content:flex-end}
.card-name a{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
/* Precio a la izquierda y estrellas a la derecha en la MISMA linea, con una raya
   fina entre el nombre y esa linea. Antes las estrellas iban encima del nombre,
   que es donde menos se ven. Patron de omorovicza.eu, medido el 16 de agosto. */
/* `flex-wrap` y el precio en una sola pieza: en una tarjeta de 172 px, que es
   lo que mide en un movil de 390, "78 € · 30 ml" se partia y dejaba "ml" solo
   en la linea de abajo. Ahora el precio no se rompe nunca y, si no cabe con la
   valoracion al lado, es la valoracion la que baja entera. */
.card-line{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:.15rem .6rem;border-top:1px solid var(--line);padding-top:.55rem}
.card-size{white-space:nowrap}
.card-rating{font-size:.72rem;color:var(--amber);letter-spacing:.05em;display:flex;gap:.35rem;align-items:center;white-space:nowrap}
.card-rating span{color:var(--ink-soft)}
.card-size{font-size:.92rem;color:var(--ink-soft);letter-spacing:.02em}
/* 14 oct, Melissa: una tarjeta sin tamaño ni reseñas dejaba la fila a 0 de alto
   y su frase subía respecto a la de al lado. Un espacio invisible en el tamaño
   vacío mantiene la fila con el mismo alto haya o no estrellas. */
.card-size:empty::before{content:"\a0"}
/* La frase que explica para que sirve: es la diferencia entre un catalogo y una
   tienda que vende. Dos lineas como tope para que las tarjetas de una misma
   hilera no se descuadren; el texto ya viene recortado por palabra desde PHP. */
/* Tres líneas, no dos. Las frases de la referencia van de 78 a 132 caracteres
   y a dos líneas se cortaban a media frase; con tres caben enteras. El
   `min-height` sube en la misma proporción para que las tarjetas de una hilera
   sigan alineadas aunque una frase sea más corta que otra. */
/* 21 de septiembre. Mónica la quiere de vuelta, en la tienda Y en la portada,
   pero corta: "una pequeña descripción del producto, máximo dos líneas,
   idealmente una, debajo del nombre", como las de monchomoreno.com.
   Dos líneas de TECHO y ningún suelo: el hueco reservado de 4,35em era lo que
   dejaba agujeros grises debajo de las frases cortas, que es lo que ella
   rechazó el 16. Las barras de compra siguen alineadas al pie porque
   `.card-add` lleva `margin-top:auto`, no porque la frase mida lo mismo. */
.card-benefit{margin-top:.45rem;font-size:.82rem;line-height:1.45;color:var(--ink-soft);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
/* Mónica, 16 de septiembre: "esto es larguísimo, tres líneas, no lo tiene
   nadie; es como el nombre y como mucho hay una línea". Esa frase es
   `.card-benefit`, recortada a tres líneas con min-height 4.35em.
   Se esconde en la rejilla de la tienda y se deja el maquetado intacto, que es
   el mismo parcial que usa la hilera de la portada. Volver atrás es borrar
   estas dos líneas. */
/* 21 de septiembre: la frase vuelve, ver el comentario de `.card-benefit`. */
/* En la hilera de la portada, fuera la frase. Decisión de Dani del 24 de agosto
   viendo las tres opciones al lado: en un carrusel la gente mira la foto y el
   precio, y tres líneas de gris debajo de cada nombre descuadran los altos y
   quitan aire. En la TIENDA se quedan, que es donde de verdad se compara.
   Ojo con el `min-height:4.35em` de arriba: por eso no basta con vaciar el
   texto ni con recortarlo a una línea, hay que quitar la caja entera. */
/* 21 de septiembre: la frase vuelve, ver el comentario de `.card-benefit`. */

/* La tarjeta mide 167 px en un movil de 390, y ahi "32 € · 15 ml" con las
   estrellas al lado se pasaba por unos pocos pixeles: la valoracion bajaba a una
   segunda linea en unas tarjetas si y en otras no, y la hilera volvia a quedar a
   escalones. Se encoge lo justo para que quepa siempre.

   Va AQUI, detras de las reglas de la tarjeta, y no arriba con el resto de
   medias queries: una media query no gana especificidad, solo la que tenga el
   selector, asi que puesta antes la pisaban `.card-price` y `.card-rating` de
   mas abajo. Medido: seguia partiendo igual. */
@media (max-width:640px){
  .card-line{gap:.35rem}
  .card-size{font-size:.82rem}
  .card-rating{font-size:.62rem;letter-spacing:0;gap:.2rem}
  /* Dos líneas de frase en móvil, no tres (11 de septiembre): con la barra de
     compra al pie, la tarjeta de 167 px medía 390 de alto, 2,3 veces su ancho;
     la referencia va a 1,8. La frase entera está en la ficha. */
  .card-benefit{-webkit-line-clamp:2}
}
/* Por debajo de 400 px la tarjeta se queda en 154 y no hay recorte de letra que
   valga: se quita el numero de resenas y se dejan las estrellas, que es lo que
   de verdad se lee de un vistazo. El numero sigue estando en la ficha. */
@media (max-width:400px){
  .card-rating span{display:none}
}

/* segunda foto de la galeria al pasar el raton */
.card-shot{display:block;position:absolute;inset:0}
.card-shot img{position:absolute;inset:0}
/* La segunda foto llena la caja entera (`cover`) en vez de encajar dentro
   (`contain`). Muchas segundas fotos traen su propio fondo, y no es el de
   estudio: hay azulados, beiges y una marrón de ambiente. Con `contain` cada
   una dibujaba su recuadro; con `cover` la foto va a sangre dentro de la
   tarjeta, que además es lo que hace la referencia. El recorte es mínimo: la
   caja es 4/5 y las fotos son 300x363, casi la misma proporción. */
/* Solo la opacidad de reposo. La transición de verdad vive en
   `.card-media img.card-shot__alt`, más arriba: aquí nunca ganaba, ver el
   comentario del 7 de septiembre en esa regla. */
.card-shot__alt{opacity:0}
/* El selector lleva `img` a propósito: `.card-media img` de más arriba impone
   `object-fit:contain` y un relleno del 8-12 %, y con la misma especificidad
   ganaba él. Sin esto, las fotos de campaña (la del contorno de ojos, la del
   salt scrub en la mano) se quedaban flotando con márgenes claros alrededor en
   vez de llenar la tarjeta. */
.card-media img.card-shot__alt{object-fit:cover;padding:0}
.card:hover .card-shot__alt{opacity:1}

/* ---------- bandas y columnas ---------- */
.band{padding-block:clamp(4rem,8vw,8.5rem)}
/* Un gris propio y no var(--bone-2), que en B se quedaba igual que el fondo.
   5 de octubre de 2026. Mónica: "quiero fondo blanco". Este gris era lo que ella
   veía como beige en la portada y en Nosotros. Las bandas pasan a blanco; las
   baldosas de las fotos siguen en gris (decisión de Dani). Volver: #F7F6F4. */
.band--tint{background:#FFFFFF}
.band--ink{background:var(--ink);color:var(--bone)}
/* --- la banda del spa, 13 de agosto --------------------------------------
   Mónica en la videollamada: la sección del spa tiene que distinguirse y ser
   "lo único más oscuro" [34:43], y Dani pide que sea del mismo verde. Se usa el
   verde oscuro `--verde-texto`, que es el mismo tono de la salvia del pie:
   sigue siendo el único bloque oscuro y ya no es negro. Sobre él, la letra en
   hueso mide 5,7:1. El ámbar del antetítulo se quita: sobre verde no se leía. */
/* 13 de septiembre: al eucalipto, el mismo del pie. Mónica lo pidió señalando
   el pie, igual que hizo con la banda de la ficha el 11.
   OJO, contradice lo del 13 de agosto que hay escrito aquí arriba: entonces
   pidió que el spa fuera "lo único más oscuro". Si el lunes vuelve a querer
   distinguirlo del resto, lo que hay que recuperar es `--verde-texto`.
   Sobre eucalipto NADA se puede quedar en hueso: la sección hereda
   `color:var(--bone)` de `.band--ink`, así que se devuelve a tinta aquí y se
   repasan uno a uno el antetítulo, el cuerpo, los filetes de la lista y el
   botón (que era blanco sobre verde oscuro y sobre claro desaparecía). */
.band--spa{background:var(--eucalyptus);color:var(--ink)}
/* La foto de la banda partida SALE del margen y llega al borde de la pantalla.

   Esto es lo que rompe que toda la página viva dentro de la misma columna, que
   es lo que la hacía leerse plana. La foto se come `var(--pad)`, que es
   exactamente el relleno de `.wrap`, así que toca el canto de la ventana sin un
   solo píxel de más ni de menos. Mismo truco que ya usa la hilera cortada de la
   portada unas líneas más arriba.

   Va con `:has()` para saber de qué lado está la foto: si es el primer hijo se
   escapa por la izquierda, y si la banda está invertida, por la derecha. Sin
   eso habría que marcar cada bloque a mano en el PHP y se olvidaría el día que
   se añada una banda nueva.

   La proporción sube de 4:5 a 4:4,4 sólo cuando se escapa: al ganar ancho, con
   4:5 la foto crecía tanto de alto que la columna de texto se quedaba corta y
   la banda salía descuadrada. Medido, no supuesto. */
.split{display:grid;grid-template-columns:1fr 1fr;gap:clamp(2rem,5.5vw,5.5rem);align-items:center}
.split-media{aspect-ratio:4/5;overflow:hidden;border-radius:3px}
@media (min-width:901px){
  .split:not(.split--rev) > .split-media:first-child{
    margin-left:calc(-1 * var(--pad));
    border-top-left-radius:0;border-bottom-left-radius:0;
    aspect-ratio:4/4.4;
  }
  .split--rev > .split-media{
    margin-right:calc(-1 * var(--pad));
    border-top-right-radius:0;border-bottom-right-radius:0;
    aspect-ratio:4/4.4;
  }
  /* 13 de septiembre, Dani: "no dejes espacio de margen a la derecha en la
     foto, que la imagen llegue hasta la derecha del todo". Es el espejo exacto
     de la regla de arriba, que solo cubría la foto cuando iba PRIMERA. La de
     Rossy va la última dentro de un `.split` normal y por eso se quedaba con el
     margen del `wrap`. Hoy `:last-child` en un `.split` sin `--rev` solo lo
     cumple ella; la de la casa va primera y ya sangra por la izquierda. */
  .split:not(.split--rev) > .split-media:last-child{
    margin-right:calc(-1 * var(--pad));
    border-top-right-radius:0;border-bottom-right-radius:0;
    aspect-ratio:4/4.4;
  }
}

/* --- Rossy de Palma: inversión al pasar el ratón -------------------------
   Pedido por Dani el 13 de septiembre. La foto ya es un duotono coral sobre
   fucsia, así que invertirla la manda al cian y no se reconoce a Rossy: se
   invierte tal cual, que es lo que se pidió: el coral se va al cian y el fucsia
   al verde. Se probaron tres en pantalla y se llevaron a la hoja de opciones:
   `invert(1)`, el negativo de verdad; `invert(1) hue-rotate(180deg)`, que sale
   marrón oscuro y embarrado y se descartó ahí mismo; y el giro de tono, que no
   invierte pero mantiene a Rossy reconocible y manda el coral al verde y el
   fucsia al azul.
   ELEGIDO POR DANI EL 13 DE SEPTIEMBRE: el giro de tono. No es la inversión
   literal que pidió al principio, es la alternativa que se dejó apuntada.
   `invert(1)` queda en la hoja por si se vuelve atrás.
   El `filter` viaja en su propia transición para no pisar la de `transform`,
   que ya hace el acercamiento. */
/* 5 de octubre de 2026. REVIERTE lo del 13 de septiembre: la clienta no quiere
   que la foto de Rossy cambie de color al pasar el ratón (se le ponía verde).
   Fuera el giro de tono y su transición de `filter`: la foto no lleva ningún
   filtro al pasar el ratón. Medido el 5 de octubre con la foto ya revelada: el
   scale(1.04) de `.split-media:hover img` NO se ve en la portada, porque el Ken
   Burns de portada.css (`.js .split-media.reveal.in img`, más específico) lo
   tapa y el transform sigue en identidad. Si la clienta quiere un zoom suave
   al pasar el ratón, hay que subir la especificidad de esa regla. */
@media (prefers-reduced-motion:reduce){
  .band--rossy .split-media img{transition:none}
}

/* --- Rossy: proporcion, aire y entrada, 14 de septiembre -----------------
   Dani, mirando la portada: "reducir ese espacio que queda algo raro y la
   foto y el texto no es 50/50, la foto debe estar algo mas hacia la izquierda
   ganando algo de terreno", y "una animacion de scroll down para que aparezca
   lo de Rossy de Palma".

   MEDIDO ANTES DE TOCAR, a 1440: la banda media 979 px de alto con 115,2 de
   relleno arriba y abajo, las dos columnas a 608,406 px exactas (o sea que SI
   era 50/50) y la foto 680x748. El texto mide 394 de alto, asi que sobraban
   177 px de aire por arriba y otros 177 por abajo. Ese es el espacio raro: no
   lo causaba el relleno, lo causaba una foto mucho mas alta que el texto.

   La foto original es APAISADA: 1600x1199, relacion 1,33. El marco era
   vertical, 0,91, o sea que `cover` se estaba comiendo los lados. Al
   ensancharlo y bajarlo se ve MAS foto, no menos, y de paso la banda encoge.
   Por eso las tres cosas van en el mismo cambio y no por separado.

   La relacion de aspecto necesita cinco clases para ganarle a la regla del
   sangrado de mas arriba, que ya lleva cuatro.

   `overflow:hidden` no es decorativo: la foto ya sangra hasta el borde
   derecho, y sin el la entrada desde la derecha sacaria barra horizontal. */
.band.band--rossy{padding-block:clamp(2.6rem,4.4vw,4rem);overflow:hidden}
@media (min-width:901px){
  .band--rossy .split{grid-template-columns:.85fr 1.15fr;gap:clamp(1.4rem,3.4vw,3.4rem)}
  .band--rossy .split:not(.split--rev) > .split-media:last-child{aspect-ratio:4/3.7}
}
/* 21 de septiembre. Dani: "en móvil no quiero que la imagen de Rossy de Palma
   tenga márgenes a los lados, quiero que sea completa de lado a lado".
   Mismo truco que el sangrado de ordenador de más arriba, pero por los dos
   lados: la foto se come `var(--pad)`, el relleno exacto de `.wrap`, así que
   mide el ancho de la ventana sin `100vw` (que en Windows cuenta la barra).
   Medido a 390: antes x=20 y 350 de ancho con radio de 3 px; ahora x=0 y 390.
   El `overflow:hidden` de la banda ya evita que la entrada desde la derecha
   saque barra horizontal. A 901 o más no entra: el ordenador no cambia. */
@media (max-width:900px){
  .band--rossy .split-media{margin-inline:calc(-1 * var(--pad));border-radius:0}
}

/* La banda YA se revelaba: todos sus elementos llevan `.reveal`. Lo que
   pasaba es que subian los mismos 26 px que el resto de la pagina y no se
   notaba. Aqui la foto entra desde la derecha y el texto sube escalonado.
   El escalon lleva `!important` y esta vez si hace falta: el JS de la portada
   escribe `el.style.transitionDelay` en linea repartiendo por indice GLOBAL
   de la pagina, que aqui daba un orden arbitrario, y un estilo en linea solo
   se le gana asi. */
.js .band--rossy .split-media.reveal{opacity:0;transform:translateX(46px)}
.js .band--rossy .split-media.reveal.in{opacity:1;transform:none;
  transition:opacity 1.1s cubic-bezier(.22,1,.36,1),transform 1.1s cubic-bezier(.22,1,.36,1)}
.js .band--rossy .split-copy .reveal{transform:translateY(34px)}
.js .band--rossy .split-copy .reveal.in{transform:none}
.js .band--rossy .split-copy .eyebrow.reveal{transition-delay:0ms!important}
.js .band--rossy .split-copy h2.reveal{transition-delay:120ms!important}
.js .band--rossy .split-copy p.reveal{transition-delay:230ms!important}
.js .band--rossy .split-copy .btn.reveal{transition-delay:330ms!important}
@media (prefers-reduced-motion:reduce){
  .js .band--rossy .split-media.reveal,
  .js .band--rossy .split-copy .reveal{opacity:1;transform:none}
}

/* --- variante de foto grande, 13 de agosto -------------------------------
   Mónica, del recuadro de Filosofía: "lo que no le gusta es que esté en
   recuadro, quiere la imagen en grande". La foto sale del `wrap`, pega con el
   borde de la pantalla y coge el alto entero de la sección; el texto conserva
   su margen. Es la misma pieza, solo cambia el encuadre.                    */
.band--foto{padding-block:0}
.band--foto .split{align-items:stretch;gap:0;max-width:none;padding-inline:0}
.band--foto .split-media{
  aspect-ratio:auto;border-radius:0;
  min-height:clamp(30rem,44vw,52rem);
}
.band--foto .split-copy{
  display:flex;flex-direction:column;justify-content:center;
  padding-block:clamp(3.5rem,7vw,7.5rem);
  padding-inline:clamp(2rem,5vw,5.5rem) var(--pad);
  max-width:calc(var(--maxw) / 2);
}
/* Al apilar, la foto ocupa el ancho entero y el texto recupera su margen. */
@media(max-width:900px){
  .band--foto .split-media{min-height:clamp(22rem,80vw,30rem)}
  .band--foto .split-copy{padding-inline:var(--pad);max-width:none}
}
.split-media img{width:100%;height:100%;object-fit:cover;transition:transform 1.2s cubic-bezier(.22,1,.36,1)}
.split-media:hover img{transform:scale(1.04)}
/* Sube, pero MENOS que los de sección, y no es una inconsistencia: es que no
   viven en el mismo sitio. Un titular de sección ocupa el ancho entero y cabe
   en una línea; éste vive en media columna de 680 px y sus frases son largas
   ("Un santuario en el corazón de Salamanca").

   Medido en navegador a 1440: a 4,8 rem los tres titulares de banda se iban a
   TRES líneas de serif de 77 px, que se comen la sección y empujan el texto
   fuera de la vista. A 4 rem se quedan en dos, que es donde tienen que estar.
   De 3,7 a 4 sigue siendo un salto, sólo que uno que cabe. */
.split-copy h2{font-family:var(--serif);font-weight:400;font-size:clamp(2.3rem,4.4vw,4rem);line-height:1.02;letter-spacing:-.018em;margin:1.4rem 0 1.5rem}
/* `font-weight:401` es la cursiva de verdad de Zodiak, que ya viene en la hoja de
   Fontshare. Sin ese peso el navegador se inventa la cursiva inclinando la
   redonda, y se nota: en `/wonder-balm/` la cursiva es 401 y aquí salía 400. */
.split-copy h2 em{font-style:italic;font-weight:401}
.split-copy p{color:var(--ink-soft);max-width:42ch;font-size:1.04rem}
.band--ink .split-copy p,.band--ink .lede{color:rgba(243,237,227,.78)}
.chips{display:flex;flex-wrap:wrap;gap:.55rem;margin:1.7rem 0 2.1rem}
.chip{font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;border:1px solid var(--line);border-radius:999px;padding:.5rem .9rem;color:var(--ink-soft)}
.band--ink .chip{border-color:rgba(243,237,227,.28);color:rgba(243,237,227,.82)}
/* Van DESPUÉS de las de `band--ink` a propósito: el verde es más claro que el
   negro, así que los textos apagados que allí se leían aquí se quedaban en
   3,7:1. Medidos uno a uno sobre el verde, no calculados a ojo. */
.band--spa .split-copy p,.band--spa .lede{color:var(--ink-soft)}
.band--spa .eyebrow{color:var(--ink-soft)}
.band--spa .split-copy h2{color:var(--ink)}
/* El filete del enlace era `--eucalyptus`: sobre eucalipto no existía. */
.band--spa .link-underline{color:var(--ink);border-bottom-color:rgba(27,26,23,.42)}
/* El botón era hueso relleno por un estilo en línea de la plantilla; sobre
   claro perdía el canto. Se le quitó el estilo en línea y se invierte aquí.
   Sin `!important`: dos clases ya ganan a `.btn` a secas, y se comprobó
   midiendo el color calculado. */
.band--spa .btn{background:var(--ink);color:var(--bone);border-color:var(--ink)}
.band--spa .btn:hover{background:var(--verde-texto);border-color:var(--verde-texto)}
.band--spa .spa-row .dur{opacity:.82}
/* El subrayado en eucalipto y la letra en tinta. El texto verde sobre hueso se
   queda en 2,57:1, asi que el verde entra solo en el filete, que es adorno. */
.link-underline{font-size:.78rem;letter-spacing:.13em;text-transform:uppercase;font-weight:600;border-bottom:1px solid var(--eucalyptus);padding-bottom:.3rem;display:inline-block;transition:opacity .3s}
.link-underline:hover{opacity:.6}

/* ---------- aparicion al desplazar ---------- */
.js .reveal{opacity:0;transform:translateY(26px);transition:opacity 1s cubic-bezier(.22,1,.36,1),transform 1s cubic-bezier(.22,1,.36,1)}
.js .reveal.in{opacity:1;transform:none}
.char{display:inline-block}
.js .char{transform:translateY(110%);transition:transform .9s cubic-bezier(.22,1,.36,1)}
.js .char.in{transform:none}
.word{display:inline-block;white-space:nowrap}
.line-mask{overflow:hidden;display:inline-block;vertical-align:top;padding-bottom:.14em;margin-bottom:-.14em}

/* Sin ratón no hay hover, y el corazón de favoritos solo aparece con él: en
   móvil se quita. (Hasta el 11 de septiembre aquí vivía también el botón de
   añadir, que en escritorio se escondía detrás del hover; ahora es la barra
   `.card-add` del pie de la tarjeta y está siempre visible en todas partes.) */
@media(hover:none){
  .card-fav{display:none}
}

@media(max-width:900px){
  .split{grid-template-columns:1fr;gap:2.2rem}
  .split--rev .split-media{order:-1}
  .grid{grid-template-columns:repeat(2,1fr);gap:1.2rem 1rem}
  .sec-head{align-items:flex-start;flex-direction:column;gap:.8rem}
}
/* ---------- reducir movimiento ----------
   El interruptor general está en `chrome.css`, que es la única hoja que entra
   en todas las páginas. Aquí sólo van los que además de dejar de transicionar
   tienen que QUEDARSE EN SU SITIO FINAL: parar la transición de un elemento
   que en reposo vale `translateY(8px)` lo deja quieto ocho píxeles más abajo,
   que es peor que animarlo.

   Y ojo con la que estaba antes: `.card-shot__alt{transition:none}` no hacía
   nada. `.card-media img` de más arriba lleva `transition:transform .8s` y es
   MÁS específico (elemento + clase contra clase sola), así que ganaba él.
   Medido en navegador con el modo activado: seguía en 0,8 s. */
@media(prefers-reduced-motion:reduce){
  .reveal,.char{opacity:1!important;transform:none!important}
  /* La foto de la tarjeta no crece AL PASAR EL RATÓN, pero conserva su zoom de
     tamaño. Escrito como `transform:none` se cargaba también `--tlr-card-zoom`,
     y el producto encogía justo al ponerle el ratón encima: un salto de tamaño
     en el sitio donde se pedía que no hubiera movimiento. La segunda foto sigue
     cambiando por fundido, que es color y no movimiento. */
  /* 17 de septiembre: también el multiplicador global (`--tlr-card-escala`),
     o bajo reducir movimiento el producto encogería al poner el ratón encima. */
  .card:hover .card-media img{transform:scale(calc(var(--tlr-card-zoom,1) * var(--tlr-card-escala,1)))!important}
  /* 5 de octubre de 2026: la segunda foto NO lleva el zoom del producto ni
     aquí. Con `reduce` esta regla se lo ponía (zoom < 1 la encogía y dejaba
     marco), que es la regresión del 13 de septiembre pero por la otra puerta.
     Va a `cover` y llena la baldosa sola. */
  .card:hover .card-media img.card-shot__alt{transform:none!important}
  /* 18 de septiembre, con el 1,30 de la hilera. La regla de aquí arriba se deja
     el `translateY` de la proporción, así que con "reducir movimiento" el
     producto SUBE su `--tlr-card-dy` al pasar el ratón: 45 px a 1440 en el
     Beauty Boost. Mientras la hilera iba a 1, ese salto cabía en los 105 px de
     aire que quedaban arriba; a 1,30 solo quedan 32 y el sérum se recortaba
     (72 px de producto pegados al borde de arriba, medido en píxeles con
     .planning/verif/p18-rail-hover.js). Se devuelve el desplazamiento SOLO en
     la hilera de la portada: la tienda se queda como está. Es el mismo aviso
     que abre este bloque: parar el movimiento sin conservar el reposo deja el
     elemento fuera de su sitio. La segunda foto no entra (`:not`): va a
     `cover` y el desplazamiento la bajaría. */
  .rail .card:hover .card-media img:not(.card-shot__alt){transform:translateY(var(--tlr-card-dy,0%)) scale(calc(var(--tlr-card-zoom,1) * var(--tlr-card-escala,1)))!important}
  /* La regla de arriba alcanzaría también a una segunda foto real que ignora
     el zoom de la galería (`--nueva`, 7 de septiembre): sin esto, quieta bajo
     reducir movimiento volvería a recortarse un 30% igual que en movimiento.
     Una clase más de especificidad, gana sobre la de arriba con el mismo
     `!important`. */
  .card:hover .card-media img.card-shot__alt.card-shot__alt--nueva{transform:none!important}
  /* El corazón aparece en su posición, sin subir. */
  .card-fav,.card:hover .card-fav{transform:none!important}
  /* La flecha del botón no se desplaza al pasar el ratón. */
  .btn:hover .arrow{transform:none!important}
}

/* ---------- el titular en negro del tema ----------
   Passim imprime EN LÍNEA, dentro de la página, un
   `@media only screen and (max-width:1024px){ .archive .qodef-h1, h1 {color:#000} }`.
   Al ir en línea, el barrido de hojas ajenas no lo ve, y al ser una regla
   directa sobre `h1` le gana a lo que el titular hereda de su contenedor.
   Resultado: en el móvil el titular de la portada salía en negro sobre la
   foto, ilegible, mientras en escritorio salía en hueso.

   Ninguna hoja nuestra le pone color al h1 a propósito: todas confían en la
   herencia. Así que se le devuelve. En la portada hereda el hueso del hero, y
   en el resto la tinta del body. */
@media (max-width: 1024px) {
  body h1 { color: inherit; }
}

/* ==========================================================================
   18 oct · Tipografía A (Oak) en la tarjeta de producto. Dani la eligió para
   toda la web (.planning/feedback/2026-10-17-dani/DIRECCION-diseno-referencias.md).
   SOLO letra: ni medidas de la tarjeta, ni foto, ni zoom, ni hover, ni colores
   (las estrellas siguen en ámbar). Las alturas de línea no se tocan, para que
   la barra de compra y la raya bajo el nombre no se muevan.
   Quitar este bloque entero devuelve la tarjeta a como estaba.
   ========================================================================== */
/* Antetítulo (Bestseller), nombre y barra de compra en la voz de etiqueta:
   Archivo 600, 11,5 px, versal, +0,16 em. */
.card-eyebrow,
.card-name{font-size:11.5px;font-weight:600;letter-spacing:var(--tlr-t-etiqueta-ls,.16em)}
.card-add{font-size:11.5px;font-weight:600;letter-spacing:var(--tlr-t-etiqueta-ls,.16em)}
/* El precio, en la misma voz pero a su tamaño de siempre (16 px): a 11,5 vuelve
   a ser el "precio enano" del 11 de septiembre. */
.card-add__precio{font-weight:600;letter-spacing:.06em}
/* Tamaño, frase y valoración: cuerpo pequeño, Archivo 300 a 13 px en tinta suave. */
.card-size,
.card-benefit{font-size:13px;font-weight:300;letter-spacing:0;color:var(--tlr-ink-soft,#3A382F)}
.card-rating,
.card-rating span{font-weight:300}
/* En el móvil el nombre va a +0,10 em y no a +0,16: con 0,16, a 390 px el techo de
   dos líneas cortaba 11 nombres de las tres páginas de tienda (ES+EN) en vez de 6
   (Rossy Hand Wash, Tuberose Mist, Deluxe Body Cream...). Con 0,10 son 5. */
@media (max-width:640px){
  .card-name{letter-spacing:.1em}
}
/* 19 oct, Mónica: "todo a la misma altura" (como Westman Atelier). El nombre arranca
   ARRIBA de su hueco de dos líneas, no abajo: un nombre de una línea (Detox Oil) ya no
   baja respecto al de dos de al lado. El hueco (min-height 2.6em) sigue igual, así que
   la raya y la barra de compra no se mueven. */
.card-name{justify-content:flex-start}
/* 19 oct, Mónica: la barra verde del precio "un poquito más estrecha, si no cobra
   demasiada importancia". Menos relleno arriba y abajo (.85rem → .6rem). */
.card-add{padding-top:.6rem;padding-bottom:.6rem}
/* 19 oct, Mónica: "estos productos tienen que estar a la misma altura". La segunda
   foto que es un packshot (clase --pack, la pone piezas.php con sus medidas) se pinta
   como la principal: encajada, mismo relleno, zoom y desplazamiento propios. Así el
   bote no salta al pasar el ratón. Las de ambiente siguen a sangre. */
.card-media img.card-shot__alt.card-shot__alt--pack{object-fit:contain;padding:8% 12% 7%;transform-origin:50% 100%;
  transform:translateY(var(--tlr-alt-dy,0%)) scale(calc(var(--tlr-alt-zoom,1) * var(--tlr-card-escala,1)))}
/* Sin el 1,045 de crecer: en el iPhone el hover se queda puesto al tocar y el bote
   salía un 4,5 % mayor que el de al lado (Body Cream junto al Salt Scrub, 19 oct). */
.card:hover .card-media img.card-shot__alt.card-shot__alt--pack{transform:translateY(var(--tlr-alt-dy,0%)) scale(calc(var(--tlr-alt-zoom,1) * var(--tlr-card-escala,1)))}
.card-media img.card-shot__alt.card-shot__alt--blanco{mix-blend-mode:multiply}
/* El enlace de las fotos aísla la mezcla: sin un fondo propio, el blanco se multiplica
   contra transparente y se queda blanco (recuadro claro medido en el ensayo). */
.card-shot:has(.card-shot__alt--blanco){background:var(--card)}
/* Con multiply lo blanco deja ver lo de debajo: la principal se apaga mientras dura el hover. */
.card:hover .card-media:has(.card-shot__alt--blanco) img:not(.card-shot__alt){opacity:0;transition:opacity .5s}
/* Con "reducir movimiento" la regla de arriba pone `transform:none!important` a la
   segunda foto: al packshot le quitaría su sitio. Este conserva el reposo, sin crecer. */
@media(prefers-reduced-motion:reduce){
  .card:hover .card-media img.card-shot__alt.card-shot__alt--pack{transform:translateY(var(--tlr-alt-dy,0%)) scale(calc(var(--tlr-alt-zoom,1) * var(--tlr-card-escala,1)))!important}
}
