/* ═══════════════════════════════════════════════════════════════════
   COMPONENTES · las piezas que Skinome resuelve con Shopify + Flickity
   ═══════════════════════════════════════════════════════════════════ */

/* ── 1 · Cinta de anuncios ─────────────────────────────────────── */
.cinta{background:var(--oliva);color:var(--crema);
  font-family:var(--fs);font-size:var(--t-xs);font-weight:500;
  text-transform:uppercase;letter-spacing:var(--tr-caps)}
.cinta .marquee__track > span{display:flex;align-items:center;
  padding:11px 0;white-space:nowrap}
.cinta .marquee__track > span > b{font-weight:500;padding-inline:28px}
.cinta .marquee__track > span > i{width:3px;height:3px;border-radius:50%;
  background:var(--oro);flex:none}

/* ── 2 · Navegación ─────────────────────────────────────────────── */
.nav-l{font-family:var(--fs);font-size:var(--t-sm);font-weight:500;
  text-transform:uppercase;letter-spacing:.1em;padding-block:6px}

/* El mega menú vive dentro del <li>, así el hover no se corta al
   bajar el mouse desde el link hacia el panel. */
/* El panel se posiciona contra .hdr, no contra el <li>: tiene que
   ocupar todo el ancho de la ventana. */
.mega-w{position:static}
/* Mismo mecanismo que el telón del header (.hdr__bg en base.css): una
   fila de grid que crece de 0fr a 1fr, no un fundido de opacidad. Nace
   pegado al borde inferior del header (top:100%, altura 0) y usa su
   misma curva — .25s ease — para que ambos se lean como una sola
   cortina bajando, no dos animaciones sueltas. */
.mega{position:absolute;left:0;right:0;top:100%;z-index:70;
  display:grid;grid-template-rows:0fr;
  background:var(--fondo);color:var(--tinta);
  border-bottom:1px solid transparent;
  transition:grid-template-rows .25s ease,border-color .25s ease,
    visibility 0s linear .25s;
  visibility:hidden;pointer-events:none}
/* .hdr__in centra su contenido, así que .mega-w (el ancho del botón
   "Tienda" nomás) queda mucho más angosto y más arriba que el panel:
   el panel ocupa todo el ancho de la ventana pero recién arranca en el
   borde inferior del header. Bajar el mouse en diagonal hacia un link
   que no esté justo debajo del botón cruza esa franja muerta, se
   pierde el :hover de .mega-w y el panel se cierra antes de llegar.
   Este pseudo-elemento cuelga del panel (no del botón): ocupa todo su
   ancho y sube a tapar el hueco, así el :hover no se corta sin
   importar en qué punto del panel se entra. Sin fondo ni borde propio,
   no se nota; hereda pointer-events de .mega, así que sólo intercepta
   mientras el panel ya está abierto. */
.mega::before{content:'';position:absolute;left:0;right:0;
  bottom:100%;height:32px}
.mega-w:hover .mega,.mega-w:focus-within .mega,.mega.abierto{
  grid-template-rows:1fr;border-bottom-color:var(--borde);
  visibility:visible;pointer-events:auto;transition-delay:0s}
/* overflow:hidden es lo que hace posible animar la fila de grid: sin
   esto el contenido asoma por encima del header mientras la fila mide
   0fr, en vez de quedar tapado hasta que termina de crecer.
   El padding-block NO puede vivir acá: un padding siempre suma a la
   altura mínima de una caja, así que si estuviera en este mismo
   elemento la fila jamás podría cerrar más allá de esos 80px (40+40) —
   la animación de salida se frenaba ahí en vez de llegar a 0 y el
   panel se cortaba de golpe al final. Por eso el padding se movió a
   .mega__grid, un nivel adentro: overflow:hidden en .mega__in lo tapa
   igual mientras la fila colapsa. */
/* width:100% porque, sin display:grid propio, .mega__in ya no recibe
   el stretch automático que tenía como item de una columna implícita
   de .mega — sin esto queda al ancho de max-content y la 4ta columna
   (la foto) se cae a una segunda fila invisible. */
.mega__in{overflow:hidden;width:100%}
.mega__grid{display:grid;gap:40px;padding-block:40px;
  grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}
.mega h3{font-family:var(--fs);font-size:var(--t-xs);font-weight:600;
  text-transform:uppercase;letter-spacing:var(--tr-caps);
  color:var(--tinta-3);margin-bottom:14px}
.mega li + li{margin-top:9px}
.mega li a{font-size:var(--t-sm)}
/* display:block es necesario para que aspect-ratio tenga efecto: es un
   <a>, y aspect-ratio (como width/height) no aplica a un inline no
   reemplazado. Sin esto la foto cae a su proporción natural (retrato,
   ~310x501) en vez de 4:3 (~310x232), y como el grid estira la fila a
   la altura de la columna más alta, esa sola foto inflaba el panel
   entero a más de 580px de alto. */
.mega__foto{display:block;aspect-ratio:4/3;overflow:hidden;background:var(--fondo-2)}
.mega__foto img{width:100%;height:100%;object-fit:cover}

/* ── 3 · Buscador ───────────────────────────────────────────────────
   Baja desde arriba tapando la cinta y el header, como en Skinome.
   Los resultados son tarjetas de producto, no una lista: una fila de
   56 px estirada sobre 1400 px de ancho deja el panel medio vacío y se
   lee como que la búsqueda está rota. */
.buscador{position:fixed;inset:0 0 auto;z-index:90;
  max-height:100dvh;overflow-y:auto;overscroll-behavior:contain;
  background:var(--superficie);border-bottom:1px solid var(--borde-panel);
  transform:translateY(-100%);visibility:hidden;
  transition:transform .4s var(--e-drawer),visibility 0s linear .4s}
.buscador.abierto{transform:translateY(0);visibility:visible;transition-delay:0s}

.buscador__campo{display:flex;align-items:center;gap:14px;
  min-height:calc(var(--hdr) + var(--cinta-h));
  border-bottom:1px solid var(--borde)}
.buscador__lupa{flex:none;fill:none;color:var(--tinta-3)}
.buscador__campo input{flex:1;min-width:0;min-height:44px;border:0;background:none;
  font-family:var(--fs);font-size:var(--t-h3);letter-spacing:var(--tr-tight)}
.buscador__campo input:focus{outline:none}
/* La X nativa de Chrome en type=search choca con nuestro botón de
   cerrar: dos cruces pegadas, una que borra y otra que cierra. */
.buscador__campo input::-webkit-search-cancel-button{-webkit-appearance:none}

.buscador__cuerpo{padding:clamp(24px,3vw,40px) 0 clamp(32px,4vw,56px)}
.buscador__meta{margin-bottom:16px;color:var(--tinta-3);font-size:var(--t-sm)}
.buscador__sug .chips{gap:10px}
.buscador__vacio{color:var(--tinta-2);max-width:52ch}
.buscador__vacio a{text-decoration:underline;text-underline-offset:3px}

/* Una fila de tarjetas compactas. Sin descripción y con la foto
   cuadrada en vez de 3:4: en un desplegable lo que importa es
   reconocer el producto, no leerlo, y una tarjeta de 440 px de alto
   deja ver una sola fila por pantalla. */
.grilla--busq{grid-template-columns:repeat(2,1fr)}
@media(min-width:700px){.grilla--busq{grid-template-columns:repeat(3,1fr)}}
@media(min-width:1000px){.grilla--busq{grid-template-columns:repeat(5,1fr)}}
.grilla--busq .card__d,.grilla--busq .rapida{display:none}
.grilla--busq .card__foto{aspect-ratio:1}
.grilla--busq .card__t{font-size:var(--t-sm)}
.grilla--busq .card__p{margin-top:6px;font-size:var(--t-sm)}

/* ── 4 · Velo y cajón ───────────────────────────────────────────── */
/* El velo va por token y a opacidad plena: --velo-tinta ya trae su
   propio alfa y está afinado por tema. Con `#000` al 40% el cajón
   quedaba a 1.1:1 del fondo en oscuro — el panel desaparecía y el
   texto parecía flotar sobre la página. */
.velo{position:fixed;inset:0;z-index:85;background:var(--velo-tinta);
  opacity:0;visibility:hidden;
  transition:opacity .4s ease,visibility 0s linear .4s}
.velo.visible{opacity:1;visibility:visible;transition-delay:0s}

.cajon{position:fixed;top:0;right:0;z-index:95;
  width:min(420px,100vw);height:100dvh;
  display:flex;flex-direction:column;
  /* --superficie y no --fondo: el panel tiene que despegarse de la
     página que quedó atrás del velo. En oscuro, con --fondo eran el
     mismo color exacto y el cajón no se leía como panel. */
  background:var(--superficie);border-left:1px solid var(--borde-panel);
  transform:translateX(100%);visibility:hidden;
  transition:transform .45s var(--e-drawer),visibility 0s linear .45s}
.cajon.abierto{transform:translateX(0);visibility:visible;transition-delay:0s}
.cajon--izq{right:auto;left:0;border-left:0;border-right:1px solid var(--borde);
  transform:translateX(-100%)}
.cajon__cab{display:flex;align-items:center;justify-content:space-between;
  padding:20px var(--gutter);border-bottom:1px solid var(--borde)}
.cajon__cab h2{font-family:var(--fs);font-size:var(--t-sm);font-weight:600;
  text-transform:uppercase;letter-spacing:var(--tr-caps)}
.cajon__cuerpo{flex:1;overflow:auto;padding:20px var(--gutter)}
.cajon__pie{padding:20px var(--gutter);border-top:1px solid var(--borde)}

.linea-cart{display:flex;gap:14px;padding-block:16px}
.linea-cart + .linea-cart{border-top:1px solid var(--borde)}
.linea-cart img,.linea-cart .ph{width:72px;height:94px;object-fit:cover;flex:none;
  background:var(--fondo-2)}
.linea-cart b{font-family:var(--fs);font-weight:500;font-size:var(--t-base)}
.linea-cart small{display:block;color:var(--tinta-3);font-size:var(--t-sm)}
.cant{display:inline-flex;align-items:center;gap:12px;margin-top:8px;
  border:1px solid var(--borde);border-radius:var(--radio)}
.cant button{width:28px;height:28px;line-height:1;color:var(--tinta-2)}
.cant button:hover{color:var(--tinta)}
.total{display:flex;justify-content:space-between;align-items:baseline;
  font-family:var(--fs);font-weight:600;margin-bottom:16px}

