/* =========================================================================
   DLunas Variety — la tienda

   MOBILE FIRST y no de boquilla: todo hasta el primer @media está escrito
   para un teléfono. Más de ocho de cada diez personas que compren aquí lo
   harán con el aparato en una mano.

   LA IDEA: LA NOCHE.
   La versión anterior era fondo crema con serif de alto contraste, que es
   exactamente el aspecto que sale por defecto cuando no se decide nada. Se
   veía correcta y no decía nada.

   Lo que sí es de esta marca y de ninguna otra: se llama LUNAS. El logotipo
   ES una luna. Así que la tienda abre de noche —fondo ciruela profundo, la
   marca encendida, el rosa haciendo de luz— y va aclarando a medida que se
   baja, hasta el papel cálido donde vive el producto. Nadie abre una tienda
   de jabón en oscuro; Aesop es crema, Buff City blanco, Herb'N Eden claro.
   Ese es el riesgo, y se sostiene porque sale del nombre de la casa.

   El contraste no viene de meter un color nuevo: viene de usar los de
   siempre en el papel contrario. La misma paleta, invertida.

   Decisiones móviles medidas (Baymard): el 85.65% de los carritos móviles se
   abandonan; el botón de comprar fijo al fondo sube la conversión entre 5 y
   12%; el 62% de las fichas de producto móviles tienen UX mediocre o peor.
   ========================================================================= */

:root {
  /* Los mismos hexadecimales de la casa. Lo que cambia es quién es fondo. */
  --papel:      #f9f5f2;
  --papel-alto: #ffffff;
  --papel-hondo:#f1ebe6;

  /* La noche: el ciruela de la marca llevado hasta donde puede ser suelo. */
  --noche:      #1f1826;
  --noche-alta: #2b2233;

  --tinta:      #2c2333;
  --tinta-suave:#6d6074;
  --linea:      #e9e0da;
  --linea-firme:#d8cbc4;

  --lavanda:      #afb4d7;
  --lavanda-honda:#616694;
  --rosa:         #e78eb1;
  --rosa-hondo:   #ad4671;
  --ciruela:      #7d4368;
  --alerta:       #b4485f;

  /* Sobre la noche hacen falta otros tonos: el rosa de la marca a plena luz
     y una tinta clara que no sea blanco puro, que corta demasiado. */
  --sobre-noche:      #f4eef2;
  --sobre-noche-suave:#bfb0c4;   /* 7.1:1 sobre --noche */

  --display: "Playfair Display", Georgia, serif;
  --ui:      "Montserrat", system-ui, -apple-system, sans-serif;

  --radio: 14px;
  --radio-chico: 9px;
  --sombra: 0 1px 2px rgba(31, 24, 38, .04), 0 18px 40px -28px rgba(31, 24, 38, .35);

  --barra-abajo: calc(3.5rem + env(safe-area-inset-bottom));
}

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  /* El rebote del final. En el iPhone, al tirar hacia arriba pasado el pie, la
     página se despega y deja a la vista un vacío de papel con la barra fija
     colgando en medio. En Chromium no ocurre —por eso no se veía midiendo
     aquí— y en Safari sí. Con esto la página se para donde termina.
     No afecta al desplazamiento normal ni al de dentro del chat. */
  overscroll-behavior-y: none;
}

body {
  margin: 0;
  background: var(--papel);
  color: var(--tinta);
  font-family: var(--ui);
  font-size: 16px;
  line-height: 1.6;
  overflow-wrap: break-word;
}

img { max-width: 100%; display: block; }
a { color: inherit; }

.saltar {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--tinta);
  color: var(--papel-alto);
  padding: .75rem 1rem;
  z-index: 100;
}
.saltar:focus { left: 0; }

.icono {
  width: 22px; height: 22px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* --- cabecera -----------------------------------------------------------
   La anatomía de Ulta y Sephora, adaptada a doce productos en vez de treinta
   mil: franja de aviso, logo, enlaces, buscador, carrito.

   Del buscador se copia la forma: subrayado y no caja, con la lupa dentro.
   Pesa menos que un campo con borde y no compite con el producto, que es de
   lo que vive una tienda de cosmética. */

.franja-aviso {
  margin: 0;
  padding: .5rem 1.25rem;
  background: var(--noche);
  color: var(--sobre-noche-suave);
  font-size: .6875rem;
  letter-spacing: .07em;
  text-align: center;
  line-height: 1.4;
}

.marca-barra {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: max(.625rem, env(safe-area-inset-top)) 1.25rem .625rem;
  background: var(--papel);
  border-bottom: 1px solid var(--linea);
}
/* El logotipo es un enlace y se pulsa con el dedo: 44 px de alto mínimo. */
/* El logotipo lleva "VARIETY" en letra muy pequeña bajo el nombre: a 34 px de
   alto esa segunda línea no se leía. Sitio hay —la cabecera usaba 183 px de
   los 390 del teléfono—, así que se agranda hasta que la marca se distinga. */
.marca-enlace { display: flex; align-items: center; min-height: 44px; margin-right: auto; }
.marca-enlace img { height: 3.25rem; width: auto; }

/* Los enlaces de la cabecera son de pantalla ancha: en el teléfono los tres
   viven abajo, donde llega el pulgar. */
.enlaces-cabecera { display: none; }

/* El buscador desplegado. En el teléfono aparece al tocar la lupa y ocupa la
   cabecera entera; de 48rem en adelante está siempre puesto. */
.buscar-cabecera { display: none; align-items: center; gap: .5rem; flex: 1; min-width: 0; }
.buscar-cabecera .lupa { width: 19px; height: 19px; color: var(--tinta-suave); }
.buscar-cabecera input {
  flex: 1;
  min-width: 0;
  min-height: 44px;
  padding: .375rem 0;
  font: inherit;
  font-size: .9375rem;
  color: var(--tinta);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--linea-firme);
  border-radius: 0;
}
.buscar-cabecera input::placeholder { color: var(--tinta-suave); }
.buscar-cabecera input:focus-visible { outline: 0; border-bottom-color: var(--ciruela); border-bottom-width: 2px; }

/* --- sugerencias del buscador -------------------------------------------
   Con foto y precio, que es lo que las hace útiles: se reconoce el producto
   sin leer. Cuelgan del campo y no empujan la página. */

.buscar-cabecera { position: relative; }

.sugerencias {
  position: absolute;
  top: calc(100% + .375rem);
  left: 0; right: 0;
  z-index: 40;
  margin: 0;
  padding: .25rem;
  list-style: none;
  background: var(--papel-alto);
  border: 1px solid var(--linea-firme);
  border-radius: var(--radio);
  box-shadow: 0 16px 40px -18px rgba(31, 24, 38, .45);
  max-height: min(60vh, 24rem);
  overflow-y: auto;
}

.sugerencias li a {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) auto;
  gap: .75rem;
  align-items: center;
  padding: .5rem;
  border-radius: var(--radio-chico);
  text-decoration: none;
  color: var(--tinta);
  min-height: 44px;
}
.sugerencias li.marcada a,
.sugerencias li a:hover { background: var(--papel-hondo); }

.sug-foto {
  width: 44px; height: 44px;
  border-radius: var(--radio-chico);
  overflow: hidden;
  background: var(--papel-hondo);
}
.sug-foto img { width: 100%; height: 100%; object-fit: cover; }
.sug-foto .baldosa { font-size: 1.125rem; }

