/* ==========================================================================
   Vidriera pública
   --------------------------------------------------------------------------
   Papel, tinta y una línea. Nada más.

   Portado del boceto de paginaDescartable/. Lo que el boceto no tenía —
   checkout, OTP, relacionados, overlays de pago — está al final del archivo,
   resuelto con el mismo vocabulario: sin cajas, una línea por debajo y
   mayúsculas chicas para las etiquetas.
   ========================================================================== */

:root {
  --paper: #f4f3f0;
  --paper-deep: #eceae5;
  --ink: #171614;
  --ink-soft: #605e58;
  --ink-faint: #a6a29a;
  --line: #d5d2ca;

  --glass: rgba(244, 243, 240, 0.72);
  --glass-blur: saturate(1.25) blur(16px);

  /* El fondo de la placa del precio. Va aparte de --paper-deep porque tiene que
     seguir separándose del papel cuando la tarjeta reacciona al mouse, y en el
     tema oscuro "más marcado" es más claro, no más oscuro. */
  --plaque: #e8e5de;
  --plaque-strong: #ddd9d0;

  /* Acentos de las etiquetas de la grilla: celeste para la oferta, rojo apagado
     para el stock que se termina. */
  --flag-oferta-bg: #9fcbe8;
  --flag-oferta-ink: #10303f;
  --flag-ultimas-bg: #d99483;
  --flag-ultimas-ink: #3d1a12;
  /* Verde agua para las etiquetas de catálogo. Va translúcido —deja ver algo
     de la foto— pero con la misma tinta oscura que los otros flags: la mayoría
     de las fotos de producto tienen fondo blanco, y un chip claro con texto
     claro ahí arriba directamente no se lee. */
  --flag-etiqueta-bg: rgba(143, 214, 201, 0.85);
  --flag-etiqueta-ink: #0d3b34;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;

  --pad: clamp(18px, 3.2vw, 52px);
  --header-h: 58px;
  /* Lo que el encabezado ocupa de verdad en pantalla: su alto más la barra de
     estado del teléfono, que con viewport-fit=cover queda por debajo. Todo lo
     que se pega abajo del encabezado tiene que usar esta y no --header-h, o en
     iPhone se mete detrás. En pantallas sin muesca las dos valen lo mismo. */
  --header-total: calc(var(--header-h) + env(safe-area-inset-top, 0px));

  --ease: cubic-bezier(0.16, 0.84, 0.24, 1);
}

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

/* La página es una columna: el alto sobrante lo toma la portada, así el pie
   nunca empuja el contenido fuera de la ventana.
   Va con la clase puesta porque tokens.css y base.css, que se cargan antes,
   pintan el tema oscuro del panel sobre el mismo selector. */
body.vidriera {
  margin: 0;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  /* Transparente a propósito: el color lo pinta <html> para que la ilustración
     del fondo (body::before, más abajo) no quede tapada. */
  background: transparent;
  color: var(--ink);
  font-family: var(--font);
  /* 14px era tamaño de interfaz, no de página que se lee de parado a un metro
     del mostrador o en un teléfono con sol. Todo lo demás sale de acá. */
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* Grano de papel */
body.vidriera::after {
  content: "";
  position: fixed;
  inset: 0;
  /* base.css usa este mismo pseudo-elemento como manchón de color: un círculo
     de 62vw. Sin resetear la caja, el grano queda recortado en círculo y se ve
     un arco enorme cruzando la página. */
  width: auto;
  height: auto;
  border-radius: 0;
  z-index: 100;
  pointer-events: none;
  opacity: 0.03;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

button,
input {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

main {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}

[hidden] { display: none !important; }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

/* Una sola familia de etiquetas chicas para toda la página */
.half-index,
.half-label,
.half-brands,
.card-brand,
.sheet-brand,
.sizes-head,
.site-footer,
.filter,
.ph-text {
  /* Mayúsculas y espaciadas se leen peor que el mismo texto en minúscula: a
     11px eran una textura gris antes que palabras. */
  font-size: 12.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   Encabezado
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 30;
  /* Con viewport-fit=cover la página llega hasta el borde del teléfono, así que
     el encabezado se agranda por debajo de la barra de estado en vez de quedar
     tapado por ella. En pantallas sin muesca el env() vale 0 y no cambia nada. */
  height: var(--header-total);
  padding-top: env(safe-area-inset-top, 0px);
  display: flex;
  align-items: center;
  gap: 40px;
  padding-left: var(--pad);
  padding-right: var(--pad);
  background: var(--glass);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  /* Capa propia: en iOS el desenfoque de un elemento pegajoso se repinta con un
     cuadro de retraso mientras se scrollea, y se ve la franja parpadeando. */
  transform: translateZ(0);
}

/* Forro que sube por detrás del encabezado. En iPhone, cuando la barra de la
   URL se contrae o el scroll rebota contra el tope, arriba del encabezado
   asoma una franja de contenido sin desenfocar; esto la tapa con el mismo
   vidrio. En el tope de la página queda fuera de la ventana, invisible. */
.site-header::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 140px;
  pointer-events: none;
  background: var(--glass);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
}

@supports not (backdrop-filter: blur(1px)) {
  .site-header,
  .site-header::before { background: var(--paper); }
}

.brand {
  margin-right: auto;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  text-decoration: none;
  color: inherit;
}

.header-nav {
  display: flex;
  gap: 26px;
}

.nav-link,
.bag-btn {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  font-size: 13px;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  transition: color 0.25s ease;
}

.nav-link {
  position: relative;
  padding-bottom: 2px;
}

/* Subrayado que crece desde la izquierda, pegado al texto y no a la caja de click */
.nav-link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 10px;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s var(--ease);
}

.nav-link:hover,
.bag-btn:hover,
.nav-link.is-active { color: var(--ink); }

.nav-link:hover::after,
.nav-link.is-active::after { transform: scaleX(1); }

.bag-btn {
  gap: 6px;
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   Portada 50 / 50
   -------------------------------------------------------------------------- */

.split {
  position: relative;
  flex: 1 0 auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: 420px;
}

/* --------------------------------------------------------------------------
   El rosal de la marca, justo en la juntura del 50/50
   --------------------------------------------------------------------------
   La portada no tenía marca por ningún lado: dos columnas de texto y nada que
   dijera de qué local es. El rosal es vertical, así que cae natural sobre la
   línea que parte la pantalla, en lugar de la línea de 1px.

   Va una vez por mitad y no una sola vez sobre el split, por dos razones:

   1. Cada mitad tiene `overflow: hidden`, o sea que recorta sola la parte del
      rosal que le toca. No hace falta ningún clip a mano.
   2. Cada media planta puede entonces llevar su propio color. Cuando la
      cortina sube en una mitad y le da vuelta el fondo, esa media planta se da
      vuelta con ella y el rosal se sigue viendo entero, mitad tinta y mitad
      papel. Antes era un solo elemento con `mix-blend-mode` y desaparecía
      contra la cortina: la cuenta que lo hacía visible sobre un fondo lo
      borraba sobre el otro.

   El trazo lo pinta `background-color` a través de una máscara con el alfa del
   PNG: así el color es una variable más y puede transicionar, cosa que con
   blend modes no se podía.

   rosalTrazo.png es el original recortado a su trazo. El recorte no es un
   detalle de peso de archivo: el PNG que vino del diseño trae, además del
   dibujo, un halo de alfa <= 10 que ocupa media tela y no se ve en pantalla.
   Con el halo adentro, `contain` centra la tela y no el rosal, y el dibujo
   queda corrido de la juntura. La proporción de acá abajo es la del recorte.
   -------------------------------------------------------------------------- */
.half-rose {
  position: absolute;
  /* De arriba a abajo del split, con el ancho que le pida la proporción del
     dibujo: es la altura la que manda, no el ancho. */
  top: 0;
  bottom: 0;
  aspect-ratio: 256 / 1247;
  z-index: 1;
  pointer-events: none;
  background-color: var(--ink);
  -webkit-mask: url("/photosSrc/rosalTrazo.png") center / contain no-repeat;
  mask: url("/photosSrc/rosalTrazo.png") center / contain no-repeat;
  opacity: 0.78;
}

/* --------------------------------------------------------------------------
   El barrido del cambio de color
   --------------------------------------------------------------------------
   La primera versión hacía el cambio con una transición de `background-color`.
   Mal: entre tinta y papel la interpolación pasa por un gris del medio que no
   contrasta con ninguno de los dos fondos, así que a mitad de camino el rosal
   se apagaba y parecía desenfocado. Y encima el cambio empezaba arriba y abajo
   a la vez, mientras la cortina iba subiendo: dos movimientos distintos.

   Ahora el color de vuelta es una capa aparte que sube igual que la cortina —
   misma curva, misma duración, mismo origen— y el rosal está siempre pintado
   de un color pleno: tinta arriba de la línea, papel abajo. Lo que se mueve es
   la línea, no el color. Como es la máscara del padre la que recorta, alcanza
   con un rectángulo.
   -------------------------------------------------------------------------- */
.half-rose::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--paper);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.62s var(--ease);
}