/* ── Código de descuento en el carrito ────────────────────────────
   Construido una sola vez por js/carrito.js (construirDescuentoUI),
   no en cada pintar() — así no se pierde lo que la persona está
   tipeando cuando cambia una cantidad y el carrito se repinta. */
.cart-descuento{margin-bottom:16px}
.cart-descuento__form .ft__campo--sm{margin-top:0;gap:8px}
.cart-descuento__form .ft__campo--sm input{min-height:40px;font-size:var(--t-sm)}
/* .ft__campo de base.css está pensado para el footer OSCURO (borde y
   texto en crema, casi invisibles acá). El cajón del carrito es claro,
   mismo problema y misma solución que .salida más abajo en este
   archivo. */
.cart-descuento__form input{border-color:var(--borde);color:var(--tinta);background:transparent}
.cart-descuento__form input::placeholder{color:var(--tinta-3)}
.cart-descuento__form input:focus{border-color:var(--oliva)}
.cart-descuento__form input[aria-invalid="true"]{border-color:var(--err)}
.cart-descuento__desglose{margin-bottom:12px}
.cart-descuento__linea{display:flex;justify-content:space-between;
  font-size:var(--t-sm);color:var(--tinta-2);padding-block:3px}
.cart-descuento__linea--ok{color:var(--ok);font-weight:600}
.cart-descuento__aplicado{display:flex;align-items:center;justify-content:space-between;
  gap:12px;padding:10px 12px;margin-bottom:12px;
  background:var(--fondo-2);border:1px solid var(--borde);border-radius:var(--radio);
  font-size:var(--t-sm)}
.cart-descuento__aplicado span{color:var(--ok);font-weight:600}
.cart-descuento__quitar{color:var(--tinta-3);text-decoration:underline;
  text-underline-offset:2px;flex:none}
.cart-descuento__quitar:hover{color:var(--tinta)}
.cart-descuento .ft__aviso{margin-top:6px;font-size:var(--t-sm);text-align:left}
/* Igual que .salida más abajo: .ft__aviso de base.css está pensado
   para el footer OSCURO (--err-cl es un rosa pensado para leerse
   sobre fondo oscuro). El cajón del carrito es claro. */
.cart-descuento .ft__aviso[data-estado="error"]{color:var(--err)}

/* ── Cajón de dirección de envío ──────────────────────────────────
   Construido por js/envio.js (mismo patrón que el cajón de sesión de
   js/auth.js), no vive en las doce páginas. Reusa el primitivo .cajon
   de más arriba — mismo velo, transform y trampa de foco que el
   carrito y la sesión, cero CSS nuevo para eso. */
.envio-intro{color:var(--tinta-2);font-size:var(--t-sm);margin-bottom:20px}
.envio-form{display:flex;flex-direction:column;gap:16px}
.envio-campo{display:flex;flex-direction:column;gap:6px}
.envio-campo label{font-family:var(--fs);font-size:var(--t-xs);font-weight:600;
  letter-spacing:.04em;text-transform:uppercase;color:var(--tinta-3)}
.envio-campo input,.envio-campo select,.envio-campo textarea{
  min-height:44px;padding:0 14px;background:transparent;
  border:1px solid var(--borde);border-radius:var(--radio);
  color:var(--tinta);font-family:var(--fb);font-size:var(--t-base)}
.envio-campo textarea{min-height:64px;padding:10px 14px;resize:vertical}
.envio-campo input:focus,.envio-campo select:focus,.envio-campo textarea:focus{
  outline:none;border-color:var(--oliva)}
.envio-campo input[aria-invalid="true"],.envio-campo select[aria-invalid="true"]{border-color:var(--err)}
.envio-fila{display:grid;grid-template-columns:1fr 140px;gap:12px}
.envio-form .ft__aviso{text-align:left;color:var(--tinta-2)}
.envio-form .ft__aviso[data-estado="error"]{color:var(--err)}

/* Navegación móvil, misma mecánica de cajón */
.movil li{border-bottom:1px solid var(--borde)}
.movil a,.movil > li > button{display:flex;width:100%;
  align-items:center;justify-content:space-between;padding:16px 0;
  font-family:var(--fs);font-size:var(--t-sm);font-weight:500;
  text-transform:uppercase;letter-spacing:.1em}
.movil ul{display:none;padding-bottom:12px}
.movil li.abierto > ul{display:block}
.movil ul a{padding:9px 0;text-transform:none;letter-spacing:0;
  font-family:var(--fb);color:var(--tinta-2)}

/* ── 5 · Tarjeta de producto ────────────────────────────────────────
   El cruce de imágenes es el hover de Skinome: la segunda foto está
   siempre en el DOM, apilada, y sólo cambia de opacidad. Si un
   producto todavía no tiene su foto de textura, .card__foto queda
   sin segunda <img> y el hover simplemente no ocurre. */
.card{display:flex;flex-direction:column;height:100%}
/* .rapida se posiciona contra .card__media, no contra .card: contra
   .card el bottom:12px caía cerca del final de la tarjeta entera y el
   botón quedaba flotando arriba de la descripción, no sobre la foto. */
.card__media{position:relative}
/* display:block es necesario: .card__foto es un <a>, inline por
   default. Cuando era hija directa de .card (flex, column) el stretch
   de los items de flex la estiraba igual y esto no se notaba; ahora
   que cuelga de .card__media (un div común) una <a> inline colapsa al
   tamaño de su contenido en vez de ocupar el ancho de la tarjeta. */
.card__foto{display:block;position:relative;aspect-ratio:3/4;overflow:hidden;
  background:var(--fondo-2)}
.card__foto img,.card__foto .ph{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover}

/* Tres de los diecisiete todavía no tienen foto. Un <img> con src vacío
   pinta el ícono de imagen rota, que se lee como error del sitio; un
   degradé de marca se lee como una foto que falta. */
.ph{display:block;background:
  radial-gradient(120% 100% at 30% 15%,var(--salvia) 0%,transparent 60%),
  linear-gradient(150deg,var(--fondo-2) 0%,var(--borde) 100%)}
/* El cruce de fotos al pasar el mouse. Se selecciona por clase y no por
   `img + img`: las fotos son <picture>, así que las dos <img> ya no son
   hermanas entre sí. Durante meses esta regla no se activó nunca porque
   hover_path era null en los diecisiete productos. */
.card__foto .card__hover{opacity:0;transition:opacity .55s ease}
.card:hover .card__foto .card__hover,
.card:focus-within .card__foto .card__hover{opacity:1}

/* ── Mientras carga la foto ──────────────────────────────────────────
   El hueco ya está reservado por el aspect-ratio de arriba, así que
   nunca hay salto; lo que faltaba era decir que algo está viniendo.
   Un brillo que recorre el hueco beige, y la foto entrando con un
   fundido corto cuando llega.

   .cargando lo pone js/ui.js y lo saca al cargar la imagen. El estado
   por defecto es "visible": si el JS no corre, las fotos se ven igual.
   Sólo la PRIMERA imagen se atenúa — la segunda es la de hover y su
   opacidad ya la maneja la regla de arriba. */
.card__foto img:not(.card__hover){transition:opacity .4s ease}
.card__foto.cargando img:not(.card__hover){opacity:0}
.card__foto.cargando{
  background-image:linear-gradient(100deg,
    transparent 22%,var(--brillo) 45%,transparent 68%);
  background-size:220% 100%;
  animation:brillo 1.3s ease-in-out infinite}

@keyframes brillo{
  from{background-position:160% 0}
  to{background-position:-60% 0}
}

@media (prefers-reduced-motion:reduce){
  .card__foto.cargando{animation:none;background-image:none}
  .card__foto.cargando img:first-of-type{opacity:1}
  .card__foto img:first-of-type{transition:none}
}

.badge{position:absolute;top:12px;left:12px;z-index:2;
  padding:5px 10px;background:var(--crema);
  border:1px solid var(--oro);border-radius:var(--radio);
  font-family:var(--fs);font-size:10px;font-weight:600;
  text-transform:uppercase;letter-spacing:var(--tr-caps);
  /* Oliva explícito, no --tinta: el badge es SIEMPRE una pastilla
     crema con filete de oro, en los dos temas. Con --tinta quedaba
     crema sobre crema en oscuro (1:1, invisible). */
  color:var(--oliva)}

/* El botón de compra rápida entra desde abajo al pasar el mouse.
   En táctil no hay hover, así que ahí queda visible siempre. */
.rapida{position:absolute;left:12px;right:12px;bottom:12px;z-index:2;
  opacity:0;transform:translateY(8px);
  transition:opacity .3s ease,transform .3s var(--e-expo)}
.card:hover .rapida,.card:focus-within .rapida{opacity:1;transform:none}
@media(hover:none){.rapida{opacity:1;transform:none}}

.card__cuerpo{padding-top:16px}
.card__t{font-family:var(--fs);font-weight:500;font-size:var(--t-base);
  line-height:1.3}
.card__d{color:var(--tinta-2);font-size:var(--t-sm);margin-top:6px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden}
.card__p{margin-top:10px}
.card__f{color:var(--tinta-3);font-size:var(--t-sm)}

/* ── 6 · Carrusel ───────────────────────────────────────────────────
   scroll-snap hace el trabajo de Flickity. El arrastre con el mouse
   lo agrega js/carrusel.js; con dedo y con rueda ya funciona solo. */
.carr{position:relative}
/* Flex y no grid: con overflow-x, un flex-basis en porcentaje se
   resuelve contra el ancho visible del carril, que es justo lo que hace
   falta para mostrar cuatro por pantalla. grid-auto-columns con calc()
   lo resuelve contra otra cosa y las columnas salen mal. */
/* overflow-y:hidden explícito, no implícito. Si sólo se declara
   overflow-x, la spec promueve overflow-y a auto por debajo, y el
   carril queda como blanco válido de scroll vertical: la rueda o el
   trackpad quedaban atrapados ahí y la página no seguía bajando. */