.sug-datos { display: flex; flex-direction: column; min-width: 0; }
.sug-nombre {
  font-size: .9375rem;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sug-reclamo {
  font-family: var(--display);
  font-style: italic;
  font-size: .8125rem;
  color: var(--ciruela);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sug-precio {
  font-size: .875rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.sugerencia-vacia {
  padding: .875rem .75rem;
  font-size: .875rem;
  color: var(--tinta-suave);
}

.marca-barra.buscando .buscar-cabecera { display: flex; }
.marca-barra.buscando .marca-enlace { display: none; }

.abrir-buscar, .barra-carrito {
  position: relative;
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  flex: none;
  color: var(--tinta);
  border-radius: var(--radio-chico);
  text-decoration: none;
}
.abrir-buscar:focus-visible, .barra-carrito:focus-visible {
  outline: 2px solid var(--lavanda-honda); outline-offset: -2px;
}

/* El interruptor de idioma.
   Dos posiciones, una encendida. Mismo alto de pulsación que la lupa y el
   carrito —44px, lo que pide un pulgar— porque vive entre ellos y en el
   teléfono son los tres únicos que se ven.
   En vez de icono lleva las dos letras: no hay dibujo que signifique "inglés"
   sin recurrir a una bandera, y una bandera es un país. */
.idiomas {
  display: flex;
  align-items: stretch;
  flex: none;
  height: 38px;
  padding: 3px;
  border: 1px solid var(--linea);
  border-radius: 999px;
  background: var(--papel-hondo);
}
.idioma {
  display: grid;
  place-items: center;
  min-width: 34px;
  padding-inline: .55rem;
  border-radius: 999px;
  font-size: .6875rem;
  font-weight: 600;
  letter-spacing: .05em;
  color: var(--tinta-suave);
  text-decoration: none;
  /* El alto de pulsación real llega a los 44px por fuera de la píldora: se ve
     de 38 y se toca de 44, que es lo que pide un pulgar sin engordar la barra. */
  position: relative;
}
.idioma::after {
  content: "";
  position: absolute;
  inset: -4px -2px;
}
/* El lado encendido. Ciruela llena y no sólo un color de letra: a 11px, la
   diferencia entre dos grises no se ve de un vistazo, y de un vistazo es
   exactamente como se lee esto. */
.idioma.activo {
  background: var(--ciruela);
  color: #fff;
  box-shadow: 0 1px 2px rgba(44, 35, 51, .18);
}
.idiomas a.idioma:hover { color: var(--ciruela); background: var(--papel-alto); }
.idiomas a.idioma:focus-visible {
  outline: 2px solid var(--lavanda-honda);
  outline-offset: 1px;
}

.cuenta-carrito {
  position: absolute;
  top: 2px; right: 2px;
  min-width: 1.125rem;
  height: 1.125rem;
  padding: 0 .25rem;
  border-radius: 999px;
  background: var(--rosa-hondo);
  color: #fff;
  font-size: .625rem;
  font-weight: 600;
  line-height: 1.125rem;
  text-align: center;
}

/* --- servicios de la cabecera -------------------------------------------
   El equivalente de "Shop Store & Delivery" y "AI Beauty Chat" de Sephora:
   dónde se recoge y con quién se habla. Sólo en portátil, que es donde hay
   sitio; en tableta y teléfono se caen, porque lo primero que se sacrifica
   cuando falta ancho es lo accesorio, no el buscador ni el carrito. */

.servicios-cabecera { display: none; }

.servicio {
  display: flex;
  align-items: center;
  gap: .5rem;
  color: var(--tinta);
  text-decoration: none;
  white-space: nowrap;
}
.servicio .icono { width: 20px; height: 20px; color: var(--ciruela); }
.servicio-texto { display: flex; flex-direction: column; line-height: 1.2; }
.servicio-texto strong { font-size: .8125rem; font-weight: 600; }
.servicio-texto small { font-size: .6875rem; color: var(--tinta-suave); }
a.servicio:hover .servicio-texto strong { color: var(--ciruela); }
a.servicio:focus-visible { outline: 2px solid var(--lavanda-honda); outline-offset: 3px; border-radius: var(--radio-chico); }

/* --- barra de categorías ------------------------------------------------
   La barra negra de Sephora. Lo que cambia es el desplegable: ellos enseñan
   subcategorías porque Skincare sola tiene miles de productos; aquí las
   categorías tienen cuatro, cuatro y seis, así que caben los productos con su
   foto. Es una ventaja de ser pequeña y desperdiciarla sería raro. */

.barra-categorias {
  position: relative;
  z-index: 18;
  background: var(--noche);
  border-bottom: 1px solid rgba(244, 238, 242, .1);
}

.cat-lista {
  display: flex;
  gap: 0;
  margin: 0;
  padding: 0 1.25rem;
  list-style: none;
  overflow-x: auto;
  scrollbar-width: none;
}
.cat-lista::-webkit-scrollbar { display: none; }

.cat-enlace {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: .625rem 1rem;
  color: var(--sobre-noche);
  font-size: .8125rem;
  letter-spacing: .03em;
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  transition: border-color .2s ease, color .2s ease;
}
.cat-enlace:hover { border-bottom-color: var(--rosa); }
.cat-enlace:focus-visible { outline: 2px solid var(--rosa); outline-offset: -3px; }

/* El desplegable no existe hasta 64rem: en teléfono y tableta se toca y se
   va a la categoría, que es lo que hace Sephora también. */
.cat-panel { display: none; }

/* --- barra de secciones: abajo en el teléfono ---------------------------- */

.secciones {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 30;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  background: var(--papel-alto);
  border-top: 1px solid var(--linea-firme);
  padding-bottom: env(safe-area-inset-bottom);
}

.seccion {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .1875rem;
  padding: .5rem .125rem .4375rem;
  min-height: 3.5rem;
  font-size: .6875rem;
  color: var(--tinta-suave);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.seccion .icono {
  width: 44px;
  height: 22px;
  padding: 0 .6875rem;
  border-radius: 999px;
  transition: background-color .18s ease, color .18s ease;
}
.seccion.activa { color: var(--tinta); }
.seccion.activa .icono { background: var(--lavanda); color: #23203a; stroke-width: 1.9; }
.seccion .cuenta-carrito.en-barra { top: .25rem; right: 50%; margin-right: -1.5rem; }

.seccion:focus-visible { outline: 2px solid var(--lavanda-honda); outline-offset: -3px; }

/* --- estructura ---------------------------------------------------------- */

#contenido {
  /* Aquí ya NO se reserva sitio para la barra de abajo.
     Lo hacía, y con el pie inmediatamente después el resultado era un vacío de
     128 px entre la última sección y el pie: 80 de este relleno más los 48 del
     margen del pie. Espacio muerto justo donde la página termina, que es donde
     más se nota.
     Quien reserva ese sitio ahora es el propio pie, que es el último elemento
     de la página y el único que de verdad puede quedar debajo de la barra.
     La ficha del producto es el caso aparte: ahí hay ADEMÁS un botón fijo de
     comprar, y su hueco se reserva abajo, sobre `.ficha`. */
  padding-bottom: 0;
}

/* La ficha, con su botón fijo encima de la barra: el alto de los dos. */
body:has(.comprar-fijo) .ficha { padding-bottom: 4.5rem; }

.franja { padding: 2.25rem 1.25rem; }
.franja + .franja { padding-top: 0; }
.franja.hunde { background: var(--papel-hondo); padding-block: 2.5rem; }

/* --- la noche: el héroe -------------------------------------------------
   La marca se llama LUNAS y su logotipo es una luna. La tienda abre de noche
   y va aclarando al bajar. El contraste que faltaba no es un color nuevo: es
   el ciruela de siempre haciendo de suelo. */

.noche {
  position: relative;
  background: var(--noche);
  color: var(--sobre-noche);
  padding: 3.5rem 1.25rem 3rem;
  overflow: hidden;
  isolation: isolate;
}

/* La luz de luna. Un solo halo, descentrado, que es lo que separa un fondo
   oscuro de un fondo negro y plano. */
.noche::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: -30%; right: -25%;
  width: 130%; aspect-ratio: 1;
  background: radial-gradient(circle at 50% 50%,
      rgba(231, 142, 177, .30) 0%,
      rgba(175, 180, 215, .16) 38%,
      transparent 68%);
  pointer-events: none;
}

.noche .marca-grande {
  width: 4.25rem;
  height: auto;
  margin-bottom: 1.5rem;
}

.noche .rotulo { color: var(--sobre-noche-suave); }

.noche .titular {
  color: var(--sobre-noche);
  font-size: clamp(2.4rem, 12vw, 3.4rem);
  letter-spacing: -.025em;
}
/* Una palabra en cursiva, no todas: es lo que hace que un titular en serif
   suene a marca y no a plantilla. */
.noche .titular em { font-style: italic; color: var(--rosa); }

.noche .entradilla { color: var(--sobre-noche-suave); }

.noche .boton {
  background: var(--rosa);
  color: #2a1420;
}
.noche .boton.suave {
  background: transparent;
  color: var(--sobre-noche);
  border: 1px solid rgba(244, 238, 242, .35);
}

/* La misma noche, para bandas de más abajo. */
.franja.noche + .franja { padding-top: 2.25rem; }

/* --- el héroe con la foto de sus productos ------------------------------
   Reemplaza el fondo de noche por el banner de marca. Dos problemas que hay
   que resolver, no uno:

   1. La foto es 1.8:1 y el teléfono es vertical. Recortarla al viewport se
      lleva por delante la composición —la tabla, las flores, dos de los tres
      productos—. Por eso en teléfono va un recorte propio, hecho desde la
      derecha, donde están el elixir y el acondicionador.
   2. El fondo pasa de ciruela oscuro a azul claro, así que TODO el texto que
      estaba en claro deja de leerse. Se invierte entero.

   El velo no es decoración: la foto tiene zonas claras y zonas con producto,
   y sin él el texto cae encima de la tabla de madera en algunos anchos. */

/* En teléfono y tablet NO va la foto, y el héroe se acorta.
   El banner es apaisado y la pantalla es vertical: para que se viera entero
   ocupaba la primera pantalla completa y empujaba la mercancía por debajo del
   pliegue. Quien entra desde el teléfono —ocho de cada diez— viene a ver
   jabones, no un cartel. Así que aquí se queda la noche de siempre, corta, y
   los productos suben. La foto entra sólo cuando hay ancho de sobra. */
.noche.con-banner {
  padding-block: 2.5rem 2.75rem;

  /* La foto TAMBIÉN en el teléfono, detrás del texto.
     Antes aquí sólo quedaba el degradado de noche, y el motivo escrito arriba
     era bueno: el banner es apaisado, y enseñarlo entero ocupaba la primera
     pantalla y empujaba la mercancía debajo del pliegue.
     Pero de ahí no se sigue que no haya foto: se sigue que no cabe ENTERA. Con
     un recorte vertical y el mismo alto de siempre, la foto entra sin robarle
     un píxel a los productos — y un degradado morado a pantalla completa es
     sitio muerto en la primera cosa que se ve de la tienda.
     El velo va oscuro y hacia abajo porque el texto es claro: sin él, el
     titular cae sobre las zonas iluminadas de la foto y deja de leerse. */
  position: relative;
  overflow: hidden;
  background-image:
    linear-gradient(180deg, rgba(28, 21, 34, .82) 0%, rgba(28, 21, 34, .72) 45%, rgba(28, 21, 34, .90) 100%),
    var(--foto-heroe);
  background-size: cover, cover;
  background-position: center, center 35%;
  background-repeat: no-repeat, no-repeat;
}
.noche.con-banner .marca-grande { width: 4.5rem; margin-bottom: .75rem; }
.noche.con-banner .titular { font-size: clamp(2rem, 8.5vw, 2.75rem); }
.noche.con-banner .entradilla { margin-bottom: 1.5rem; }

/* Y en teléfono, primero lo que se vende y después por dónde empezar: el
   catálogo antes que el índice. Se hace por orden visual, sin mover el HTML,
   porque en escritorio el orden bueno es el otro. */
/* El orden en teléfono, dicho sección por sección y no con `:last-of-type`.
   Con esa regla, añadir una sección nueva cambiaba el orden de todo sin que
   nadie lo pidiera —pasó al meter Destacados—. Ahora cada franja dice dónde
   va, y meter otra no descoloca a las demás.

   Primero lo que ella empuja, luego por dónde entrar, luego el resto del
   catálogo, y la firma de "sin sulfatos" al final. Quien llega desde el
   teléfono viene a ver mercancía. */
[data-seccion="inicio"] main { display: flex; flex-direction: column; }
[data-seccion="inicio"] main > .franja.noche          { order: 0; }
[data-seccion="inicio"] main > .franja.banda-destacados { order: 1; }
[data-seccion="inicio"] main > .franja.banda-categorias { order: 2; }
[data-seccion="inicio"] main > .franja.banda-catalogo   { order: 3; }
[data-seccion="inicio"] main > .franja.tira-promesas    { order: 4; }
[data-seccion="inicio"] main > .franja                  { order: 5; }

/* --- tipografía ---------------------------------------------------------- */

.titular {
  font-family: var(--display);
  font-size: clamp(2rem, 9vw, 2.75rem);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: -.01em;
  margin: 0;
  text-wrap: balance;
}

.subtitular {
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 400;
  line-height: 1.15;
  margin: 0 0 .875rem;
  text-wrap: balance;
}

.entradilla {
  font-size: 1.0625rem;
  line-height: 1.65;
  color: var(--tinta-suave);
  margin: .875rem 0 0;
  max-width: 34rem;
}

.rotulo {
  font-size: .6875rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  margin: 0 0 .5rem;
}

.nota { font-size: .8125rem; line-height: 1.55; color: var(--tinta-suave); margin: .5rem 0 0; }

/* --- botones ------------------------------------------------------------- */

.boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-height: 48px;
  padding: .75rem 1.5rem;
  border: 0;
  border-radius: var(--radio-chico);
  background: var(--tinta);
  color: var(--papel-alto);
  font-family: var(--ui);
  font-size: .9375rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  text-align: center;
}
.boton:disabled { background: var(--linea-firme); color: var(--tinta-suave); cursor: not-allowed; }
.boton.ancho { width: 100%; }
.boton.suave { background: var(--papel-alto); color: var(--tinta); border: 1px solid var(--linea-firme); }
.boton:focus-visible, .boton-texto:focus-visible { outline: 2px solid var(--lavanda-honda); outline-offset: 2px; }

.boton-texto {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: .5rem 0;
  background: none;
  border: 0;
  color: var(--lavanda-honda);
  font: inherit;
  font-size: .9375rem;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
}

/* --- rejilla de productos ------------------------------------------------
   Dos por fila desde el teléfono. Una sola columna obliga a desplazarse el
   doble para ver lo mismo, y con la foto cuadrada dos entran de sobra. */

.rejilla {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.25rem .875rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pieza { min-width: 0; }
.pieza a { text-decoration: none; display: block; }

.pieza-foto {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--radio);
  overflow: hidden;
  background: var(--papel-hondo);
}
.pieza-foto img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .5s cubic-bezier(.2, .7, .3, 1);
}
/* Al tocar o al pasar por encima, la foto se acerca un punto. Es el único
   movimiento de la rejilla: doce tarjetas moviéndose a la vez sería ruido. */
.pieza a:hover .pieza-foto img,
.pieza a:focus-visible .pieza-foto img { transform: scale(1.05); }
.pieza a:focus-visible { outline: 2px solid var(--lavanda-honda); outline-offset: 4px; border-radius: var(--radio); }

/* La baldosa con la inicial mientras no hay foto. Es lo que hace Loyverse en
   su lista de artículos, y evita que una tienda sin fotos se vea rota. */
/* La baldosa de cuando no hay foto. Llevaba la inicial del nombre a 44 px, y
   una "J" gigante en mitad del catálogo no se lee como un empaque: se lee
   como una base de datos a medio llenar. Ahora lleva la luna de la casa —la
   tienda se llama Lunas— en blanco translúcido. Mismo hueco, misma función,
   y de lejos parece marca en vez de error. */
.baldosa {
  display: grid;
  place-items: center;
  width: 100%; height: 100%;
  color: #fff;
  user-select: none;
}
.baldosa-luna {
  width: 38%;
  max-width: 5rem;
  height: auto;
  fill: currentColor;
  opacity: .36;
}

.pieza-nombre {
  font-family: var(--display);
  font-size: 1.0625rem;
  line-height: 1.25;
  margin: .625rem 0 0;
  color: var(--tinta);
}
.pieza-dato {
  display: block;
  font-family: var(--display);
  font-style: italic;
  font-size: .9375rem;
  line-height: 1.3;
  color: var(--ciruela);
  margin-top: .25rem;
}
.pieza-precio {
  display: block;
  margin-top: .25rem;
  font-size: .9375rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.pieza.agotada .pieza-foto { opacity: .55; }
.marca-agotado {
  position: absolute;
  left: .5rem; bottom: .5rem;
  padding: .1875rem .5rem;
  border-radius: 999px;
  background: var(--papel-alto);
  color: var(--tinta-suave);
  font-size: .625rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* --- promesas y lo que NO lleva -----------------------------------------
   Las dos referencias que dio la dueña abren con esto. Herb'N Eden lista lo
   que no contiene antes que lo que sí; Buff City repite "handmade daily" y
   sus Soap Makeries. Es lo que separa un jabón artesanal de uno cualquiera, y
   se dice antes de que lo pregunten. */

.tira-promesas { text-align: center; padding-block: 2.75rem; }

.acciones-heroe { display: flex; flex-wrap: wrap; gap: .75rem; margin: 1.75rem 0 0; }
.acciones-fin { margin: 1.75rem 0 0; }

.promesas {
  display: flex;
  flex-direction: column;
  gap: .875rem;
  margin: 0 auto;
  padding: 0;
  list-style: none;
  max-width: 30rem;
}
.promesas li {
  font-family: var(--display);
  font-size: 1.125rem;
  line-height: 1.3;
}
.promesas li + li { border-top: 1px solid var(--linea); padding-top: .875rem; }

.sin-que-linea {
  margin: 1.5rem auto 0;
  max-width: 32rem;
  font-size: .8125rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  line-height: 1.7;
}

/* En la ficha va como lista de marcas, que se lee más rápido que un párrafo. */
.sin-que {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.sin-que li {
  padding: .375rem .75rem;
  border: 1px solid var(--linea-firme);
  border-radius: 999px;
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .03em;
  color: var(--tinta-suave);
}

/* El reclamo: el aroma y qué hace, justo bajo el nombre. Es la línea que
   Buff City pone en cada tarjeta y lo primero que se lee de un producto. */
.ficha-reclamo {
  margin: .5rem 0 0;
  font-family: var(--display);
  font-size: 1.125rem;
  font-style: italic;
  line-height: 1.35;
  color: var(--ciruela);
}

/* --- categorías ---------------------------------------------------------- */

/* Las pastillas se doblan, no se desplazan. Con tres categorías la fila mide
   495 px en una pantalla de 390: "Velas" quedaba fuera y nadie la veía, sin
   ninguna señal de que hubiera más a la derecha. Una categoría entera
   escondida por una decisión de maquetado. */
.categorias {
  display: flex;
  flex-wrap: wrap;
  gap: .625rem;
  margin: 0;
  padding: .25rem 0 1rem;
  list-style: none;
}
.categorias::-webkit-scrollbar { display: none; }
.categorias li { scroll-snap-align: start; flex: none; }

.pastilla {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: .5rem 1rem;
  border-radius: 999px;
  background: var(--papel-hondo);
  color: var(--lavanda-honda);
  font-size: .8125rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}
.pastilla.activa { background: var(--tinta); color: var(--papel-alto); }

/* --- categorías como fichas ---------------------------------------------
   Home Depot no pone sus categorías como texto: las pone como imágenes con su
   llamada dentro. Con doce productos no hace falta su densidad, pero sí ese
   cambio — una foto invita a entrar y una pastilla gris no. Cuando la
   categoría no tiene foto propia se toma la de uno de sus productos. */

.rejilla-cat {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: .875rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.tarjeta-cat a {
  display: block;
  text-decoration: none;
  border-radius: var(--radio);
  overflow: hidden;
  background: var(--papel-alto);
  border: 1px solid var(--linea);
  box-shadow: var(--sombra);
}
.tarjeta-cat .cat-foto {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--papel-hondo);
}
.tarjeta-cat .cat-foto img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .5s cubic-bezier(.2, .7, .3, 1);
}
.tarjeta-cat a:hover .cat-foto img,
.tarjeta-cat a:focus-visible .cat-foto img { transform: scale(1.06); }
.tarjeta-cat a:focus-visible { outline: 2px solid var(--lavanda-honda); outline-offset: 3px; }
.tarjeta-cat .cat-foto .baldosa { font-size: 2.25rem; }
.tarjeta-cat .cat-texto { padding: .75rem .875rem 1rem; }
.tarjeta-cat .cat-nombre {
  font-family: var(--display);
  font-size: 1.0625rem;
  line-height: 1.2;
  margin: 0;
  color: var(--tinta);
}
.tarjeta-cat .cat-cuantos {
  display: block;
  margin-top: .1875rem;
  font-size: .75rem;
  color: var(--tinta-suave);
}

/* --- miga de pan --------------------------------------------------------- */

.miga {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .375rem;
  font-size: .8125rem;
  color: var(--tinta-suave);
  margin-bottom: .875rem;
}
.miga a { color: var(--lavanda-honda); text-decoration: none; padding: .375rem 0; }
.miga a:hover { text-decoration: underline; }
.miga span[aria-current] { color: var(--tinta); }
.franja-miga { padding: 1.25rem 1.25rem 0; margin: 0; }

/* --- buscador ------------------------------------------------------------ */

.oculto-visual {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* El buscador del catálogo: centrado y con medida.
   A todo el ancho de la pantalla parecía un formulario de trámite. Con 34rem
   y centrado bajo el título es lo que hace Sephora en su página de resultados:
   la caja tiene el ancho de una frase, no el de la ventana. */
.buscador {
  display: flex;
  gap: .5rem;
  margin: 1.25rem auto 1.5rem;
  width: min(34rem, 100%);
}
.buscador input[type="search"] {
  flex: 1;
  min-width: 0;
  min-height: 48px;
  padding: .625rem 1rem;
  font: inherit;
  font-size: 1rem;
  color: var(--tinta);
  background: var(--papel-alto);
  border: 1px solid var(--linea-firme);
  border-radius: 999px;      /* redondo, como la píldora de las categorías */
}
.buscador input::placeholder { color: var(--tinta-suave); }
.buscador input:focus-visible { outline: 2px solid var(--lavanda-honda); outline-offset: 1px; }
.buscador button {
  display: grid; place-items: center;
  width: 48px; min-height: 48px;
  border: 0;
  border-radius: 50%;
  background: var(--tinta);
  color: var(--papel-alto);
  cursor: pointer;
  transition: transform .18s ease, background .18s ease;
}
.buscador button:hover { transform: scale(1.06); background: var(--ciruela); }

/* El título y el buscador van juntos y centrados: es la cabecera de la página
   del catálogo, no una barra de herramientas pegada al margen. */
[data-seccion="tienda"] .franja > .titular { text-align: center; }
[data-seccion="tienda"] .cuantos-hay { text-align: center; }
.buscador button:focus-visible { outline: 2px solid var(--lavanda-honda); outline-offset: 2px; }

.cuantos-hay {
  margin: 0 0 .875rem;
  font-size: .8125rem;
  color: var(--tinta-suave);
}

/* --- ficha del producto -------------------------------------------------- */

.ficha-foto {
  aspect-ratio: 1;
  background: var(--papel-hondo);
  overflow: hidden;
}
.ficha-foto img { width: 100%; height: 100%; object-fit: cover; }
.ficha-foto .baldosa { font-size: 5rem; }

.ficha-cabeza { padding: 1.5rem 1.25rem 0; }

.ficha-categoria {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: .6875rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  text-decoration: none;
}

.ficha-nombre {
  font-family: var(--display);
  font-size: clamp(1.75rem, 7.5vw, 2.25rem);
  font-weight: 400;
  line-height: 1.1;
  margin: .5rem 0 0;
  text-wrap: balance;
}
.ficha-que {
  display: block;
  font-size: .8125rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  margin-top: .375rem;
}

.ficha-precio {
  display: flex;
  align-items: baseline;
  gap: .625rem;
  margin-top: 1rem;
}
.ficha-precio .valor {
  font-family: var(--display);
  font-size: 1.875rem;
  font-variant-numeric: tabular-nums;
}
.ficha-precio .peso { font-size: .875rem; color: var(--tinta-suave); }

.ficha-cuerpo { padding: 1.5rem 1.25rem 0; display: flex; flex-direction: column; gap: 1.75rem; }

.ficha-texto { font-size: 1.0625rem; line-height: 1.7; margin: 0; }

/* Los ingredientes a la vista, como en Lush. No es letra pequeña legal: es el
   argumento de venta de un jabón hecho a mano. */
.ingredientes {
  background: var(--papel-alto);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  padding: 1.125rem 1.25rem;
}
.ingredientes ol {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
}
.ingredientes li {
  padding: .5rem 0;
  font-size: .9375rem;
  line-height: 1.45;
}
.ingredientes li + li { border-top: 1px solid var(--linea); }
.ingredientes .orden {
  display: inline-block;
  width: 1.5rem;
  color: var(--tinta-suave);
  font-size: .75rem;
  font-variant-numeric: tabular-nums;
}

.aviso-uso {
  border-left: 3px solid var(--lavanda);
  padding-left: .875rem;
  font-size: .9375rem;
  color: var(--tinta-suave);
  margin: 0;
}

/* El enlace de Ofertas en la barra de categorías. En rosa y en negrita porque
   es lo único de esa fila que tiene fecha de caducidad. */
.cat-ofertas { color: var(--rosa-hondo); font-weight: 700; }

/* --- ofertas: el precio de antes tachado ---------------------------------

   El tachado va en gris y más pequeño; el de hoy manda. Al revés —los dos del
   mismo tamaño— la mirada tiene que decidir cuál de los dos números le importa,
   y ése es trabajo que la tienda no debe pedirle a nadie. */
.precio-antes {
  color: var(--tinta-suave);
  font-size: .85em;
  font-weight: 400;
  text-decoration-thickness: 1px;
  margin-right: .375rem;
}
.ficha-precio .valor.rebajado { color: var(--rosa-hondo); }

/* El distintivo sobre la foto, en la esquina contraria a la de "Agotado": las
   dos no pueden salir a la vez —lo agotado no se ofrece— pero si algún día
   coinciden por un cambio, no se pisan. */
.marca-oferta {
  position: absolute;
  top: .5rem; left: .5rem;
  z-index: 2;
  padding: .25rem .5rem;
  border-radius: 999px;
  background: var(--rosa-hondo);
  color: #fff;
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: .02em;
}

.ficha-oferta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .5rem;
  margin: .625rem 0 0;
  font-size: .9375rem;
  color: var(--tinta-suave);
}
.ficha-oferta-pct {
  padding: .1875rem .5rem;
  border-radius: 999px;
  background: rgba(173, 70, 113, .12);
  color: var(--rosa-hondo);
  font-weight: 700;
  font-size: .8125rem;
}

/* En la barra fija el tachado se apila encima, que es donde hay sitio: la
   barra mide 3,5 rem y dos números en fila dejarían el botón sin espacio. */
.comprar-fijo .precio { display: flex; flex-direction: column; line-height: 1.1; }
.comprar-fijo .precio-antes { margin: 0; font-size: .75rem; }

/* --- el combo: elegir tres jabones ---------------------------------------

   Una rejilla de fotos con casilla, no una lista con cuadraditos. Lo que se
   elige aquí se elige con los ojos —son jabones, y el que se ve bonito gana—,
   así que la foto manda el tamaño y el nombre va debajo.

   El área de toque es la tarjeta ENTERA, no la casilla. En un teléfono, una
   casilla de 16 px rodeada de foto es la forma más fiable de que alguien crea
   que ya eligió y no haya elegido nada. */
.combo { display: flex; flex-direction: column; gap: .875rem; }

.combo-cuenta {
  margin: 0;
  font-size: .9375rem;
  font-variant-numeric: tabular-nums;
  color: var(--tinta-suave);
}
/* Cuando ya están los tres, el contador deja de ser un dato y pasa a ser un
   permiso: cambia de color para que se vea desde el rabillo del ojo, que es
   donde está mirando quien acaba de tocar el tercero. */
.combo-cuenta[data-listo] { color: var(--ciruela); font-weight: 600; }

.combo-opciones {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: .75rem;
}

.combo-opcion {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: .5rem;
  cursor: pointer;
  border-radius: var(--radio-chico);
  /* El borde existe siempre, transparente. Si apareciera sólo al marcar, la
     tarjeta crecería 2 px y toda la rejilla daría un salto al elegir. */
  border: 2px solid transparent;
  padding: .25rem;
  transition: border-color .16s ease, background-color .16s ease;
}
.combo-opcion:hover { background: var(--papel-hondo); }

.combo-opcion input {
  position: absolute;
  opacity: 0;
  width: 1px; height: 1px;
  margin: 0;
}
/* El foco del teclado se dibuja sobre la tarjeta, ya que la casilla real está
   escondida. Sin esto, quien navega con el tabulador no ve dónde está.

   `:focus-visible` y no `:focus-within`: con el segundo, el jabón que se acaba
   de tocar con el dedo o con el ratón se quedaba con un aro lavanda encima del
   borde ciruela de elegido. Dos señales para el mismo estado, y la de teclado
   puesta a quien no está usando el teclado. */
.combo-opcion:has(input:focus-visible) {
  outline: 2px solid var(--lavanda-honda);
  outline-offset: 2px;
}

.combo-foto {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radio-chico);
  background: var(--papel-hondo);
}
/* El jabón sin foto. NO reutiliza `.baldosa`: aquélla se estira al alto de su
   caja (`height:100%`) y aquí la caja no tiene alto propio —lo pone la
   proporción cuadrada—, así que las dos reglas se peleaban por el mismo píxel. */
.combo-inicial {
  display: grid;
  place-items: center;
  color: #fff;
  font-family: var(--display);
  font-size: 1.75rem;
  user-select: none;
}
.combo-nombre {
  font-size: .75rem;
  line-height: 1.3;
  color: var(--tinta-suave);
  text-align: center;
}

.combo-marca {
  position: absolute;
  top: .5rem; right: .5rem;
  z-index: 2;
  width: 1.375rem; height: 1.375rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--papel-alto);
  border: 1px solid var(--linea-firme);
  color: transparent;
  transition: background-color .16s ease, color .16s ease, border-color .16s ease;
}
.combo-marca svg { width: .875rem; height: .875rem; }

.combo-opcion:has(input:checked) { border-color: var(--ciruela); background: var(--papel-hondo); }
.combo-opcion:has(input:checked) .combo-marca {
  background: var(--ciruela);
  border-color: var(--ciruela);
  color: #fff;
}
/* Un grupo por tamaño. El título dice el precio, que es lo que distingue a un
   grupo de otro: sin él, tres rejillas seguidas de jabones parecen una sola
   partida en tres. */
.combo-grupo { border: 0; padding: 0; margin: 0; }
.combo-grupo + .combo-grupo { margin-top: 1.25rem; }
.combo-grupo-tit {
  padding: 0;
  margin-bottom: .625rem;
  font-size: .8125rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--tinta-suave);
}
.combo-grupo:has(input:checked) .combo-grupo-tit { color: var(--ciruela); }