/* Centrado sobre la juntura: cada mitad pone su caja a caballo de su propio
   borde interno y el overflow se queda con la mitad de afuera. */
.half:first-child .half-rose {
  left: 100%;
  transform: translateX(-50%);
}

.half + .half .half-rose {
  right: 100%;
  transform: translateX(50%);
}

/* Con el rosal puesto, la línea divisoria sobra: son dos separadores haciendo
   el mismo trabajo, uno encima del otro. */
.split .half + .half::before { opacity: 0; }

.half {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--pad);
  overflow: hidden;
}

/* Toda la mitad entra a la categoría (ver portada.js), así que toda la mitad
   tiene que parecer clickeable. */
.half:not(.is-empty) { cursor: pointer; }

.half + .half::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--line);
}

/* Cuerpo centrado de cada mitad. Va por encima de la cortina. */
.half-body {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  width: min(100%, 460px);
}

.half-title {
  margin: 0;
  font-size: clamp(34px, 4.6vw, 68px);
  font-weight: 500;
  line-height: 0.94;
  letter-spacing: -0.035em;
}

.half-data {
  display: flex;
  justify-content: center;
  gap: clamp(32px, 4vw, 56px);
  margin: 26px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  width: min(100%, 340px);
}

.half-data dt {
  font-size: 12.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* El dato es lo que la clienta vino a buscar ("¿tenés mi talle?"): tiene que
   pesar más que su etiqueta, no lo mismo. */
.half-data dd {
  margin: 6px 0 0;
  font-size: clamp(20px, 1.9vw, 26px);
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}

.half-brands {
  margin: 14px 0 0;
  max-width: 44ch;
  line-height: 1.9;
  color: var(--ink-faint);
}

/* Botones de acción: una barra de ancho fijo con la línea abajo.
   Mismas dimensiones en la portada y en la ficha. */
.half-cta,
.add-btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: min(100%, 280px);
  min-height: 48px;
  padding: 0 0 2px;
  font-size: 13.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.half-cta { margin-top: 30px; }

.half-cta::before,
.half-cta::after,
.add-btn::before,
.add-btn::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 1px;
  width: 100%;
}

.half-cta::before,
.add-btn::before { background: var(--line); }

.half-cta::after,
.add-btn::after {
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.5s var(--ease);
}

.half-cta:hover::after,
.add-btn:hover::after { transform: scaleX(1); }

/* La flecha se corre unos píxeles al pasar */
.btn-arrow {
  font-size: 14px;
  letter-spacing: 0;
  color: var(--ink-soft);
  transition: transform 0.4s var(--ease), color 0.3s ease;
}

.half-cta:hover .btn-arrow,
.add-btn:hover .btn-arrow {
  transform: translateX(4px);
  color: var(--ink);
}

/* --------------------------------------------------------------------------
   Catálogo
   -------------------------------------------------------------------------- */

.catalog { padding-bottom: clamp(64px, 12vh, 140px); }

.catalog-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  padding: clamp(28px, 5vh, 56px) var(--pad) 20px;
}

.catalog-title {
  margin: 0;
  font-size: clamp(28px, 3.4vw, 48px);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.035em;
}

.catalog-count {
  margin: 0 0 8px;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.back-link {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  color: var(--ink-soft);
  font-size: 13px;
  letter-spacing: 0.06em;
  transition: color 0.25s ease;
}

.back-link:hover { color: var(--ink); }

.catalog-bar {
  position: sticky;
  top: var(--header-total);
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px 32px;
  padding: 14px var(--pad);
  background: var(--glass);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-bottom: clamp(26px, 4vh, 44px);
}

@supports not (backdrop-filter: blur(1px)) {
  .catalog-bar { background: var(--paper); }
}

/* Filtros: texto, sin cajas */
/* Con los chips recuadrados el aire va por fuera de la caja y no entre dos
   palabras sueltas: 22px de separación los dejaba flotando de a uno. */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.filter {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding-bottom: 1px;
  color: var(--ink-faint);
  transition: color 0.25s ease;
}

.filter::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 7px;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s var(--ease);
}

.filter:hover { color: var(--ink-soft); }

.filter.is-active { color: var(--ink); }

.filter:hover::after,
.filter.is-active::after { transform: scaleX(1); }

.tools {
  display: flex;
  align-items: center;
  gap: 28px;
}

.search input {
  width: 200px;
  padding: 9px 0;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  transition: border-color 0.3s ease;
}

.search input::placeholder { color: var(--ink-faint); }

.search input:focus {
  outline: none;
  border-bottom-color: var(--ink);
}

/* "Ampliar", "Limpiar filtros", "Ver más": son botones y hasta ahora eran
   texto gris en mayúsculas, indistinguibles de las etiquetas que los rodean.
   Con el recuadro se ven antes de tocarlos. */
.grid-toggle {
  flex: none;
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 0 16px;
  white-space: nowrap;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: var(--paper-deep);
  border: 1px solid var(--line);
  transition: color 0.25s ease, background-color 0.25s ease, border-color 0.25s ease;
}

.grid-toggle:hover {
  color: var(--paper);
  background: var(--ink);
  border-color: var(--ink);
}

/* --------------------------------------------------------------------------
   Grilla
   -------------------------------------------------------------------------- */

.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(34px, 4.5vh, 56px) var(--pad);
  padding: 0 var(--pad);
}

.grid.is-wide { grid-template-columns: repeat(3, 1fr); }

/* Columna: el bloque del precio se va al fondo con `margin-top: auto` (más
   abajo) y así las placas de una misma fila quedan a la misma altura sin
   reservarle renglones de más al nombre. */
.card {
  display: flex;
  flex-direction: column;
  width: 100%;
  text-align: left;
  /* Perspectiva más corta que la del boceto: con la misma inclinación, cuanto
     más cerca está el punto de fuga más se nota el volumen. */
  perspective: 800px;

  /* Las escribe el JS con la posición del puntero */
  --rx: 0deg;
  --ry: 0deg;
}

/* Vidriera de sólo exhibición: la tarjeta se sigue viendo (y se sigue
   inclinando con el puntero) pero no se ofrece como algo en lo que entrar. */
.card.is-solo-vista { cursor: default; }

.card-photo {
  position: relative;
  /* En la columna flex la foto no se achica: manda su proporción. */
  flex: none;
  aspect-ratio: 3 / 4;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--paper-deep);
  transform-style: preserve-3d;
  transform: rotateX(var(--rx)) rotateY(var(--ry));
  transition: transform 0.7s var(--ease), background-color 0.5s ease;
}

.card.is-tilting .card-photo { transition: background-color 0.5s ease; }