.carr__pista{display:flex;gap:16px;
  overflow-x:auto;overflow-y:hidden;scroll-snap-type:x mandatory;
  /* overscroll-behavior-y explícito en auto (su valor por defecto), no
     por omisión: -x en contain ya evita que un arrastre horizontal
     "pise" la página cuando llega al final del carril; -y en auto dice
     lo contrario a propósito — que la rueda vertical SIGA de largo
     hacia la página en vez de quedar contenida acá, que es justo lo
     que el wheel de más abajo necesita para poder reenviarla.

     touch-action es al dedo lo que overscroll-behavior es a la rueda,
     pero con el eje invertido: acá hay que decir qué eje SÍ maneja el
     navegador de forma nativa, no cuál rebota. pan-y (el valor viejo)
     le decía al navegador que este carril se paneaba verticalmente y
     dejaba el eje horizontal sin dueño — de ahí que un swipe lateral no
     moviera el carril y sólo quedara el :active de la tarjeta, que se
     ve como si el dedo únicamente cambiara la foto. pan-x es lo
     correcto: el navegador scrollea el carril con el dedo en horizontal
     y deja que el gesto vertical siga de largo hacia la página. */
  overscroll-behavior-x:contain;overscroll-behavior-y:auto;touch-action:pan-x;
  scrollbar-width:none;padding-bottom:4px}
.carr__pista::-webkit-scrollbar{display:none}
.carr__pista > *{flex:0 0 72vw;scroll-snap-align:start}
.carr__pista.arrastrando{scroll-snap-type:none;cursor:grabbing;
  user-select:none}
@media(min-width:640px){.carr__pista > *{flex-basis:38vw}}
@media(min-width:1024px){
  .carr__pista{gap:20px}
  .carr__pista > *{flex-basis:calc((100% - 3*20px)/4)}
}

.carr__btn{display:none;position:absolute;top:calc(50% - 60px);z-index:3;
  width:44px;height:44px;border-radius:50%;
  background:var(--fondo);border:1px solid var(--borde);
  place-items:center;transition:border-color .2s ease,opacity .2s ease}
.carr__btn:hover{border-color:var(--tinta)}
.carr__btn[disabled]{opacity:0;pointer-events:none}
.carr__btn svg{width:16px;height:16px;fill:currentColor}
.carr__btn--prev{left:-14px}
.carr__btn--next{right:-14px}
@media(min-width:1024px){.carr__btn{display:grid}}

/* ── 7 · Solapas ────────────────────────────────────────────────── */
.solapas{display:flex;gap:28px;justify-content:center;flex-wrap:wrap;
  margin-bottom:clamp(28px,4vw,52px)}
/* padding-block, no sólo abajo: 25 px de alto es un objetivo táctil
   incómodo, y las solapas son el control principal de la sección. */
.solapa{font-family:var(--fs);font-size:var(--t-sm);font-weight:600;
  text-transform:uppercase;letter-spacing:var(--tr-caps);
  color:var(--tinta-3);padding:10px 2px;transition:color .25s ease}
.solapa::after{bottom:4px}
.solapa[aria-selected="true"]{color:var(--tinta)}
.solapa[aria-selected="true"]::after{transform:scaleX(1)}
.panel[hidden]{display:none}

/* ── 8 · Banners a sangre ───────────────────────────────────────── */
.banner{position:relative;isolation:isolate;overflow:hidden;
  min-height:clamp(440px,64vh,720px);display:flex;align-items:end;
  color:var(--crema)}
.banner__bg{position:absolute;inset:0;z-index:-2}
.banner__bg img,.banner__bg video{width:100%;height:100%;object-fit:cover}
/* El degradé existe para que el texto tenga contraste real sobre
   cualquier foto, no como efecto. Las fotos de Verde Oliva son claras
   y contraluz: con un velo suave el titular queda al borde de lo
   legible, así que el velo es más denso y sube más alto de lo que se
   vería necesario mirando una sola foto. */
.banner::after{content:'';position:absolute;inset:0;z-index:-1;
  background:linear-gradient(to top,rgba(24,22,20,.78) 0%,
             rgba(24,22,20,.55) 38%,rgba(24,22,20,.18) 72%,
             rgba(24,22,20,.06) 100%)}
/* Mismo motivo que .hero2 > .wrap, y mismo arreglo: el .wrap es hijo
   de un contenedor flex, así que se achica a su contenido y el
   margin-inline:auto que trae lo centra entero en vez de dejarlo
   pegado al gutter. Por eso el tope de ancho vive en .banner__in,
   que es un div ADENTRO del wrap — si estuviera sobre el wrap
   mismo, volvería a centrarse. */
.banner > .wrap{width:100%}
.banner__in{padding-block:clamp(40px,7vh,88px);max-width:640px}
.banner__in .lead{color:var(--crema-2)}
.banner--centro .banner__in{max-width:720px;margin-inline:auto}
.banner--centro .lead{margin-inline:auto}

/* ── 8b · Banner en claro ───────────────────────────────────────────
   La variante para fotos de producto sobre fondo crema, donde el
   velo oscuro de .banner sería un despropósito: taparía justo la
   superficie clara que hace que la botella se lea.

   Todo lo que cambia respecto de .banner es la polaridad. El velo se
   invierte dos veces: de oscuro a claro, y de vertical a horizontal
   —de abajo-hacia-arriba (texto apoyado abajo) a izquierda-hacia-
   derecha (texto apoyado a la izquierda)—. Es el mismo mecanismo que
   .hero2::after, que ya resuelve exactamente este problema con la
   foto del Arauco, sólo que en claro.

   Por qué hace falta un velo si la foto YA es clara: en desktop no
   hace casi nada y se nota poco. El que lo necesita es el celular:
   con object-fit:cover y la pantalla angosta, el recorte corre la
   botella hacia el centro y el texto le puede quedar encima. El velo
   garantiza el contraste ahí sin lavar la foto en desktop, que es lo
   que pasaría con una capa pareja.

   color-mix en vez de un rgba() literal: el color sale del token, no
   de un hex suelto — tokens.css es el único archivo que declara
   colores literales y esa regla se mantiene. */
/* La sección toma la proporción de la foto en vez de un alto fijo.
   Con el min-height heredado de .banner (64vh = ~500px a 1440 de
   ancho) la caja quedaba en 2.89:1 contra los 1.79:1 de la foto, y
   cover se comía el 38% del alto: la botella perdía la tapa y la
   base de un saque. La foto ES el diseño de este bloque, así que
   manda ella y el alto sale de su relación de aspecto.

   El min-height de .banner sigue actuando como piso en pantallas
   angostas, donde la proporción daría una franja demasiado baja.

   La foto original venía a 2752x1536 (1.79:1) con la botella
   ocupando el 91% del alto — medido, no estimado. Con esa proporción
   la sección quedaba en 804px a 1440 de ancho: más alta que la
   ventana. Y recortarla no era opción: el ratio más ancho que deja
   la botella entera es 1.84, así que cualquier franja baja le cortaba
   la tapa y la base. Se ensanchó el LIENZO en su lugar (800px de
   fondo a la izquierda, 250 a la derecha, espejando el fondo plano)
   hasta 3802x1536. La botella quedó intacta y en el 69% del ancho,
   y la sección bajó a 581px. */
.banner--claro{color:var(--tinta);align-items:center;
  aspect-ratio:3802/1536;min-height:0}
/* Los dos valores de arriba se eligieron juntos y ninguno sobra:

   El clamp(440px,64vh,720px) que .banner hereda TIENE que salir de
   acá: un min-height en píxeles pelea con el aspect-ratio y el
   navegador termina sacando el ANCHO del alto en vez de al revés —
   a 390px de ventana la sección medía 1337px y desbordaba la página.

   Pero dejarlo en 0 tampoco sirve: entre 900 y 1000px de ancho la
   proporción da una franja más baja que el texto, y como .banner es
   overflow:hidden el botón quedaba cortado (medido: a 910px la
   sección daba 368px y el texto pedía 373).

   min-height:fit-content parecía el arreglo elegante para las dos
   cosas a la vez, pero se probó y no funciona: en un contenedor flex
   no levanta el piso y el texto se seguía cortando. Se resuelve con
   lo aburrido y verificable — el modo superpuesto empieza recién a
   los 1024px, donde la proporción ya da alto de sobra, y el padding
   vertical de esta variante es más corto que el de .banner para
   ensanchar todavía más ese margen. */
.banner--claro .banner__in{padding-block:clamp(24px,4vh,64px)}

/* Bajo 1024px la proporción de la foto da una franja más baja que el
   texto (medido: a 910px la sección daba 368px y el texto pedía 373,
   y .banner es overflow:hidden, así que el botón quedaba cortado). No
   entra el texto, y con la foto de fondo el titular termina encima de
   la botella (el velo no llega hasta ahí sin lavar la foto entera).
   Así que abajo de ese ancho se apila: la foto arriba en 4:3, corrida
   al 66% para que la botella quede centrada en su recorte, y el texto
   debajo sobre fondo sólido, donde el contraste no depende de qué
   píxel de la foto le tocó atrás. */
@media(max-width:1023px){
  .banner--claro{display:block;aspect-ratio:auto;background:var(--fondo)}
  .banner--claro::after{content:none}
  .banner--claro .banner__bg{position:static;aspect-ratio:4/3}
  .banner--claro .banner__bg img{object-position:66% 50%}
  .banner--claro .banner__in{max-width:none;padding-block:clamp(28px,6vw,44px)}
}
.banner--claro::after{
  background:linear-gradient(90deg,
    color-mix(in srgb,var(--fondo) 88%,transparent) 0%,
    color-mix(in srgb,var(--fondo) 64%,transparent) 34%,
    color-mix(in srgb,var(--fondo) 20%,transparent) 54%,
    transparent 70%)}
/* --hoja-t es el único verde que brand/04 habilita como texto: el
   Hoja #6B7B3C no llega a contraste de cuerpo y el Oro nunca es
   texto, sólo filete. */
.banner--claro .kicker{color:var(--hoja-t)}
.banner--claro .lead{color:var(--tinta-2)}
.banner--claro .banner__in{max-width:520px}

/* El titular va en serif, no en Space Grotesk como el resto de los
   .d2: es la misma excepción que ya hace .hero2__h1, y por el mismo
   motivo — los dos son bloques a sangre con foto donde el título
   hace de portada, no de rótulo de sección. Fraunces ya está cargada
   por el hero, así que no suma una tipografía más. */
.banner__h{font-family:'Fraunces',Georgia,'Times New Roman',serif;
  font-weight:500;font-optical-sizing:auto;font-variation-settings:'opsz' 72;
  font-size:var(--t-h2);line-height:1.14;letter-spacing:-.005em;
  margin:14px 0 0;text-wrap:balance}