/* Sin `:has` —Safari por debajo de 15.4, que todavía se ve en estos teléfonos—
   la elección seguiría funcionando pero no se vería. La casilla vuelve a la
   vista y hace de señal. */
@supports not selector(:has(*)) {
  .combo-opcion input {
    position: static;
    opacity: 1;
    width: 1.125rem; height: 1.125rem;
    align-self: center;
  }
  .combo-marca { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .combo-opcion, .combo-marca { transition: none; }
}

/* El botón de comprar, fijo al fondo y por encima de la barra de secciones.
   Baymard mide entre 5 y 12% más de conversión sólo por no obligar a subir
   hasta el precio para poder pulsar. */
.comprar-fijo {
  position: fixed;
  left: 0; right: 0;
  bottom: var(--barra-abajo);
  z-index: 25;
  display: flex;
  align-items: center;
  gap: .875rem;
  padding: .75rem 1.25rem;
  background: var(--papel-alto);
  border-top: 1px solid var(--linea-firme);
  box-shadow: 0 -8px 24px -20px rgba(44, 35, 51, .5);
}
.comprar-fijo .precio {
  font-family: var(--display);
  font-size: 1.25rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.comprar-fijo .boton { flex: 1; }

/* --- carrito ------------------------------------------------------------- */

.renglones { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: .75rem; }

.renglon {
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr);
  gap: .875rem;
  align-items: start;
  background: var(--papel-alto);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  padding: .875rem;
}
.renglon-foto { aspect-ratio: 1; border-radius: var(--radio-chico); overflow: hidden; background: var(--papel-hondo); }
.renglon-foto img { width: 100%; height: 100%; object-fit: cover; }
.renglon-foto .baldosa { font-size: 1.5rem; }
.renglon-datos { display: flex; flex-direction: column; gap: .375rem; min-width: 0; }
.renglon-nombre { font-family: var(--display); font-size: 1.0625rem; line-height: 1.2; }
.renglon-precio { font-size: .875rem; color: var(--tinta-suave); font-variant-numeric: tabular-nums; }
/* Los tres jabones del combo. Van pegados al nombre y en ciruela, no en gris:
   es lo que se revisa antes de pagar, y en gris se lee como letra pequeña. */
.renglon-elegidos {
  font-size: .8125rem;
  line-height: 1.35;
  color: var(--ciruela);
}

/* El contador y "Quitar" van juntos. Antes "Quitar" llevaba margen automático
   y en pantalla ancha acababa a 900 px del botón de más, al otro extremo de
   una fila de 1024: se leía como algo suelto, no como la acción de ese
   renglón. Lo que va a la derecha es el total, que es lo que se busca al
   revisar un carrito. */
.contador { display: flex; align-items: center; flex-wrap: wrap; gap: .5rem; }
/* `:not(.quitar)` no es adorno. Sin él este selector —una clase y un tipo,
   especificidad (0,1,1)— le gana al `.quitar` de abajo (0,1,0) esté donde
   esté en el archivo, y le impone los 44x44 fijos, el borde y los 18 px. La
   palabra "Quitar" mide 55 px y se salía de su propia caja: quedaba un
   recuadro con la palabra atravesándolo, calcado a los de "−" y "+".
   Por eso no se encontraba cómo eliminar nada del carrito. */
.contador button:not(.quitar) {
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 1px solid var(--linea-firme);
  border-radius: var(--radio-chico);
  background: var(--papel-alto);
  color: var(--tinta);
  font-size: 1.125rem;
  cursor: pointer;
}
.contador .cuantos { min-width: 2rem; text-align: center; font-variant-numeric: tabular-nums; font-weight: 600; }
/* "Quitar" tiene que leerse como OTRA cosa que "−" y "+": papelera, ciruela,
   y del ancho que pida el texto. 44 px de alto, que es lo que acierta un dedo
   sin apuntar. */
.quitar {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  width: auto;
  min-width: 44px;
  min-height: 44px;
  padding: 0 .75rem;
  margin-left: .25rem;
  border: 1px solid var(--linea-firme);
  border-radius: var(--radio-chico);
  background: var(--papel-alto);
  color: var(--ciruela);
  font-family: var(--ui);
  font-size: .875rem;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
}
.quitar svg {
  width: 16px; height: 16px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.quitar:hover { color: var(--alerta); border-color: var(--alerta); background: var(--papel); }
.quitar:focus-visible { outline: 2px solid var(--alerta); outline-offset: 2px; }
.quitar:hover { text-decoration: underline; }
.quitar:focus-visible { outline: 2px solid var(--alerta); outline-offset: 2px; border-radius: var(--radio-chico); }

.renglon-total {
  margin-left: auto;
  font-size: 1rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.suma {
  background: var(--papel-alto);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  padding: 1.125rem 1.25rem;
  display: flex;
  flex-direction: column;
  gap: .625rem;
}
.suma-linea { display: flex; justify-content: space-between; gap: 1rem; font-size: .9375rem; }
.suma-linea.total {
  border-top: 1px solid var(--linea-firme);
  padding-top: .75rem;
  font-family: var(--display);
  font-size: 1.375rem;
}
.suma-linea .cifra { font-variant-numeric: tabular-nums; }

.vacio-caja {
  text-align: center;
  padding: 3rem 1.25rem;
  color: var(--tinta-suave);
}

/* --- el formulario del pedido -------------------------------------------
   Lo que dice la investigación y aquí faltaba entero:

   · El rótulo ENCIMA del campo, no al lado. Baymard lo mide: evita el
     desplazamiento lateral en teléfono y el rótulo no desaparece al escribir.
   · Una sola columna. En un pedido no hay nada que comparar de lado a lado.
   · Campos anchos y altos. 52 px es lo que hace que un dedo acierte a la
     primera.
   · El foco tiene que verse siempre: quien llega con el teclado necesita
     saber dónde está.
   · El error se avisa al SALIR del campo, no en cada tecla —regañar mientras
     alguien escribe su nombre es lo peor de las dos opciones— ni sólo al
     enviar, que obliga a volver arriba a buscar qué falló.

   Antes esto no tenía ni una regla: los rótulos salían al lado del campo, en
   versalitas, y las áreas de texto en monoespaciada, porque el navegador no
   hereda la tipografía en textarea. */

.formulario-pedido {
  display: flex;
  flex-direction: column;
  gap: 1.375rem;
  background: var(--papel-alto);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
  padding: 1.5rem 1.25rem;
}

.seccion-datos { margin-top: 2.5rem; }

.campo-forma {
  display: flex;
  flex-direction: column;
  gap: .4375rem;
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
}

.campo-forma > label,
.campo-forma > legend {
  font-size: .875rem;
  font-weight: 600;
  color: var(--tinta);
  padding: 0;
}
.campo-forma .opcional {
  font-weight: 400;
  font-size: .75rem;
  color: var(--tinta-suave);
  margin-left: .25rem;
}

/* `font: inherit` no es opcional: sin él, textarea sale en monoespaciada. */
.campo-forma input[type="text"],
/* Faltaba `email`: al pedir el correo en el pedido, ese campo salía con el
   estilo del navegador —21 px de alto y borde gris de sistema— en medio de
   campos de 53 px. Y por debajo de 16 px de fuente, Safari en iPhone hace
   zoom al tocarlo y descuadra la pantalla entera. */
.campo-forma input[type="email"],
.campo-forma input[type="tel"],
.campo-forma textarea {
  width: 100%;
  min-height: 52px;
  padding: .875rem 1rem;
  font: inherit;
  font-size: 1rem;
  line-height: 1.45;
  color: var(--tinta);
  background: var(--papel);
  border: 1px solid var(--linea-firme);
  border-radius: var(--radio-chico);
  transition: border-color .18s ease, box-shadow .18s ease;
}
.campo-forma textarea { resize: vertical; }
.campo-forma input::placeholder,
.campo-forma textarea::placeholder { color: var(--tinta-suave); }

.campo-forma input:focus,
.campo-forma textarea:focus {
  outline: 0;
  border-color: var(--ciruela);
  box-shadow: 0 0 0 3px rgba(125, 67, 104, .16);
  background: var(--papel-alto);
}

.campo-ayuda { margin: 0; font-size: .8125rem; color: var(--tinta-suave); line-height: 1.45; }
.pie-forma { text-align: center; }

/* El aviso de error tiene su sitio SIEMPRE, esté o no escrito.
   Antes aparecía y desaparecía cambiando el alto del campo, y eso movía el
   botón de confirmar hacia abajo justo entre el "aprieto" y el "suelto" del
   dedo: la persona pulsaba, el aviso salía, el botón se corría, y la
   pulsación no contaba. Había que pulsar dos veces sin saber por qué.
   Reservando el renglón, el aviso aparece sin mover nada. */
.campo-error {
  margin: 0;
  font-size: .8125rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--alerta);
}
/* `hidden` quita el elemento de la caja y del lector de pantalla. Aquí se
   sustituye por un hueco reservado: sigue sin anunciarse vacío porque no
   tiene texto, y el sitio ya está pedido. */
/* `!important` porque hay una regla global `[hidden] { display: none
   !important }` que si no gana siempre. Es el mismo tropiezo que tuvo el menú
   desplegable de la cabecera: el elemento se calculaba visible y medía cero. */
.campo-forma .campo-error[hidden] {
  display: block !important;
  min-height: 1.1rem;
  visibility: hidden;
}
.campo-forma.mal input,
.campo-forma.mal textarea { border-color: var(--alerta); }
.campo-forma.mal input:focus,
.campo-forma.mal textarea:focus { box-shadow: 0 0 0 3px rgba(180, 72, 95, .18); }

/* Cómo lo recibe: dos opciones que se tocan enteras, no dos puntitos.
   Un desplegable de dos elementos esconde la mitad de la decisión. */
.opciones { gap: .625rem; }
.opcion {
  display: flex;
  align-items: flex-start;
  gap: .75rem;
  padding: .875rem 1rem;
  border: 1px solid var(--linea-firme);
  border-radius: var(--radio-chico);
  cursor: pointer;
  transition: border-color .18s ease, background-color .18s ease;
}
.opcion:hover { background: var(--papel); }
.opcion input { margin: .1875rem 0 0; accent-color: var(--ciruela); width: 18px; height: 18px; flex: none; }
.opcion span { display: flex; flex-direction: column; gap: .125rem; }
.opcion strong { font-size: .9375rem; font-weight: 600; }
.opcion small { font-size: .8125rem; color: var(--tinta-suave); }
.opcion:has(input:checked) { border-color: var(--ciruela); background: var(--papel); }
.opcion:has(input:focus-visible) { outline: 2px solid var(--lavanda-honda); outline-offset: 2px; }

/* --- métodos de pago ----------------------------------------------------- */

.metodos { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: .5rem; }
.metodo {
  background: var(--papel-alto);
  border: 1px solid var(--linea);
  border-radius: var(--radio-chico);
  padding: .875rem 1rem;
}
.metodo .nombre { font-weight: 600; font-size: .9375rem; }
.metodo .dato { font-size: .875rem; color: var(--tinta-suave); }

/* --- pie ----------------------------------------------------------------- */

/* --- el pie ---------------------------------------------------------------
   Era una columna pegada a la izquierda con tres enlaces; en escritorio
   dejaba más de la mitad del ancho vacío y no respondía ninguna de las
   preguntas que trae quien llega abajo sin comprar.

   Ahora son tres bloques con tres trabajos —quién es, qué vende, cómo se
   pide— y una franja legal debajo, que es la anatomía que usan las tiendas
   grandes. Con una diferencia: aquí todo sale de datos que ya existen, así
   que no hay un solo enlace que lleve a una página vacía. */

.pie {
  margin-top: 3rem;
  background: var(--papel-hondo);
  border-top: 1px solid var(--linea);
  /* Abajo reserva el alto de la barra fija. Quien reservaba sitio era
     `#contenido`, y el pie va FUERA de él —cierra el <main> antes— así que su
     última línea quedaba debajo de la barra. Se ve poco porque ahí está el
     crédito, pero está tapado igual. */
  padding: 2.5rem 0 calc(var(--barra-abajo) + .5rem);
}
.pie-caja {
  display: grid;
  gap: 2.25rem;
  padding: 0 1.25rem 2.25rem;
  max-width: 68rem;
  margin-inline: auto;
}
.pie-columna { min-width: 0; }

.pie-marca { font-family: var(--display); font-size: 1.375rem; margin: 0 0 .5rem; }
.pie-lema {
  font-family: var(--display);
  font-style: italic;
  font-size: 1rem;
  color: var(--ciruela);
  margin: 0 0 .9rem;
  max-width: 22rem;
}
/* La lista de lo que NO llevan, en versalitas chicas: es una firma, no un
   párrafo, y a este tamaño se lee de un vistazo sin competir con nada. */
.pie-sin {
  margin: 0;
  font-size: .75rem;
  letter-spacing: .06em;
  line-height: 1.7;
  text-transform: uppercase;
  color: var(--tinta-suave);
  max-width: 22rem;
}

.pie-titulo {
  font-family: var(--ui);
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ciruela);
  margin: 0 0 .85rem;
}
.pie-lista { list-style: none; margin: 0; padding: 0; }
.pie-lista li { margin-bottom: .35rem; }
.pie-lista a {
  color: var(--tinta);
  font-size: .9375rem;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  min-height: 40px;      /* el dedo, no el ojo */
}
.pie-lista a:hover { color: var(--ciruela); text-decoration: underline; text-underline-offset: 3px; }

/* Las tres familias en fila: son tres palabras cortas y en vertical parecen
   una letanía. */
.pie-familias { display: flex; flex-wrap: wrap; gap: 0 1.5rem; margin-bottom: .35rem; }

.pie-dato { display: block; font-size: .875rem; color: var(--tinta-suave); line-height: 1.6; }
.pie-dato-titulo { display: block; font-size: .9375rem; color: var(--tinta); }

/* La franja de abajo, un punto más honda. Es donde vivirán las páginas
   legales el día que existan; hoy lleva el aviso, el crédito y la luna. */
.pie-franja {
  background: rgba(44, 35, 51, .05);
  border-top: 1px solid var(--linea);
  padding: 1.25rem 1.25rem calc(var(--barra-abajo) + 1.25rem);
}
.pie-franja-caja { max-width: 68rem; margin-inline: auto; }
.pie-aviso { margin: 0 0 .35rem; font-size: .8125rem; color: var(--tinta-suave); }
.credito { margin: 0; font-size: .8125rem; color: var(--tinta-suave); }

@media (min-width: 48rem) {
  .pie-caja { grid-template-columns: 1.4fr 1fr 1.2fr; gap: 3rem; padding-inline: 2rem; }
  .pie-franja { padding-inline: 2rem; }
  .pie-franja-caja {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem 1.25rem;
  }
  .pie-aviso { margin: 0; }
  .credito { margin-left: auto; }
  .puerta-luna { margin-top: 0; }
}
.credito a {
  color: var(--lavanda-honda);
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* --- botón flotante de WhatsApp -----------------------------------------
   En rosa hondo y no en el verde de WhatsApp: el símbolo ya lo identifica, y
   un verde de otra marca en una esquina rompe la paleta de ésta.

   Por qué #ad4671 y no el ciruela: muestreando el PNG del logotipo, sus
   colores de marca son rosas (#e478a8 el dominante) y el azul de la luna
   (#9cb4cc). El ciruela #7d4368 está en la paleta pero NO aparece en el
   dibujo, así que el botón se leía más morado que la luna que tiene al lado.
   El rosa hondo es el que ya usa la insignia del carrito y queda cerca del
   rosa real de la marca sin perder contraste con el símbolo blanco.

   La altura se calcula, no se pone a ojo: tiene que quedar por encima de la
   barra de secciones y, en la ficha del producto, también por encima del
   botón de comprar. Taparle a alguien el botón de comprar con el de
   preguntar sería cambiar una venta por una consulta. */

.flotante-wa {
  position: fixed;
  right: 1rem;
  bottom: calc(var(--barra-abajo) + 1rem);
  z-index: 35;
  display: grid;
  place-items: center;
  width: 52px; height: 52px;
  border-radius: 50%;
  background: var(--rosa-hondo);
  color: #fff;
  box-shadow: 0 6px 20px -6px rgba(31, 24, 38, .55);
  transition: transform .25s cubic-bezier(.2, .7, .3, 1), box-shadow .25s ease;
}
.flotante-wa svg { width: 27px; height: 27px; fill: currentColor; position: relative; z-index: 1; }

/* Dos movimientos y ninguno más.
   Uno: entra solo, un segundo después de cargar, subiendo desde abajo. Que
   aparezca de golpe con la página lo convierte en parte del fondo; que llegue
   un momento después hace que el ojo lo registre una vez.
   Dos: un aro que se abre cada seis segundos y se desvanece. Es la señal de
   "aquí hay alguien" sin ser un reclamo parpadeante. Seis segundos es
   deliberado: a menos, cansa. */
/* `backwards` y no `both`. Con `both`, la animación de entrada se queda
   sujetando `transform: none` para siempre, y una animación le gana a una
   declaración normal: el `scale(1.07)` de :hover dejaba de hacer efecto. Con
   `backwards` el estado inicial se aplica antes de empezar, y al terminar el
   botón vuelve a sus reglas de siempre. */
.flotante-wa {
  animation: wa-entra .55s cubic-bezier(.2, .9, .3, 1.15) .9s backwards;
}

/* Dos aros, no uno, y desfasados. Uno solo a 22% del ciclo se ve poco más de
   un segundo cada seis y se pierde. Dos escalonados leen como un latido, que
   es lo que se quiere decir: aquí hay alguien.
   Van en un tono más claro que el botón —el aro era del MISMO color que el
   fondo del botón y por eso apenas se distinguía al salir. */
.flotante-wa::before,
.flotante-wa::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid var(--rosa);
  animation: wa-aro 2.8s linear infinite;
  pointer-events: none;
}
/* Medio ciclo de desfase, no dos segundos. Antes el aro tardaba 5 s en dar
   la vuelta y sólo se veía durante 2,2: quedaban casi tres segundos de nada, y
   quien miraba en ese hueco no veía ningún movimiento. Con 2,8 s de ciclo y el
   segundo aro a la mitad, siempre hay uno en el aire — el latido no se para. */
.flotante-wa::before { animation-delay: 0s; }
.flotante-wa::after  { animation-delay: 1.4s; }

@keyframes wa-entra {
  from { opacity: 0; transform: translateY(14px) scale(.92); }
  to   { opacity: 1; transform: none; }
}
/* El aro nace ya despegado (1.06) y se apaga a lo largo de TODO el ciclo, no
   en el primer 70 %. Antes tenía dos huecos: uno al nacer —a escala 1 el aro
   cae justo sobre el canto del botón y no se distingue— y otro al final, con
   el aro viejo ya invisible y el nuevo todavía sin salir. Con la caída lineal
   y medio ciclo de desfase siempre hay un aro a media altura. */
@keyframes wa-aro {
  0%   { transform: scale(1.06); opacity: .85; }
  100% { transform: scale(2);    opacity: 0; }
}

/* Quien pide menos movimiento no ve el latido. Es una preferencia del sistema
   operativo, y para mucha gente con migraña o vértigo no es un capricho. */
@media (prefers-reduced-motion: reduce) {
  .flotante-wa::before,
  .flotante-wa::after { animation: none; opacity: 0; }
  .flotante-wa { animation: none; }
}
.flotante-wa:hover, .flotante-wa:focus-visible { transform: scale(1.07); box-shadow: 0 10px 26px -8px rgba(31, 24, 38, .6); }
.flotante-wa:focus-visible { outline: 2px solid var(--rosa); outline-offset: 3px; }

/* En la ficha, el botón de comprar está fijo al fondo: hay que subir por
   encima de él. `:has` deja resolverlo sin marcar el body desde PHP. */
body:has(.comprar-fijo) .flotante-wa {
  bottom: calc(var(--barra-abajo) + 5.25rem);
}

/* --- aviso flotante ------------------------------------------------------ */

.aviso {
  position: fixed;
  left: 1rem; right: 1rem;
  bottom: calc(var(--barra-abajo) + 1rem);
  z-index: 40;
  padding: .875rem 1rem;
  background: var(--tinta);
  color: var(--papel-alto);
  border-radius: var(--radio-chico);
  font-size: .9375rem;
  box-shadow: 0 6px 24px rgba(20, 23, 15, .25);
}
.aviso[data-tipo="error"] { background: var(--alerta); }

/* =========================================================================
   TABLETA — de 48rem en adelante

   Aquí la barra de secciones sube: con el aparato en dos manos el pulgar ya no
   manda, y tener el menú arriba deja el fondo libre para el contenido.
   ========================================================================= */

@media (min-width: 48rem) {
  :root { --barra-abajo: 0px; }

  body { font-size: 17px; }

  /* Una sola fila, como Ulta: logo, enlaces, buscador, carrito. Antes eran
     dos barras —una con el logo solo y otra con las secciones— que sumaban
     120 px para lo que cabe en una. */
  .marca-barra { padding-inline: 2rem; gap: 1.5rem; }
  /* En computadora el logotipo va casi a su tamaño natural (201x72): es donde
     se ve más nítido y donde hay sitio de sobra —la cabecera usa 769 px de
     1440—. En el teléfono se queda en 3.25rem, que es lo que cabe al lado de
     la lupa y el carrito. */
  .marca-enlace img { height: 5rem; }
  .marca-enlace { margin-right: 0; }

  .enlaces-cabecera {
    display: flex;
    gap: 1.75rem;
    flex: none;
  }
  /* Sin esto "Nuestra historia" se parte en dos líneas y desnivela la fila. */
  .enlaces-cabecera a { white-space: nowrap; }
  /* El subrayado se dibuja desde el centro hacia los dos lados. Es un solo
     gesto y va con el resto: la portada se ordena al abrir, las piezas suben
     al entrar en pantalla, y aquí la línea se abre bajo la palabra. Un cambio
     de color a secas no dice nada; esto sí se siente al pasar. */
  .enlaces-cabecera a {
    position: relative;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    font-size: .9375rem;
    color: var(--tinta);
    text-decoration: none;
    transition: color .25s ease;
  }
  .enlaces-cabecera a::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: .5rem;
    height: 2px;
    background: var(--ciruela);
    transform: scaleX(0);
    transition: transform .32s cubic-bezier(.2, .7, .3, 1);
  }
  .enlaces-cabecera a:hover { color: var(--ciruela); }
  .enlaces-cabecera a:hover::after,
  .enlaces-cabecera a:focus-visible::after { transform: scaleX(1); }
  /* La sección en la que se está ya viene dibujada, y no se borra al pasar
     por otra: saber dónde se está no puede depender de dónde está el ratón. */
  .enlaces-cabecera a[aria-current] { color: var(--ciruela); }
  .enlaces-cabecera a[aria-current]::after { transform: scaleX(1); }
  .enlaces-cabecera a:focus-visible { outline: 2px solid var(--lavanda-honda); outline-offset: 2px; }

  /* En pantalla ancha el buscador está siempre puesto y la lupa suelta sobra. */
  .buscar-cabecera { display: flex; flex: 1 1 12rem; max-width: 22rem; margin-inline: auto; }
  .abrir-buscar { display: none; }

  /* Con ancho de sobra, el interruptor respira un poco más. Las dos letras se
     quedan: con los dos idiomas a la vista y uno marcado, escribir "English"
     entero ya no aclara nada y sí desequilibra la barra. */
  .idiomas { height: 40px; }
  .idioma { min-width: 38px; padding-inline: .7rem; font-size: .75rem; }
  .marca-barra.buscando .marca-enlace { display: flex; }

  /* La barra de secciones deja de hacer falta arriba: sus enlaces ya están en
     la cabecera. Se queda sólo en el teléfono. */
  .secciones { display: none; }

  #contenido { padding-bottom: 0; }

  .franja { padding: 3rem 2rem; }
  .rejilla { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.75rem 1.25rem; }

  /* La ficha en dos columnas: la foto a un lado y lo que se lee al otro, sin
     tener que desplazarse para ver el precio. */
  .ficha {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 0 2.5rem;
    align-items: start;
    padding: 2rem;
  }
  .ficha-foto { border-radius: var(--radio); grid-row: span 2; position: sticky; top: 5rem; }
  .ficha-cabeza, .ficha-cuerpo { padding: 0; }
  .ficha-cuerpo { margin-top: 1.75rem; }

  /* Con el precio y el botón a la vista, el botón fijo sobra. */
  .comprar-fijo {
    position: static;
    padding: 1.25rem 0 0;
    border-top: 0;
    box-shadow: none;
    background: none;
  }
  .comprar-fijo .precio { display: none; }

  .aviso { left: auto; right: 2rem; bottom: 2rem; max-width: 22rem; }
  /* Sin barra inferior el botón baja, y el aviso se aparta para no chocar. */
  .flotante-wa { right: 1.75rem; bottom: 1.75rem; width: 56px; height: 56px; }
  body:has(.comprar-fijo) .flotante-wa { bottom: 1.75rem; }
  .aviso { right: 6.5rem; }
  .pie { padding: 3rem 0 0; }
}

/* =========================================================================
   COMPUTADORA — de 64rem en adelante
   ========================================================================= */

@media (min-width: 64rem) {
  /* El ancho lo pone la FRANJA con su relleno, no cada hijo con margen
     automático. Con lo anterior, cualquier hijo que trajera su propio
     max-width —la entradilla, 34rem— se centraba solo: el titular arrancaba
     en 208 px y su párrafo en 448. Doscientos cuarenta píxeles de desfase que
     sólo se ven en computadora, y que en el teléfono no existían. */
  .franja { padding-inline: max(2rem, calc(50% - 40rem)); }
  .marca-barra { padding-inline: max(2rem, calc(50% - 40rem)); }
  .secciones { padding-inline: max(2rem, calc(50% - 40rem)); }

  .rejilla { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2rem 1.5rem; }
  .rejilla-cat { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.5rem; }

  /* Los servicios sólo caben aquí. En tableta se caen enteros: cuando falta
     ancho, lo primero que se sacrifica es lo accesorio. */
  .servicios-cabecera { display: flex; gap: 1.5rem; align-items: center; }

  .barra-categorias { padding-inline: max(2rem, calc(50% - 40rem)); }
  .cat-lista { padding: 0; overflow: visible; }
  .cat-item { position: static; }

  /* El panel cuelga de la barra entera, no de su enlace: así puede ocupar el
     ancho del contenido y las fotos se ven de verdad. */
  .cat-panel {
    display: block;
    position: absolute;
    left: 0; right: 0;
    top: 100%;
    background: var(--papel-alto);
    border-bottom: 1px solid var(--linea);
    box-shadow: 0 20px 40px -24px rgba(31, 24, 38, .45);
    padding: 1.75rem max(2rem, calc(50% - 40rem));
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity .22s ease, transform .22s ease, visibility .22s;
  }
  .cat-item:hover .cat-panel,
  .cat-item:focus-within .cat-panel {
    opacity: 1;
    visibility: visible;
    transform: none;
  }

  /* Una columna por subcategoría, con su nombre de cabecera enlazado — la
     anatomía de Sephora. El nombre de la columna ES un enlace y no un rótulo
     muerto: es la forma más corta de llegar a la subcategoría, y si no lo
     fuera, el menú obligaría a pasar por la familia entera. */
  .cat-panel-columnas {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: 1.75rem 2.25rem;
    margin-bottom: 1.25rem;
  }
  /* `min-width: 0` no es adorno. Una celda de rejilla no se encoge por debajo
     del tamaño NATURAL de lo que lleva dentro, y las fotos de producto miden
     1024 px: sin esto, cada columna se plantaba en 1024 px de ancho, la foto
     salía a tamaño completo y el menú desplegable medía 3.422 px de alto.
     El `max-height` de la foto es el cinturón: aunque algo vuelva a empujar,
     una miniatura de menú no puede pasar de ahí. */
  .cat-columna { min-width: 0; }
  .cat-panel-lista li { min-width: 0; }
  .cat-columna-titulo {
    display: block;
    font-family: var(--display);
    font-size: 1.0625rem;
    color: var(--tinta);
    text-decoration: none;
    padding-bottom: .55rem;
    margin-bottom: .85rem;
    border-bottom: 1px solid var(--linea);
  }
  .cat-columna-titulo:hover { color: var(--ciruela); }

  .cat-panel-lista {
    display: grid;
    grid-template-columns: 1fr;
    gap: .85rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .cat-panel-lista a {
    display: grid;
    grid-template-columns: 3.25rem 1fr;
    align-items: center;
    gap: .1rem .7rem;
    text-decoration: none;
    color: var(--tinta);
    min-width: 0;
  }
  .cat-panel-lista a > .cat-panel-foto { grid-row: 1 / 3; max-width: 3.25rem; }
  .cat-panel-lista a > .cat-panel-nombre,
  .cat-panel-lista a > .cat-panel-precio { min-width: 0; overflow-wrap: anywhere; }
  .cat-panel-foto {
    aspect-ratio: 1;
    width: 100%;
    max-width: 5.5rem;
    border-radius: var(--radio-chico);
    overflow: hidden;
    background: var(--papel-hondo);
  }
  .cat-panel-foto img { width: 100%; height: 100%; object-fit: cover; transition: transform .4s ease; }
  .cat-panel-lista a:hover .cat-panel-foto img { transform: scale(1.06); }
  .cat-panel-foto .baldosa { font-size: 1.75rem; }
  .cat-panel-nombre { font-size: .875rem; line-height: 1.25; }
  .cat-panel-precio { font-size: .8125rem; font-weight: 600; font-variant-numeric: tabular-nums; }
  .cat-panel-lista a:focus-visible { outline: 2px solid var(--lavanda-honda); outline-offset: 3px; border-radius: var(--radio-chico); }

  .cat-panel-todo {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    color: var(--ciruela);
    font-size: .875rem;
    font-weight: 600;
    text-decoration: none;
  }
  .cat-panel-todo:hover { text-decoration: underline; }
  .franja-miga { padding-inline: max(2rem, calc(50% - 40rem)); }
  .buscador { max-width: 30rem; }

  /* De 64rem en adelante cabe el banner entero: los productos a la derecha y
     el texto en el cielo vacío de la izquierda, que es donde la composición
     dejó sitio a propósito. */
  [data-seccion="inicio"] main { display: block; }

  /* --- el héroe con la foto de la casa ---------------------------------
     La foto va TAL CUAL la entregó la dueña: 1376x768, sin recortar y sin
     alargar. El intento anterior le añadía mármol por la izquierda para
     llegar a la proporción de la banda, y el resultado era que el bodegón
     quedaba pequeño y lejos del texto.

     Aquí la banda no se llena estirando la foto: se llena con un degradado
     que continúa el propio muro y la propia encimera de la imagen —los tonos
     están muestreados de su columna izquierda, del #d2c7b7 de la pared al
     #e8e7e3 del mármol—, y la foto entra por la derecha fundiéndose sobre él.
     Así la foto se puede poner grande sin que sobre lienzo por ningún lado. */
  .noche.con-banner {
    color: var(--tinta);
    position: relative;
    overflow: hidden;
    padding-block: clamp(1.75rem, 5vh, 4rem);

    /* Una sola variable manda: el alto de la banda. De ahí sale el ancho que
       ocupa la foto (su proporción por la escala), y de ahí sale tanto la
       reserva de sitio del texto como dónde funde el degradado. Con números
       sueltos, cada alto de ventana descuadraba una de las tres cosas. */
    --banda: min(34rem, calc(100vh - 13rem));
    /* 1.30 y no 1.14. Medido contra los bordes del bodegón en la foto: a
       1.14 el grupo de productos ocupaba el 75 % del alto de la banda y en un
       portátil bajo se quedaba en 314 px —la etiqueta del BALANCE no se leía—.
       A 1.30 sube al 86 %, que es donde vive un héroe de comercio. El tope
       seguro es 1.37: pasado eso el recorte de abajo empieza a morder el higo. */
    --escala: 1.30;
    --foto: calc(var(--banda) * 1.792 * var(--escala));

    min-height: var(--banda);
    display: flex;
    flex-direction: column;
    justify-content: center;

    /* El muro y la encimera, continuados. */
    background-image: linear-gradient(to bottom,
      #d2c7b7 0%, #cfc0ae 30%, #cbb8a3 45%, #c4b098 53%,
      #e3ded6 59%, #e8e5df 70%, #ebeae6 86%, #e8e7e3 100%);

    /* El texto se detiene antes del jabón. El bodegón empieza al 46 % del
       ancho de la foto, así que se reserva el 54 % de la foto y un dedo más. */
    padding-right: calc(var(--foto) * .54 + 1.5rem);
  }

  /* La foto, en su propia capa para poder fundirle el canto izquierdo. Un
     borde duro sobre el degradado se ve como un recorte pegado; con la
     máscara, la imagen aparece del muro. */
  .noche.con-banner::after {
    content: "";
    position: absolute;
    inset: 0;
    /* La foto la pone PHP en `--foto-heroe` desde lo que la dueña subió. El
       valor de reserva es el de fábrica: si algún día el ajuste se queda
       vacío, la portada sigue teniendo fondo en vez de un rectángulo gris. */
    background: var(--foto-heroe, url("/assets/img/hero-lunas.jpg")) right center / auto calc(var(--escala) * 100%) no-repeat;
    -webkit-mask-image: linear-gradient(to right,
      transparent calc(100% - var(--foto)),
      #000 calc(100% - var(--foto) + 7rem));
    mask-image: linear-gradient(to right,
      transparent calc(100% - var(--foto)),
      #000 calc(100% - var(--foto) + 7rem));
    pointer-events: none;
  }
  .noche.con-banner > * { position: relative; z-index: 1; }

  .noche.con-banner > * { max-width: 36rem; }

  /* Sobre azul claro se invierte todo el texto del héroe: lo que estaba en
     crema sobre ciruela deja de leerse en cuanto el fondo se aclara. */
  .noche.con-banner::before { display: none; }
  /* El ciruela de marca sobre el muro da 4.22:1 y este rótulo son 11 px:
     por debajo del 4.5:1 que exige la norma para texto pequeño. Un paso más
     hondo del MISMO ciruela lo lleva a 5.41:1 sin salirse de la paleta. El
     `em` del titular se queda en el ciruela de siempre: a 44 px el umbral es
     3:1 y lo pasa de sobra. */
  .noche.con-banner .rotulo { color: #6c3759; }
  .noche.con-banner .titular { color: var(--tinta); }
  .noche.con-banner .titular em { color: var(--ciruela); }
  .noche.con-banner .entradilla { color: #4a3f52; }
  .noche.con-banner .boton { background: var(--tinta); color: var(--papel-alto); }
  .noche.con-banner .boton.suave {
    background: rgba(255, 255, 255, .78);
    color: var(--tinta);
    border: 1px solid rgba(44, 35, 51, .25);
  }
  /* La luna suelta se va del héroe en escritorio. Sobraba por dos motivos: el
     logotipo entero ya está en la cabecera, 200 px más arriba —dos marcas
     apiladas—, y aquí caía justo encima de la pastilla de champú, que se lee
     como un descuido y no como una decisión. En teléfono sí se queda: allí no
     hay foto y es lo único que pone marca sobre la noche. */
  .noche.con-banner .marca-grande { display: none; }

  .ficha {
    /* El mismo relleno que `.franja`, `.marca-barra` y `.secciones`, y por la
       misma razón. Antes era una caja de 64rem con margen automático, y a
       exactamente 1024 px de ventana ese margen valía cero: el nombre del
       producto, el precio y el texto tocaban los dos bordes de la pantalla sin
       un milímetro de aire.

       Con `max(2rem, ...)` el contenido sigue topando en 64rem cuando hay
       sitio —de 1088 px en adelante mide exactamente lo mismo que antes— y
       nunca baja de 2rem de respiro cuando no lo hay. */
    width: auto;
    margin-inline: 0;
    padding-inline: max(2rem, calc(50% - 40rem));
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: 0 4rem;
  }
  /* El pie ya NO lleva relleno lateral: lo ponen sus cajas de dentro. Con el
     relleno aquí, la franja de abajo se quedaba en 1.024 px flotando en mitad
     de la pantalla en vez de tocar los dos bordes. */
  .pie { padding-inline: 0; }
  /* .pie-franja SI necesita esta formula: es una barra a todo el ancho y asi
     centra su contenido en 68rem. .pie-caja NO: ya se centra sola con su
     max-width:68rem y margin-inline:auto (linea 1595). Al aplicarle ademas
     este relleno —cuyo 50% es de la PANTALLA, no de la caja— los dos
     mecanismos se sumaban y el relleno se comia el contenido desde dentro:
     a 1920 dejaba 256px para tres columnas, que caian a 62/44/53 y partian
     las palabras por la mitad. Conserva el padding-inline: 2rem de la linea
     1661, que es el que le toca. */
  .pie-franja { padding-inline: max(2rem, calc(50% - 34rem)); }
}

/* --- aparición al bajar --------------------------------------------------
   Un solo gesto, repetido: lo que entra en pantalla sube dos centímetros y se
   revela. Escalonado dentro de cada rejilla, para que se lea como una mano
   colocando piezas y no como doce cosas saltando a la vez.

   Sin JavaScript no se anima nada y todo se ve: la clase que oculta se pone
   desde el script, así que si falla, la tienda queda completa y quieta. */

.js .aparece {
  opacity: 0;
  transform: translateY(18px);
}
.js .aparece.visible {
  opacity: 1;
  transform: none;
  transition: opacity .7s ease, transform .7s cubic-bezier(.2, .7, .3, 1);
}
/* El escalonado va en variable para poder ponerlo desde el marcado. */
.js .aparece.visible { transition-delay: calc(var(--turno, 0) * 70ms); }

/* La entrada de la portada: no espera a que se baje, se ordena sola al abrir. */
.js .noche .entra {
  opacity: 0;
  transform: translateY(14px);
  animation: entrar .8s cubic-bezier(.2, .7, .3, 1) forwards;
  animation-delay: calc(var(--turno, 0) * 110ms + 120ms);
}
@keyframes entrar { to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  /* Quien pidió menos movimiento no puede quedarse con la página en blanco
     esperando una animación que ya no corre. */
  .js .aparece, .js .noche .entra { opacity: 1 !important; transform: none !important; }
  .flotante-wa { animation: none; opacity: 1; transform: none; }
  .flotante-wa::before, .flotante-wa::after { display: none; }
}

/* --- el relato de "Nuestra historia" ------------------------------------
   Una columna de lectura, no una caja de texto. La medida se corta a unos 62
   caracteres porque una línea más larga obliga al ojo a buscar dónde empieza
   la siguiente, y este texto está para leerse entero, no para escanearse.

   Es el único sitio de la tienda donde el texto manda sobre la imagen. */

.relato {
  max-width: 34rem;
  margin-inline: auto;
}
.relato p {
  font-size: 1.0625rem;
  line-height: 1.75;
  color: var(--tinta-suave);
  margin-bottom: 1.15rem;
}
.relato p:last-child { margin-bottom: 0; }
.relato .subtitular { margin-bottom: 1.5rem; }

/* La cita destacada. En Playfair y en ciruela, con aire arriba y abajo: es la
   frase que sostiene el resto —la de la hija— y necesita el silencio. */
.relato-cita {
  font-family: var(--display);
  font-size: clamp(1.375rem, 4.5vw, 1.75rem);
  font-style: italic;
  line-height: 1.35;
  color: var(--ciruela);
  margin: 2.25rem 0 2.25rem;
  padding-left: 1.25rem;
  border-left: 2px solid var(--rosa);
}

.relato-firma {
  font-family: var(--display);
  font-size: 1.5rem;
  font-style: italic;
  color: var(--tinta);
  margin-top: 2rem;
}
.relato-lema {
  font-size: .8125rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ciruela);
  margin-top: .5rem;
}

/* La entrada de la página va en la noche de siempre, no en el banner: aquí no
   se vende producto, se presenta a una persona, y la foto de tres frascos
   competiría con eso. */
.historia-entrada { text-align: center; }
.historia-entrada .entradilla { margin-inline: auto; max-width: 34rem; }

/* --- el carril de productos de la portada ---------------------------------
   Una fila que se desliza, no un carrusel que se mueve solo. La diferencia
   importa: el auto-avance es la parte de los carruseles de tienda que la
   gente odia —te quita el control justo cuando ibas a leer el precio— y los
   datos de clics en carruseles son malos precisamente por eso.

   Aquí manda el dedo. Lo que sí se hace es dejar la siguiente tarjeta
   ASOMADA: es lo único que hace falta para que se entienda, sin flechas ni
   puntitos, que eso se corre. */

.carril-caja { position: relative; }

.carril {
  display: flex;
  gap: .875rem;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-left: 0;
  padding-bottom: .5rem;
  /* La barra de desplazamiento se esconde, pero el desplazamiento con teclado
     sigue existiendo: la lista es focalizable y responde a las flechas. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.carril::-webkit-scrollbar { display: none; }
.carril:focus-visible { outline: 2px solid var(--ciruela); outline-offset: 6px; border-radius: var(--radio-chico); }

.carril > li {
  flex: 0 0 62%;              /* 62% deja asomar la siguiente en el teléfono */
  scroll-snap-align: start;
  min-width: 0;
}

/* Las flechas, ARRIBA Y A LA DERECHA, y en todos los tamaños.
   
   Antes sólo salían a partir de 1024 px, flotando a los lados del carril. El
   razonamiento estaba escrito aquí: "en el teléfono estorban y el gesto ya
   existe". Es medio cierto — estorban si van ENCIMA de una tarjeta, que es
   donde estaban — pero se comió la otra mitad del problema: el gesto existe
   sólo para quien adivina que existe. Con la tarjeta asomando se entiende
   cuando ya sabes lo que buscas; si no, la fila parece un producto y medio y
   ahí se acaba el catálogo.
   
   Puestas aquí no tapan nada, se ven sin desplazarse, y son la misma pieza en
   los tres tamaños en vez de dos mecanismos distintos que hay que mantener. */
.carril-caja { padding-top: 3rem; }
/* El carril cabe entero: no habrá flechas nunca, así que tampoco su hueco. */
.carril-caja.sin-flechas { padding-top: 0; }

.carril-flecha {
  display: grid;
  place-items: center;
  position: absolute;
  top: 0;
  width: 2.5rem; height: 2.5rem;
  border-radius: 50%;
  border: 1px solid var(--linea-firme);
  background: var(--papel-alto);
  color: var(--tinta);
  cursor: pointer;
  z-index: 2;
  transition: transform .2s ease, box-shadow .2s ease, opacity .2s ease;
}
.carril-flecha svg { width: 20px; height: 20px; }
.carril-flecha.atras    { right: 3rem; }
.carril-flecha.adelante { right: 0; }
.carril-flecha:hover { transform: scale(1.08); box-shadow: 0 10px 22px -8px rgba(31, 24, 38, .45); }

/* Escondida pero SIN quitarle el sitio: con `display:none` las dos flechas
   bailaban de posición al llegar al principio o al final del carril.
   `visibility` también la saca del árbol de accesibilidad, así que un lector
   de pantalla tampoco la anuncia. */
.carril-flecha[hidden] { display: grid; visibility: hidden; opacity: 0; }

@media (min-width: 48rem) {
  .carril > li { flex-basis: 32%; }
  .carril-flecha { width: 2.75rem; height: 2.75rem; }
}

@media (min-width: 64rem) {
  .carril > li { flex-basis: 23.5%; }
}

@media (prefers-reduced-motion: reduce) {
  .carril { scroll-behavior: auto; }
}

/* El título de Destacados lleva la estrella delante: es la misma que la dueña
   enciende en el panel, así que lo que ella pulsa y lo que sale en la portada
   se reconocen entre sí. */
.subtitular.con-estrella { display: flex; align-items: center; gap: .55rem; }
.estrella-titulo { width: 1.1em; height: 1.1em; fill: var(--rosa-hondo); flex: 0 0 auto; }

/* --- el ritmo de la portada -----------------------------------------------
   El problema medido: desde que acaba el héroe hasta el pie había 1.589 px
   seguidos del mismo papel, con los tres títulos de sección idénticos byte a
   byte y el mismo respiro de 48 px en todas. Bajando, la página era una
   llanura.

   La salida es UNA banda, no cinco. Destacados pasa a papel hondo a sangre
   completa, y con eso el tramo continuo se parte en dos de unos 600 px. Una
   sola franja basta porque la portada sólo tiene tres secciones de contenido;
   más bandas la convertirían en una plantilla a rayas.

   Y una escala que baja: la categoría manda, luego lo que ella empuja, luego
   el catálogo. Es la jerarquía dicha con tamaños en vez de con palabras. */

.banda-destacados {
  background: var(--papel-hondo);
  /* A sangre: se sale de la caja del contenido para tocar los dos bordes. */
  margin-inline: calc(50% - 50vw);
  padding-inline: max(1.25rem, calc(50vw - 32rem));
  padding-block: 3.25rem;
  border-block: 1px solid var(--linea);
}

/* En la banda, la ficha se mete en una caja blanca. Es la diferencia entre
   escaparate y estantería, y evita que Destacados y "Lo que hay ahora"
   parezcan la misma sección dos veces sin inventar un componente nuevo. */
.banda-destacados .pieza {
  background: var(--papel-alto);
  border-radius: var(--radio);
  padding: .75rem .75rem 1rem;
  box-shadow: 0 10px 26px -20px rgba(31, 24, 38, .45);
}
.banda-destacados .pieza-foto { border-radius: var(--radio-chico); }

/* La escala descendente. Sólo en la portada: `.subtitular` es un estilo de
   todo el sitio y tocarlo aquí a secas habría cambiado también los títulos de
   la ficha de producto, del carrito y de Nuestra historia. */
#empezar-titulo { font-size: clamp(1.75rem, 4vw, 2.125rem); }
.banda-destacados .subtitular { font-size: clamp(1.5rem, 3.2vw, 1.75rem); }

/* El precio era el texto más chico de la ficha en escritorio —13 px— y es el
   dato con el que se decide comprar. */
@media (min-width: 64rem) {
  .pieza-precio { font-size: .9375rem; }
}

/* En teléfono y tablet la tarjeta de categoría medía MENOS que la de
   producto, justo al revés de lo que se quería. A una sola columna vuelve a
   ser lo más grande de la página. */
/* La tarjeta de categoría tiene que ser lo más grande de la página. Medido,
   no supuesto: en teléfono era 166x125 contra un producto de 217x217, y en
   tablet 241x180 contra 226x226. O sea, al revés. A una columna en teléfono y
   a dos en tablet vuelve a ganar por bastante. */
@media (max-width: 47.99rem) {
  .rejilla-cat { grid-template-columns: 1fr; }
  .rejilla-cat .tarjeta-cat img,
  .rejilla-cat .tarjeta-cat .baldosa { aspect-ratio: 16 / 10; }
}
@media (min-width: 48rem) and (max-width: 63.99rem) {
  .rejilla-cat { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .rejilla-cat .tarjeta-cat img,
  .rejilla-cat .tarjeta-cat .baldosa { aspect-ratio: 4 / 3; }
}

/* La puerta de la dueña, al final del pie. Una luna apagada que sólo se
   enciende al pasar por encima o al llegar con el teclado: quien no sabe que
   está, no la ve; quien la busca, la encuentra siempre en el mismo sitio. */
.puerta-luna {
  display: inline-grid;
  place-items: center;
  width: 2.25rem; height: 2.25rem;
  margin-top: .75rem;
  border-radius: 50%;
  /* Al 22% seguía sin verse: la puerta existía, medía sus 36 px y no la
     encontraba nadie. Discreta no es invisible — lo que la hace discreta es
     que no lleva rótulo, no que haya que adivinar dónde está.
     Al 55% y con su propio círculo de fondo se lee como un botón para quien
     lo busca, y sigue sin decirle nada a quien no. */
  color: rgba(44, 35, 51, .55);
  background: rgba(44, 35, 51, .06);
  border: 1px solid rgba(44, 35, 51, .12);
  transition: color .25s ease, transform .25s ease;
}
.puerta-luna svg { width: 19px; height: 19px; fill: currentColor; }
.puerta-luna:hover,
.puerta-luna:focus-visible {
  color: var(--papel-alto);
  background: var(--ciruela);
  border-color: var(--ciruela);
  transform: scale(1.1);
}
.puerta-luna:focus-visible { outline: 2px solid var(--rosa); outline-offset: 3px; }

/* --- Nuestra historia ------------------------------------------------------
   El retrato va DENTRO de la columna de lectura y no a sangre: es una foto de
   alguien, no una portada. Redondeada por arriba para que no parezca un carné.

   El cierre son los dos únicos caminos que tiene sentido ofrecer después de
   leerse la historia: ver lo que hace, o hablarle. */

.retrato {
  margin: 0 0 1.75rem;
  border-radius: var(--radio);
  overflow: hidden;
  background: var(--papel-hondo);
  aspect-ratio: 4 / 3;
}
.retrato img { width: 100%; height: 100%; object-fit: cover; }

.relato-cierre {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  margin-top: 2.25rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--linea);
}

/* --- el pie en teléfono ----------------------------------------------------
   Medido: 886 px, el 23 % de la página entera, con casi 90 px de aire entre
   un enlace y el siguiente. El culpable es el área de toque de 40 px sumada a
   un margen por renglón: en escritorio no se nota porque hay tres columnas;
   apilado, cada hueco se suma al de abajo.

   Aquí el toque se conserva (44 px, que es lo que exige un dedo) pero se hace
   con relleno DENTRO del enlace en vez de con margen fuera, y las dos listas
   de la columna del catálogo dejan de ser dos bloques separados. */

@media (max-width: 47.99rem) {
  .pie-caja { gap: 1.5rem; padding-bottom: 1.5rem; }

  .pie-lista li { margin-bottom: 0; }
  .pie-lista a { min-height: 44px; padding-block: .1rem; }
  .pie-familias { gap: 0 1.25rem; margin-bottom: 0; }

  .pie-lema { margin-bottom: .6rem; }
  .pie-sin  { line-height: 1.55; }

  .pie-titulo { margin-bottom: .35rem; }

  .pie-franja { padding-block: 1rem; }
  .pie-aviso  { margin-bottom: .5rem; line-height: 1.5; }
  /* "Creado por @herasi.dev" no se parte por la mitad: o cabe entero en su
     renglón o baja entero. Partido —"Creado por" arriba y el enlace solo
     debajo— se lee como un descuadre. */
  .credito .credito-firma { white-space: nowrap; }
}

/* --- las fotos de Nuestra historia ----------------------------------------
   Tres fotos reales para tres huecos. Comparten mano, patio y luz de tarde,
   así que puestas juntas se leen como una sesión intencional y no como
   relleno — que es justo lo que las separa de una foto de banco.

   Una imagen cada 800 px de scroll, que es la densidad medida en Herb'N Eden
   y Buff City. Ni una más: esto es un relato, no una galería. */

/* El héroe: la foto en círculo, como la luna del logotipo. */
.historia-entrada.con-foto { text-align: left; }
.historia-entrada.con-foto .entradilla { margin-inline: 0; }
.historia-luna {
  margin: 1.75rem auto 0;
  width: min(15rem, 62vw);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  /* El halo lavanda separa la foto del ciruela sin ponerle un marco: un
     borde duro sobre fondo oscuro parece una pegatina. */
  box-shadow: 0 0 0 1px rgba(175, 180, 215, .45), 0 24px 48px -24px rgba(0, 0, 0, .6);
}
.historia-luna img { width: 100%; height: 100%; object-fit: cover; }

/* La misión: foto y texto, uno al lado del otro. */
.mision-foto { margin: 0 0 1.5rem; border-radius: var(--radio); overflow: hidden; }
.mision-foto img { width: 100%; height: auto; display: block; }

/* La del relato va DENTRO de la columna de lectura, después de la cita.
   SIN proporción forzada: la caja era 4:3 y la foto es cuadrada, así que el
   recorte le cortaba la mano por arriba y el frasco por abajo — justo las dos
   cosas que la foto tiene que enseñar. La imagen manda su forma; la columna
   sólo le pone el ancho. Y un tope de alto para que un retrato muy vertical
   no se coma la pantalla entera. */
.relato-foto {
  margin: 1.75rem 0 1.9rem;
  border-radius: var(--radio);
  overflow: hidden;
}
.relato-foto img {
  width: 100%;
  height: auto;
  max-height: 34rem;
  object-fit: contain;
  display: block;
}

@media (min-width: 48rem) {
  .historia-entrada.con-foto {
    display: grid;
    grid-template-columns: 1.35fr .65fr;
    align-items: center;
    gap: 2.5rem;
    text-align: left;
  }
  .historia-luna { margin: 0; width: min(17rem, 100%); }

  .franja.mision-con-foto {
    display: grid;
    grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr);
    align-items: center;
    gap: 3rem;
  }
  .franja.mision-con-foto .relato { margin: 0; max-width: 34rem; }
  .mision-foto { margin: 0; aspect-ratio: 4 / 5; }
  .mision-foto img { height: 100%; object-fit: cover; }
}

/* --- área de toque: 44 px, en todas partes --------------------------------
   La auditoría midió migas de 33 px y enlaces del pie de 40 en tablet. Los
   44 px no son un número redondo: es el ancho de la yema de un dedo, y por
   debajo se falla el toque y se acaba pulsando el de al lado.

   El pie tenía 44 sólo en teléfono; en tablet se quedaba en 40 porque la
   regla vivía dentro del breakpoint pequeño. La tablet también se toca. */
.pie-lista a { min-height: 44px; }

.miga a, .miga span[aria-current] {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* --- las redes en el pie ---------------------------------------------------
   Icono y usuario juntos: un icono suelto obliga a pulsar para saber a qué
   cuenta lleva, y quien ya tiene Instagram abierto prefiere buscar el nombre
   allí que salir del sitio.

   Los iconos van en trazo, no rellenos, para que pesen lo mismo que la luna
   del pie y no se conviertan en dos manchas de color de otras marcas dentro
   de esta paleta. */

.pie-redes {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .25rem 1.25rem;
}
.pie-redes a {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: 44px;
  color: var(--tinta);
  text-decoration: none;
  font-size: .875rem;
}
.pie-redes svg {
  width: 20px; height: 20px;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.pie-redes a:hover { color: var(--ciruela); }
.pie-redes a:hover span { text-decoration: underline; text-underline-offset: 3px; }
.pie-redes a:focus-visible { outline: 2px solid var(--ciruela); outline-offset: 3px; border-radius: var(--radio-chico); }


/* --- la esquina de abajo, que tiene dueños fijos --------------------------
   Encima de la franja del pie viven dos cosas que no se mueven con el
   scroll: el botón flotante de WhatsApp (abajo a la derecha, siempre) y, en
   teléfono, la barra de secciones. Medido con la página abajo del todo, las
   dos se comían la luna de la dueña: en teléfono la barra, en tablet el
   botón. La puerta estaba ahí, del tamaño correcto y con su color, y no se
   veía porque tenía algo encima.

   Al reestructurar el pie en tres columnas se perdió además el hueco que la
   versión anterior le dejaba a la barra de secciones (`--barra-abajo`), que
   vivía en `.pie` y se quedó sin sitio al pasar el relleno a las cajas de
   dentro. Aquí vuelve. */

/* El botón flotante está pegado al borde derecho de la VENTANA, no del
   contenido. Así que la franja sólo se libra sola cuando su caja centrada
   termina antes que el botón — y eso pasa por encima de 79rem (1264 px), no
   de 64. A 1024 justos, que es la tablet apaisada, la luna caía debajo. */
@media (max-width: 79rem) {
  .pie-franja { padding-right: 5.5rem; }
}
/* La barra de secciones sólo existe en teléfono, y es fija: el hueco de abajo
   se le reserva sólo ahí. */
@media (max-width: 47.99rem) {
  .pie-franja { padding-bottom: calc(var(--barra-abajo) + 1.5rem); }
}

/* ---------------------------------------------------------------------------
   Política de la tienda

   Una página de leer, no de mirar. Por eso el ancho está atado a la medida de
   lectura (unos 68 caracteres) y no al ancho de la franja: una línea de texto
   que cruza un monitor de 27 pulgadas obliga a buscar dónde empieza la
   siguiente, y esta es justo la página donde nadie va a hacer ese esfuerzo.

   El índice queda pegado arriba en pantalla grande. Quien entra viene con UNA
   pregunta; poder saltar a ella sin volver a subir es la diferencia entre que
   la lea o escriba por WhatsApp.
   --------------------------------------------------------------------------- */
.politica {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
}
.politica-cabeza { max-width: 34rem; }
.politica-fecha {
  margin: .75rem 0 0;
  font-size: .8125rem;
  color: var(--tinta-suave);
}

.politica-indice ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
}
/* 2.75rem de alto mínimo, que son los 44px que un dedo acierta sin apuntar.
   Con el padding suelto salían de 26px: cuatro dianas diminutas justo en lo
   que más se toca de esta página, porque nadie la lee entera — la salta. */
.politica-indice a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  padding: .5rem 1rem;
  border: 1px solid var(--lavanda);
  border-radius: 999px;
  font-size: .875rem;
  font-weight: 600;
  color: var(--lavanda-honda);
  text-decoration: none;
}
.politica-indice a:hover,
.politica-indice a:focus-visible {
  background: var(--lavanda);
  color: var(--papel-alto);
}

.politica-cuerpo { max-width: 38rem; }
.politica-seccion + .politica-seccion {
  margin-top: 3rem;
  padding-top: 3rem;
  border-top: 1px solid var(--papel-hondo);
}
/* `scroll-margin-top` y no un hueco falso: al saltar desde el índice, el
   título tiene que quedar debajo de la cabecera fija, no tapado por ella. */
.politica-seccion { scroll-margin-top: 6rem; }
.politica-cuerpo p { line-height: 1.65; }
.politica-sub {
  margin: 2rem 0 .5rem;
  font-size: 1rem;
  font-weight: 700;
  color: var(--ciruela);
}
.politica-lista {
  margin: 0 0 1rem;
  padding-left: 1.1rem;
}
.politica-lista li {
  margin-bottom: .4rem;
  line-height: 1.6;
}

.politica-pie {
  max-width: 38rem;
  padding: 1.5rem;
  border-radius: 14px;
  background: var(--papel-hondo);
}
.politica-pie p { margin: 0; }

@media (min-width: 60rem) {
  .politica {
    grid-template-columns: 14rem minmax(0, 1fr);
    align-items: start;
    column-gap: 4rem;
  }
  .politica-cabeza { grid-column: 1 / -1; }
  .politica-indice { position: sticky; top: 6rem; }
  .politica-indice ul { flex-direction: column; }
  .politica-indice a { text-align: center; }
  .politica-pie { grid-column: 2; }
}

/* ---------------------------------------------------------------------------
   Subir el comprobante del pago

   Va en la pantalla de "pedido recibido", debajo del botón de WhatsApp y no
   encima: quien acaba de pedir todavía no ha pagado en la mayoría de los
   casos, así que la acción principal sigue siendo escribir. Esto es la
   segunda, para quien ya pagó.

   El `input` de archivo real se esconde y el que se ve es la etiqueta. No es
   maquillaje: el control de archivo del navegador se dibuja distinto en cada
   sistema y en un teléfono sale como un botón gris diminuto que no parece
   pulsable. La etiqueta envuelve al campo, así que sigue funcionando con
   teclado y con lector de pantalla.
   --------------------------------------------------------------------------- */
.comprobante-caja {
  margin-top: 1.5rem;
  padding: 1.25rem;
  border: 1px dashed var(--lavanda);
  border-radius: 14px;
  background: var(--papel-alto);
}
.comprobante-caja.hecho {
  border-style: solid;
  border-color: var(--lavanda-honda);
}
.comprobante-titulo {
  margin: 0 0 .35rem;
  font-size: 1rem;
  font-weight: 700;
}
.comprobante-boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-top: .9rem;
  padding: .7rem 1.2rem;
  min-height: 2.75rem;      /* que el dedo lo acierte sin apuntar */
  border-radius: 999px;
  background: var(--lavanda-honda);
  color: var(--papel-alto);
  font-size: .9375rem;
  font-weight: 600;
  cursor: pointer;
}
.comprobante-boton input[type="file"] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
/* El foco se ve en la etiqueta, que es lo que está en pantalla: sin esto,
   quien navega con teclado no sabría nunca dónde está parado. */
.comprobante-boton:focus-within {
  outline: 2px solid var(--ciruela);
  outline-offset: 2px;
}
.comprobante-boton:has(input:disabled) {
  background: var(--papel-hondo);
  color: var(--tinta-suave);
  cursor: default;
}
.comprobante-estado {
  margin: .75rem 0 0;
  min-height: 1.2rem;       /* reservado, para que nada se mueva al responder */
  font-size: .875rem;
  font-weight: 600;
}
.comprobante-estado.bien { color: var(--lavanda-honda); }
.comprobante-estado.mal  { color: var(--alerta); }

/* ===========================================================================
   RESEÑAS
   =========================================================================== */

/* Para texto que sólo debe existir para un lector de pantalla. `display:none`
   no vale: eso también se lo esconde al lector, que es a quien va dirigido. */
.visualmente-oculto {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* --- la página donde escribe la clienta --- */
.resena-pagina { max-width: 34rem; }
.resena-cabeza { margin-bottom: 2rem; }

.resena-forma {
  margin-bottom: 2rem;
  padding: 1.5rem 1.35rem;
  border-radius: 16px;
  border: 1px solid var(--papel-hondo);
  background: var(--papel-alto);
}
.resena-quien {
  display: flex; align-items: center; gap: .8rem;
  padding-bottom: 1.1rem; margin-bottom: 1.2rem;
  border-bottom: 1px solid var(--papel-hondo);
}
.resena-quien img { width: 60px; height: 60px; border-radius: 10px; object-fit: cover; }
.resena-quien strong { display: block; font-size: .95rem; }
.resena-quien span { font-size: .78rem; color: var(--tinta-suave); }

/* Las estrellas se pintan en orden inverso (5,4,3,2,1) en el HTML para que
   `~` pueda alcanzar a las que van DESPUÉS en el documento, que son las de
   menor valor. Es el único modo de encender "las de la izquierda" en CSS
   puro, sin una línea de JavaScript. */
.estrellas-elegir { border: 0; padding: 0; margin: 0 0 1.3rem; display: flex; flex-wrap: wrap; }
.estrellas-elegir legend {
  padding: 0; margin-bottom: .5rem; width: 100%;
  font-size: .8125rem; font-weight: 600;
}
.estrellas-elegir input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.estrellas-elegir label { cursor: pointer; padding: .15rem; line-height: 0; order: 1; }
.estrellas-elegir svg { width: 2.4rem; height: 2.4rem; fill: #ddd6ce; transition: fill .12s; }
.estrellas-elegir label:hover svg,
.estrellas-elegir label:hover ~ label svg,
.estrellas-elegir input:checked + label svg,
.estrellas-elegir input:checked + label ~ label svg { fill: var(--oro-resena); }
.estrellas-elegir input:focus-visible + label { outline: 2px solid var(--ciruela); outline-offset: 1px; border-radius: 6px; }

.resena-foto-boton {
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 2.75rem; padding: .85rem;
  margin-bottom: .5rem;
  border: 1px dashed var(--lavanda); border-radius: 12px;
  color: var(--lavanda-honda); font-size: .875rem; font-weight: 600;
  cursor: pointer;
}
.resena-foto-boton svg { fill: none; stroke: currentColor; stroke-width: 1.8; }
.resena-foto-boton input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.resena-foto-boton:focus-within { outline: 2px solid var(--ciruela); outline-offset: 2px; }
.resena-foto-boton.puesta { border-style: solid; border-color: var(--lavanda-honda); }

.resena-forma .campo-ayuda { margin: 0 0 1.2rem; }
.resena-error { margin-top: .75rem; }
.resena-hechas, .resena-legal { font-size: .8125rem; color: var(--tinta-suave); line-height: 1.6; }
.resena-legal { margin-top: 1.5rem; }
.resena-forma.enviada { border-color: var(--lavanda-honda); }

/* --- el bloque en la ficha del producto --- */
:root { --oro-resena: #c9922f; }

.resenas-bloque { margin-top: 3.5rem; }
.resenas-resumen {
  display: grid; gap: 1.6rem;
  padding: 1.5rem 1.4rem; margin-bottom: 1.5rem;
  border-radius: 16px; border: 1px solid var(--papel-hondo);
  background: var(--papel-alto);
}
.resenas-media { display: flex; align-items: baseline; gap: .7rem; }
.resenas-media .num {
  font-family: var(--titulo, 'Playfair Display'), Georgia, serif;
  font-size: 3rem; font-weight: 600; line-height: 1;
}
.resenas-media .de { display: block; font-size: .8125rem; color: var(--tinta-suave); margin-top: .2rem; }

.resenas-barras { display: grid; gap: .35rem; }
.resenas-barra {
  display: grid; grid-template-columns: 2.6rem 1fr 2.2rem;
  align-items: center; gap: .6rem;
  font-size: .78rem; color: var(--tinta-suave);
}
.resenas-barra .riel { height: 7px; border-radius: 99px; background: var(--papel-hondo); overflow: hidden; }
.resenas-barra .lleno { display: block; height: 100%; border-radius: 99px; background: var(--oro-resena); }

/* La tira desborda a propósito y se arrastra con el dedo. `min-width:0` en el
   padre porque una rejilla NO encoge a sus hijos por debajo de su contenido, y
   sin eso las fotos empujan la tarjeta fuera de la pantalla. */
.resenas-resumen > div { min-width: 0; }
.resenas-tira { display: flex; gap: .5rem; overflow-x: auto; max-width: 100%; padding-bottom: .3rem; }
.resenas-tira img { width: 78px; height: 78px; border-radius: 11px; object-fit: cover; flex: 0 0 auto; }
.resenas-tira-tit {
  margin: 0 0 .55rem; font-size: .72rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--tinta-suave);
}

.resenas-orden { display: flex; gap: .4rem; flex-wrap: wrap; margin: 1.4rem 0; padding: 0; list-style: none; }
.resenas-orden a {
  display: inline-flex; align-items: center; min-height: 2.5rem;
  padding: .4rem .9rem; border-radius: 999px;
  border: 1px solid var(--papel-hondo); color: var(--tinta-suave);
  font-size: .8125rem; font-weight: 600; text-decoration: none;
}
.resenas-orden a.activa { background: var(--tinta); border-color: var(--tinta); color: var(--papel-alto); }

.resena { padding: 1.35rem 0; border-top: 1px solid var(--papel-hondo); }
.resena-cab { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; }
.resena-autor { font-size: .875rem; font-weight: 600; }
.resena-fecha { font-size: .75rem; color: var(--tinta-suave); white-space: nowrap; }
.resena-insignia {
  display: inline-flex; align-items: center; gap: .3rem;
  margin-left: .5rem; padding: .12rem .5rem; border-radius: 999px;
  background: rgba(97, 102, 148, .13); color: var(--lavanda-honda);
  font-size: .68rem; font-weight: 700;
}
.resena-insignia svg { width: .72rem; height: .72rem; fill: none; stroke: currentColor; stroke-width: 3; }
.resena-estrellas { line-height: 0; margin: .4rem 0 .1rem; display: block; }
.resena-estrellas svg { width: .82rem; height: .82rem; }
.resena h3 { margin: .35rem 0 .3rem; font-size: .95rem; font-weight: 700; }
.resena p { margin: 0; font-size: .875rem; line-height: 1.65; }
.resena-imagen { margin-top: .8rem; width: 104px; height: 104px; border-radius: 11px; object-fit: cover; }

/* La respuesta de Paola. Va DENTRO de la reseña y con su barra a la
   izquierda: es una contestación, no otra opinión al mismo nivel. */
.resena-respuesta {
  margin-top: .9rem; padding: .85rem 1rem;
  border-left: 3px solid var(--ciruela); border-radius: 0 12px 12px 0;
  background: rgba(125, 67, 104, .06);
}
.resena-respuesta b { display: block; font-size: .78rem; color: var(--ciruela); margin-bottom: .25rem; }
.resena-respuesta p { font-size: .84rem; }

.estrella-llena { fill: var(--oro-resena); }
.estrella-vacia { fill: #ddd6ce; }

/* --- la franja de la portada --- */
.testimonios { display: grid; gap: 1.25rem; }
@media (min-width: 48rem) { .testimonios { grid-template-columns: repeat(3, 1fr); } }
.testimonio {
  display: flex; flex-direction: column; gap: .7rem;
  padding: 1.35rem; border-radius: 16px;
  background: var(--papel-alto); border: 1px solid var(--papel-hondo);
}
.testimonio img { width: 100%; aspect-ratio: 4/3; object-fit: cover; border-radius: 11px; }
.testimonio p { margin: 0; font-size: .9rem; line-height: 1.6; }
.testimonio .quien { margin-top: auto; font-size: .78rem; color: var(--tinta-suave); }
.testimonio .quien b { color: var(--tinta); font-weight: 600; }
/* El nombre del producto es un enlace, y de los pocos que se tocan en la
   portada con el pulgar. Suelto medía 15 px de alto; con esto llega a los 44
   sin cambiar cómo se ve, porque el relleno va hacia arriba y hacia abajo del
   renglón y la tarjeta ya tenía ese hueco. */
.testimonio .quien a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--ciruela);
}

/* El aviso pasa a llevar un botón dentro, para el "Deshacer" al quitar del
   carrito. Sin deshacer, que el "−" del último saque el renglón sería una
   trampa en vez de una comodidad. */
.aviso { display: flex; align-items: center; justify-content: space-between; gap: .75rem; }
.aviso-deshacer {
  flex: none;
  min-height: 44px;
  padding: 0 .875rem;
  border: 1px solid var(--lavanda);
  border-radius: var(--radio-chico);
  background: none;
  color: var(--lavanda);
  font-family: var(--ui);
  font-size: .875rem;
  font-weight: 600;
  cursor: pointer;
}
.aviso-deshacer:hover { background: var(--lavanda); color: var(--tinta); }

/* ===========================================================================
   MIS PEDIDOS — la página a la que vuelve la clienta desde el correo
   =========================================================================== */
.pedido-pagina { max-width: 34rem; }
.pedido-cabeza { margin-bottom: 2rem; }
.pedido-numero {
  margin: 0 0 .4rem;
  font-size: .75rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--tinta-suave);
}

/* La línea de pasos. Vertical y no horizontal: en un teléfono de 390 px,
   cinco pasos en fila obligan a abreviar los nombres hasta que dejan de
   entenderse ("Prep.", "Env."). En vertical caben enteros y con su fecha. */
.pedido-linea {
  list-style: none;
  margin: 0 0 2rem;
  padding: 0;
  position: relative;
}
.pedido-linea li {
  position: relative;
  display: flex; align-items: baseline; gap: .75rem;
  padding: 0 0 1.5rem 1.75rem;
  color: var(--tinta-suave);
}
.pedido-linea li:last-child { padding-bottom: 0; }
/* El hilo que une los puntos. Va en el `li` y no en el `ol` para que se corte
   solo en el último, sin una clase extra. */
.pedido-linea li::before {
  content: "";
  position: absolute;
  left: .3125rem; top: 1rem; bottom: 0;
  width: 2px;
  background: var(--papel-hondo);
}
.pedido-linea li:last-child::before { display: none; }
.pedido-linea li.hecho::before { background: var(--lavanda); }
.pedido-linea .punto {
  position: absolute; left: 0; top: .3rem;
  width: .75rem; height: .75rem; border-radius: 50%;
  background: var(--papel-alto);
  border: 2px solid var(--papel-hondo);
}
.pedido-linea li.hecho .punto { background: var(--lavanda); border-color: var(--lavanda); }
.pedido-linea li.ahora .punto {
  background: var(--ciruela); border-color: var(--ciruela);
  box-shadow: 0 0 0 4px rgba(125, 67, 104, .15);
}
.pedido-linea li.hecho { color: var(--tinta); }
.pedido-linea li.ahora .que { font-weight: 700; color: var(--ciruela); }
.pedido-linea .que { font-size: .9375rem; }
.pedido-linea .cuando { margin-left: auto; font-size: .75rem; white-space: nowrap; }

.pedido-guia {
  margin-bottom: 2rem; padding: 1.25rem;
  border-radius: 14px; background: var(--papel-hondo);
}
.pedido-guia-tit {
  margin: 0 0 .3rem;
  font-size: .72rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--tinta-suave);
}
/* Tabular para que los dígitos no bailen, y seleccionable de un toque: una
   guía de 22 números se copia, no se transcribe. */
.pedido-guia-num {
  margin: 0 0 1rem;
  font-size: 1.0625rem; font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
  word-break: break-all;
  user-select: all;
}

.pedido-detalle { margin-bottom: 2rem; }
.pedido-lineas { list-style: none; margin: 1rem 0 0; padding: 0; }
.pedido-lineas li {
  display: flex; align-items: center; gap: .8rem;
  padding: .8rem 0; border-bottom: 1px solid var(--papel-hondo);
}
.pedido-lineas img { width: 52px; height: 52px; border-radius: 9px; object-fit: cover; flex: none; }
.pedido-lineas .que { flex: 1; min-width: 0; }
.pedido-lineas .que a { font-size: .9375rem; font-weight: 600; text-decoration: none; color: inherit; }
.pedido-lineas .que small { display: block; font-size: .78rem; color: var(--tinta-suave); }
/* Los tres del combo, en ciruela para que no se confundan con la cantidad y el
   precio que van justo debajo en el mismo tamaño. */
.pedido-lineas .que .pedido-dentro { color: var(--ciruela); }
.pedido-lineas .cuanto { font-weight: 600; font-variant-numeric: tabular-nums; }

.pedido-cuentas { margin: 1.1rem 0 0; }
.pedido-cuentas > div { display: flex; justify-content: space-between; padding: .3rem 0; font-size: .9rem; }
.pedido-cuentas dt, .pedido-cuentas dd { margin: 0; }
.pedido-cuentas dd { font-variant-numeric: tabular-nums; }
.pedido-cuentas .total {
  margin-top: .4rem; padding-top: .7rem;
  border-top: 1px solid var(--papel-hondo);
  font-size: 1.0625rem; font-weight: 700;
}
.pedido-como { margin-top: 1.1rem; font-size: .875rem; color: var(--tinta-suave); line-height: 1.6; }
.pedido-ayuda { margin-top: 2rem; font-size: .875rem; color: var(--tinta-suave); }

/* La insignia de clienta anterior va en gris y no en lavanda: dice algo
   verdadero pero más débil que "compra verificada", y el color tiene que
   decirlo también. Igualarlas sería igualar dos cosas que no son iguales. */
.resena-insignia.anterior {
  background: var(--papel-hondo);
  color: var(--tinta-suave);
}
/* Lo que la reseñadora declaró de su relación con la tienda. En su propia
   pastilla y no dentro de la insignia: son dos hechos distintos. */
.resena-relacion {
  display: inline-block;
  margin-left: .35rem;
  padding: .12rem .5rem;
  border-radius: 999px;
  background: rgba(173, 70, 113, .1);
  color: var(--rosa-hondo);
  font-size: .68rem;
  font-weight: 700;
}

/* Las estrellas en la tarjeta de la rejilla. Pequeñas y sobre el precio: es un
   dato de apoyo, no el titular — el titular sigue siendo el producto. */
.pieza-nota {
  display: flex;
  align-items: center;
  gap: .1rem;
  margin-top: .25rem;
  line-height: 0;
}
.pieza-nota small {
  margin-left: .25rem;
  font-size: .7rem;
  line-height: 1;
  color: var(--tinta-suave);
  font-variant-numeric: tabular-nums;
}

/* "¿Dónde está mi pedido?" en el pie. Va plegado: es una salida de emergencia,
   no algo que se use a diario, y desplegado le robaría sitio a lo que sí. */
.pie-buscar-pedido summary { cursor: pointer; }
.pie-buscar-pedido[open] summary { margin-bottom: .5rem; }
.pie-forma { display: flex; flex-direction: column; gap: .5rem; max-width: 22rem; }
.pie-forma input {
  padding: .5rem .625rem;
  border-radius: var(--radio-chico);
  border: 1px solid var(--linea);
  background: var(--papel-alto);
  font: inherit;
  font-size: .875rem;
}
.pie-forma button {
  align-self: start;
  min-height: 44px;
  padding: 0 1rem;
  border: 0;
  border-radius: 999px;
  background: var(--ciruela);
  color: var(--papel-alto);
  font: inherit;
  font-size: .875rem;
  font-weight: 600;
  cursor: pointer;
}
.pie-forma button[disabled] { opacity: .6; cursor: progress; }

/* --- "Ayúdame a elegir" ---------------------------------------------------
   Tres preguntas, una por pantalla. Las opciones son del tamaño de una tarjeta
   y no de un renglón de lista: se contesta con el pulgar, de una pasada, sin
   apuntar. Y una por línea aunque sobre ancho — dos columnas obligan a
   comparar cuatro cosas a la vez cuando la pregunta es sencilla. */
.guia-paso {
  margin: 0 0 .35rem;
  font-size: .75rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--tinta-suave);
}
.guia .subtitular { margin-top: 0; }

.guia-opciones {
  list-style: none;
  margin: 1.25rem 0 0;
  padding: 0;
  display: grid;
  gap: .625rem;
  max-width: 34rem;
}
.guia-opcion {
  display: block;
  padding: 1rem 1.125rem;
  background: var(--papel-alto);
  border: 1px solid var(--linea);
  border-radius: var(--radio-chico);
  color: var(--tinta);
  text-decoration: none;
  font-size: 1rem;
  line-height: 1.35;
  transition: border-color .18s, transform .18s, box-shadow .18s;
}
.guia-opcion:hover {
  border-color: var(--ciruela);
  transform: translateY(-1px);
  box-shadow: 0 6px 18px -12px rgba(44, 35, 51, .5);
}
.guia-opcion:focus-visible { outline: 2px solid var(--lavanda-honda); outline-offset: 2px; }

.guia-volver { margin-top: 1.5rem; font-size: .9375rem; }
.guia-volver a { color: var(--tinta-suave); }
.guia-volver a:hover { color: var(--ciruela); }

/* El aviso del dermatólogo. Va PEGADO a la recomendación y no en el pie:
   ahí abajo lo lee nadie, y aquí es donde significa algo. En lavanda y no en
   rojo — no es una alarma, es una cortesía honesta. */
.guia-aviso {
  margin: 1.75rem 0 0;
  padding: .875rem 1rem;
  border-left: 3px solid var(--lavanda);
  border-radius: 0 8px 8px 0;
  background: rgba(175, 180, 215, .12);
  font-size: .875rem;
  line-height: 1.55;
  color: var(--tinta-suave);
  max-width: 42rem;
}

/* La entrada desde el catálogo. Es una línea, no un cartel: quien ya sabe lo
   que busca no tiene que esquivarla. */
.guia-entrada {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  margin: 0 0 1.25rem;
  padding: .625rem .875rem;
  border: 1px dashed var(--linea-firme);
  border-radius: 999px;
  font-size: .9375rem;
  color: var(--tinta);
  text-decoration: none;
}
.guia-entrada:hover { border-color: var(--ciruela); border-style: solid; }
.guia-entrada svg { width: 18px; height: 18px; stroke: var(--ciruela); fill: none; stroke-width: 1.7; }

/* ===== El asistente =======================================================
   La burbuja va ENCIMA de la de WhatsApp, no en su sitio: no son la misma
   acción. Una lleva a una persona; ésta recomienda un jabón a las once de la
   noche, cuando Paola duerme. Se distinguen por color y por forma —ciruela con
   trazo, frente al rosa lleno de WhatsApp— para que no se lean como dos
   botones del mismo sitio. */
.asistente-burbuja {
  position: fixed;
  right: 1rem;
  /* En el sitio donde estaba WhatsApp. Una sola burbuja: dos círculos
     apilados en la misma esquina hacen dudar de cuál es cuál, y WhatsApp
     ahora vive dentro del chat. */
  bottom: calc(var(--barra-abajo) + 1rem);
  z-index: 35;
  display: grid;
  place-items: center;
  width: 52px; height: 52px;
  border: 1px solid var(--linea-firme);
  border-radius: 50%;
  background: var(--papel-alto);
  color: var(--ciruela);
  box-shadow: 0 6px 20px -8px rgba(31, 24, 38, .45);
  cursor: pointer;
  transition: transform .2s, box-shadow .2s;
}
.asistente-burbuja svg { width: 26px; height: 26px; }
.asistente-burbuja:hover { transform: translateY(-2px); box-shadow: 0 10px 24px -8px rgba(31, 24, 38, .5); }
.asistente-burbuja:focus-visible { outline: 2px solid var(--lavanda-honda); outline-offset: 3px; }
.asistente-burbuja[aria-expanded="true"] { opacity: 0; pointer-events: none; }

/* En la ficha de un producto, el botón de comprar está fijo al fondo, y la
   burbuja le caía encima: tapaba sus últimos 48 px. El centro seguía
   recibiendo el toque —por eso nadie lo reportó— pero el borde derecho del
   botón estaba muerto en las 62 fichas.

   Esta regla ya existía para `.flotante-wa`, la burbuja de WhatsApp. Cuando el
   asistente ocupó su sitio, la burbuja se mudó y la regla se quedó atrás. */
body:has(.comprar-fijo) .asistente-burbuja {
  bottom: calc(var(--barra-abajo) + 5.25rem);
}

/* El panel. En el teléfono es una hoja que sube desde abajo y ocupa lo que
   necesita, no toda la pantalla: se sigue viendo la tienda detrás, que es lo
   que se está comprando. */
.asistente-panel {
  position: fixed;
  right: 0; left: 0;
  bottom: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  max-height: min(78vh, 620px);
  background: var(--papel);
  border-top: 1px solid var(--linea);
  border-radius: 18px 18px 0 0;
  box-shadow: 0 -14px 40px -18px rgba(31, 24, 38, .55);
  animation: asistente-sube .32s cubic-bezier(.2, .8, .3, 1);
}
.asistente-panel[hidden] { display: none; }
@keyframes asistente-sube { from { transform: translateY(14px); opacity: 0; } }

.asistente-cabeza {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: .875rem 1rem .75rem;
  border-bottom: 1px solid var(--linea);
}
.asistente-titulo {
  margin: 0;
  font-family: var(--titulo, "Playfair Display", serif);
  font-size: 1.0625rem;
  color: var(--tinta);
}
/* Que es una máquina, dicho en la cabecera y no en un mensaje que se pierde
   al desplazarse. Quien entra tiene derecho a saberlo ANTES de contarle nada
   de su piel. */
.asistente-que-soy {
  margin: .15rem 0 0;
  font-size: .75rem;
  color: var(--tinta-suave);
}
.asistente-cerrar {
  display: grid; place-items: center;
  width: 34px; height: 34px;
  flex: none;
  border: 0; background: none; cursor: pointer;
  color: var(--tinta-suave);
  border-radius: 50%;
}
.asistente-cerrar svg { width: 20px; height: 20px; }
.asistente-cerrar:hover { background: var(--papel-hondo); color: var(--tinta); }

.asistente-hilo {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 1rem .875rem;
  display: flex;
  flex-direction: column;
  gap: .5rem;
  -webkit-overflow-scrolling: touch;
}

/* ===== Que se lea como una conversación ==================================
   La primera versión pintaba tarjetas: rectángulos del mismo ancho, sin cola,
   sin cara y sin hora. Se leía como una lista de avisos, no como alguien
   hablando — que es justo lo que hay que sentir aquí.
   Lo que convierte unos rectángulos en un chat son cuatro cosas, y ninguna es
   decorativa: el hilo tiene FONDO PROPIO para que los globos floten encima;
   los globos miden lo que mide su texto y no todo el ancho; llevan COLA, que
   es lo que apunta a quién habla; y llevan HORA, que es lo que convierte una
   secuencia en una conversación. */
.asistente-hilo {
  background: var(--papel-hondo);
}

.asis-fila {
  display: flex;
  align-items: flex-end;
  gap: .375rem;
  max-width: 100%;
}
.asis-fila.de-ella { justify-content: flex-start; }
.asis-fila.de-mi   { justify-content: flex-end; }

/* La cara: la luna de la marca. Cuando va vacía —debajo de un producto o de
   los botones— sigue ocupando su sitio, para que todo lo del asistente quede
   alineado en la misma columna. */
.asis-cara {
  flex: none;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--ciruela);
  color: #fff;
  margin-bottom: 2px;
}
.asis-cara svg { width: 15px; height: 15px; fill: currentColor; }
.asis-cara:empty { background: none; }

.asis-globo {
  position: relative;
  max-width: 78%;
  padding: .5rem .7rem .375rem;
  border-radius: 14px;
  font-size: .9375rem;
  line-height: 1.45;
  box-shadow: 0 1px 1px rgba(31, 24, 38, .07);
}
.de-ella .asis-globo {
  background: var(--papel-alto);
  color: var(--tinta);
  border-bottom-left-radius: 4px;
}
.de-mi .asis-globo {
  background: var(--ciruela);
  color: #fff;
  border-bottom-right-radius: 4px;
}

/* La cola. Un triángulo pegado a la esquina de abajo, del mismo color que el
   globo: es lo que dice de quién es el mensaje sin leer una palabra. */
.asis-globo::after {
  content: "";
  position: absolute;
  bottom: 0;
  width: 0; height: 0;
  border: 7px solid transparent;
}
.de-ella .asis-globo::after {
  left: -6px;
  border-right-color: var(--papel-alto);
  border-bottom-color: var(--papel-alto);
  border-left: 0;
}
.de-mi .asis-globo::after {
  right: -6px;
  border-left-color: var(--ciruela);
  border-bottom-color: var(--ciruela);
  border-right: 0;
}

.asis-texto { display: block; }

/* La hora, pequeña y al final. Va DENTRO del globo y alineada a la derecha,
   como en cualquier mensajería: fuera, empuja las líneas y descoloca el hilo. */
.asis-hora {
  display: block;
  margin-top: .1rem;
  font-size: .625rem;
  line-height: 1;
  text-align: right;
  opacity: .55;
}

/* La nota del dermatólogo. No es un globo —no lo dice el asistente, lo dice la
   tienda— así que se distingue: sin cola, en lavanda y en cursiva pequeña. */
.asis-nota {
  max-width: 82%;
  padding: .5rem .7rem;
  border-left: 3px solid var(--lavanda);
  border-radius: 0 10px 10px 0;
  background: rgba(175, 180, 215, .22);
  font-size: .78rem;
  line-height: 1.45;
  color: var(--tinta-suave);
}

/* Las respuestas rápidas. Se tocan, no se escriben: en el teléfono, escribir
   "para mi cara" es cinco veces más trabajo que dar un toque. */
.asis-opciones { display: flex; flex-wrap: wrap; gap: .4rem; max-width: 88%; }
.asis-opcion {
  padding: .45rem .75rem;
  border: 1px solid var(--ciruela);
  border-radius: 999px;
  background: var(--papel-alto);
  color: var(--ciruela);
  font-size: .8125rem;
  font-family: inherit;
  cursor: pointer;
  transition: background .16s, color .16s;
}
.asis-opcion:hover { background: var(--ciruela); color: #fff; }
.asis-opcion:focus-visible { outline: 2px solid var(--lavanda-honda); outline-offset: 2px; }

/* El producto DENTRO de la conversación: como un adjunto, no como una tarjeta
   de catálogo. Una tarjeta grande aquí taparía lo que se está hablando. */
.asis-producto {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 82%;
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr) auto;
  align-items: center;
  gap: .625rem;
  padding: .45rem .55rem;
  background: var(--papel-alto);
  border-radius: 14px;
  border-bottom-left-radius: 4px;
  color: var(--tinta);
  text-decoration: none;
  box-shadow: 0 1px 1px rgba(31, 24, 38, .07);
  transition: transform .16s, box-shadow .16s;
}
.asis-producto:hover { transform: translateY(-1px); box-shadow: 0 6px 16px -8px rgba(31, 24, 38, .45); }
.asis-producto img, .asis-producto .sinfoto {
  width: 48px; height: 48px; border-radius: 10px; object-fit: cover;
  background: var(--papel-hondo);
}
.asis-producto .que { min-width: 0; }
.asis-producto .nom { display: block; font-weight: 600; font-size: .84rem; line-height: 1.2; }
.asis-producto .dice {
  display: block; font-size: .72rem; color: var(--tinta-suave); line-height: 1.3; margin-top: .1rem;
}
.asis-producto .pre { font-weight: 600; font-size: .84rem; white-space: nowrap; }

.asis-wa {
  align-self: center;
  margin-left: 32px;
  font-size: .8125rem;
  color: var(--ciruela);
  text-decoration: underline;
}

/* Los tres puntos, dentro de su globo. */
.asis-pensando { display: flex; gap: .25rem; padding: .7rem .8rem; }
.asis-pensando span {
  width: 6px; height: 6px; border-radius: 50%; background: var(--tinta-suave);
  animation: asis-punto 1.3s infinite ease-in-out;
}
.asis-pensando span:nth-child(2) { animation-delay: .16s; }
.asis-pensando span:nth-child(3) { animation-delay: .32s; }
@keyframes asis-punto { 0%, 60%, 100% { opacity: .25; } 30% { opacity: 1; } }

.asistente-escribir {
  display: flex;
  gap: .5rem;
  padding: .75rem 1rem calc(.75rem + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--linea);
  background: var(--papel-alto);
  border-radius: 0 0 18px 18px;
}
.asistente-escribir input {
  flex: 1 1 auto;
  min-width: 0;
  padding: .7rem .875rem;
  border: 1px solid var(--linea-firme);
  border-radius: 999px;
  /* 16px o el navegador del iPhone hace zoom al enfocar y descoloca la hoja. */
  font-size: 16px;
  font-family: inherit;
  background: var(--papel);
  color: var(--tinta);
}
.asistente-escribir input:focus-visible { outline: 2px solid var(--lavanda-honda); outline-offset: 1px; }
.asistente-escribir button {
  display: grid; place-items: center;
  width: 44px; height: 44px; flex: none;
  border: 0; border-radius: 50%;
  background: var(--ciruela); color: #fff; cursor: pointer;
}
.asistente-escribir button svg { width: 20px; height: 20px; }
.asistente-escribir button:disabled { opacity: .45; cursor: default; }

.asistente-sin-js { padding: 1rem; margin: 0; }

/* En pantalla ancha no es una hoja: es una tarjeta en la esquina, como la de
   cualquier tienda grande. Ocupar todo el ancho de un monitor para una
   conversación de tres líneas sería absurdo. */
@media (min-width: 48rem) {
  .asistente-panel {
    left: auto;
    right: 1.25rem;
    bottom: 1.25rem;
    width: 380px;
    max-height: min(72vh, 640px);
    border-radius: 18px;
    border: 1px solid var(--linea);
  }
  .asistente-escribir { border-radius: 0 0 18px 18px; }
  .asistente-burbuja { bottom: 1.25rem; right: 1.25rem; }
}

@media (prefers-reduced-motion: reduce) {
  .asistente-panel { animation: none; }
  .asis-pensando span { animation: none; opacity: .5; }
}