.card:hover .card-photo { background: #e5e2dc; }

/* Marco interior: el único indicio de que la tarjeta es un plano en el espacio */
.card-photo::before {
  content: "";
  position: absolute;
  inset: 18px;
  z-index: 1;
  border: 1px solid rgba(23, 22, 20, 0.13);
  transform: translateZ(34px);
  transition: inset 0.7s var(--ease), border-color 0.5s ease;
}

.card:hover .card-photo::before {
  inset: 12px;
  border-color: rgba(23, 22, 20, 0.22);
}

.ph-text {
  color: var(--ink-faint);
  transform: translateZ(48px);
}

.card-brand {
  margin: 20px 0 0;
  color: var(--ink-faint);
}

.card-name {
  margin: 7px 0 16px;
  font-size: 18px;
  font-weight: 400;
}

/* --------------------------------------------------------------------------
   La placa del precio
   --------------------------------------------------------------------------
   Agrandarlo alcanzó para encontrarlo, pero seguía siendo un renglón más de la
   misma columna de texto. La placa lo separa del resto sin recurrir a un
   recuadro, que en esta hoja sería un cuerpo extraño: el fondo apenas se
   despega del papel y lo que dibuja la forma son cuatro escuadras de 1px en
   las esquinas, del mismo vocabulario que la línea bajo los botones. La
   etiqueta de precio de una vidriera de verdad, no una caja.

   Sirve para los dos precios: el de lista arriba y el de efectivo abajo, que
   es la razón de que sea una columna y no una línea.
   -------------------------------------------------------------------------- */
.price-tag,
.sheet-price {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  padding: 9px 18px 10px;
  background: var(--plaque);
  transition: background-color 0.5s ease;
}

/* Las escuadras: dos pseudo-elementos, dos esquinas cada uno. */
.price-tag::before,
.price-tag::after,
.sheet-price::before,
.sheet-price::after {
  content: "";
  position: absolute;
  width: 9px;
  height: 9px;
  border: 0 solid var(--ink-faint);
  transition: border-color 0.5s ease;
}

.price-tag::before,
.sheet-price::before {
  top: 0;
  left: 0;
  border-top-width: 1px;
  border-left-width: 1px;
}

.price-tag::after,
.sheet-price::after {
  right: 0;
  bottom: 0;
  border-right-width: 1px;
  border-bottom-width: 1px;
}

/* El aire sobrante de la tarjeta se junta acá, entre el nombre y la placa: es
   el único lugar donde un hueco de más se lee como aire y no como un olvido.
   `align-self` es lo que le impide estirarse a todo el ancho de la columna. */
.price-tag {
  align-self: flex-start;
  /* El mínimo lo pone el margen de abajo de .card-name; esto sólo se come lo
     que sobra. */
  margin-top: auto;
}

/* La tarjeta entera responde al mouse; la placa se suma en vez de quedarse
   quieta mientras todo lo demás se mueve. */
.card:hover .price-tag { background: var(--plaque-strong); }
.card:hover .price-tag::before,
.card:hover .price-tag::after { border-color: var(--ink); }

/* El precio es de lo primero que se busca en una tarjeta: iba del mismo tamaño
   que el resto y en gris, o sea que había que ir a encontrarlo. */
.card-price {
  margin: 0;
  font-size: 18px;
  line-height: 1.25;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.card-price s {
  margin-left: 10px;
  color: var(--ink-faint);
}

/* El precio en efectivo va debajo del de lista, más chico: es una condición de
   pago, no el precio del producto. La línea del medio es la misma que separa
   todo lo demás en esta hoja, y acá además dice que son dos precios del mismo
   producto y no un precio partido en dos renglones. */
.card-price-cash,
.lightbox-price-cash {
  align-self: stretch;
  padding-top: 5px;
  border-top: 1px solid var(--line);
}

.card-price-cash {
  display: block;
  margin: 0;
  font-size: 15px;
  line-height: 1.25;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}

.card-price-cash small {
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.empty {
  padding: 0 var(--pad);
  color: var(--ink-faint);
}

/* --------------------------------------------------------------------------
   Ficha: repite el 50 / 50 de la portada
   -------------------------------------------------------------------------- */

.overlay {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: flex;
  align-items: stretch;
  background: rgba(23, 22, 20, 0.18);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  animation: fade 0.3s ease both;
  /* El gesto de scroll muere acá: no se lo pasa al catálogo de atrás cuando la
     ficha llega a su tope. */
  overscroll-behavior: contain;
}

.sheet {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  width: 100%;
  max-width: 1400px;
  margin: auto;
  max-height: 100svh;
  overflow: auto;
  background: var(--paper);
  animation: sheet-in 0.55s var(--ease) both;
}

@keyframes fade {
  from { opacity: 0; }
}

@keyframes sheet-in {
  from {
    opacity: 0;
    transform: translateY(18px);
  }
}

.sheet-close {
  position: absolute;
  top: 14px;
  right: var(--pad);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.sheet-close:hover { color: var(--ink); }

.sheet-photo {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 54svh;
  overflow: hidden;
  background: var(--paper-deep);
  perspective: 1200px;

  --mx: 50%;
  --my: 50%;
  --tx: 0px;
  --ty: 0px;
}

/* Luz suave que sigue al puntero: es el único brillo de la página */
.sheet-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(
    460px circle at var(--mx) var(--my),
    rgba(255, 255, 255, 0.4),
    rgba(255, 255, 255, 0) 68%
  );
}

.sheet-photo .ph-text {
  position: relative;
  z-index: 1;
  transform: translate3d(var(--tx), var(--ty), 30px);
  transition: transform 0.6s var(--ease);
}

.sheet-photo.is-tracking .ph-text { transition: none; }

.sheet-info {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  padding: clamp(40px, 6vh, 76px) var(--pad);
  /* Sin esto, la columna de la información puede crecer más allá de su mitad y
     aplastar a la de la foto hasta 0px. El culpable es cualquier hijo que se
     desplace de costado —hoy el carrusel de "de la misma marca"—: por defecto
     un ítem de grid tiene `min-width: auto`, así que reclama el ancho de todo
     su contenido en vez de dejarlo scrollear. Pasó de verdad: la ficha se abría
     sin foto en cada producto que tuviera relacionados. */
  min-width: 0;
}

.sheet-brand {
  margin: 0;
  color: var(--ink-faint);
}

.sheet-title {
  margin: 14px 0 0;
  font-size: clamp(24px, 2.4vw, 36px);
  font-weight: 500;
  line-height: 1.05;
  letter-spacing: -0.03em;
}

/* La ficha usa la misma placa que la tarjeta (ver "La placa del precio"), con
   el aire que le corresponde a un precio de este tamaño. Es una columna: el de
   lista arriba y el de efectivo abajo. */
.sheet-price {
  margin: 18px 0 0;
  padding: 13px 22px 14px;
  font-size: 18px;
  font-variant-numeric: tabular-nums;
}

.sheet-price s,
.sale-tag {
  font-size: 13px;
  color: var(--ink-faint);
}

.sheet-text {
  margin: 22px 0 0;
  padding-top: 20px;
  border-top: 1px solid var(--line);
  max-width: 46ch;
  color: var(--ink-soft);
}

.sheet-code {
  margin: 14px 0 0;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.sizes {
  width: min(100%, 560px);
  margin-top: 30px;
}

.sizes-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin: 0 0 14px;
  color: var(--ink-faint);
}

.sizes-note { letter-spacing: 0.1em; }

/* Talles: números en una fila, sin cajas */
/* Con los talles recuadrados el aire va por fuera de la caja: 18px entre dos
   números sueltos los dejaba flotando, entre dos fichas los separa. */
.sizes-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.size {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Se tocan con el dedo: 44px es el mínimo que se acierta sin apuntar. */
  min-width: 44px;
  min-height: 44px;
  font-size: 18px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
  transition: color 0.25s ease;
}

.size::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 7px;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transition: transform 0.3s var(--ease);
}

.size:hover,
.size.is-active { color: var(--ink); }

.size:hover::after,
.size.is-active::after { transform: scaleX(1); }

.size:disabled {
  color: var(--ink-faint);
  cursor: default;
  text-decoration: line-through;
}

.size:disabled::after { display: none; }

.add-btn { margin-top: 34px; }

/* --------------------------------------------------------------------------
   Pie y aviso
   -------------------------------------------------------------------------- */

.site-footer {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 32px;
  padding: 22px var(--pad);
  border-top: 1px solid var(--line);
  color: var(--ink-faint);
}

.site-footer p { margin: 0; }

.toast {
  position: fixed;
  left: var(--pad);
  bottom: 26px;
  z-index: 60;
  padding: 13px 0;
  border-top: 1px solid var(--ink);
  min-width: 260px;
  background: var(--paper);
  font-size: 13px;
  animation: toast-in 0.4s var(--ease) both;
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}

/* --------------------------------------------------------------------------
   Movimiento: un solo gesto, la persiana
   -------------------------------------------------------------------------- */

.reveal {
  clip-path: inset(0 0 102% 0);
  transform: translateY(14px);
}

.reveal.is-in {
  clip-path: inset(0 0 -20% 0);
  transform: none;
  transition: clip-path 0.9s var(--ease) var(--reveal-delay, 0s),
              transform 0.9s var(--ease) var(--reveal-delay, 0s);
}

/* --------------------------------------------------------------------------
   Pantallas chicas
   -------------------------------------------------------------------------- */

@media (max-width: 1200px) {
  .grid { grid-template-columns: repeat(3, 1fr); }
  .grid.is-wide { grid-template-columns: repeat(2, 1fr); }
}


@media (max-width: 820px) {
  :root { --header-h: 56px; }

  /* En el teléfono la ilustración entra recortada por los lados y las tarjetas
     le tapan casi todo el hueco: sube para que al menos se lea como textura. */
  body.vidriera:not(.en-portada) { --bg-ilustracion: 0.14; }

  .site-header { gap: 10px; }

  /* En 390px entran cuatro cosas en el encabezado (marca, dos categorías y
     Staff): hay que apretar tipografía y tracking o "Staff" queda cortado
     contra el borde. */
  .brand {
    font-size: 10px;
    letter-spacing: 0.08em;
    white-space: nowrap;
  }

  .header-nav { gap: 12px; }

  .nav-link { font-size: 11px; }

  .staff-link { font-size: 9px; }

  .split { grid-template-columns: 1fr; }

  /* Apiladas y a mitad de pantalla cada una: la portada sigue entrando entera
     sin scroll, que es su razón de ser. */
  .vidriera.en-portada .split { grid-template-rows: 1fr 1fr; }

  .half { min-height: 0; }

  /* Con las mitades apiladas, la juntura pasa a estar en el medio de la
     pantalla, entre el botón de una categoría y el título de la otra: el rosal
     ahí no separa nada, se mete en el medio. Sube a la cabecera de la primera
     mitad, que en un teléfono es lo primero que se ve, y hace de sello de la
     marca. La segunda media planta no tiene juntura que marcar y se va. */
  .half + .half .half-rose { display: none; }

  .half:first-child .half-rose {
    top: 14px;
    bottom: auto;
    left: 50%;
    transform: translateX(-50%);
    /* La caja mide justo el medallón, y la máscara va al ancho de la caja: el
       recorte cae exacto sobre el círculo de la "S". El rosal entero y tan
       chico no se lee, y con un pelo más de caja asoman hojas cortadas. */
    width: 96px;
    height: 96px;
    aspect-ratio: auto;
    -webkit-mask-size: 96px auto;
    mask-size: 96px auto;
    -webkit-mask-position: center 50%;
    mask-position: center 50%;
    /* Y el redondel se queda con el redondel: la caja cuadrada dejaba asomar
       las puntas de las hojas de arriba y de abajo, cortadas al ras. */
    clip-path: circle(49%);
  }

  /* Le deja el lugar al sello para que no se monte sobre el primer título, sin
     empujar: la portada tiene que seguir entrando sin scroll. */
  .split .half:first-child { padding-top: calc(var(--pad) + 106px); }

  /* Vuelve la línea divisoria: acá el rosal ya no está separando las mitades. */
  .split .half + .half::before { opacity: 1; }

  .half-title { font-size: clamp(30px, 9vw, 46px); }

  .half + .half::before {
    left: var(--pad);
    right: var(--pad);
    top: 0;
    bottom: auto;
    width: auto;
    height: 1px;
  }

  .catalog-head {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  .catalog-bar {
    flex-direction: column;
    align-items: stretch;
    gap: 14px;
  }

  .tools { justify-content: space-between; }

  .search { flex: 1; }

  .search input { width: 100%; }

  /* En una columna la ficha mide más que la pantalla (foto + talles + el
     formulario de envío). El que scrollea es el overlay, no la ficha: así el
     alto de la ficha es libre y no hay nada que quede fuera de alcance.
     Antes la ficha crecía dentro de un overlay fijo de 100svh sin scroll y
     todo lo que pasaba del primer pantallazo era inaccesible. */
  .overlay {
    align-items: flex-start;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    /* Sin el desenfoque: la ficha tapa la pantalla entera, así que no se ve, y
       mientras esté puesto el navegador toma al overlay como marco de
       referencia de los hijos fijos y el botón de cerrar se va con el scroll. */
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  .sheet {
    grid-template-columns: 1fr;
    max-height: none;
    min-height: 100%;
    margin: 0;
    overflow: visible;
    /* Sólo el fundido, sin el desplazamiento de entrada: al terminar, una
       animación con transform deja el elemento con una matriz identidad puesta,
       y eso alcanza para que el navegador lo tome como marco de referencia del
       botón de cerrar, que entonces scrollea con la ficha en vez de quedarse
       fijo. El desplazamiento de 18px no se extraña en un teléfono. */
    animation: fade 0.35s ease both;
  }

  /* Queda flotando sobre la foto: al scrollear la ficha, la salida sigue ahí.
     Funciona porque ni el overlay ni la ficha tienen ya filtro ni transform
     puestos: cualquiera de los dos lo volvería el marco de referencia del
     botón y entonces se iría con el contenido en vez de quedarse fijo. */
  .sheet-close {
    position: fixed;
    top: 10px;
    right: var(--pad);
    z-index: 5;
    min-height: 44px;
    padding: 0 14px;
    background: var(--paper);
    border: 1px solid var(--line);
    color: var(--ink);
  }

  .grid,
  .grid.is-wide { grid-template-columns: repeat(2, 1fr); }

  /* Proporción de foto en vez de un alto arbitrario: con min-height la caja
     quedaba casi cuadrada y una foto vertical dejaba dos franjas de papel a los
     costados. Con 4/5 la foto llena el ancho de la pantalla. */
  .sheet-photo {
    min-height: 0;
    aspect-ratio: 4 / 5;
  }

  .toast {
    left: var(--pad);
    right: var(--pad);
  }
}

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

  .reveal {
    clip-path: none;
    transform: none;
  }

  .overlay,
  .sheet,
  .toast { animation: none; }

  * { transition-duration: 0.01ms !important; }
}

/* ==========================================================================
   Puente con el sistema real
   --------------------------------------------------------------------------
   El boceto era una maqueta suelta. Acá se le enchufan los nombres de clase
   que ya usan los módulos de vidriera/ y las piezas que la maqueta no tenía.
   ========================================================================== */

/* base.css pinta dos manchones de color fijos con body::before/::after para el
   panel oscuro. Acá no van: el ::before se reusa para la ilustración del local
   y el ::after para el grano. */
body.vidriera::before { content: none; }

/* --------------------------------------------------------------------------
   Fondo: la ilustración del local
   --------------------------------------------------------------------------
   El dibujo a tinta de la vidriera, en negativo y muy bajo, detrás del
   catálogo y del acceso staff. En la portada NO va: ahí las dos mitades son
   todo el diseño y cualquier cosa por detrás las ensucia.

   Va en un pseudo-elemento fijo y no en background-attachment: fixed, que en
   iOS se mueve a los saltos. Para que el z-index negativo no lo deje detrás
   del fondo de la página, el color base lo pinta <html> y no <body>.
   -------------------------------------------------------------------------- */

html { background: var(--paper); }

body.vidriera:not(.en-portada)::before {
  content: "";
  position: fixed;
  inset: 0;
  /* base.css usa este mismo pseudo-elemento como manchón de color: un círculo
     de 62vw anclado arriba a la izquierda. Sin resetear la caja, inset: 0 no
     alcanza —width y height siguen mandando— y el dibujo queda encerrado en un
     cuadrado en un rincón. Es el mismo reset que hace el grano del ::after. */
  width: auto;
  height: auto;
  border-radius: 0;
  background-color: transparent;
  z-index: -1;
  pointer-events: none;
  background: url("/background-tienda.jpg?v=20260803") center / cover no-repeat;
  /* El dibujo es tinta negra sobre papel claro: invertido queda trazo claro
     sobre el fondo oscuro, que es el mismo dibujo leído al revés. */
  filter: invert(1) grayscale(1);
  /* El encuadre es el mismo en todas las pantallas: el dibujo entero, centrado.
     Lo que cambia es cuánto se ve — en el catálogo va más bajo que en el acceso
     porque compite con el título de la categoría y con las tarjetas. */
  opacity: var(--bg-ilustracion, 0.09);
}

/* El contenido cuelga de #login-screen, así que es él —y no <body>— quien tiene
   que estirarse: si no, el pie queda flotando a media pantalla. */
.vidriera #login-screen {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  min-height: 100svh;
}

/* Los módulos ocultan cosas con .hidden, no con el atributo [hidden]. */
.vidriera .hidden { display: none !important; }

/* Con la ficha abierta el catálogo de atrás no se mueve. El overflow tiene que
   ir también en <html>: el elemento que scrollea la página es él, así que
   ponerlo sólo en <body> dejaba el fondo corriéndose por debajo de la ficha
   mientras la ficha misma no se movía (se veía en el celular sobre todo). */
html:has(> body.body-no-scroll),
body.body-no-scroll {
  overflow: hidden;
  overscroll-behavior: none;
}

/* --------------------------------------------------------------- Arranque */

.vidriera .loading-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  background: var(--paper);
  color: var(--ink-faint);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.vidriera .loader,
.vidriera .spinner-loader {
  width: 26px;
  height: 26px;
  border: 1px solid var(--line);
  border-top-color: var(--ink);
  border-radius: 50%;
  animation: vidriera-spin 0.9s linear infinite;
}

@keyframes vidriera-spin {
  to { transform: rotate(360deg); }
}

/* ------------------------------------------------------- Encabezado y pie */

.staff-link {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink-faint);
  transition: color 0.25s ease;
}

.staff-link:hover { color: var(--ink); }

/* --------------------------------------------------------------------------
   El pie
   --------------------------------------------------------------------------
   Era una línea de 1px y tres columnas de texto suelto: lo único que lo
   separaba de la última fila de tarjetas. Ahora es una banda con fondo propio
   —el mismo tono de la placa del precio— y con aire arriba, así que se lee
   como el final de la página y no como una tarjeta más que salió gris.
   -------------------------------------------------------------------------- */
.site-footer {
  display: block;
  margin-top: clamp(56px, 9vh, 110px);
  padding: clamp(38px, 6vh, 62px) var(--pad) 30px;
  background: var(--plaque);
  color: var(--ink-soft);
}

.footer-cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 34px clamp(32px, 5vw, 72px);
}