/* Filete de oro entre el título y el cuerpo. Uso conforme: es un
   filete de 1px, no texto. */
.banner__filete{display:block;width:56px;height:1px;background:var(--oro);
  margin:26px 0}
/* El <span> intermedio existe por el motor de animación, igual que en
   finca.html: image-in recorta el contenedor y desplaza a su HIJO
   DIRECTO, y <picture> es display:contents, o sea que no es una caja
   que se pueda mover. El span sí. */
.banner__bg-in{display:block;width:100%;height:100%}

/* El Arauco: foto fija y clara (no video), texto a la izquierda.
   isolation:isolate + overflow:hidden por la misma razón que .banner:
   contener el ::after del velo. */
/* 100svh exactos, y la foto a sangre hasta el borde del pliegue: es
   una decisión del cliente (28/08/2026), no un default heredado.

   Hubo una versión con «asomo» — el hero medía calc(100svh - 96px)
   para que asomara una franja beige de #eco por debajo de la foto y
   se viera que la página seguía. Se sacó: esa franja se leía como que
   la foto quedaba cortada, y la foto del Arauco es lo primero que
   representa a la marca. No reponerla sin preguntar.

   El costo de volver a 100svh es que la pista de scroll ahora depende
   toda de JS (el tirón de main.tiron y la guía .asomo-guia, las dos
   en js/asomo.js). Sin JS no queda ninguna señal de que hay más
   abajo — a cambio, la foto entra casi entera: con el hero a 100svh
   la relación de aspecto queda muy cerca de la de la foto (1.79) y
   cover casi no recorta, mientras que restándole el asomo el recorte
   vertical trepaba. */
.hero2{position:relative;isolation:isolate;overflow:hidden;
  min-height:100svh;display:flex;align-items:center}
/* object-position:55% 50% — hero-arauco.jpg tiene la botella y el
   frasco corridos a la derecha del centro, no en el medio. Con cover
   y el 50% 50% por defecto, en un celular angosto el recorte horizontal
   dejaba el producto casi afuera de cuadro. 55% alcanza para que se vea
   el pico y la etiqueta. Verificado a 390px y a 1440px. */
.hero2__bg{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:55% 50%;z-index:-2}
/* Velo direccional, no parejo: el mismo mecanismo que ya resuelve este
   problema en .banner y .finca-hero (degradé oscuro + texto --crema),
   girado 90° porque acá el texto vive a la izquierda, no abajo. Un
   velo parejo (rgba(247,244,236,.45) sobre todo el hero) se probó
   antes: garantizaba el contraste pero lavaba la foto de punta a
   punta, botella incluida. Este oscurece solo donde vive el texto y
   deja el producto, a la derecha, intacto. */
.hero2::after{content:'';position:absolute;inset:0;z-index:-1;
  background:linear-gradient(105deg,rgba(24,22,20,.76) 0%,
    rgba(24,22,20,.5) 30%,rgba(24,22,20,.16) 56%,rgba(24,22,20,0) 74%)}

/* ── <picture> transparente al layout ───────────────────────────────
   Al pasar las fotos a <picture> con srcset, el <picture> se mete como
   caja en línea entre el contenedor y el <img>, y rompe todo lo que
   dependía de que el <img> fuera hijo directo: .hero2__bg posicionado
   absoluto, .card__foto img+img para el cruce al pasar el mouse, y
   cualquier `> img` de la grilla.

   display:contents lo saca del layout sin sacarlo del DOM: el <img>
   vuelve a comportarse como hijo directo de su contenedor y ninguna
   regla anterior necesita cambiar. */
picture{display:contents}
/* Sin esto el .wrap de adentro, al ser hijo de un flex container, se
   achica a su contenido y el margin-inline:auto lo centra entero en
   vez de ocupar el ancho completo — el bloque de texto quedaba corrido
   al medio en vez de pegado al gutter izquierdo, como el resto del sitio. */
.hero2 > .wrap{width:100%}
.hero2__in{max-width:600px;margin-top:clamp(48px,8vh,100px)}
/* Bajo 768px el crop de hero-arauco.jpg queda mucho más cerrado que en
   desktop (misma foto, contenedor mucho más angosto y alto) y la
   botella entra bastante más a la izquierda del cuadro. Sin este tope
   el título en dos líneas la alcanzaba; 270px es lo que deja el borde
   de la botella libre a los anchos de mobile probados (ver el
   comentario de object-position, arriba). */
@media(max-width:768px){
  .hero2__in{max-width:270px}
}
.hero2 .kicker{color:var(--crema-2)}
.hero2 .lead{color:var(--crema-2)}
.hero2__h1{font-family:'Fraunces',Georgia,'Times New Roman',serif;
  font-weight:500;font-optical-sizing:auto;font-variation-settings:'opsz' 72;
  font-size:clamp(2.25rem,1.7rem + 2.4vw,3.5rem);line-height:1.12;
  letter-spacing:-.005em;color:var(--crema);margin-top:10px;text-wrap:balance}
.hero2__sellos{display:flex;gap:32px;margin-top:44px;flex-wrap:wrap}
.hero2__sellos li{display:flex;flex-direction:column;align-items:flex-start;gap:10px}
.hero2__sellos svg{width:26px;height:26px;color:var(--crema-2)}
.hero2__sellos span{font-family:var(--fs);font-size:11px;font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;color:var(--crema-2)}

/* ── La guía ────────────────────────────────────────────────
   Tercer intento. Los dos primeros (filete+gota, 2026-08-31) eran
   demasiado sutiles: uno leía como invisible, el retoque leía como un
   borrón. El cliente comparó seis alternativas en un artifact de
   comparación y pidió la combinación de "doble chevron" + "texto +
   flecha": un rótulo corto en mayúsculas y dos flechas cayendo en
   cascada debajo — más peso visual, sigue sin ser un bloque sólido de
   oro (brand/04: el oro es detalle, no texto ni relleno grande — acá
   el oro no aparece en absoluto, todo es crema sobre la foto).

   Va alineada al gutter izquierdo, debajo de los sellos, y no
   centrada abajo del hero como sería lo convencional — acá el hero
   es de texto alineado a la izquierda, y hero-arauco.jpg usa
   object-position:55% 50% porque la botella vive a la derecha del
   cuadro (ver el comentario más arriba, en .hero2__bg). Un indicador
   centrado en mobile le caería encima a la botella, justo la franja
   que el velo direccional dejó limpia a propósito.

   Es un <a href="#eco"> real: funciona sin JS, entra en el tab order,
   y el scroll-padding-top de base.css ya evita que el header fijo
   tape el destino al llegar. js/asomo.js sólo le agrega el scroll
   suave y la clase --ida cuando ya cumplió su función (el usuario
   scrolleó, o clickeó la guía misma). Los dos <span> del texto y los
   dos <i> de los chevrones son aria-hidden: el nombre accesible lo da
   el aria-label del enlace. */
.asomo-guia{display:flex;flex-direction:column;align-items:center;gap:10px;
  width:max-content;margin-top:32px;transition:opacity .4s ease}
.asomo-guia:focus-visible{outline:2px solid var(--crema);outline-offset:4px}
.asomo-guia__t{font-family:var(--fs);font-size:var(--t-xs);font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--crema)}
/* Área de toque real de 24px aunque los chevrones midan menos: el
   padding la completa sin agrandar el dibujo. */
.asomo-guia__chev{display:flex;flex-direction:column;align-items:center;
  gap:2px;padding-block:6px}
.asomo-guia__chev i{width:11px;height:11px;opacity:0;
  border-right:2px solid var(--crema);border-bottom:2px solid var(--crema);
  transform:rotate(45deg);
  animation:guiaChev 1.8s ease-in-out infinite}
.asomo-guia__chev i:last-child{animation-delay:.18s}
/* El !important no es pereza: .asomo-guia lleva data-aos="hero", y ese
   sistema le corre heroFade con animation-fill-mode:both. Una animación
   con fill retiene su estado final (opacity:1) por encima de cualquier
   declaración normal —así ordena la cascada—, así que un opacity:0 a
   secas acá no apaga nada y la guía se queda prendida para siempre. */
.asomo-guia--ida{opacity:0 !important;pointer-events:none}

/* ── 9 · Tarjeta de rutina ──────────────────────────────────────── */
.rutina{background:var(--superficie);border:1px solid var(--borde);
  display:flex;flex-direction:column;height:100%}
.rutina__fotos{position:relative;display:grid;grid-auto-flow:column;
  aspect-ratio:4/3;background:var(--fondo-2)}
.rutina__fotos img,.rutina__fotos .ph{width:100%;height:100%;object-fit:cover}
.rutina__cuerpo{padding:20px;display:flex;flex-direction:column;flex:1}
.rutina__pasos{margin:12px 0 20px;color:var(--tinta-2);font-size:var(--t-sm)}
.rutina__pasos li{padding-left:20px;position:relative}
.rutina__pasos li + li{margin-top:6px}
.rutina__pasos li::before{content:'';position:absolute;left:6px;top:.62em;
  width:4px;height:4px;border-radius:50%;background:var(--oro)}
.rutina__pie{margin-top:auto;display:flex;align-items:center;
  justify-content:space-between;gap:12px;padding-top:16px;
  border-top:1px solid var(--borde)}

/* La sección «Del ritual de» de la ficha reusa la tarjeta de rutina
   tal cual, en flujo normal en vez de carrusel: acá aparece como mucho
   una a la vez, salvo que un producto esté en más de un ritual. */
.ritual__grilla{display:grid;gap:24px;
  grid-template-columns:repeat(auto-fit,minmax(280px,1fr));max-width:900px}

/* ── 10 · Tarjeta editorial ─────────────────────────────────────── */
.edi{display:grid;gap:16px}
.edi__foto{aspect-ratio:3/4;overflow:hidden;background:var(--fondo-2)}
.edi__foto img{width:100%;height:100%;object-fit:cover}
/* .edi__cifra/.edi__n/.edi__nl vivían acá: el reemplazo tipográfico
   (1890 / 3 / 17) que ocupó el lugar de la foto mientras no hubo
   imágenes. Se borraron el 29/08/2026, cuando llegaron las tres fotos
   y el marcado volvió al <a class="edi__foto zoom"> de siempre. */
.grid3{display:grid;gap:clamp(20px,3vw,36px);
  grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}

/* ── 11 · Marquee de sellos ─────────────────────────────────────── */
.sellos .marquee__track > span{display:flex;align-items:center;gap:48px;
  padding-right:48px}
.sello{display:flex;align-items:center;gap:12px;font-style:normal;height:56px;
  padding:0 18px;border:1px solid var(--borde);border-radius:var(--radio);
  font-family:var(--fs);font-size:var(--t-xs);font-weight:600;
  text-transform:uppercase;letter-spacing:var(--tr-caps);
  color:var(--tinta-2);text-align:left;line-height:1.3;white-space:nowrap}
.sello svg{width:24px;height:24px;flex:none;color:var(--oliva)}
/* El texto del sello llevaba un <br> a mano para partirse en dos
   líneas. Se sacó porque rompía la traducción: el <br> deja «Libre de»
   y «gluten» como dos nodos de texto separados, y el motor de idioma
   busca la frase entera —nunca encontraba ni «Libre de gluten» ni el
   innerHTML, que además arrastra el <svg>. Ahora el corte lo hace el
   ancho, que además se adapta solo a un inglés más corto
   («Gluten free» entra en una línea). */
.sello__t{white-space:normal;max-width:12ch}

/* ── 12 · Acordeón ──────────────────────────────────────────────── */
.acc{border-top:1px solid var(--borde)}
.acc:last-of-type{border-bottom:1px solid var(--borde)}
.acc__b{display:flex;width:100%;align-items:center;justify-content:space-between;
  gap:16px;padding:18px 0;text-align:left;
  font-family:var(--fs);font-size:var(--t-base);font-weight:500}
.acc__b svg{width:14px;height:14px;flex:none;fill:currentColor;
  transition:transform .3s var(--e-expo)}
.acc__b[aria-expanded="true"] svg{transform:rotate(180deg)}
.acc__p{padding-bottom:20px;color:var(--tinta-2);max-width:64ch}
.acc__p[hidden]{display:none}

/* ═══════════════════════════════════════════════════════════════════
   CATÁLOGO
   ═══════════════════════════════════════════════════════════════════ */

/* Las páginas sin hero arrancan bajo un header ya relleno, así que el
   primer bloque tiene que reservar su alto más el de la cinta. */
.cat-cab,.ficha{padding-top:calc(var(--sect) + var(--hdr) + var(--cinta-h))}

.filtros{display:flex;flex-wrap:wrap;gap:clamp(20px,3vw,44px);
  align-items:flex-start;padding-bottom:20px;
  border-bottom:1px solid var(--borde)}
.filtros__t{display:block;margin-bottom:10px;
  font-family:var(--fs);font-size:var(--t-xs);font-weight:600;
  text-transform:uppercase;letter-spacing:var(--tr-caps);color:var(--tinta-3)}
/* A la derecha sólo cuando hay ancho: en móvil, margin-left:auto deja
   el grupo alineado a la derecha y los otros dos a la izquierda. */
@media(min-width:900px){.filtros__grupo--orden{margin-left:auto}}
.filtros__grupo--orden select{min-height:38px;padding:0 12px;
  background:var(--superficie);border:1px solid var(--borde);
  border-radius:var(--radio);font-size:var(--t-sm)}

.chips{display:flex;flex-wrap:wrap;gap:8px}
.chip{display:inline-flex;align-items:center;min-height:40px;
  padding:0 16px;border:1px solid var(--borde);border-radius:999px;
  background:var(--superficie);
  font-family:var(--fs);font-size:var(--t-sm);font-weight:500;
  color:var(--tinta-2);
  transition:border-color .2s ease,background .2s ease,color .2s ease}
.chip:hover{border-color:var(--borde-fuerte);color:var(--tinta)}
/* El filtro activo se marca con el relleno oliva y texto crema, que es
   la misma pareja verificada del CTA. */
.chip[aria-pressed="true"]{background:var(--oliva);border-color:var(--oliva);
  color:var(--crema)}

.cuenta{margin-top:16px;color:var(--tinta-3);font-size:var(--t-sm)}
.vacio{padding:clamp(40px,8vw,80px) 0;text-align:center;color:var(--tinta-2)}

.grilla{display:grid;gap:clamp(20px,2.4vw,32px);
  grid-template-columns:repeat(2,1fr)}
@media(min-width:768px){.grilla{grid-template-columns:repeat(3,1fr)}}
@media(min-width:1200px){.grilla{grid-template-columns:repeat(4,1fr)}}

/* Bloque de texto largo a dos columnas: el título queda arriba a la
   izquierda y el cuerpo corre a la derecha, como el texto de colección
   de Skinome. */
.dos-col{display:grid;gap:clamp(20px,4vw,64px)}
@media(min-width:900px){.dos-col{grid-template-columns:.8fr 1.2fr}}
.dos-col__texto > * + *{margin-top:18px}

/* ═══════════════════════════════════════════════════════════════════
   FICHA
   ═══════════════════════════════════════════════════════════════════ */
.ficha__in{display:grid;gap:clamp(28px,4vw,64px)}
@media(min-width:900px){.ficha__in{grid-template-columns:.8fr 1.2fr;align-items:start}}

.ficha__foto{aspect-ratio:3/4;overflow:hidden;background:var(--fondo-2)}
.ficha__foto img,.ficha__foto .ph{width:100%;height:100%;object-fit:cover}
/* La galería queda fija mientras se lee la columna de la derecha. El
   offset es el header más la cinta, si no la foto se pega debajo de la
   barra y queda cortada. */
@media(min-width:900px){
  .ficha__gal{position:sticky;top:calc(var(--hdr) + var(--cinta-h) + 20px)}
}

/* Sólo aparecen cuando hay una segunda foto real (hover_path). Hoy
   ninguno de los 17 productos la tiene todavía. */
.ficha__minis{display:flex;gap:10px;margin-top:10px}
.ficha__mini{width:64px;aspect-ratio:1;padding:0;overflow:hidden;
  border:1px solid var(--borde);background:none;cursor:pointer}
.ficha__mini img{width:100%;height:100%;object-fit:cover;display:block}
.ficha__mini--activa{border-color:var(--tinta)}

.ficha__precio{margin:22px 0 20px;font-size:var(--t-lead)}

/* Mismo bullet que ya usa .rutina__pasos: sellos reales, no un ícono
   nuevo por cada uno. */
.ficha__claims{display:flex;flex-wrap:wrap;gap:10px 20px;margin-bottom:20px}
.ficha__claims li{padding-left:16px;position:relative;
  font-size:var(--t-sm);color:var(--tinta-2)}
.ficha__claims li::before{content:'';position:absolute;left:0;top:.55em;
  width:4px;height:4px;border-radius:50%;background:var(--oro)}

.ficha__cta{width:100%}

/* Fila de confianza: pastillas con ícono, mismo look que .chip pero sin
   estado interactivo de filtro. */
.ficha__confianza{margin-top:14px}
.ficha__confianza-fila{display:flex;flex-wrap:wrap;gap:8px}
.ficha__confianza-i{display:inline-flex;align-items:center;gap:6px;
  padding:6px 12px;border:1px solid var(--borde);border-radius:999px;
  background:var(--superficie);font-size:var(--t-sm);color:var(--tinta-2);
  text-decoration:none;transition:border-color .2s ease,color .2s ease}
.ficha__confianza-i svg{width:15px;height:15px;flex:none}
.ficha__confianza-i:hover{border-color:var(--borde-fuerte);color:var(--tinta)}
.ficha__confianza-nota{margin-top:10px;font-size:var(--t-sm);color:var(--tinta-3)}

.ficha__datos{margin-top:28px;padding-top:20px;border-top:1px solid var(--borde)}
.ficha__datos > div{display:flex;gap:16px;padding:7px 0}
.ficha__datos dt{flex:0 0 88px;color:var(--tinta-3);font-size:var(--t-sm)}
.ficha__datos dd{margin:0;font-size:var(--t-sm)}

.ficha__combo{margin-top:20px;padding-top:20px;border-top:1px solid var(--borde)}
.ficha__combo-card{display:flex;align-items:center;gap:14px;margin-bottom:14px}
.ficha__combo-foto{width:64px;aspect-ratio:1;flex:none;overflow:hidden;background:var(--fondo-2)}
.ficha__combo-foto img,.ficha__combo-foto .ph{width:100%;height:100%;object-fit:cover}
.ficha__combo-nombre{font-size:var(--t-sm);font-weight:500}
.ficha__combo-precio{margin-top:2px;font-size:var(--t-sm);color:var(--tinta-3)}
.ficha__combo-btn{width:100%}