/* Cada columna arranca con su título y su línea: es la misma regla que separa
   los datos en la portada y el texto en la ficha. */
.footer-title {
  color: var(--ink);
  margin-bottom: 16px !important;
  padding-bottom: 11px;
  border-bottom: 1px solid var(--line);
}

.footer-col p + p { margin-top: 7px; }

/* La dirección, el teléfono y el Instagram son lo único del pie en lo que se
   puede hacer click, y hasta ahora eran idénticos a los horarios de al lado:
   el subrayado aparecía recién al pasar por encima, o sea nunca en un
   teléfono. Ahora está siempre y lo que cambia al tocarlos es el color. */
.site-footer a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  transition: border-color 0.25s ease, color 0.25s ease;
}

.site-footer a:hover {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

.footer-bottom {
  margin-top: clamp(34px, 5vh, 52px);
  padding-top: 18px;
  border-top: 1px solid var(--line);
  color: var(--ink-faint);
}

/* --------------------------------------------------------------- Portada */

/* Una categoría sin nada cargado no se puede abrir. */
.half.is-empty { opacity: 0.55; }

.half.is-empty .half-cta { cursor: default; }
.half.is-empty .half-cta::after { display: none; }

/* ---------------------------------------------------------------- Filtros */

.filter-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  flex: 1;
}

.filter-row {
  display: flex;
  align-items: baseline;
  gap: 18px;
  min-width: 0;
}

.filter-label {
  flex: none;
  width: 74px;
  white-space: nowrap;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* --------------------------------------------------------------------------
   Los chips que dibuja filtros.js
   --------------------------------------------------------------------------
   Eran palabras sueltas en gris con un subrayado que aparecía al pasar por
   encima: hasta que el mouse no los tocaba no había manera de saber que se
   podían tocar, y en una fila de talles se leían como una lista de números.
   Ahora cada uno tiene su recuadro, y el elegido se da vuelta —tinta de fondo,
   papel de letra—, que es el mismo gesto de la cortina de la portada.
   -------------------------------------------------------------------------- */
.store-talle-filter-btn,
.store-filter-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 0 13px;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: var(--paper-deep);
  border: 1px solid var(--line);
  cursor: pointer;
  transition: color 0.25s ease, background-color 0.25s ease, border-color 0.25s ease;
}

.store-talle-filter-btn { font-variant-numeric: tabular-nums; }

.store-talle-filter-btn:hover,
.store-filter-chip:hover {
  color: var(--ink);
  border-color: var(--ink-faint);
}

.store-talle-filter-btn.active,
.store-filter-chip.active {
  color: var(--paper);
  background: var(--ink);
  border-color: var(--ink);
}

.tools { flex: none; }

/* ----------------------------------------------------------------- Grilla */

.card-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.6s ease;
}

.card-img.loaded { opacity: 1; }

/* "¿Tenés mi talle?" es la pregunta que hace todo el mundo antes de mirar nada
   más: a 11px en gris flojo no se leía de un vistazo. Va debajo de la placa,
   no encima: los talles son una condición del precio, y arriba partían en dos
   el bloque de nombre y precio. */
.card-sizes {
  margin: 10px 0 0;
  font-size: 13px;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}

.card-flags {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 3;
  /* Levantadas en el eje Z para que floten junto con el marco cuando la
     tarjeta se inclina, en vez de quedar pegadas al fondo. */
  transform: translateZ(40px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 10px;
}

/* Las dos únicas manchas de color de toda la vidriera: son las que tienen que
   frenar el ojo mientras se recorre la grilla, y por eso se salen del papel y
   la tinta. */
.card-flag {
  padding: 3px 8px;
  background: var(--flag-ultimas-bg);
  color: var(--flag-ultimas-ink);
  font-size: 9px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.card-flag-offer {
  background: var(--flag-oferta-bg);
  color: var(--flag-oferta-ink);
}

.card-price.is-offer s {
  margin: 0 8px 0 0;
  color: var(--ink-faint);
}

.load-more {
  padding: clamp(30px, 5vh, 52px) var(--pad) 0;
  text-align: center;
}

/* ------------------------------------------------------------------ Ficha */

/* El formulario de compra es largo: la ficha se lee de arriba hacia abajo y
   no centrada como en el boceto, que sólo tenía cuatro renglones. */
.sheet-info { justify-content: flex-start; }

.sheet-photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  transform: translate3d(var(--tx), var(--ty), 0);
  transition: opacity 0.6s ease, transform 0.6s var(--ease);
}

.sheet-photo img.loaded { opacity: 1; }

/* Con foto cargada sobra el cartel de "Sin foto". */
.sheet-photo img.loaded ~ .ph-text { display: none; }

@media (min-width: 821px) {
  /* La foto acompaña el scroll del formulario en vez de irse para arriba. */
  .sheet-photo {
    position: sticky;
    top: 0;
    align-self: start;
    height: 100svh;
  }
}

.sheet-countdown {
  margin-top: 10px;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* Talles de la ficha: mismo trazo que .size del boceto. */
/* --------------------------------------------------------------------------
   Los talles de la ficha
   --------------------------------------------------------------------------
   Eran números de 15px en gris flojo con un subrayado que aparecía al pasar el
   mouse: no se leían y no parecían botones. Y elegir uno es el paso obligado
   de toda la compra —sin talle no hay nada que despachar—, así que tiene que
   ser lo más visible de la ficha.

   Ahora son fichas de verdad: recuadro, número grande, y el elegido se da
   vuelta (tinta de fondo, papel de letra), el mismo gesto que los filtros del
   catálogo y la cortina de la portada.
   -------------------------------------------------------------------------- */
.store-lightbox-talle-btn {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  min-width: 56px;
  min-height: 52px;
  padding: 6px 12px;
  background: var(--paper-deep);
  border: 1px solid var(--line);
  cursor: pointer;
  font-size: 19px;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  transition: color 0.2s ease, background-color 0.2s ease, border-color 0.2s ease;
}

.store-lightbox-talle-btn:hover {
  border-color: var(--ink-faint);
  background: var(--plaque-strong);
}

.store-lightbox-talle-btn.active {
  color: var(--paper);
  background: var(--ink);
  border-color: var(--ink);
}

.talle-low-stock-badge {
  font-size: 9.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--flag-ultimas-bg);
}

/* Sobre el talle elegido el fondo es tinta: el rojo apagado del aviso no
   contrasta contra eso. */
.store-lightbox-talle-btn.active .talle-low-stock-badge { color: var(--paper); }

/* Apagado se tiene que ver apagado.
   --------------------------------------------------------------------------
   Antes sólo cambiaba de gris: el botón se leía igual de disponible, se lo
   apretaba, y no pasaba nada —porque falta elegir el talle y eso no lo decía
   nadie—. Ahora baja la opacidad, se le va la línea de abajo y el propio texto
   dice qué falta (ver ficha.js). */
.add-btn.disabled,
.add-btn:disabled {
  color: var(--ink-faint);
  cursor: not-allowed;
  opacity: 0.5;
}

.add-btn.disabled::before,
.add-btn:disabled::before { background: transparent; }

.add-btn.disabled::after,
.add-btn:disabled::after { display: none; }

.add-btn.disabled .btn-arrow,
.add-btn:disabled .btn-arrow { opacity: 0; }

/* ------------------------------------------------- Formulario de compra */

.sheet-form,
.sheet-otp {
  width: min(100%, 560px);
  margin-top: 30px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}

.form-group { margin-bottom: 16px; }

/* Las etiquetas eran de 11px en el gris más flojo de la paleta: contra el
   fondo se leían como una textura y no como palabras, y en un formulario de
   ocho campos hay que poder saber cuál es cuál sin acercarse. */
.sheet-form label,
.sheet-otp label {
  display: block;
  margin-bottom: 7px;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* Los campos eran una línea de 1px sobre el fondo: sin caja, no se veía dónde
   había que escribir. Ahora tienen su propia superficie —la misma que la placa
   del precio— y un borde completo. */
.sheet-form input,
.sheet-form select,
.sheet-otp input[type="text"],
.sheet-otp input[type="tel"] {
  width: 100%;
  padding: 11px 13px;
  background: var(--plaque);
  border: 1px solid var(--line);
  color: var(--ink);
  font-size: 15px;
  transition: border-color 0.25s ease, background-color 0.25s ease;
}

.sheet-form input::placeholder,
.sheet-otp input::placeholder { color: var(--ink-faint); }

.sheet-form input:hover,
.sheet-form select:hover,
.sheet-otp input:hover { border-color: var(--ink-faint); }

.sheet-form input:focus,
.sheet-form select:focus,
.sheet-otp input:focus {
  outline: none;
  border-color: var(--ink);
  background: var(--plaque-strong);
}

.delivery-options {
  display: flex;
  gap: 22px;
  flex-wrap: wrap;
}

.delivery-options.is-stacked {
  flex-direction: column;
  gap: 10px;
}

/* Las opciones de radio también son <label>, así que necesitan ganarle a la
   regla de arriba: si no, salen en mayúsculas y con el punto encima del texto. */
.sheet-form .delivery-option,
.sheet-otp .delivery-option {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin: 0;
  font-size: 13px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
  cursor: pointer;
}

.delivery-option input {
  width: auto;
  accent-color: var(--ink);
}

.sheet-form .delivery-option:hover { color: var(--ink); }

.form-hint {
  margin: 8px 0 0;
  font-size: 12px;
  color: var(--ink-soft);
}

/* La aclaración de cada medio de pago: "Mercado Pago" y "Tarjeta de crédito o
   débito" solos alcanzan para elegir, pero la línea de abajo saca la duda de
   qué entra en cada uno. Va en su renglón, en gris, sin competir con la
   opción. */
.payment-method-hint {
  display: block;
  margin-top: 2px;
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--ink-faint);
}

/* Lo que sale pagando de esa forma, al lado del nombre de la opción. Dos
   formas de pagar el mismo par cuestan distinto, y elegir entre ellas sin ver
   los dos números es elegir a ciegas: por eso el precio va acá y no sólo en el
   total de abajo. Firme y no gris —es un dato de la decisión, no una
   aclaración— pero sin negrita, para no pelearle al total. */
.payment-method-price {
  margin-left: 6px;
  font-style: normal;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  white-space: nowrap;
}

/* Con la aclaración debajo, la opción deja de ser un renglón: el redondel
   tiene que alinear con la primera línea y no con el medio del bloque. */
.sheet-form #payment-method-options .delivery-option {
  align-items: flex-start;
}