/* Expandido, nunca en solapas: es regla de brand/07. */
.uso{display:grid;gap:clamp(20px,2.6vw,36px);margin-top:clamp(24px,3vw,40px);
  grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
.uso__t{font-family:var(--fs);font-size:var(--t-xs);font-weight:600;
  text-transform:uppercase;letter-spacing:var(--tr-caps);
  color:var(--tinta-3);margin-bottom:10px}

.uso__b p{color:var(--tinta-2);max-width:46ch}


/* ═══ ANTES DE IRTE ══════════════════════════════════════════════════
   Diálogo de salida. Lo crea js/ui.js y sólo aparece en desktop, una
   vez por sesión. Desde 2026-08-31 SÍ es un descuento real (10%, ver
   el comentario largo en ui.js) — antes era solo una invitación al
   newsletter, sin oferta.

   Ojo con el formulario: reusa .ft__campo y .ft__aviso, que están
   pensados para el footer OSCURO. Acá el fondo es claro, así que hay
   que devolverles los colores de texto sobre claro — si no, el aviso
   sale color crema sobre crema y no se lee.
   ═══════════════════════════════════════════════════════════════════ */
.salida{position:fixed;inset:0;z-index:120;
  display:flex;align-items:center;justify-content:center;padding:20px}
/* El `display:flex` de arriba anularía el atributo `hidden` que le
   pone js/ui.js — lo cubre la regla global `[hidden]` de base.css.
   Ver el comentario largo ahí: es la razón por la que existe. */
.salida__velo{position:absolute;inset:0;background:var(--velo-tinta);
  opacity:0;transition:opacity .3s ease}
.salida--abierta .salida__velo{opacity:1}
.salida__caja{position:relative;width:min(440px,100%);
  padding:clamp(28px,4vw,40px);
  background:var(--superficie);border:1px solid var(--borde-panel);
  border-radius:var(--radio);box-shadow:0 20px 60px var(--sombra-flota-fuerte);
  opacity:0;transform:translateY(14px) scale(.98);
  transition:opacity .3s ease,transform .3s var(--e-drawer)}
.salida--abierta .salida__caja{opacity:1;transform:none}
.salida__x{position:absolute;top:10px;right:10px}
.salida__caja .d3{margin:10px 0 12px}
.salida__p{color:var(--tinta-2)}
.salida__form{margin-top:22px}

/* Devolverle al formulario los colores de fondo claro. */
.salida .ft__campo{margin-top:0}
.salida .ft__campo input{border-color:var(--borde);color:var(--tinta)}
.salida .ft__campo input::placeholder{color:var(--tinta-3)}
.salida .ft__campo input:focus{border-color:var(--oliva)}
.salida .ft__campo input[aria-invalid="true"]{border-color:var(--err)}
.salida .ft__aviso{text-align:left;color:var(--tinta-2)}
.salida .ft__aviso[data-estado="error"]{color:var(--err)}
.salida .ft__aviso[data-estado="ok"]{color:var(--ok)}

/* Panel de éxito: reemplaza al form (ver ui.js, descuentoForm) cuando
   ya se generó el código. --tr-tight/tabular-nums porque es un valor
   que cambia cada segundo — sin tabular-nums el ancho de la cuenta
   regresiva baila con cada dígito. */
.salida__codigo{margin-top:22px;padding:16px;text-align:center;
  background:var(--fondo-2);border:1px solid var(--oro);border-radius:var(--radio);
  font-family:var(--fs);font-size:var(--t-lead);font-weight:600;
  letter-spacing:.12em;color:var(--tinta)}
.salida__vence{margin-top:10px;text-align:center;color:var(--tinta-2)}
.salida__vence span{font-variant-numeric:tabular-nums;font-weight:600;color:var(--tinta)}
.salida .salida__exito .ft__aviso{margin-top:10px;color:var(--tinta-3)}

@media (prefers-reduced-motion:reduce){
  .salida__velo,.salida__caja{transition:none}
  .salida__caja{transform:none}
}


/* ═══ 404 ════════════════════════════════════════════════════════════
   El header es fijo y transparente sobre el hero en las otras páginas;
   acá no hay hero, así que el contenido arranca despejado del header.
   ═══════════════════════════════════════════════════════════════════ */
.e404{padding-top:calc(var(--hdr) + var(--sect))}
.e404__in{max-width:640px}
.e404__t{margin:10px 0 18px;font-size:var(--t-h1)}
.e404__acc{display:flex;flex-wrap:wrap;gap:12px;margin-top:32px}
.e404__necesidad{margin-top:clamp(40px,5vw,64px);
  padding-top:clamp(28px,3vw,40px);border-top:1px solid var(--borde)}
.e404__necesidad .chips{margin-top:14px}

/* ── Resultado del pago ─────────────────────────────────────────────
   Mismo layout que el 404 —una columna angosta, centrada arriba— y por
   la misma razón: son páginas a las que se llega sin querer o de paso,
   donde lo único que importa es entender qué pasó y tener una salida.
   El padding-top compensa el header fijo igual que .e404. */
.pago{padding-top:calc(var(--hdr) + var(--sect))}
.pago__in{max-width:640px}
.pago__t{margin:10px 0 18px;font-size:var(--t-h1)}
.pago__acc{display:flex;flex-wrap:wrap;gap:12px;margin-top:32px}
.pago__ref{margin-top:24px;padding:14px 18px;
  background:var(--fondo-2);border-left:2px solid var(--oro);
  font-size:var(--t-sm);color:var(--tinta-2)}
.pago__ref strong{color:var(--tinta);font-variant-numeric:tabular-nums}

/* ── Páginas legales e informativas ─────────────────────────────────
   terminos, privacidad, envios, devoluciones. Una sola columna angosta
   y medida en ch, no en px: lo que hace legible un texto largo es
   cuántos caracteres entran por renglón, no cuántos píxeles mide.

   El h2 va en tamaño de cuerpo con peso, no como título de sección del
   resto del sitio: son trece numerales seguidos, y con versalitas
   grandes la página se lee como un índice en vez de como un texto. */
.legal{padding-top:calc(var(--hdr) + var(--sect))}
.legal__in{max-width:100%}
.legal__t{margin:10px 0 10px}
.legal__fecha{font-size:var(--t-sm);color:var(--tinta-2);margin-bottom:40px}
.legal__cuerpo{max-width:68ch}
.legal__cuerpo>.lead{margin-bottom:40px}
.legal__cuerpo section+section{margin-top:32px}
.legal__cuerpo h2{font-size:1rem;font-weight:600;margin-bottom:10px;
  font-family:var(--fb)}
.legal__cuerpo p+p{margin-top:14px}
.legal__cuerpo ul{margin-top:12px;display:grid;gap:10px}
/* La lista sí lleva viñeta: son ítems sueltos, no navegación, y sin
   marca se leen como párrafos partidos. El reset global las saca. */
.legal__cuerpo li{padding-left:18px;position:relative}
.legal__cuerpo li::before{content:"";position:absolute;left:0;top:.62em;
  width:5px;height:5px;border-radius:50%;background:var(--oro)}
.legal__cuerpo a{color:var(--hoja-t);text-decoration:underline;
  text-underline-offset:2px;text-decoration-color:var(--oro)}
.legal__cuerpo a:hover{color:var(--tinta)}

/* ── Olivoterapia · página editorial ────────────────────────────────
   Encabezado de texto, sin foto: es una pieza educativa, no el retrato
   de un lugar. La finca sí tiene el suyo, a sangre, más abajo. */
.olivo__hero{padding-top:calc(var(--hdr) + var(--sect));padding-bottom:0}
.olivo__t{margin-top:10px}
.olivo__bajada{margin-top:18px;max-width:34ch}
.finca__col,.olivo__col{max-width:62ch;
  /* margin-inline:0 porque estas clases van sobre el mismo nodo que
     .wrap, que se autocentra: sin esto la columna angosta quedaba
     centrada en la pantalla y no alineada con su propio título. */
  margin-inline:0}
.finca__h,.olivo__h{margin:10px 0 22px}
.finca__col .lead+.lead,.olivo__col p+p{margin-top:16px}
.finca__acc,.olivo__acc{display:flex;flex-wrap:wrap;gap:12px;margin-top:32px}


/* ═══ LA FINCA ═══════════════════════════════════════════════════════
   La página del lugar. No hay fotografía del olivar: lo que hay son
   dos fotos de marca y catorce de producto, y las de producto llevan
   la etiqueta mal escrita (ver analisis-imagenes-productos.md), así
   que no se pueden mostrar en grande. De ahí la regla de esta página:
   las fotos que existen se usan donde el texto las reclama, y todo lo
   demás se DIBUJA — mismo trazo de 1,4 px del set de íconos, mismo
   componente de ramas que ya usa el home. Nada de banco de imágenes.

   El oro aparece siempre como filete de 1 px y nunca como texto
   (brand/04).

   ── 1 · Encabezado a sangre ────────────────────────────────────────
   Misma mecánica que el hero del home: la foto pasa por debajo del
   header, que arranca transparente (por eso finca.html NO lleva
   .hdr--fijo) y se vuelve sólido al scrollear. El contraste del
   título lo garantiza el velo de ::after, no la foto: hero-arauco es
   una pared beige a contraluz, y sin velo el crema se apoyaría sobre
   crema. El tramo de arriba del degradé tampoco es decorativo — es lo
   que sostiene el contraste del header transparente sobre la parte
   más clara de la foto. */
.finca-hero{position:relative;isolation:isolate;overflow:hidden;
  display:flex;align-items:flex-end;color:var(--crema);
  min-height:clamp(460px,74svh,760px);
  padding-top:calc(var(--hdr) + var(--cinta-h))}
.finca-hero__bg{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:64% 50%;z-index:-2}
.finca-hero::after{content:'';position:absolute;inset:0;z-index:-1;
  background:linear-gradient(to top,rgba(24,22,20,.82) 0%,
             rgba(24,22,20,.58) 30%,rgba(24,22,20,.30) 62%,
             rgba(24,22,20,.46) 100%)}
/* width:100% por lo mismo que .hero2 > .wrap: hijo de un contenedor
   flex, si no se encoge a su contenido y el margin-inline:auto lo
   centra en vez de dejarlo pegado al gutter. */
.finca-hero > .wrap{width:100%;padding-block:clamp(32px,6vh,72px)}
.finca-hero .kicker{color:var(--crema-2)}
.finca-hero__t{margin-top:12px;max-width:13ch}
.finca-hero__bajada{margin-top:20px;max-width:40ch;color:var(--crema-2)}
/* El renglón del lugar: lo primero que se le pregunta a una finca es
   dónde queda. Va sobre filete de oro, con un guión de oro entre
   ítems en vez de un punto medio — el mismo recurso, no un glifo. */
.finca-hero__lugar{display:flex;flex-wrap:wrap;gap:8px 16px;
  margin-top:clamp(26px,5vh,48px);padding-top:16px;
  border-top:1px solid var(--oro);
  font-family:var(--fs);font-size:var(--t-xs);font-weight:600;
  text-transform:uppercase;letter-spacing:var(--tr-caps);color:var(--crema)}
.finca-hero__lugar li{display:inline-flex;align-items:center;gap:16px}
.finca-hero__lugar li+li::before{content:'';display:block;
  width:14px;height:1px;background:var(--oro)}

/* ── 2 · Las tres cifras ────────────────────────────────────────────
   brand/01 las llama así: el año, la edad de los árboles, la cosecha
   única. Van como libro mayor —tres columnas separadas por filete—
   y no como tarjetas: son un dato del lugar, no un producto. La cifra
   va en tinta, porque a este cuerpo el oro sería texto. */
.finca__cifras{display:grid;gap:30px}
.finca__cifra{padding-top:20px;border-top:1px solid var(--oro)}
.finca__cifra-n{display:block;font-family:var(--fs);font-weight:500;
  font-size:clamp(2.75rem,1.6rem + 4.2vw,4.5rem);line-height:1;
  letter-spacing:var(--tr-tight);color:var(--tinta);
  font-variant-numeric:tabular-nums}
.finca__cifra-u{font-size:.3em;font-weight:600;letter-spacing:var(--tr-caps);
  text-transform:uppercase;margin-left:.7em;color:var(--tinta-2);
  vertical-align:.9em}
.finca__cifra-l{display:block;margin-top:16px;max-width:28ch;
  font-size:var(--t-sm);line-height:1.55;color:var(--tinta-2)}
@media(min-width:760px){
  .finca__cifras{grid-template-columns:repeat(3,1fr);gap:clamp(24px,4vw,56px)}
}

/* ── 3 · La cita ────────────────────────────────────────────────────
   Deja de ser una nota al margen y pasa a ser el descanso de la
   columna: entre dos filetes de oro y en cuerpo de titular. Antes era
   un borde izquierdo de 2 px, que a este tamaño se lee como alerta. */
.finca__cita{margin:clamp(36px,5vw,56px) 0 0;
  padding-block:clamp(24px,3vw,34px);
  border-top:1px solid var(--oro);border-bottom:1px solid var(--oro);
  font-family:var(--fs);font-weight:500;
  font-size:clamp(1.375rem,1.05rem + 1.1vw,2rem);line-height:1.24;
  letter-spacing:var(--tr-tight);color:var(--tinta);text-wrap:balance}

/* ── 4 · Pares de imagen y texto ────────────────────────────────────
   --inv cambia el orden en pantalla ancha sin tocar el del marcado,
   que es el que queda en móvil y el que lee un lector de pantalla. */
.finca__par{display:grid;gap:clamp(28px,4vw,64px);align-items:center}
.finca__par-txt{max-width:52ch}
.finca__foto{overflow:hidden;background:var(--fondo-2);
  aspect-ratio:4/5;max-height:min(76vh,660px)}
.finca__foto-in{display:block;width:100%;height:100%}
.finca__foto img{width:100%;height:100%;object-fit:cover}
/* Marco corrido: un filete de oro de 1 px desplazado detrás de la
   imagen. Da profundidad sin una sombra —este chasis casi no usa
   sombras— y con el mismo recurso que ordena el resto de la página. */
.finca__marco{position:relative}
.finca__marco::before{content:'';position:absolute;
  inset:clamp(12px,1.8vw,22px) calc(-1 * clamp(12px,1.8vw,22px))
        calc(-1 * clamp(12px,1.8vw,22px)) clamp(12px,1.8vw,22px);
  border:1px solid var(--oro)}
.finca__marco > *{position:relative}
@media(min-width:900px){
  .finca__par{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .finca__par--inv .finca__par-media{order:2}
}

/* ── 5 · El plato botánico ──────────────────────────────────────────
   El hueco de la sección del Arauco. Las dos fotos del Vallesi tienen
   la etiqueta mal escrita («WIELDE OLIVA», «300 ML»), así que a este
   tamaño no se pueden usar: en su lugar va una rama dibujada por el
   mismo js/olivos.js que dibuja las del home —hojas de lanza
   orientadas con la tangente del trazo, frutos en oro—, sobre panel
   claro y con filete interior. Cuando exista una foto real del olivar
   con etiqueta correcta, este bloque se reemplaza por un
   .finca__foto y nada más cambia.

   El .olivo-decor de olivos.css se apaga por debajo de 900 px porque
   allá es una decoración de borde que se mete debajo del texto. Acá
   no es decoración sino el contenido del bloque, así que se vuelve a
   encender: dos clases le ganan a la regla de una del media query. */
.finca__plato{position:relative;aspect-ratio:4/5;max-height:min(76vh,660px);
  background:var(--superficie);border:1px solid var(--borde);
  display:grid;place-items:center}
.finca__plato::after{content:'';position:absolute;
  inset:clamp(10px,1.4vw,16px);border:1px solid var(--oro);
  pointer-events:none}
.finca__plato .olivo-decor{display:block;position:absolute;
  left:50%;translate:-50% 0;
  width:clamp(110px,24vw,180px);top:9%;bottom:19%}
.finca__plato .olivo__tallo{stroke:var(--borde-fuerte);stroke-width:1.6}
.finca__plato .olivo__hoja{fill:var(--borde-fuerte)}
.finca__plato figcaption{position:absolute;left:0;right:0;
  bottom:clamp(26px,3.4vw,40px);text-align:center;
  font-family:var(--fs);font-size:var(--t-xs);font-weight:600;
  text-transform:uppercase;letter-spacing:var(--tr-caps);
  color:var(--tinta-2)}

/* ── 6 · El año, como ciclo ─────────────────────────────────────────
   Antes eran cuatro columnas de texto suelto. El año de una finca es
   un ciclo, así que se dibuja como tal: cuatro nodos unidos por un
   filete de oro —vertical en móvil, horizontal en pantalla ancha— con
   un glifo por estación dibujado a mano. El fruto en oro aparece sólo
   donde el fruto está de verdad, otoño y verano: mismo criterio que
   .olivo__fruto. */
.finca__anio{--anio-gap:clamp(20px,3vw,40px);
  display:grid;gap:34px;margin-top:clamp(36px,5vw,56px)}
/* El filete que une un nodo con el siguiente va POR NODO y no como
   una sola línea absoluta de punta a punta: el alto de cada bloque
   depende de su texto, y una línea única no sabe dónde cae el centro
   del último círculo. */
.finca__est{position:relative;padding-left:80px;min-height:56px}
.finca__est::before{content:'';position:absolute;background:var(--oro);
  left:28px;top:56px;bottom:-34px;width:1px}
.finca__est:last-child::before{content:none}
.finca__est-ico{position:absolute;left:0;top:0;
  width:56px;height:56px;display:grid;place-items:center;
  border:1px solid var(--oro);border-radius:50%;
  background:var(--oliva);color:var(--crema)}
.finca__est-ico svg{width:28px;height:28px;
  fill:none;stroke:currentColor;stroke-width:1.4;
  stroke-linecap:round;stroke-linejoin:round}
.finca__est-ico .lleno{fill:var(--oro);stroke:none}
.finca__est h3{font-family:var(--fs);text-transform:uppercase;
  letter-spacing:var(--tr-caps);font-size:var(--t-sm);margin:0 0 10px}
.finca__est p{color:var(--crema-2);max-width:32ch}
@media(min-width:860px){
  .finca__anio{grid-template-columns:repeat(4,1fr);gap:var(--anio-gap)}
  .finca__est{padding-left:0}
  .finca__est::before{left:56px;right:calc(-1 * var(--anio-gap));
    top:28px;bottom:auto;width:auto;height:1px}
  .finca__est-ico{position:relative}
  .finca__est h3{margin-top:22px}
}
/* Las ramas del componente de olivos son más angostas acá que en el
   home: allá flanquean un texto centrado y sobra lugar a los lados;
   acá tienen enfrente una grilla de cuatro columnas a todo el ancho,
   y por debajo de 1200 px se le meterían encima. */
.finca__olivos .olivo-decor{width:clamp(110px,10vw,180px)}
@media(max-width:1200px){ .finca__olivos .olivo-decor{display:none} }

/* ── 7 · El cierre ──────────────────────────────────────────────────
   Después del bloque oscuro, un cierre claro y centrado. La firma de
   arriba es el mismo vocabulario botánico del resto de la página,
   quieta y en chico, entre dos filetes: una firma, no un adorno. */
.finca__cierre{text-align:center}
.finca__cierre .lead{margin-inline:auto}
.finca__cierre .finca__acc{justify-content:center}
.finca__firma{display:flex;align-items:center;justify-content:center;
  gap:20px;margin-bottom:clamp(24px,3vw,36px)}
.finca__firma::before,.finca__firma::after{content:'';flex:1;
  height:1px;max-width:140px;background:var(--oro)}
.finca__rama{flex:none;width:48px;height:40px;color:var(--borde-fuerte);
  fill:none;stroke:currentColor;stroke-width:1.4;
  stroke-linecap:round;stroke-linejoin:round}
.finca__rama .lleno{fill:var(--oro);stroke:none}


.olivo__tres{margin-top:40px}
.olivo__tres h3{margin-bottom:12px}
.olivo__dato{margin-top:48px;padding-top:28px;border-top:1px solid var(--borde)}

/* Los cinco rituales: número al costado en pantalla ancha, encima en
   móvil. El número es decorativo pero se deja como texto y no como
   ::before para que no se pierda al copiar la página. */
.olivo__rituales{margin-top:44px;display:grid;gap:40px}
.olivo__ritual{display:grid;gap:14px;align-items:start}
.olivo__num{font-family:var(--fs);font-size:var(--t-h2);line-height:1;
  color:var(--borde-fuerte)}
.olivo__ritual h3{margin-bottom:12px}
.olivo__regla{margin-top:14px;padding:14px 18px;background:var(--superficie);
  border-left:2px solid var(--oro);font-size:var(--t-sm)}
.olivo__prod{margin-top:14px;font-size:var(--t-sm);color:var(--tinta-2)}
@media(min-width:768px){
  .olivo__ritual{grid-template-columns:120px minmax(0,62ch);gap:28px}
}

/* Carrito vacío: el texto y la salida, centrados en el cajón. */
.cart-vacio{display:flex;flex-direction:column;align-items:flex-start;gap:18px}
.cart-vacio p{color:var(--tinta-2)}


/* ═══ BARRA DE COMPRA FIJA ═══════════════════════════════════════════
   El punto donde más se pierde una compra en móvil es tener que
   scrollear de vuelta hasta el botón. Aparece recién cuando el botón
   real salió de pantalla, así que nunca hay dos CTA compitiendo.

   Desde 1024px no existe: ahí la caja de compra es sticky y el botón
   está siempre a la vista.
   ═══════════════════════════════════════════════════════════════════ */
.compra-fija{position:fixed;inset:auto 0 0;z-index:70;
  background:var(--superficie);border-top:1px solid var(--borde);
  box-shadow:0 -2px 16px var(--sombra-flota);
  transform:translateY(100%);transition:transform .3s var(--e-drawer);
  padding-bottom:env(safe-area-inset-bottom)}
.compra-fija--visible{transform:none}
.compra-fija__in{display:flex;align-items:center;gap:16px;
  justify-content:space-between;padding-block:10px}
.compra-fija__txt{min-width:0}
.compra-fija__n{font-size:var(--t-sm);font-weight:500;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.compra-fija__p{margin-top:2px;font-size:var(--t-sm);color:var(--tinta-2)}
.compra-fija .btn{flex:none}

@media(min-width:1024px){ .compra-fija{display:none} }
@media (prefers-reduced-motion:reduce){ .compra-fija{transition:none} }


/* ═══ VOLVER ARRIBA ══════════════════════════════════════════════════
   Se sienta justo encima del botón de contacto, que mide 72px con sus
   cuatro bordes anidados. --fam-alto existe para que los dos nunca se
   pisen: si cambia el tamaño del de contacto, este se corre solo.
   El marcado lo crea js/ui.js.
   ═══════════════════════════════════════════════════════════════════ */
.arriba{--fam-alto:72px;
  position:fixed;right:16px;
  bottom:calc(16px + var(--piso,0px) + env(safe-area-inset-bottom) + var(--fam-alto) + 12px);
  z-index:60;width:44px;height:44px;
  display:flex;align-items:center;justify-content:center;
  border:1px solid var(--borde);border-radius:var(--radio);
  background:var(--superficie);color:var(--tinta);cursor:pointer;
  box-shadow:0 2px 10px var(--sombra-flota);
  opacity:0;transform:translateY(8px);pointer-events:none;
  transition:opacity .25s ease,transform .25s var(--e-drawer),
             bottom .3s var(--e-drawer),
             border-color .2s ease,background .2s ease}
.arriba--visible{opacity:1;transform:none;pointer-events:auto}
/* Con el panel de contacto abierto, la caja crece a 168×218 y se come
   la posición de este botón: los dos comparten z-index 60, y .arriba
   gana por orden de DOM (ui.js corre después de family-contacto.js),
   así que quedaba tapando una de las filas del panel. Mientras el
   contacto está abierto, este se aparta. */
.fam--abierto ~ .arriba{opacity:0;pointer-events:none}
.arriba:hover{background:var(--fondo-2);border-color:var(--borde-fuerte)}
.arriba:focus-visible{outline:2px solid var(--oliva);outline-offset:2px}

@media (prefers-reduced-motion:reduce){
  .arriba{transition:opacity .01s;transform:none}
}


/* ═══ BOTÓN DE CONTACTO ══════════════════════════════════════════════
   Reescritura del FamilyButton de cult-ui en CSS plano (antes era una
   isla React que se reescribió a mano (sin CDN) — ver js/family-contacto.js
   para el porqué). Geometría calcada del original: cuatro bordes
   anidados de 1px con radios 24/23/22/21, 64×64 cerrado, 168×218
   abierto, toggle de 44×44 abajo al centro.

   Nota sobre brand/04 ("animar sólo transform y opacity"): acá el
   contenedor sí anima width/height, porque la caja creciendo ES el
   componente. No cuesta reflow: está en position:fixed, así que no
   empuja nada del documento.
   ═══════════════════════════════════════════════════════════════════ */
/* --piso: cuánto hay que subir para no quedar tapado por la barra de
   compra fija. Lo setea js/producto.js; en el resto de las páginas no
   existe y el fallback 0px deja todo donde estaba. env(safe-area-inset-
   bottom): mismo motivo que .compra-fija más abajo — sin esto, en un
   iPhone con gesture bar el botón queda pegado al borde del sistema. */
.fam{position:fixed;right:16px;
  bottom:calc(16px + var(--piso,0px) + env(safe-area-inset-bottom));z-index:60;
  transition:bottom .3s var(--e-drawer);
  border:1px solid var(--fam-borde-osc);border-radius:24px;
  background:linear-gradient(180deg,var(--oliva) 0%,var(--oliva-hondo) 100%);
  box-shadow:0 1px 2px var(--fam-sombra)}
.fam__b2{border:1px solid var(--fam-borde-osc);border-radius:23px}
.fam__b3{border:1px solid var(--fam-borde-cl);border-radius:22px}
.fam__b4{border:1px solid var(--fam-borde-in);border-radius:21px;
  display:flex;align-items:center;justify-content:center}

.fam__caja{position:relative;width:64px;height:64px;border-radius:21px;
  border:1px solid var(--fam-vidrio);
  background:linear-gradient(180deg,var(--oliva) 0%,var(--oliva-h) 100%);
  color:var(--crema);overflow:hidden;
  transition:width .42s var(--e-drawer),height .42s var(--e-drawer),
             border-radius .42s var(--e-drawer),background .3s ease}
.fam--abierto .fam__caja{width:168px;height:218px;border-radius:20px;
  background:none}

/* ── El panel ────────────────────────────────────────────────────── */
.fam__panel{display:flex;flex-direction:column;gap:8px;
  padding:12px 12px 0;width:100%;
  opacity:0;pointer-events:none;
  transition:opacity .28s ease}
.fam--abierto .fam__panel{opacity:1;pointer-events:auto;
  transition:opacity .4s ease .3s}   /* espera a que la caja termine */

.fam__rotulo{margin:0 0 2px;text-align:center;font-family:var(--fs);
  font-size:10px;font-weight:500;text-transform:uppercase;
  letter-spacing:var(--tr-caps);color:var(--fam-tinta-3)}

.fam__via{display:flex;align-items:center;gap:12px;
  padding:10px 12px;border-radius:14px;
  background:var(--fam-vidrio);color:var(--crema);text-decoration:none;
  transition:background .2s ease}
.fam__via:hover{background:var(--fam-vidrio-h)}
.fam__via:focus-visible{outline:2px solid var(--crema);outline-offset:2px}
.fam__via-ico{flex:none;display:flex;align-items:center;justify-content:center;
  width:32px;height:32px;border-radius:50%;overflow:hidden;
  background:var(--crema);color:var(--oliva)}
.fam__via-ico--wsp{color:var(--wsp)}
.fam__via-ico img{height:16px;width:auto}
.fam__via-txt{font-size:var(--t-sm);font-weight:500}

/* ── El toggle ───────────────────────────────────────────────────── */
.fam__toggle{position:absolute;left:50%;bottom:6px;
  transform:translateX(-50%);
  width:44px;height:44px;border-radius:15px;
  display:flex;align-items:center;justify-content:center;
  cursor:pointer;padding:0;
  background:var(--crema);border:1px solid var(--fam-borde-osc);
  box-shadow:0 12px 24px var(--fam-sombra);
  transition:background .3s ease,border-color .3s ease}
.fam--abierto .fam__toggle{background:var(--fam-vidrio);
  border-color:var(--fam-tinta-3)}
.fam--abierto .fam__toggle:hover{border-color:var(--crema)}
.fam__toggle:focus-visible{outline:2px solid var(--crema);outline-offset:3px}

/* La etiqueta accesible: existe para el lector de pantalla, no se ve. */
.fam__etiqueta{position:absolute;width:1px;height:1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap}

/* Las dos marcas en diagonal, sólo en estado cerrado. */
.fam__marcas{position:absolute;inset:0;transition:opacity .2s ease}
.fam__marca{position:absolute;display:flex;align-items:center;
  justify-content:center;width:20px;height:20px;border-radius:7px;
  overflow:hidden}
.fam__marca--wsp{top:4px;left:4px;background:var(--wsp);color:var(--crema)}
.fam__marca--vo{bottom:4px;right:4px;background:var(--oliva)}
.fam__marca--vo img{height:11px;width:auto}
.fam--abierto .fam__marcas{opacity:0}

/* La × del estado abierto. El giro reemplaza al layoutId compartido
   que usaba Motion para morfear un ícono en el otro. */
.fam__x{position:absolute;display:flex;color:var(--fam-tinta-2);
  opacity:0;transform:rotate(-180deg);
  transition:opacity .25s ease,transform .4s var(--e-drawer),color .2s ease}
.fam--abierto .fam__x{opacity:1;transform:rotate(0deg);
  transition:opacity .25s ease .12s,transform .4s var(--e-drawer) .12s,
             color .2s ease}
.fam__toggle:hover .fam__x{color:var(--crema)}

@media (prefers-reduced-motion:reduce){
  .fam__caja,.fam__panel,.fam__x,.fam__marcas,.fam__toggle{transition:none}
  .fam__x{transform:none}
}

/* ── Cajón de sesión ────────────────────────────────────────────────
   Reusa .cajon entero (js/auth.js lo inyecta con esa clase), así que
   acá sólo está lo propio del contenido: quién sos y el botón de
   Google. Todo lo demás — panel, velo, animación — ya estaba. */
.cuenta-quien{display:flex;align-items:center;gap:14px;margin-bottom:24px}
.cuenta-avatar{border-radius:50%;object-fit:cover;flex:none}
.cuenta-nombre{font-weight:600;line-height:1.3}
.cuenta-mail{font-size:var(--t-sm);color:var(--tinta-2);
  /* El mail puede ser largo y el cajón mide 420px: sin esto empuja el
     ancho del flex y desborda el panel. */
  overflow-wrap:anywhere}
.cuenta-intro{margin-bottom:20px;color:var(--tinta-2)}
.cuenta-gbtn{display:flex;justify-content:center;
  /* Reserva la altura del botón de Google antes de que GIS lo dibuje:
     si no, el cajón salta cuando llega el iframe. */
  min-height:44px}
.cuenta-error{margin-top:16px;font-size:var(--t-sm);color:var(--err-cl)}

/* El botón del header con la foto de la cuenta. El overflow va acá y
   no en .icono-btn porque ese lo comparte con el contador del carrito,
   que justamente tiene que poder asomar fuera del cuadro. */
.icono-btn--avatar{overflow:hidden;border-radius:50%}
.cuenta-avatar-mini{border-radius:50%;object-fit:cover;display:block}

/* ── Aviso flotante ─────────────────────────────────────────────────
   Sobre el cajón (z-index 95) porque puede avisar de algo que pasó
   dentro de él: "cerraste sesión" se dispara con el panel abierto. */
.aviso{position:fixed;left:50%;bottom:24px;z-index:120;
  max-width:min(380px,calc(100vw - 32px));
  padding:14px 20px;border-radius:var(--radio);
  background:var(--oliva);color:var(--crema);
  font-size:var(--t-sm);line-height:1.45;text-align:center;
  box-shadow:0 12px 32px -10px rgba(28,25,23,.4);
  opacity:0;transform:translate(-50%,12px);pointer-events:none;
  transition:opacity .25s ease,transform .25s var(--e-drawer)}
.aviso.visible{opacity:1;transform:translate(-50%,0)}

@media (prefers-reduced-motion:reduce){
  .aviso{transition:opacity .25s ease;transform:translate(-50%,0)}
}