.sheet-form #payment-method-options .delivery-option input {
  margin-top: 2px;
}

/* Con un solo medio no hay nada que elegir: se muestra igual —el que compra
   quiere saber a dónde lo mandan— pero sin el redondel, que invitaría a
   marcar algo que ya está marcado. */
.sheet-form #payment-method-options .delivery-option.is-unico {
  cursor: default;
  color: var(--ink);
}

.sheet-form #payment-method-options .delivery-option.is-unico input {
  display: none;
}

/* La aclaración de cada forma de entrega: qué cuesta y dónde se retira. Misma
   letra chica que la de los medios de pago —son la misma clase de dato— pero
   en su propio renglón, para que el costo del envío no se lea como parte del
   nombre de la opción. */
.delivery-option-hint {
  display: block;
  margin-top: 2px;
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--ink-faint);
}

.sheet-form .delivery-options .delivery-option {
  align-items: flex-start;
}

.sheet-form .delivery-options .delivery-option input {
  margin-top: 2px;
}

.shipping-address-container {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}

/* ------------------------------------------------- Total del checkout

   El desglose de lo que se va a pagar, pegado al botón. Enterarse del flete
   recién en la pantalla del medio de pago es la forma más rápida de perder
   una venta, así que el número vive acá, a la vista, antes del clic. */

.checkout-total {
  margin: 18px 0 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

.checkout-total-linea {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 7px;
  font-size: 13px;
  color: var(--ink-soft);
}

.checkout-total-linea span:last-child {
  font-variant-numeric: tabular-nums;
}

.checkout-total-linea.is-total {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 15px;
  color: var(--ink);
}

/* El envío que todavía no tiene número: "a calcular" hasta que el cliente
   elija su provincia, "a convenir" cuando no hay tarifa para ese destino. Va
   en cursiva y apagado para que se lea como un estado y no como un precio —un
   renglón de plata que dice palabras tiene que verse distinto de uno que dice
   pesos—. */
.checkout-envio-pendiente {
  font-style: italic;
  color: var(--ink-faint);
}

.checkout-total-nota {
  margin: 10px 0 0;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--ink-faint);
}

/* El resumen del pedido coordinado, en la pantalla de "ya lo anotamos". Es el
   mismo desglose de arriba, así que reusa sus renglones. */
.coordinado-resumen {
  margin: 14px 0 16px;
  padding: 12px 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

/* ---------------------------------------------------------------- OTP */

.otp-title {
  margin: 0 0 12px;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
}

.otp-text {
  margin: 0 0 12px;
  font-size: 13px;
  color: var(--ink-soft);
}

.otp-warn { color: var(--ink); }

.otp-timer {
  margin-bottom: 18px;
  padding: 10px 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}

.otp-timer strong {
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.otp-input {
  font-size: 22px !important;
  letter-spacing: 0.4em;
  font-variant-numeric: tabular-nums;
}

.otp-actions {
  display: flex;
  align-items: center;
  gap: 26px;
}

.otp-actions .add-btn { margin-top: 0; }

.btn-store-resend {
  flex: none;
  min-height: 44px;
  background: none;
  border: 0;
  cursor: pointer;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  transition: color 0.25s ease;
}

.btn-store-resend:hover { color: var(--ink); }

.add-btn.is-wa {
  text-decoration: none;
  color: inherit;
}

.otp-waiting {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 18px;
  font-size: 12px;
  color: var(--ink-faint);
}

.otp-waiting .spinner-loader {
  width: 15px;
  height: 15px;
}

/* -------------------------------------------------------- Relacionados */

.sheet-related {
  width: min(100%, 560px);
  margin-top: 34px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}

/* El rótulo y las flechas comparten renglón: las flechas pertenecen a esta
   sección y no a la tarjeta de al lado. */
.related-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}

.related-title {
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.related-nav {
  display: flex;
  gap: 6px;
}

.related-arrow {
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  padding: 0;
  background: var(--plaque);
  border: 1px solid var(--line);
  color: var(--ink-soft);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease;
}

.related-arrow:hover {
  border-color: var(--ink-faint);
  color: var(--ink);
}

/* Una fila que se desplaza de costado en vez de una grilla de cuatro. El
   ancho de la tarjeta lo fija `flex: 0 0 ...`: sin eso, flex las apretaría
   para que entren todas y se verían como estampillas.

   La barra de scroll se esconde porque la navegación son las flechas y el
   gesto táctil; dejarla visible en escritorio parte el diseño al medio. */
.related-grid {
  display: flex;
  gap: 18px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -ms-overflow-style: none;
  /* La fila se desplaza dentro del ancho que le den, no lo estira. Junto con
     el `min-width: 0` de .sheet-info es lo que evita que el carrusel empuje el
     layout de la ficha. */
  min-width: 0;
}

.related-grid::-webkit-scrollbar { display: none; }

.related-card {
  flex: 0 0 calc((100% - 36px) / 3);
  scroll-snap-align: start;
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

.related-card-photo {
  position: relative;
  display: block;
  aspect-ratio: 3 / 4;
  background: var(--paper-deep);
  overflow: hidden;
}

.related-card-photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.related-card-name {
  margin: 10px 0 0;
  font-size: 13px;
  color: var(--ink);
}

.related-card-price {
  margin: 3px 0 0;
  font-size: 12px;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------- Avisos, pago y diálogos */

/* Los avisos van al margen izquierdo, no centrados como en el panel. Hay que
   deshacer el centrado entero de components/dialogs.css: dejando puesto su
   translateX(-50%) el aviso se iba media pantalla para afuera y se leía
   cortado ("...tu Nombre"), tanto en el celular como en la computadora. */
.vidriera .toast-host {
  position: fixed;
  left: var(--pad);
  bottom: 26px;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  width: min(480px, calc(100vw - var(--pad) * 2));
  transform: none;
}

/* El aviso se dibuja como el resto de la vidriera: papel, una línea arriba y
   nada más. Hay que apagar a mano la caja que trae components/dialogs.css
   (esquinas redondeadas, borde de color y sombra), que es del panel oscuro y
   acá quedaba como un cartel pegado encima del papel. */
.vidriera .toast-host .toast,
.vidriera .toast-host > div {
  min-width: 260px;
  padding: 13px 0;
  border: 0;
  border-top: 1px solid var(--ink);
  border-radius: 0;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  background: var(--paper);
  color: var(--ink);
  font-size: 13px;
  animation: toast-in 0.4s var(--ease) both;
}

.vidriera .payment-status-modal,
.vidriera .store-payment-overlay,
.vidriera .app-dialog-overlay {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--pad);
  background: rgba(23, 22, 20, 0.18);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

.vidriera .payment-status-card,
.vidriera .store-payment-overlay-card,
.vidriera .app-dialog {
  width: min(100%, 420px);
  padding: clamp(28px, 4vh, 44px);
  background: var(--paper);
  border: 1px solid var(--line);
  color: var(--ink);
  text-align: left;
}

.vidriera .store-payment-overlay-card { text-align: center; }

.vidriera .payment-status-card h3,
.vidriera .store-payment-overlay-card h3,
.vidriera .app-dialog h3 {
  margin: 18px 0 10px;
  font-size: 20px;
  font-weight: 500;
  letter-spacing: -0.02em;
}

.vidriera .payment-status-card p,
.vidriera .store-payment-overlay-card p,
.vidriera .app-dialog p {
  margin: 0;
  color: var(--ink-soft);
}

.vidriera .store-payment-overlay-card .spinner-loader {
  width: 30px;
  height: 30px;
  margin: 0 auto;
}

.vidriera .app-dialog-accent { display: none; }

.vidriera .app-dialog-input {
  width: 100%;
  margin-top: 16px;
  padding: 9px 0;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line);
}

.vidriera .app-dialog-actions,
.vidriera .payment-status-card .btn-payment-status-close {
  margin-top: 26px;
}

.vidriera .app-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 26px;
}

.vidriera .btn-payment-status-close,
.vidriera .app-dialog-actions button {
  min-height: 40px;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  transition: color 0.25s ease;
}

.vidriera .btn-payment-status-close:hover,
.vidriera .app-dialog-actions button:hover { color: var(--ink); }

.vidriera .app-dialog-actions .btn-primary { color: var(--ink); }

/* ------------------------------------------------------ Pantallas chicas */

@media (max-width: 820px) {
  .filter-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
  }

  .filter-label { width: auto; }

  .form-row { grid-template-columns: 1fr; gap: 0; }

  .footer-cols { grid-template-columns: 1fr; }

  /* En el teléfono entran dos y se asoma la tercera, que es lo que le
     avisa al que mira que la fila sigue. */
  .related-card { flex-basis: calc((100% - 18px) / 2.3); }

  .otp-actions {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }

  .vidriera .toast-host {
    left: var(--pad);
    right: var(--pad);
    width: auto;
  }
}

/* Precio de la ficha: lo escribe fichaPrecio.js con sus propias clases. */
/* En la ficha el precio es el protagonista, no un dato más del párrafo. */
.lightbox-price {
  font-size: clamp(26px, 2.4vw, 34px);
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.lightbox-price-cash {
  display: block;
  /* El gap de la placa ya separa los renglones. */
  margin: 0;
  /* El precio en efectivo es el que termina pagando casi todo el mundo: tiene
     que leerse como precio, no como nota al pie. */
  font-size: 19px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}

.lightbox-price-cash small {
  font-size: 13px;
  color: var(--ink-faint);
}

.lightbox-price .price-old {
  margin-right: 10px;
  font-size: 17px;
  color: var(--ink-faint);
}

/* ==========================================================================
   Portada a pantalla completa
   --------------------------------------------------------------------------
   En la portada no se ve nada más que las dos mitades: ni encabezado ni pie.
   Al entrar a un catálogo vuelven los dos.
   ========================================================================== */

.vidriera.en-portada .site-header,
.vidriera.en-portada .site-footer { display: none; }

.vidriera.en-portada .split {
  min-height: 100svh;
  height: 100svh;
}

.vidriera.en-portada #login-screen { min-height: 100svh; }

/* Sin encabezado ni pie no hay nada que scrollear: la portada es una pantalla
   fija y el rebote vertical sólo distrae. */
.vidriera.en-portada { overflow: hidden; }

/* Salvo que no entre. Apiladas, las dos mitades tienen que compartir el alto de
   un teléfono, y en los más bajos el botón de entrar al catálogo quedaba
   recortado por el overflow de la mitad, sin manera de llegar a él porque la
   página tampoco scrolleaba. Con alto mínimo en vez de fijo, cuando entra se ve
   igual que antes y cuando no entra, se puede scrollear. */
@media (max-width: 820px) {
  .vidriera.en-portada { overflow: auto; }

  .vidriera.en-portada .split {
    height: auto;
    grid-template-rows: auto auto;
  }

  .vidriera.en-portada .half { min-height: 50svh; }
}

/* --------------------------------------------------------------- La cortina */

/* Se despliega de abajo hacia arriba al posar el mouse y tiñe la mitad entera.
   Es el mismo gesto de persiana que usan las apariciones al scrollear, y por
   eso comparte la curva de aceleración. */
.half-curtain {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--ink);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.62s var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .half:not(.is-empty):hover .half-curtain { transform: scaleY(1); }

  /* Con la cortina abajo se invierte el papel: tinta de fondo, papel encima. */
  .half:not(.is-empty):hover .half-title,
  .half:not(.is-empty):hover .half-data dd,
  .half:not(.is-empty):hover .half-cta { color: var(--paper); }

  .half:not(.is-empty):hover .half-data dt,
  .half:not(.is-empty):hover .half-brands,
  .half:not(.is-empty):hover .btn-arrow { color: rgba(244, 243, 240, 0.55); }

  .half:not(.is-empty):hover .half-data { border-top-color: rgba(244, 243, 240, 0.22); }

  .half:not(.is-empty):hover .half-cta::before { background: rgba(244, 243, 240, 0.3); }
  .half:not(.is-empty):hover .half-cta::after { background: var(--paper); }

  .half:not(.is-empty):hover .half-cta .btn-arrow { color: var(--paper); }

  /* La media planta se da vuelta con la mitad, al mismo tiempo y al mismo
     ritmo que la cortina. `--ink` y `--paper` ya se intercambian solos entre
     los dos temas, así que esto vale para los dos: el rosal siempre es lo
     contrario del fondo que tiene detrás. */
  .half:not(.is-empty):hover .half-rose::after { transform: scaleY(1); }
}

/* El texto acompaña a la cortina, con un pelo de retraso para que se lea el
   barrido y no un cambio de color seco. */
.half-title,
.half-brands,
.half-cta,
.half-data,
.half-data dt,
.half-data dd,
.btn-arrow {
  transition: color 0.45s var(--ease) 0.08s, border-color 0.45s var(--ease) 0.08s;
}

/* La línea divisoria queda por encima de las cortinas. */
.half + .half::before { z-index: 2; }

@media (prefers-reduced-motion: reduce) {
  .half-curtain,
  .half-rose::after { transition: none; }
}

/* ==========================================================================
   Cajón de filtros
   --------------------------------------------------------------------------
   Reemplaza la barra de tres renglones que empujaba la grilla hacia abajo y,
   al ser translúcida y pegajosa, dejaba ver las tarjetas por debajo al
   scrollear. Ahora cerrado es un solo renglón opaco, y el panel se despliega
   por encima de la grilla al acercar el mouse.
   ========================================================================== */

.catalog-bar {
  position: sticky;
  /* Justo debajo del encabezado, que también es pegajoso: con top: 0 los dos
     compiten por el mismo lugar y el cajón desaparece detrás. */
  top: var(--header-total);
  z-index: 25;
  display: block;
  padding: 0;
  /* Opaco a propósito: el panel se superpone a la grilla y tiene que taparla. */
  background: var(--paper);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-bottom: clamp(26px, 4vh, 44px);
}

.dock-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 11px var(--pad);
}

.dock-trigger {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  min-height: 34px;
  color: var(--ink-faint);
  transition: color 0.25s ease;
}

.dock-trigger-label {
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
}

.dock-summary {
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  transition: color 0.25s ease;
}

.dock-trigger:hover .dock-summary,
.is-open .dock-summary { color: var(--ink-soft); }

/* Un triangulito que gira: el único indicio de que el renglón se abre. */
.dock-caret {
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 4px solid var(--ink-faint);
  transition: transform 0.45s var(--ease);
}

.catalog-bar.is-open .dock-caret { transform: rotate(180deg); }

/* El panel se revela como una persiana vertical y encima se superpone a la
   grilla, en vez de empujarla: la posición de las tarjetas no se mueve. */
.dock-panel {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  z-index: 1;
  padding: 0 var(--pad);
  background: var(--paper);
  border-bottom: 1px solid var(--line);
  clip-path: inset(0 0 100% 0);
  opacity: 0;
  pointer-events: none;
  /* Cerrado se esconde de verdad: recortado con clip-path los chips seguían
     siendo tabulables con el teclado, aunque no se vieran. La visibilidad
     cambia recién al terminar el cierre para no cortar la persiana. */
  visibility: hidden;
  transition: clip-path 0.5s var(--ease), opacity 0.3s ease, padding 0.5s var(--ease),
    visibility 0s linear 0.5s;
}

.catalog-bar.is-open .dock-panel {
  padding: 20px var(--pad) 24px;
  clip-path: inset(0 0 0 0);
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transition: clip-path 0.5s var(--ease), opacity 0.3s ease, padding 0.5s var(--ease),
    visibility 0s linear 0s;
}

/* Las filas entran escalonadas detrás de la persiana. */
.dock-panel .filter-row {
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
}

.catalog-bar.is-open .dock-panel .filter-row {
  opacity: 1;
  transform: none;
}

.catalog-bar.is-open .dock-panel .filter-row:nth-child(1) { transition-delay: 0.08s; }
.catalog-bar.is-open .dock-panel .filter-row:nth-child(2) { transition-delay: 0.14s; }
.catalog-bar.is-open .dock-panel .filter-row:nth-child(3) { transition-delay: 0.2s; }

.dock-clear { margin-top: 16px; }

@media (prefers-reduced-motion: reduce) {
  .dock-panel,
  .dock-panel .filter-row { transition: none; }
}

@media (max-width: 820px) {
  .dock-row {
    flex-wrap: wrap;
    gap: 12px;
  }

  .dock-row .tools {
    width: 100%;
    justify-content: space-between;
    gap: 16px;
  }

  .dock-row .search { flex: 1; }
}

/* ==========================================================================
   Tema oscuro  — TEMPORAL
   --------------------------------------------------------------------------
   Sólo invierte la paleta: papel y tinta cambian de lugar y el resto de la
   hoja sigue funcionando sin tocar nada, porque todo el diseño se apoya en
   estas seis variables. Se borra entero cuando se elija una de las dos
   versiones (ver js/views/vidriera/tema.js).
   ========================================================================== */

/* Los grises venían calcados del tema claro, donde funcionan porque el fondo es
   papel. Invertidos quedaban muy por debajo: --ink-faint daba 3:1 contra el
   fondo (el mínimo legible es 4.5:1), así que las marcas y las etiquetas se
   desvanecían. Ahora --ink-soft da ~8:1 y --ink-faint ~6:1. */
:root[data-tema="oscuro"] {
  --paper: #131211;
  --paper-deep: #1c1a18;
  --ink: #f2f0ec;
  --ink-soft: #b3ada3;
  --ink-faint: #9a948a;
  --line: #3a3630;

  --plaque: #1f1d1a;
  --plaque-strong: #2b2724;

  --glass: rgba(19, 18, 17, 0.72);

  --flag-oferta-bg: #7db4d6;
  --flag-oferta-ink: #07202c;
  --flag-ultimas-bg: #c8806e;
  --flag-ultimas-ink: #2c110b;
}

/* El grano es una textura negra: sobre fondo oscuro hay que invertirla para
   que se siga notando. */
:root[data-tema="oscuro"] body.vidriera::after {
  filter: invert(1);
  opacity: 0.04;
}

/* Con la paleta dada vuelta la cortina entra clara sobre fondo oscuro, que es
   el mismo contraste al revés. El destello de la ficha sí hay que bajarlo: en
   oscuro un blanco al 40% quema. */
:root[data-tema="oscuro"] .sheet-photo::after {
  background: radial-gradient(
    460px circle at var(--mx) var(--my),
    rgba(255, 255, 255, 0.07),
    rgba(255, 255, 255, 0) 68%
  );
}

:root[data-tema="oscuro"] .card:hover .card-photo { background: #24211e; }

:root[data-tema="oscuro"] .card-photo::before { border-color: rgba(242, 240, 236, 0.14); }

:root[data-tema="oscuro"] .card:hover .card-photo::before { border-color: rgba(242, 240, 236, 0.24); }

/* El texto invertido de la cortina: en oscuro la cortina es clara, así que lo
   de encima tiene que volver a ser tinta oscura. */
@media (hover: hover) and (pointer: fine) {
  :root[data-tema="oscuro"] .half:not(.is-empty):hover .half-title,
  :root[data-tema="oscuro"] .half:not(.is-empty):hover .half-data dd,
  :root[data-tema="oscuro"] .half:not(.is-empty):hover .half-cta { color: #131211; }

  :root[data-tema="oscuro"] .half:not(.is-empty):hover .half-data dt,
  :root[data-tema="oscuro"] .half:not(.is-empty):hover .half-brands,
  :root[data-tema="oscuro"] .half:not(.is-empty):hover .btn-arrow,
  :root[data-tema="oscuro"] .half:not(.is-empty):hover .half-cta .btn-arrow { color: rgba(19, 18, 17, 0.55); }

  :root[data-tema="oscuro"] .half:not(.is-empty):hover .half-data { border-top-color: rgba(19, 18, 17, 0.22); }

  :root[data-tema="oscuro"] .half:not(.is-empty):hover .half-cta::before { background: rgba(19, 18, 17, 0.3); }
  :root[data-tema="oscuro"] .half:not(.is-empty):hover .half-cta::after { background: #131211; }
}

/* --------------------------------------------------------------------------
   Cajón de filtros: contención del alto
   --------------------------------------------------------------------------
   Con muchas marcas o modelos el panel llegaba a ocupar dos tercios de la
   pantalla y no quedaba dónde mover el mouse para que se cerrara. Ahora tiene
   techo y, si aun así sobra, scrollea por dentro.
   -------------------------------------------------------------------------- */

.catalog-bar.is-open .dock-panel {
  max-height: 55svh;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* "+30 más" / "Ver menos": del alto y el recuadro de los chips que abre, pero
   sin fondo, para que se lea como la acción de la fila y no como un valor más
   de la lista. */
.chip-mas {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 0 13px;
  background: none;
  border: 1px dashed var(--line);
  cursor: pointer;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  transition: color 0.25s ease, border-color 0.25s ease;
}

.chip-mas:hover {
  color: var(--ink);
  border-color: var(--ink-faint);
}

/* Aviso de la fila que todavía no se puede usar (modelo sin marca elegida). */
.filter-hint {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
}

.filter-row.is-locked .filter-label { opacity: 0.55; }

/* ==========================================================================
   Barras de desplazamiento
   --------------------------------------------------------------------------
   base.css las pinta con el naranja y el azul del panel. Acá van en tinta
   sobre papel, y siguen al tema porque salen de las mismas variables. Los
   selectores van sin prefijo a propósito: esta hoja sólo se carga en la
   vidriera, así que no puede alcanzar al panel de admin.
   ========================================================================== */

:root {
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}

::-webkit-scrollbar {
  width: 9px;
  height: 9px;
}

::-webkit-scrollbar-track { background: transparent; }

::-webkit-scrollbar-thumb {
  background: var(--line);
  border: 2px solid var(--paper);
  border-radius: 0;
}

::-webkit-scrollbar-thumb:hover { background: var(--ink-faint); }

::-webkit-scrollbar-corner { background: transparent; }

:root[data-tema="oscuro"] .card-photo::before { border-color: rgba(242, 240, 236, 0.16); }

:root[data-tema="oscuro"] .card:hover .card-photo::before { border-color: rgba(242, 240, 236, 0.3); }

/* ==========================================================================
   Renglones parejos y objetivos de toque
   --------------------------------------------------------------------------
   Dos arreglos de uso, no de estilo.
   ========================================================================== */

/* Los nombres de uno y de dos renglones desalineaban los talles y el precio de
   las tarjetas vecinas. En la grilla grande eso ahora lo resuelve la columna
   flex de .card, que manda la placa al fondo: reservarle dos renglones al
   nombre además de eso dejaba un hueco enorme abajo de los nombres cortos.
   En los relacionados, que son tarjetas chicas sin placa, la reserva sigue
   siendo lo único que las alinea. */
.card-name {
  line-height: 1.3;
}

.related-card-name {
  line-height: 1.3;
  min-height: 2.6em;
}

/* --------------------------------------------------------------------------
   Touch: nada por debajo de 44px
   --------------------------------------------------------------------------
   Los talles del cajón de filtros medían 16 x 30 px reales: con el dedo se le
   erraba casi siempre. El área de toque crece; el tamaño de letra queda igual,
   así que el diseño no cambia.
   -------------------------------------------------------------------------- */

@media (max-width: 820px) {
  .store-talle-filter-btn,
  .store-filter-chip,
  .chip-mas,
  .filter {
    min-height: 44px;
  }

  .store-talle-filter-btn {
    justify-content: center;
    min-width: 44px;
  }

  .filters { gap: 8px; }

  .size,
  .store-lightbox-talle-btn {
    min-height: 48px;
    min-width: 48px;
  }

  .brand,
  .grid-toggle,
  .dock-trigger,
  .staff-link,
  .nav-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  .nav-link::after { bottom: 12px; }

  /* El redondel del radio mide 13px: lo que se toca es el renglón entero. */
  .sheet-form .delivery-option,
  .sheet-otp .delivery-option { min-height: 44px; }

  .search input,
  .sheet-form input,
  .sheet-form select,
  .sheet-otp input[type="text"],
  .sheet-otp input[type="tel"] { min-height: 44px; }

  /* Direccion, telefono e Instagram del pie tambien se tocan. */
  .footer-col a {
    display: inline-flex;
    align-items: center;
    min-height: 36px;
  }
}

/* ==========================================================================
   Etiquetas del catálogo
   --------------------------------------------------------------------------
   Las que el local define en Ajustes ("Basket", "Running"). Aparecen como chip
   en la tarjeta, como lista en la ficha y como fila de filtros en el cajón.
   ========================================================================== */

/* En la tarjeta va una sola y en un tono propio: no compite con la de oferta,
   que es la que tiene que ganar la mirada. */
.card-flag-tag {
  background: var(--flag-etiqueta-bg);
  color: var(--flag-etiqueta-ink);
  backdrop-filter: blur(6px);
}

.sheet-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 8px 0 4px;
}

/* Son botones, no calcomanías: tocarlos filtra el catálogo por esa etiqueta. */
.sheet-tag {
  padding: 5px 11px;
  border-radius: 999px;
  border: 1px solid var(--border-color);
  background: rgba(255, 255, 255, 0.05);
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}

@media (hover: hover) {
  .sheet-tag:hover {
    color: var(--accent-orange);
    border-color: var(--accent-orange);
  }
}
