/* EL MUNDO DE TERA — la hoja de la tienda.
 *
 * Un taller de encuadernación que es también un gabinete de curiosidades. Todo
 * está pegado, cosido y torcido, y lo que se pega ENCIMA son especímenes: cada
 * referencia del lote tiene su escarabajo o su planta, con su binomio y su
 * número de registro, como las láminas del XIX.
 *
 * ================================ LOS DOS TEMAS =============================
 *
 * La tienda tiene dos caras y son la MISMA página con otra luz:
 *
 *   [data-theme="dia"]    el gabinete    — el jardín INVADE
 *   [data-theme="noche"]  el jardín      — el jardín ALUMBRA
 *
 * ⭐⭐⭐ Cada tema tiene UNA regla, y la regla es lo que lo sostiene:
 *
 *   De día, el espécimen SIEMPRE se sale de su caja. Un bicho contenido dentro
 *   de un recuadro es una ilustración; un bicho que invade el margen y tapa una
 *   esquina es un gabinete. Si todos quedan alineados y adentro, el tema murió.
 *
 *   De noche, la luz VIENE DE ALGÚN LADO y todas las sombras caen igual. Un
 *   modo oscuro es un fondo oscuro; una noche es una escena iluminada. Si un
 *   halo apunta hacia otro lado, se nota antes de saber por qué.
 *
 * ⭐⭐⭐ La noche NO es una hoja aparte: REMAPEA LOS TOKENS. `--crema` pasa a
 * ser la noche y `--sepia` la luz, conservando los nombres. Con eso casi toda
 * la hoja de arriba funciona sin tocarla, y el diff entre los dos temas dice la
 * verdad — es corto porque de verdad cambia poco.
 *
 * ⚠️⚠️ Lo que la inversión NO arregla está anotado UNO POR UNO al final, bajo
 * «la noche». Son tres familias y conviene reconocerlas antes de agregar nada:
 *   · lo que estaba en hex quemado (no hay token que voltear),
 *   · lo que YA era oscuro de día (el pie, el cajón: invertirlo lo aclararía),
 *   · lo que SIGUE siendo de papel de noche (la prueba, la nota escrita a mano:
 *     son objetos físicos y un objeto no cambia de color porque anochezca).
 *
 * ⚠️ Ninguna sección aparece ni desaparece con el tema. El marcado es uno solo
 * —ver la cabecera de `app.js`—: si una banda se ocultara de día, cambiaría el
 * alto de la página y las anclas del pie dejarían de caer donde dicen.
 */

/* ══════════════════════════════════════════════════════════ LA MÁQUINA ══════
 *
 * TLWG Typewriter, del Thai Linux Working Group. No está en Google Fonts, así
 * que se sirve desde el repo, subconjuntada a latino: 20-24 KB por estilo contra
 * los 96-112 del TTF completo.
 *
 * ⚠️ Licencia GPL-2+ **con excepción de fuente**. La excepción es lo que permite
 * usarla en una tienda comercial sin contagiar la licencia a la página. Servir el
 * .woff2 ES distribuir, así que `fuentes/LICENCIA-TLWG.txt` no es opcional.
 *
 * La negrita cursiva no se declara porque no se usa en ningún sitio; si algún día
 * hace falta, el navegador la sintetiza.
 */
@font-face {
  font-family: 'TLWG Typewriter';
  src: url('fuentes/TlwgTypewriter.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'TLWG Typewriter';
  src: url('fuentes/TlwgTypewriter-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'TLWG Typewriter';
  src: url('fuentes/TlwgTypewriter-Oblique.woff2') format('woff2');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

:root {
  color-scheme: light;

  /* Papel envejecido: la lámina entomológica vive sobre papeles ocres, no
     sobre crema limpio. */
  --crema: #f3ead9;
  --kraft: #e0cfae;
  --kraft-osc: #c7b291;

  /* ⭐⭐⭐ LA CARTA ES NEGRA, Y ES EL MISMO NEGRO DE SU CAMPO. Se pintaba con
     `--kraft` —el mismo valor exacto de `.band--kraft`, así que en la portada la
     carta y la banda eran indistinguibles— y después con un papel intermedio que
     solo daba 1,13:1 contra los dos fondos: entre `--crema` y `--kraft` no hay
     sitio, los dos papeles de la tienda distan apenas 1,28:1.
     El negro del arcano sale de ese callejón por arriba: **11,6:1 contra el
     kraft de día**. Y de paso la carta se vuelve una sola pieza —campo y cartela
     en el mismo negro, separados por el filete de oro— en vez de una lámina
     oscura pegada sobre un papel.
     ⚠️ Se declara UNA vez y apunta a `--campo`, que ya cambia con el tema: con el
     hex escrito a mano, el día y la noche se separarían en cuanto alguien tocara
     uno de los dos. */
  --carta-papel: var(--campo);
  --carta-canto: var(--oro-30);

  /* La tinta de la carta. La carta es oscura en los DOS temas —igual que su
     campo y que su oro—, así que se lee siempre con la LUZ y nunca con la tinta
     del papel. Por eso estos dos no se remapean de noche: no hay nada que
     invertir. Dan 14,5:1 y 7,2:1 sobre el negro del arcano. */
  --carta-tinta: #efe7d4;
  --carta-tinta-70: #efe7d4ad;

  /* ⭐⭐⭐ LA MESA NO ES PAPEL DE LA PÁGINA, Y ESO HAY QUE PINTARLO. Se pintaba
     con `--kraft`: sobre una banda kraft el panel y la página eran **el mismo
     valor exacto** —1,00:1, invisible— y sobre crema daban 1,28. De noche,
     1,14. Es la misma trampa que ya mordió con la carta: dos superficies
     vecinas iguales, y ninguna prueba de contraste lo ve porque todas miran
     TEXTO sobre su fondo.
     La salida es la de siempre: se sale por arriba o por abajo, no por el
     medio. Y acá cada tema sale por SU lado, que es exactamente para lo que
     sirve remapear un token — de día la mesa es un cartón más oscuro que los
     dos papeles; de noche es la superficie que la luz alcanza. En los dos
     casos ≥1,5:1 contra el papel más cercano y ≥1,7 contra el otro.
     ⚠️ Bajar el papel de día aprieta su tinta: `--sepia-70` caía a 3,6:1 y la
     terracota a 2,2 (y ya estaban en 4,59 y 3,44 antes de tocar nada — la
     terracota llevaba tiempo por debajo del mínimo sin que nada lo mirara). Por
     eso la mesa lleva su propia tinta secundaria y su propio enlace: no es
     decoración, es lo que sostiene el papel nuevo. */
  --mesa-papel: #bda683;
  --mesa-tinta-70: #33281fe0;
  --mesa-enlace: #692a1a;

  /* ⭐⭐⭐ EL POZO — el fondo de un campo de formulario, y su borde.
     El owner señaló que los campos «no se distinguen del fondo», y tenía razón
     por partida doble: el relleno era `--crema`, o sea EL MISMO valor exacto de
     la página (1,00:1), y el borde era `--kraft-osc`, que da **1,72:1** contra
     el papel cuando **WCAG 1.4.11 exige 3,0 para el contorno de un control**.
     Ese segundo número es el defecto de verdad: el relleno se puede discutir,
     el borde de un campo tiene norma y no la cumplía.

     ⚠️ Y el relleno NO puede salir por arriba: la página de día ya es un papel
     claro, así que un pozo más blanco llega como mucho a 1,19:1 contra ella.
     Se sale por abajo, igual que la mesa —«se sale por arriba o por abajo,
     nunca por el medio»— y de noche al revés, subiendo hacia la luz.

     Medidos: día pozo 1,13:1 contra la página y borde 3,44:1; noche 1,25:1 y
     4,27:1. La tinta encima da 12,9:1 de día y 10,8:1 de noche. */
  --pozo: #e9dcc4;
  --pozo-borde: #8f7a5c;

  /* ⭐⭐⭐ EL FRENTE DEL CAJÓN. Se pintaba con `--crema` — el MISMO valor exacto
     de la pared, 1,00:1— y lo único que lo separaba era un filete de `--hilo` a
     1,43:1. Las tarjetas «no contrastaban» porque literalmente no había
     ninguna superficie: había un borde.

     ⚠️ Y no se arregla subiendo el relleno. Acá hay TRES superficies en juego
     —pared, cajón y la mesa flotante, que pasa por encima— y empujar el cajón
     hasta 1,4:1 contra la pared lo mete a 1,44 de la mesa. Sale por el canto:
     un cajón de verdad se distingue por su BORDE y su sombra, no porque su
     madera sea mucho más oscura que la pared.

     Medidos: relleno 1,24:1 contra la pared y 1,59 contra la mesa; canto
     2,21:1 contra la pared. La tinta encima da 9,7:1. */
  --cajon: #e2d3b4;
  --cajon-canto: #b59c74;
  --cajon-luz: #f6efdf;

  /* La lámina de colección. Va sobre la banda kraft, así que sale por el otro
     lado que el cajón: la gaveta es madera y baja, esto es papel y sube. Y NO
     puede parecerse al cajón (1,29:1 entre los dos) porque no es lo mismo —
     una colección atraviesa los cajones, no es uno más. */
  --lamina: #f6efe0;
  --lamina-canto: #9a8258;

  /* ⚠️ El enlace dentro de un párrafo lleva token PROPIO y no `--terracota`.
     La terracota da 4,41:1 sobre el papel del día y AA pide 4,5 — falla por
     nueve centésimas, que es justo el margen que nadie mira. Bajarla de tono
     en el token general habría movido el acento, los bordes y las sombras de
     media tienda; acá solo cambia lo que se lee de corrido. Día 5,04:1. */
  --enlace: #9c4c31;

  --sepia: #33281f;
  --sepia-70: #33281fb8;
  --tinta: #1f1811;
  --terracota: #a85438;
  --oliva: #5e6b47;
  --hilo: #33281f30;

  /* Tinta del grabado. Va aparte del texto a propósito: un espécimen impreso
     nunca es tan negro como la tipografía, y si lo fuera competiría con ella. */
  --grabado: #4a3a2a;
  --elitro: #6b4326;
  --esp-relleno: var(--crema);

  /* ⭐ El oro de la carta NO se voltea con el tema, y es a propósito: la carta es
     un objeto OSCURO en los dos temas —como el cajón entomológico, que ya lo era
     de día—, así que su tinta no tiene por qué invertirse. Lo que cambia con el
     tema es el PAPEL que la rodea. */
  --oro: #c9a25a;
  --oro-70: #c9a25ab0;
  --oro-30: #c9a25a4d;
  --campo: #1c1710;

  /* Los tres colores del logo. Están acá y no dentro del <svg> porque el logo
     tiene que cambiar con el tema: con los hex quemados se veía bien de día y
     se apagaba de noche. Cuando llegue el logo definitivo del owner, se pinta
     con estas mismas variables. */
  --marca-a: #3a2e25;
  --marca-b: #b4644a;
  --marca-c: #f6efe2;

  /* ⚠️ El verde de WhatsApp es lo ÚNICO del sitio que no se remapea de noche, y
     no es un descuido: es una marca ajena. El botón se reconoce porque es ese
     verde exacto —el usuario no lo lee, lo identifica—, y un verde que cambia
     con el tema deja de ser la marca y vuelve a ser un botón cualquiera. Por eso
     va en hex quemado a propósito y con nombre propio: para que se vea que la
     excepción es deliberada y no un token que se olvidó de invertir.
     El borde oscuro no es adorno: le da un contorno medible al círculo contra el
     papel del día, donde un verde claro sobre crema casi no se recorta. */
  --wa: #25d366;
  --wa-borde: #075e54;

  /* ⭐ Tres familias, tres papeles, y el nombre del token lo dice:
     · --voz     lo que se MIRA — titulares, rótulos, numerales, cifras, fichas
     · --lectura lo que se LEE de corrido — párrafos
     · --mano    lo que finge estar escrito a mano
     La regla al editar: si es un dato o un rótulo, --voz; si es prosa, --lectura.

     TLWG es monoespaciada (292 de 299 glifos miden 0,6 em) y de altura-x baja
     (0,42 em contra 0,52 de Karla). Por eso NO se lleva los párrafos: la medida
     caería de 65 caracteres por línea a 48. */
  --voz: 'TLWG Typewriter', 'Courier New', monospace;
  --lectura: 'Karla', -apple-system, 'Segoe UI', Helvetica, sans-serif;
  --mano: 'Newsreader', 'Iowan Old Style', Georgia, serif;

  --pad: clamp(18px, 4vw, 56px);
  /* El ancho de la columna de lectura de «Sobre mí». Es un token y no un número
     escrito dos veces porque lo usan DOS bloques que tienen que coincidir: la
     biografía y el sello que la cierra. Escrito aparte, el sello se centraría
     en el `wrap` entero y caería a la derecha del texto — que es exactamente
     como se veía antes de atarlos. */
  --ancho-bio: 68ch;
  /* Desaceleración exponencial, SIN sobrepaso. La sensación táctil de esta
     dirección la dan la sombra dura y el desplazamiento del botón al pulsarlo,
     no un rebote: un objeto de papel no rebota. */
  /* El alto de la pestaña de la mesa. Nació sirviendo a cuatro sitios —su
     `height`, el `translateY` que la dejaba asomada, el `margin-bottom` del pie
     y el flotante de WhatsApp— y hoy solo le queda el primero: la pestaña ya no
     asoma con el panel cerrado, así que no hay nada debajo a lo que dejarle
     hueco. Se queda como token porque sigue siendo UNA medida con nombre.
     ⚠️ Hay otro `54px` en el archivo, el ancho del tirador del cajón, que NO es
     este alto y no se toca. */
  --mesa-tab: 54px;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-soft: cubic-bezier(0.25, 0.8, 0.35, 1);
}

/* ============================================================== LA NOCHE (1/2)
 *
 * La inversión. Los NOMBRES se conservan —`--crema` sigue llamándose crema
 * aunque acá valga verde noche— y esa es justamente la razón por la que la hoja
 * de arriba no se toca: `background: var(--crema)` escrito una sola vez sirve
 * para los dos temas.
 *
 * Los arreglos que la inversión no cubre viven al final del archivo, en «LA
 * NOCHE (2/2)». Acá SOLO van valores de token; si algo necesita un selector
 * nuevo, va allá.
 */
[data-theme='noche'] {
  color-scheme: dark;

  --crema: #16211a;
  --kraft: #1e2c24;
  --kraft-osc: #35493c;

  /* De noche la mesa sube en vez de bajar: la página ya es lo oscuro, así que un
     panel más oscuro se pierde igual —el negro de la carta da 1,13:1 contra el
     jardín, y por eso la carta necesita su filete de oro—. Acá es la superficie
     ILUMINADA, que además es la regla del tema. */
  --mesa-papel: #36493d;
  --mesa-tinta-70: #efe7d4e0;
  --mesa-enlace: #e8a891;

  /* El pozo, al revés que de día: la página ya es lo oscuro, así que un campo
     más oscuro se pierde. Sube hacia la luz, que además es la regla del tema.
     ⚠️ Y se queda por DEBAJO de `--mesa-papel` (1,38:1 entre los dos): el
     resumen del pedido está al lado y son dos superficies distintas. */
  --pozo: #243329;
  --pozo-borde: #6b8875;

  /* El cajón, de noche: sube hacia la luz en vez de bajar, como la mesa. ⚠️ Y
     se queda POR DEBAJO de `--mesa-papel` (1,40:1 entre los dos), porque la
     mesa flota justo encima de estas tarjetas y dos superficies vecinas que
     midan igual son una sola superficie. Canto a 3,06:1 contra la pared. */
  --cajon: #22322a;
  --cajon-canto: #557060;
  --cajon-luz: #3d5548;

  --lamina: #304238;
  --lamina-canto: #6b8875;

  /* De noche la terracota ya da 5,15:1 sobre el jardín: no hace falta bajarla. */
  --enlace: var(--terracota);

  --sepia: #efe7d4;
  --sepia-70: #efe7d4ad;
  --tinta: #0d1410;
  --terracota: #d2775a;
  --oliva: #94a87a;
  --hilo: #efe7d42b;

  /* De noche el grabado no es tinta: es el latón del alfiler devolviendo la
     luz. Es el único metal de la paleta y por eso marca lo importante — un
     segundo dorado lo volvería adorno. */
  --laton: #c9a25a;
  --laton-70: #c9a25ab0;
  --grabado: var(--laton);
  --elitro: #b8905180;

  --marca-a: #efe7d4;
  --marca-b: #c9a25a;
  --marca-c: #16211a;

  /* Del oro de la carta solo se mueve el campo: el marrón de la noche pasa a
     verde para que la carta se lea en el mismo jardín que la rodea. El oro
     se queda como está — ver el comentario del `:root`. */
  --campo: #0c1310;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* La cabecera es `sticky`: sin esto, cada ancla del menú deja su titular
     DEBAJO de la cabecera y el usuario aterriza en mitad de un párrafo. Se nota
     mucho más en móvil, donde la cabecera se come más proporción de pantalla. */
  scroll-padding-top: 88px;
}

body {
  margin: 0;
  font-family: var(--lectura);
  font-size: 16.5px;
  line-height: 1.62;
  color: var(--sepia);
  background: var(--crema);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

/* Grano de papel real sobre TODO el fondo. Es lo que hace que la pantalla no
   se sienta plana; sin esto, la dirección se cae. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  opacity: 0.5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='4'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)' opacity='.34'/%3E%3C/svg%3E");
  mix-blend-mode: multiply;
}

img,
svg {
  display: block;
  max-width: 100%;
}
a {
  color: inherit;
  text-decoration: none;
}
button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}
::selection {
  background: var(--terracota);
  color: var(--crema);
}
:focus-visible {
  outline: 2px dashed var(--terracota);
  outline-offset: 4px;
}

.wrap {
  width: 100%;
  max-width: 1320px;
  margin-inline: auto;
  padding-inline: var(--pad);
  position: relative;
  z-index: 2;
}

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

h1,
h2,
h3 {
  font-family: var(--voz);
  font-weight: 500;
  line-height: 1.02;
  letter-spacing: -0.012em;
  margin: 0;
}

/* ⚠️ Un 25% por debajo de la escala de Newsreader, y no es capricho: TLWG avanza
   0,6 em por carácter contra los ~0,45 de una proporcional. Con el cuerpo de
   antes, cada titular se partía en una línea de más y los <br> del marcado
   dejaban de significar nada. */
.h-xl {
  font-size: clamp(31px, 4.7vw, 66px);
  line-height: 1.08;
  letter-spacing: -0.02em;
}
.h-lg {
  font-size: clamp(23px, 3.3vw, 45px);
  line-height: 1.12;
  letter-spacing: -0.02em;
}
.h-md {
  font-size: clamp(18px, 2vw, 27px);
  line-height: 1.22;
}

.kicker {
  /* Un rótulo es un DATO, no prosa: va en la voz. Los cuatro rótulos que
     estaban en la familia de lectura se movieron acá de una vez. */
  font-family: var(--voz);
  font-size: 12px;
  /* ⚠️ Menos tracking que con la proporcional: una monoespaciada ya reparte el
     espacio ella sola, y el 0,2em de antes desmigaba las versalitas. */
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--terracota);
}

.lede {
  font-size: clamp(16.5px, 1.25vw, 19.5px);
  color: var(--sepia-70);
  max-width: 48ch;
}

/* Anotación a mano: cursiva de --mano con inclinación. Se usa para las
   notas al margen, nunca para información necesaria. */
.hand {
  /* ⚠️ NO hereda de --voz. Es la única nota manuscrita de la tienda, y el
     contraste entre lo que la máquina escribe y lo que la mano anota es media
     marca. Si algún día esto se vuelve monoespaciado, se perdió el gesto. */
  font-family: var(--mano);
  font-style: italic;
  color: var(--terracota);
  font-size: 19px;
  line-height: 1.25;
  transform: rotate(-2.2deg);
  display: inline-block;
}

/* Costura: dos filetes punteados que imitan un pespunte. */
.stitch-top {
  border-top: 2px dashed var(--hilo);
  padding-top: 3px;
  background-image: linear-gradient(var(--hilo), var(--hilo));
  background-size: 100% 1px;
  background-repeat: no-repeat;
  background-position: 0 0;
}

/* -------------------------------------------------------------- cabecera */

.head {
  position: sticky;
  top: 0;
  z-index: 60;
  background: color-mix(in srgb, var(--crema) 92%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--kraft-osc);
}
.head__in {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  /* `min-height` y no `height`. Con altura fija, cualquier cosa que crezca
     —una marca larga, una traducción— se sale por abajo en vez de empujar, y se
     encima con el contenido. Es exactamente lo que pasó al cambiar «Bramante»
     por «El mundo de Tera». */
  min-height: 72px;
}

/* ⚠️ La marca NO se parte. «El mundo de Tera» a 27px fijos medía 175 px de alto
   —cinco líneas— dentro de una cabecera de 73, y tapaba el titular del hero en
   las tres páginas a cualquier ancho de teléfono.
   El tamaño es fluido y el `nowrap` es la garantía: si algún día no cabe, se
   encoge; nunca se apila. */
.brand {
  font-family: var(--voz);
  font-size: clamp(19px, 5.4vw, 27px);
  letter-spacing: -0.015em;
  display: flex;
  align-items: center;
  gap: clamp(7px, 2vw, 9px);
  white-space: nowrap;
  min-width: 0;
}
/* ⭐⭐⭐ EL SELLO DE LA MARCA — el logo oficial (llegó el 2026-08-13).

   ⚠️ Se llama `sello-marca` y NO `sello` a secas porque en este repo «el
   sello» ya era otra cosa: el de **VENDIDA** (`.pdp__vendida`), que es como lo
   nombran los comentarios del gate. La clase estaba libre y aun así el nombre
   no lo estaba — una palabra que significa dos cosas deja de significar
   cualquiera.

   Es una polilla grabada dentro de un anillo, y el archivo es de UNA sola
   tinta sobre transparente.

   ⚠️⚠️ Va en `.webp` y NO en `.png` porque `.gitignore` ignora los `.png` de
   `img/` —esa regla existe para los crudos de gpt-image-2—, así que un png acá
   no se commitearía NUNCA: se vería perfecto en local, el gate pasaría en
   verde, y producción daría 404.
   (Y ese glob no se escribe acá tal cual: lleva un asterisco seguido de barra,
   que CIERRA este comentario. Eso ya pasó, y lo que dejó fue la regla de abajo
   entera sin aplicarse — el sello a 132×0, invisible, con el gate contento.)

   Por eso NO se pinta como imagen sino como
   MÁSCARA: el archivo aporta la silueta y la tinta la pone `currentColor`,
   exactamente igual que los especímenes de `especimenes.js`. Con la tinta
   quemada en el archivo se vería bien de día y se perdería de noche — que es
   literalmente lo que advierte el marcador del logo en CLAUDE.md.
   Así, el sello no necesita ni una regla en «LA NOCHE (2/2)»: hereda el color
   de donde lo pongan, y donde lo pongan ya está resuelto para los dos temas.

   ⏳ Es un PUENTE, no el destino. Del owner falta el VECTORIAL; cuando llegue,
   esto pasa a ser un `<svg>` como el resto de la tienda y la máscara sobra.

   ⚠️ El respaldo —un navegador sin `mask`— pinta el archivo tal cual, y el
   archivo es de tinta CLARA a propósito: es lo correcto sobre el pie, que es
   oscuro en LOS DOS temas. El día que el sello vaya sobre papel, ese respaldo
   hay que volver a mirarlo: ahí quedaría claro sobre claro.

   ⚠️ La proporción es la del ARCHIVO y está escrita a mano, así que se separa
   de él en cuanto alguien lo reemplace. No se deja al aire: `check_wireframes`
   compara esta caja con las medidas naturales del archivo.

   ⭐⭐ **Hay DOS marcas y un solo mecanismo.** El sello completo va donde hay
   sitio (el pie) y la POLILLA SOLA donde no lo hay (la cabecera, 21-26 px, y el
   favicon). Cuál se pinta entra por `--sello`, así que el `@supports` se
   escribe UNA vez: duplicarlo sería tener dos sitios donde arreglar la máscara.
   ⚠️ Por eso `var()` lleva respaldo — sin él, una clase sin `--sello` deja la
   declaración inválida y el elemento invisible, que es el fallo que ya costó
   una corrida acá. */
.sello-marca {
  display: block;
  /* ⚠️ `aspect-ratio` solo actúa con una de las dos dimensiones en `auto`:
     quien use la clase declara UNA —el ancho en el pie, el alto en la
     cabecera— y la otra jamás. */
  background: var(--sello, url('img/sello.webp')) center / contain no-repeat;
}
@supports (mask-image: url('img/sello.webp')) or (-webkit-mask-image: url('img/sello.webp')) {
  .sello-marca {
    background: currentColor;
    -webkit-mask: var(--sello, url('img/sello.webp')) center / contain no-repeat;
    mask: var(--sello, url('img/sello.webp')) center / contain no-repeat;
  }
}

/* ⭐⭐⭐ La POLILLA SOLA, en la cabecera. El sello completo no cabe ahí y no es
   por tamaño: su anillo YA dice «EL MUNDO DE TERA», que es justo lo que la
   cabecera pone en texto al lado. Además, a 26 px el anillo es una mancha gris
   y la polilla se sigue leyendo como polilla.

   ⚠️⚠️ Acá se declara el ALTO y no el ancho, al revés que en el pie: el hueco
   de la cabecera es de alto fijo y la marca es APAISADA (1,74:1), así que
   fijando el ancho crecería hacia abajo y reventaría la barra. El ancho lo
   deduce `aspect-ratio` y por eso NO se escribe.
   ⚠️ Y ocupa más a lo ancho que el `<svg>` cuadrado que reemplazó: 45 px contra
   26 a tamaño de escritorio. En un teléfono de 360 px eso se paga, así que el
   gate mide que la marca siga cabiendo en su cabecera. */
.head .brand .sello-marca {
  --sello: url('img/polilla.webp');
  aspect-ratio: 424 / 244;
  height: clamp(19px, 4.8vw, 25px);
  flex: none;
}

.nav {
  display: flex;
  gap: 26px;
  font-size: 15px;
}

/* Los cinco cajones solo salen DENTRO del panel del teléfono, sangrados para
   que se lean como hijos de «El gabinete». En escritorio la puerta es el
   índice: ocho enlaces en la barra se parten en dos líneas y no caben.

   ⚠️⚠️ Esto se oculta por ANCHO, no por tema. La regla del marcado único prohíbe
   que algo aparezca o desaparezca al cambiar de LUZ; el punto de corte es otra
   cosa, y es lo que ya hace `.mesa-btn` bajo 680 px. Y es `display: none` a
   propósito: saca del orden de tabulación. Con `opacity` el teclado seguiría
   cayendo en cinco enlaces invisibles. */
.nav__cajon {
  display: none;
}
.nav a {
  position: relative;
  padding-block: 4px;
}
/* Subrayado dibujado: un trazo SVG irregular, no una línea recta. */
.nav a::after {
  content: '';
  position: absolute;
  left: -2px;
  right: -2px;
  bottom: -1px;
  height: 6px;
  background: no-repeat center/100% 100%
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 90 6' preserveAspectRatio='none'%3E%3Cpath d='M1 4.2C18 1.6 38 5 52 2.4 66 .2 78 4.6 89 2.2' stroke='%23B4644A' stroke-width='1.7' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  opacity: 0;
  transform: translateY(3px);
  transition:
    opacity 0.3s,
    transform 0.35s var(--ease);
}
.nav a:hover::after,
.nav a[aria-current]::after {
  opacity: 1;
  transform: none;
}

.head__actions {
  display: flex;
  align-items: center;
  gap: 16px;
  font-size: 14.5px;
}
.mesa-btn {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 17px;
  border-radius: 3px;
  border: 1.5px solid var(--sepia);
  background: var(--kraft);
  box-shadow: 2px 2px 0 var(--sepia);
  transition:
    transform 0.18s var(--ease),
    box-shadow 0.18s var(--ease);
}
.mesa-btn:hover {
  transform: translate(-1px, -1px);
  box-shadow: 3px 3px 0 var(--sepia);
}
.mesa-btn:active {
  transform: translate(2px, 2px);
  box-shadow: 0 0 0 var(--sepia);
}
/* ⭐ Abierto SE VE, no solo se anuncia. El botón alterna, y un alternador que se
   ve igual en sus dos estados obliga a pulsarlo para saber qué hace: se queda
   hundido mientras el panel está arriba, y se tiñe del papel de la mesa para
   decir cuál es el panel que abrió.
   ⭐⭐ Cuelga del MISMO `aria-expanded` que ya escribe `setOpen`. Una clase
   aparte sería un segundo sitio donde apuntar «abierto», y dos sitios se
   desincronizan — que es literalmente el fallo que tenía este botón. */
.mesa-btn[aria-expanded='true'] {
  transform: translate(2px, 2px);
  box-shadow: 0 0 0 var(--sepia);
  background: var(--mesa-papel);
}
.mesa-btn b {
  font-weight: 700;
}
/* La bolsa. En escritorio acompaña al rótulo; en el teléfono ES el botón. */
.mesa-btn__i {
  width: 19px;
  height: 19px;
  flex: none;
}
/* El botón del menú. En escritorio no existe; en móvil es la ÚNICA puerta a la
   navegación, así que se dibuja como botón de verdad y no como un texto. */
.burger {
  display: none;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: none;
  margin-left: -8px; /* alinea el trazo del icono con el borde óptico */
  border-radius: 3px;
  color: var(--sepia);
}
.burger__i {
  grid-area: 1 / 1;
  width: 24px;
  height: 24px;
}
.burger__i--cerrar,
.burger[aria-expanded='true'] .burger__i--abrir {
  display: none;
}
.burger[aria-expanded='true'] .burger__i--cerrar {
  display: block;
}

/* --------------------------------------------------------- conmutador de luz */

/* Deliberadamente CALLADO: sin borde, sin sombra dura, sin relleno. La mesa de
   trabajo que tiene al lado es la acción principal de la cabecera y las dos
   compitiendo obligarían a decidir cuál mirar. Acá el peso lo da el hueco. */
.tema {
  display: grid;
  place-items: center;
  /* 38 px con ratón, 44 con el dedo. El corte lo decide el PUNTERO y no el
     ancho: un portátil con pantalla táctil también necesita el objetivo grande,
     y a 1280 px una media query de ancho no lo ve. */
  width: 38px;
  height: 38px;
  flex: none;
  border-radius: 50%;
  color: var(--sepia-70);
  border: 1px solid transparent;
  transition:
    color 0.2s,
    border-color 0.2s,
    background-color 0.2s;
}
.tema:hover {
  color: var(--sepia);
  border-color: var(--kraft-osc);
  background: color-mix(in srgb, var(--kraft) 55%, transparent);
}
/* Los dos iconos viven apilados en la misma celda: así el botón no cambia de
   tamaño al alternar y la cabecera no da un salto de un píxel. */
.tema__i {
  grid-area: 1 / 1;
  width: 19px;
  height: 19px;
}
/* Se muestra el icono del tema al que se VA, igual que el `aria-label`. Un
   botón con sol estando de día no dice nada: describe lo que ya se ve. */
.tema__i--sol {
  display: none;
}
[data-theme='noche'] .tema__i--sol {
  display: block;
}
[data-theme='noche'] .tema__i--luna {
  display: none;
}
/* El rótulo solo se ve dentro del panel del teléfono; en la cabecera no cabe y
   el nombre lo pone el `aria-label`. `display:none` lo saca también del árbol de
   accesibilidad, que es lo correcto acá: si se viera Y se anunciara aparte,
   serían dos textos que mantener a la vez. Cuando SÍ se ve, `mountTema()`
   escribe la misma frase en los dos sitios (WCAG 2.5.3). */
.tema__rotulo {
  display: none;
}

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

.btn {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  padding: 15px 27px;
  border-radius: 3px;
  background: var(--sepia);
  color: var(--crema);
  border: 1.5px solid var(--sepia);
  box-shadow: 3px 3px 0 var(--terracota);
  font-weight: 600;
  font-size: 15.5px;
  transition:
    transform 0.2s var(--ease),
    box-shadow 0.2s var(--ease);
}
.btn:hover {
  transform: translate(-1.5px, -1.5px);
  box-shadow: 5px 5px 0 var(--terracota);
}
.btn:active {
  transform: translate(3px, 3px);
  box-shadow: 0 0 0 var(--terracota);
}
/* ⚠️ `.btn` se usa como `<a>` y —desde que «Ir a pagar» pasó a ejecutar una
   acción en vez de navegar— también como `<button>`. Un botón NO hereda la
   tipografía del documento: la hoja del navegador se la impone. Sin esto,
   «Ir a pagar» salía en la fuente del sistema al lado de enlaces que sí
   heredan, y el cambio se ve pero no da error. */
button.btn {
  font-family: inherit;
  cursor: pointer;
  -webkit-appearance: none;
}

/* Carrito vacío o cobro en vuelo. El realce se apaga para que no invite a
   pulsar; el hover también, o el botón se levanta cuando no hace nada.
   ⚠️ Baja el contraste del rótulo. Eso lo EXIME la propia WCAG 1.4.3, que no
   aplica a componentes inactivos — se anota acá porque en este proyecto la
   excepción se escribe y exime la REGLA, no una lista de selectores. */
.btn:disabled,
.btn:disabled:hover {
  opacity: 0.55;
  cursor: default;
  transform: none;
  box-shadow: 0 0 0 var(--terracota);
}

.btn--out {
  background: transparent;
  color: var(--sepia);
  box-shadow: 3px 3px 0 var(--kraft-osc);
}
.btn--out:hover {
  box-shadow: 5px 5px 0 var(--kraft-osc);
}

/* ------------------------------------------------------------------- cinta */

/* Trozo de cinta de papel. Se coloca sobre las esquinas de lo que está
   "pegado" a la mesa. */
.tape {
  position: absolute;
  width: 104px;
  height: 30px;
  background: #e8dcc0d9;
  border-left: 1px dashed #00000012;
  border-right: 1px dashed #00000012;
  box-shadow: 0 1px 3px #3a2e2521;
  transform: rotate(-4deg);
  z-index: 3;
}
.tape--r {
  transform: rotate(3.4deg);
}

/* --------------------------------------------------------------------- hero */

.hero {
  padding-block: clamp(40px, 6vw, 84px) clamp(48px, 7vw, 96px);
  position: relative;
}
.hero__in {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(24px, 5vw, 76px);
  align-items: center;
}
.hero h1 {
  margin-bottom: 22px;
}
.hero h1 em {
  font-style: italic;
  color: var(--terracota);
}
.hero__cta {
  display: flex;
  gap: 13px;
  flex-wrap: wrap;
  margin-top: 30px;
}
.hero__note {
  margin-top: 34px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
}
.hero__note svg {
  flex: none;
  margin-top: 4px;
}

/* Collage: tres piezas pegadas con rotaciones distintas y profundidad real. */
.collage {
  position: relative;
  aspect-ratio: 1 / 1.02;
}
.collage__piece {
  position: absolute;
  background: var(--crema);
  border: 1px solid var(--kraft-osc);
  padding: 13px 13px 44px;
  box-shadow: 0 12px 28px #3a2e2521;
  transition: transform 0.55s var(--ease-soft);
}
.collage__piece figcaption {
  position: absolute;
  left: 15px;
  right: 15px;
  bottom: 13px;
  font-family: var(--voz);
  font-style: italic;
  font-size: 14.5px;
  color: var(--sepia-70);
}
.collage__piece:nth-child(1) {
  width: 58%;
  left: 0;
  top: 4%;
  transform: rotate(-4.6deg);
  z-index: 2;
}
.collage__piece:nth-child(2) {
  width: 47%;
  right: 2%;
  top: 0;
  transform: rotate(3.8deg);
  z-index: 3;
}
/* La tercera pieza se corre a la derecha para no tapar el pie de la primera:
   el montón debe verse casual, no descuidado. */
.collage__piece:nth-child(3) {
  width: 52%;
  right: 0;
  bottom: 0;
  transform: rotate(-1.8deg);
  z-index: 4;
}
.collage:hover .collage__piece:nth-child(1) {
  transform: rotate(-6.4deg) translate(-6px, -5px);
}
.collage:hover .collage__piece:nth-child(2) {
  transform: rotate(5.6deg) translate(5px, -7px);
}
.collage:hover .collage__piece:nth-child(3) {
  transform: rotate(-3deg) translate(2px, 6px);
}

/* 2/3 = la proporción nativa de gpt-image-2 en vertical (1024×1536): la foto
   entra sin recorte. `--tela` sostiene el color mientras carga. */
.swatch-box {
  aspect-ratio: 2 / 3;
  border-radius: 1px;
  position: relative;
  overflow: hidden;
  background: var(--tela, #e2d4ba);
}
.swatch-box img,
.carta__ventana img,
.pdp__stage img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ---------------------------------------------------------------- secciones */

section {
  position: relative;
}
.band {
  padding-block: clamp(52px, 7.5vw, 108px);
}
.band--kraft {
  background: var(--kraft);
}
.band--kraft::before,
.band--kraft::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: 9px;
  background: repeating-linear-gradient(
    90deg,
    var(--kraft) 0 12px,
    var(--crema) 12px 22px
  );
  opacity: 0.55;
}
.band--kraft::before {
  top: 0;
}
.band--kraft::after {
  bottom: 0;
}

.band__intro {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(20px, 4vw, 64px);
  align-items: end;
  margin-bottom: clamp(34px, 4vw, 58px);
}

/* --------------------------------------------------------------- proceso */

.pasos {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(16px, 2.6vw, 34px);
}
.paso {
  background: var(--crema);
  border: 1px solid var(--kraft-osc);
  padding: 28px 26px 30px;
  position: relative;
  box-shadow: 0 6px 16px #3a2e2514;
  transition: transform 0.4s var(--ease-soft);
}
.paso:nth-child(1) {
  transform: rotate(-0.9deg);
}
.paso:nth-child(2) {
  transform: rotate(0.5deg);
}
.paso:nth-child(3) {
  transform: rotate(-0.4deg);
}
.paso:hover {
  transform: rotate(0deg) translateY(-6px);
}
/* La foto del paso va arriba, sangrada contra los bordes de la ficha: la
   tarjeta se lee como una lámina pegada, no como un bloque de texto. */
.paso__img {
  aspect-ratio: 1;
  margin: -28px -26px 20px;
  overflow: hidden;
  background: var(--kraft);
  border-bottom: 1px solid var(--kraft-osc);
}
.paso__img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.paso__n {
  font-family: var(--voz);
  font-size: 56px;
  line-height: 0.8;
  color: var(--kraft-osc);
  display: block;
  margin-bottom: 14px;
}
.paso h3 {
  margin-bottom: 9px;
}
.paso p {
  margin: 0;
  font-size: 15px;
  color: var(--sepia-70);
}

/* -------------------------------------------------- comparador de gramaje */

.probe {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: clamp(22px, 4vw, 62px);
  align-items: center;
}

.probe__viewer {
  position: relative;
  aspect-ratio: 5 / 4;
  border: 1px solid var(--kraft-osc);
  background: #fdf9ef;
  overflow: hidden;
  box-shadow: inset 0 0 44px #3a2e2512;
  cursor: ew-resize;
  touch-action: none;
}
.probe__face,
.probe__back {
  position: absolute;
  inset: 0;
}
.probe__back {
  clip-path: inset(0 0 0 var(--split, 50%));
  background: #f4ecdd;
}
.probe__label {
  position: absolute;
  top: 12px;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
  background: #fdf9efd9;
  padding: 4px 9px;
  border: 1px solid var(--kraft-osc);
}
.probe__label--a {
  left: 12px;
}
.probe__label--b {
  right: 12px;
}
.probe__handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--split, 50%);
  width: 2px;
  background: var(--sepia);
  z-index: 4;
}
.probe__handle::after {
  content: '↔';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--crema);
  border: 1.5px solid var(--sepia);
  display: grid;
  place-items: center;
  font-size: 16px;
  box-shadow: 2px 2px 0 var(--sepia);
}

.probe__mark {
  position: absolute;
  border-radius: 50%;
  filter: blur(1px);
}

.probe__controls {
  display: flex;
  gap: 9px;
  flex-wrap: wrap;
  margin-top: 22px;
}
.gchip {
  padding: 9px 16px;
  border: 1.5px solid var(--sepia);
  border-radius: 3px;
  font-size: 14px;
  font-weight: 600;
  background: transparent;
  transition:
    background 0.25s,
    color 0.25s,
    box-shadow 0.2s;
}
.gchip[aria-pressed='true'] {
  background: var(--sepia);
  color: var(--crema);
  box-shadow: 2px 2px 0 var(--terracota);
}

/* ---------------------------------------------------------------- catálogo */

/* ⚠️ La carta es más estrecha y más alta que la tarjeta que reemplazó: la
   columna baja de 258 a 230 px. `min(100%, 230px)` para que en un teléfono
   estrecho el track pueda bajar de 230 en vez de desbordar. */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 230px), 1fr));
  gap: clamp(20px, 3vw, 38px);
}

/* --- el objeto carta ------------------------------------------------ */

/* ⭐⭐⭐ LA CARTA SON TRES PIEZAS, Y EL REPARTO ES LO QUE IMPORTA.
   Arriba el NAIPE: la fotografía a sangre, que gira al tocarla. Debajo la
   PISTA: el galón y la frase, que cambia con la cara. Y al pie la CARTELA:
   nombre, precio y «Ver más», que es el único camino a la ficha.

   El texto salió de la carta, y eso es lo que le devolvió el producto. Medido a
   1280 px, la foto pasó de 160×268 a 210×314 —un 54% más de área— y de 0,59 a
   2:3 exactos, que es la proporción con que se tomó. La ventana ya no se
   recorta y la carta no lleva nada encima.

   ⚠️ `.carta` ya NO es el naipe: es la CELDA de la rejilla. La perspectiva, la
   sombra y el radio se mudaron a `.carta__naipe`. Se mantiene como raíz —y con
   todos sus `data-*`— porque de ella cuelgan el filtro del catálogo, el orden
   por precio y el `hidden`: mover la raíz habría repartido un renombrado por
   cuatro sitios sin ganar nada. */
.carta {
  display: grid;
  align-content: start;
}
/* ⚠️ El filtro de la colección marca `hidden` en vez de re-renderizar: sin esta
   regla el filtro deja de filtrar, porque `<article>` no es `display:none` por
   defecto cuando el CSS le impone una caja de grid. */
.carta[hidden] {
  display: none;
}

/* El naipe: lo único que gira. Acá viven las medidas del objeto —el radio, el
   canto, la perspectiva y el gesto de levantarse—; lo que se pinta vive en
   `.carta__cara`, que hay dos.
   ⚠️ El `box-shadow` y el `border-radius` se quedan en el objeto y no en las
   caras: la sombra es del naipe apoyado en la mesa, y una sombra que gira con
   la cara delataría que son dos hojas y no un objeto. */
.carta__naipe {
  position: relative;
  border-radius: 13px;
  perspective: 1400px;
  box-shadow:
    0 1px 0 #ffffff26 inset,
    0 2px 3px -1px #0000002e,
    0 14px 30px -14px #00000073;
  transition:
    transform 0.42s var(--ease-soft),
    box-shadow 0.42s var(--ease-soft);
}
.carta:hover .carta__naipe {
  transform: translateY(-8px) rotate(-0.7deg);
  box-shadow:
    0 1px 0 #ffffff26 inset,
    0 3px 4px -1px #00000038,
    0 24px 42px -16px #00000085;
}
/* Con la carta volteada el gesto se apaga: lo que está a la vista es una ficha
   para leer, y una ficha que se mueve al acercar el ratón se lee peor. */
.carta[data-cara='dorso']:hover .carta__naipe {
  transform: none;
}

/* --- la mecánica del volteo ----------------------------------------- */

/* El giro vive acá y no en el naipe: el naipe ya usa su `transform` para el
   gesto de levantarse al pasar el ratón, y una sola propiedad no puede llevar
   las dos cosas. */
.volteo__in {
  position: relative;
  /* `grid` y no `block`: es lo que estira el FRENTE hasta el alto del naipe.
     Con `block`, la cara medía solo su contenido y en las cartas más bajas de
     la fila asomaban píxeles de fondo de página por debajo del papel. */
  display: grid;
  width: 100%;
  min-height: 100%;
  transition: transform 0.8s var(--ease);
  transform-style: preserve-3d;
}
.carta[data-cara='dorso'] .volteo__in {
  transform: rotateY(180deg);
}

/* Las dos caras, una encima de la otra. */
.carta__cara {
  border-radius: 13px;
  background: var(--carta-papel);
  /* El canto del naipe. Va en la CARA y no en el naipe porque es la cara la que
     tiene el papel: un borde sobre el objeto transparente se vería flotando por
     fuera de las dos caras al girar. */
  border: 1px solid var(--carta-canto);
  font-family: var(--voz);
  color: var(--oro);
  display: grid;
  backface-visibility: hidden;
  /* ⚠️⚠️ `backface-visibility` esconde la cara de atrás A LA VISTA, pero la deja
     en el ORDEN DE TABULACIÓN: sin `visibility` el teclado cae en la ficha del
     dorso con la carta de frente. Es la misma familia del fallo de la mesa
     cerrada, y ya mordió dos veces en este proyecto.
     Se transiciona para que la cara que se va no se evapore a mitad del giro:
     `visibility` es discreta pero en transición se comporta. */
  transition: visibility 0.8s;
}
/* ⚠️ El DORSO sí es absoluto y el frente no: el frente va en flujo porque es
   quien le da alto al naipe, y el dorso se superpone a ese alto. */
.carta--dorso {
  position: absolute;
  inset: 0;
  transform: rotateY(180deg);
  align-content: center;
  padding: 14px 0;
}
/* ⭐ Quién se esconde lo decide el CSS a partir de `data-cara`, y por eso el JS
   no escribe `visibility` en línea. Con una sola fuente, la cara de atrás está
   fuera del orden de tabulación desde el primer pintado — antes de que corra
   `mountVolteo()`, y aunque no llegara a correr. */
.carta[data-cara='frente'] .carta--dorso,
.carta[data-cara='dorso'] .carta__cara:not(.carta--dorso) {
  visibility: hidden;
}

/* El campo: la fotografía, a sangre y en la proporción con que se tomó.
   ⚠️ `2 / 3` no es una decisión de estilo: es la proporción de los archivos
   (900×1350). Acá la ventana ES el campo, así que la proporción del campo y la
   de la foto son la misma cosa y no hay nada que despejar. Cualquier otro
   número vuelve a recortar la pieza con `object-fit: cover`. */
.carta__campo {
  position: relative;
  aspect-ratio: 2 / 3;
  overflow: hidden;
  border-radius: 12px;
  background: var(--campo);
  display: block;
}

/* ⭐ El espécimen CUELGA de la esquina, como se monta un ejemplar de verdad, y
   del mismo hilo de lino con que se cosen las bitácoras. Ahora cae sobre la
   fotografía: va relleno de `--campo` con trazo de oro, así que se lee sobre
   cualquier toma. */
.carta__emblema {
  position: absolute;
  top: 13%;
  right: 3.5%;
  width: 15%;
  z-index: 3;
  rotate: 7deg;
  transform-origin: top center;
  filter: drop-shadow(0 3px 5px #00000080);
}
/* El hilo del que pende. Cuelga del CAMPO y no del emblema: como
   pseudo-elemento del emblema saldría por encima de su propia caja y el
   `overflow: hidden` del campo lo recortaría entero. Cae justo sobre el centro
   del ejemplar — 3,5% de margen + la mitad de su 15% de ancho. */
/* ⚠️ El hilo cuelga del CAMPO, así que no desaparece solo cuando la pieza no
   lleva ejemplar: se ata a que HAYA ejemplar con el hermano adyacente. Sin esto,
   las catorce piezas sin foto quedaban con un hilo de oro colgando de la nada. */
.carta__campo:has(.carta__emblema)::before {
  content: '';
  position: absolute;
  top: 0;
  right: 11%;
  width: 1px;
  height: 13%;
  background: var(--oro-70);
  z-index: 3;
  pointer-events: none;
}
.carta__emblema .esp {
  display: block;
  width: 100%;
  height: auto;
  color: var(--oro);
  --esp-relleno: var(--campo);
}

/* La ventana: la pieza, del canto al canto. */
.carta__ventana {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
.carta__ventana img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(1.04) contrast(1.04);
}

/* El filete de oro por dentro del canto. No es adorno suelto: es lo que hace
   que una foto a sangre siga leyéndose como una lámina enmarcada y no como una
   foto pegada, ahora que el arco se fue. */
.carta__filete {
  position: absolute;
  inset: 7px;
  z-index: 2;
  border: 1px solid var(--oro-70);
  border-radius: 7px;
  pointer-events: none;
}

/* La placa: lo que ocupa la ventana cuando la pieza todavía no tiene foto. No
   es un hueco con adorno — es la lámina del espécimen a tamaño de lámina, que
   es de donde salió toda la marca. El trazo se afina al dibujarla porque a este
   tamaño el grosor de la lámina chica se ve tosco. */
.carta__lamina {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  color: var(--oro-70);
}
.carta__lamina .esp {
  width: 68%;
  height: auto;
}

/* El sello de vendida, cruzado sobre la ventana. Lleva banda OPACA propia por
   dos razones que van juntas: un texto sobre una FOTO no tiene contraste
   medible —depende de lo que haya en esa esquina de la toma—, y `--campo` con
   `--oro` es la pareja ya probada, 7,46:1 de día y 7,88:1 de noche.

   Y lleva la palabra «Vendida» como TEXTO, no como dibujo: un sello que solo
   existe en el CSS no lo lee nadie que no vea, y es el dato que decide si la
   pieza se puede comprar.

   ⚠️ `pointer-events: none` no es opcional. La superficie de giro está DEBAJO y
   cubre el campo entero; sin esto el sello se come el toque y la carta deja de
   girar justo por la franja donde cruza. */
.carta__sello {
  position: absolute;
  left: 0;
  right: 0;
  top: 44%;
  z-index: 3;
  padding: 7px 0;
  background: var(--campo);
  color: var(--oro);
  font-family: var(--voz);
  font-size: 11.5px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  text-align: center;
  pointer-events: none;
}

/* Los mismos dos estados, en la ficha de producto. Acá el sello no va cruzado
   sobre nada: va al lado del precio tachado, que es donde se mira. */
.pdp__vendida {
  display: inline-block;
  margin-left: 10px;
  padding: 4px 12px;
  vertical-align: middle;
  background: var(--campo);
  color: var(--oro);
  font-family: var(--voz);
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
.pdp__precio--muestra {
  font-family: var(--voz);
  font-size: 17px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sepia-70);
}

/* ⭐ La pieza PAUSADA conserva su cifra —tiene precio y vuelve— y le cuelga el
   aviso debajo. Es a propósito distinta de las otras dos: la vendida tacha la
   cifra porque ya no se puede tener, la de muestra no tiene cifra porque nunca
   la tuvo, y esta la enseña entera porque es lo que va a costar. Tres estados,
   tres formas de pintarse: si dos se vieran igual, no harían falta dos. */
.carta__precio--pausada span,
.pdp__precio--pausada {
  display: block;
  font-family: var(--voz);
  font-size: 11.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--terracota);
}
.pdp__precio--pausada {
  display: inline-block;
  font-size: 13px;
  margin-left: 8px;
  vertical-align: middle;
}

/* ⭐⭐ «Quedan pocas» NO se pinta como los tres avisos de arriba, y eso es el
   punto: los otros dicen que NO se puede comprar, y este dice que sí y que hay
   que apurarse. En terracota, como los que cierran la puerta, se leería como
   una advertencia — y sería la cuarta cosa que se ve igual sin significar lo
   mismo. Va en la tinta de la página, discreto, al lado de la cifra.
   ⚠️ Y solo aparece con 3 o menos (`quedanTexto`): un «quedan 40» es ruido
   disfrazado de urgencia, y la urgencia inventada se nota. */
.carta__quedan,
.pdp__quedan {
  display: block;
  font-family: var(--voz);
  font-size: 11.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--sepia-70);
}
.pdp__quedan {
  display: inline-block;
  font-size: 13px;
  margin-left: 8px;
  vertical-align: middle;
}

/* La pieza que nunca estuvo a la venta. No es un precio tachado —eso es otra
   cosa, y la carta tiene que distinguirlas— sino la ausencia de precio dicha en
   palabras. */
.carta__precio--muestra {
  font-family: var(--voz);
  font-size: 11.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  line-height: 1.25;
  max-width: 9em;
  color: var(--sepia-70);
}

/* El numeral, recortado en el borde superior del CAMPO como en la referencia:
   una muesca de papel que cuelga dentro de lo oscuro.
   ⚠️ SOLO se dibuja si la pieza tiene lámina, y de eso se encarga el JS. La
   versión anterior imprimía la muesca siempre y las piezas sin grabado —los
   accesorios de taller, el cuaderno de campo— quedaban con una pestaña de kraft
   EN BLANCO colgando sobre la foto. Un recorte de papel vacío no es un numeral
   discreto: es un defecto.
   ⚠️ Y va sobre el campo oscuro, no sobre papel. Lo que lo hace legible no es su
   color, es lo oscuro que tiene detrás. */
.carta__num {
  position: absolute;
  top: 0;
  left: 50%;
  translate: -50% 0;
  z-index: 4;
  margin: 0;
  min-width: 68px;
  padding: 3px 14px 5px;
  text-align: center;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.2em;
  color: var(--sepia);
  background: var(--kraft);
  border: 1px solid var(--oro-30);
  border-top: 0;
  border-radius: 0 0 42% 42% / 0 0 100% 100%;
}

/* --- la pista: el galón y la frase ---------------------------------- */

/* Entre el naipe y el precio. Hace dos trabajos: decir que la imagen se toca, y
   prestarle su texto a los DOS botones del volteo como nombre accesible.

   ⭐ Son dos frases y UN solo sitio. La versión anterior ponía la de vuelta
   dentro del dorso y dejaba esta fija: con la carta volteada, la ficha decía
   «volver» y el renglón de fuera seguía diciendo «ver la ficha», a dos
   centímetros. Un rótulo que no sigue al estado no es un rótulo.

   ⚠️ Apilada —galón arriba, frase debajo— y no en fila. En fila, a 212 px de
   columna la frase se parte en dos y el galón queda colgado del primer renglón;
   y con el naipe JUSTO encima, una flecha que apunta de lado señala a cualquier
   otra cosa.

   ⚠️ Dos renglones RESERVADOS. «Toca para volver a la imagen» es más largo que
   «Toca para ver la ficha» y en columna estrecha pasa a dos líneas: sin reservar
   el alto, voltear una carta empujaría su propio precio y dejaría la fila
   desalineada. */
.carta__pista {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  min-height: calc(18px + 3px + 2 * 11px * 1.3);
  margin: 10px 0 0;
  font-family: var(--voz);
  font-size: 11px;
  letter-spacing: 0.06em;
  line-height: 1.3;
  text-transform: uppercase;
  color: var(--sepia-70);
  text-align: center;
}

/* El galón. En TRAZO y no en un carácter «↑»: la tienda entera está hecha de
   grabados de una línea y un glifo de sistema se ve pegado encima — y además un
   trazo se puede animar y un carácter no. `currentColor` para que herede el
   color de la frase y no haya dos sitios que acordarse al cambiar el tema. */
.galon {
  flex: none;
  width: 20px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Los dos suben por turnos, el de atrás medio paso después. */
@keyframes carta-galon {
  0%,
  100% {
    translate: 0 0;
    opacity: 0.55;
  }
  50% {
    translate: 0 -3px;
    opacity: 1;
  }
}
.galon__a {
  animation: carta-galon 1.7s var(--ease-soft) infinite;
}
.galon__b {
  animation: carta-galon 1.7s var(--ease-soft) 0.22s infinite;
}

/* El relevo de la frase: la que llega entra subiendo y aclarándose. Tres
   décimas, porque no es un efecto sino un acuse de recibo — un renglón de once
   píxeles que cambia sin avisar no se nota.
   ⚠️ Se anima el `<span>` y no el `<p>`: el `<p>` lleva también el galón, y un
   galón que se desvanece con cada volteo parpadearía en toda la rejilla. */
@keyframes carta-frase {
  from {
    opacity: 0;
    translate: 0 4px;
  }
  to {
    opacity: 1;
    translate: 0 0;
  }
}
.carta__pista--cambia {
  animation: carta-frase 0.3s var(--ease-soft);
}

/* --- girar la carta -------------------------------------------------- */

/* ⭐ El naipe entero gira al tocarlo, así que el control NO se pinta: es una
   superficie transparente que cubre el campo. Que siga siendo un `<button>` es
   lo que le da el orden de tabulación, Enter y espacio, y el estado anunciado.
   Su nombre sale de la frase visible, por `aria-labelledby`. */
.girar {
  position: absolute;
  inset: 0;
  z-index: 5;
  border: 0;
  padding: 0;
  background: none;
  cursor: pointer;
  /* Sin texto propio: el nombre accesible lo presta la frase. Un `font-size: 0`
     evita cualquier sorpresa si alguien le mete contenido por error. */
  font-size: 0;
}
/* ⚠️ En el dorso la superficie va ENCIMA, igual que en el frente. Debajo —como
   estaba— la placa de la ficha se comía el toque y la carta solo volvía tocando
   el margen oscuro. El trato es «se toca la imagen y gira», en las dos
   direcciones. Lo que cuesta es que el texto de la ficha no se pueda marcar con
   el dedo en la rejilla: está completo, y seleccionable, en la página de
   producto — que es a donde lleva «Ver más». */
.girar--dorso {
  z-index: 5;
}
/* El realce va en el NAIPE, no en el botón: lo que se toca es la carta entera y
   el foco tiene que verse en la carta entera. */
.girar:focus-visible {
  outline: 2px dashed var(--terracota);
  outline-offset: -6px;
  border-radius: 10px;
}
[data-theme='noche'] .girar:focus-visible {
  outline-color: var(--oro);
}

/* --- la cartela: nombre, precio y «Ver más» ------------------------- */

/* Vive FUERA del naipe, sobre el papel de la página. Eso cambia una cosa que no
   se ve y decide si se lee: la tinta ya no es la de la carta —crema sobre
   negro— sino la del sitio, `--sepia`, que es la pareja de todo el texto de la
   tienda y se voltea sola con el tema. */
.carta__cartela {
  text-align: center;
  padding-top: 9px;
}
/* El nombre va en `<h3>`, no en `<p>`: es lo que le da a la rejilla un nivel por
   el que navegar —un catálogo sin un solo encabezado de producto no se puede
   recorrer con lector de pantalla— y lo que, vía `aria-labelledby`, le pone
   nombre accesible a cada `<article class="carta">`.
   ⚠️ Con el encabezado llega la regla global `h1, h2, h3 { line-height: 1.02 }`,
   y estos nombres van en mayúsculas: a 1,02 la tilde de «CÁÑAMO» se sale de su
   línea. Por eso el `line-height` propio.
   ⚠️ Dos líneas RESERVADAS, aunque el nombre ocupe una. «Lucanus, lámina I» se
   parte en dos y estiraba su fila entera: sus tres vecinas quedaban con el
   precio 20 px más arriba, que en una rejilla se lee como un desalineado y no
   como un nombre largo.
   `calc()` y no `2lh`: la unidad `lh` es reciente y esto tiene que valer también
   en el navegador de un teléfono viejo. */
.carta__nombre {
  margin: 0;
  min-height: calc(2 * 13px * 1.3);
  font-family: var(--voz);
  font-size: 13px;
  line-height: 1.3;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--sepia);
}
.carta__pie {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 7px;
}
.carta__precio {
  margin: 0;
  font-size: 15px;
  font-weight: 700;
  color: var(--sepia);
}

/* «Ver más». Es el ÚNICO camino a la ficha de producto desde la rejilla, así
   que se pinta como botón y no como enlace de texto: lo que hace falta que se
   vea es que hay dónde pulsar.
   ⚠️ 38 px de alto y no 30: por encima del mínimo de WCAG 2.5.8 y, sobre todo,
   cómodo para un pulgar — desde que la foto dejó de llevar a ninguna parte, este
   botón carga con toda la compra. */
.carta__ver {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 38px;
  padding: 0 18px;
  border: 1px solid var(--sepia-70);
  border-radius: 2px;
  font-family: var(--voz);
  font-size: 11.5px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--sepia);
  text-decoration: none;
  white-space: nowrap;
  transition:
    background 0.24s var(--ease-soft),
    color 0.24s var(--ease-soft);
}
.carta__ver:hover,
.carta__ver:focus-visible {
  background: var(--sepia);
  color: var(--crema);
}
.carta__ver:focus-visible {
  outline: 2px dashed var(--terracota);
  outline-offset: 2px;
}
[data-theme='noche'] .carta__ver:focus-visible {
  outline-color: var(--oro);
}

/* La cinta de «Más vendida» sigue viviendo dentro de la ventana: es el único
   rótulo que va sobre la fotografía y por eso NO se renombró con el resto.
   ⚠️ Va al PIE de la ventana, y ahí se queda. Arriba la cortaba el arco cuando
   la ventana lo tenía —se leía «AS VENDIDA»—, y cuando probó a subir al hombro
   derecho se metió en el sitio del NUMERAL: la muesca de papel le tapaba la
   primera palabra y se leía «VENDIDA», que es decir lo contrario. Abajo a la
   izquierda no hay nada que se la coma. */
.pc__flag {
  position: absolute;
  bottom: 14px;
  left: 14px;
  background: var(--terracota);
  color: var(--crema);
  font-size: 10.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-weight: 700;
  padding: 4px 9px;
  z-index: 3;
  transform: rotate(-2deg);
}

/* Texto que solo existe para quien no ve. Lo usa «Ver más» para llevar el
   nombre de la pieza detrás de su texto visible. */
.visualmente-oculto {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- el dorso: la ficha técnica ------------------------------------- */

/* El dorso es lo que le faltaba al catálogo: hasta acá el gramaje traducido
   —«160 g» no dice nada, «marcador sin traspaso» sí— solo existía en la ficha de
   producto y en el comparador de la portada. Es la obligación 2 de
   `docs/NICHO.md` puesta donde se decide la compra.
   La CARA vive arriba, con la mecánica del volteo; acá solo lo que se pinta
   dentro de ella. */

/* El campo del dorso, liso. La trama de rombos que se probó era un enrejado de
   líneas doradas de lado a lado: demasiado ruido para una cara que existe solo
   para que se lea una ficha técnica. El adorno, si lo lleva, es UNA pieza. */
.dorso__campo {
  position: absolute;
  inset: 0;
  border-radius: 12px;
  overflow: hidden;
  background: var(--campo);
  border: 1px solid var(--oro-30);
  pointer-events: none;
}
/* El cielo: unas pocas estrellas, eco del frente. Nada más — y ninguna línea
   que cruce la carta. */
.dorso--cielo .dorso__estrella {
  position: absolute;
  color: var(--oro);
  opacity: 0.7;
}
/* La ficha va sobre una PLACA de papel. Enmascarar el campo por el centro no
   sirve: el texto está alineado a la izquierda y el hueco quedaría donde no hay
   nada que leer. */
/* ⚠️⚠️ La placa SE SALÍA de la carta por arriba y por abajo, y a ojo no se veía
   —la sombra del naipe disimula los doce píxeles de cada lado—: medida, 341 px
   de placa en una carta de 317. Una bitácora tiene cinco campos y «Acuarela
   profesional» se parte en dos, que es el caso más alto del catálogo.
   Esta ficha estaba escrita para la carta vieja, que tenía cartela dentro y era
   más alta. Se aprietan el interlineado y el aire entre campos; los TAMAÑOS de
   letra NO se tocan, que son los que hacen legible un gramaje.
   El radio la ata al naipe: una placa de esquinas vivas dentro de un objeto de
   esquinas redondas se lee como pegada encima y no como parte de él. */
.dorso__ficha {
  position: relative;
  z-index: 2;
  display: block;
  margin-inline: 16px;
  padding: 13px 13px 10px;
  border-radius: 4px;
  font-size: 12.5px;
  line-height: 1.5;
  text-align: left;
  color: var(--sepia);
  background: var(--kraft);
  border: 1px solid var(--oro-70);
}
.dorso__ficha b {
  display: block;
  color: var(--sepia-70);
  font-size: 10.5px;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.dorso__ficha i {
  display: block;
  font-style: normal;
  font-weight: 700;
  margin-bottom: 6px;
}
.dorso__pie {
  display: block;
  text-align: center;
  font-size: 10.5px;
  color: var(--sepia-70);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border-top: 1px dashed var(--hilo);
  margin-top: 1px;
  padding-top: 7px;
}

/* ---------------------------------------------------------------- nota */

.nota {
  max-width: 720px;
  margin-inline: auto;
  background: #fdf8ec;
  border: 1px solid var(--kraft-osc);
  padding: clamp(28px, 4vw, 52px);
  position: relative;
  transform: rotate(-0.8deg);
  box-shadow: 0 14px 30px #3a2e2517;
  background-image: repeating-linear-gradient(
    var(--crema) 0 30px,
    #3a2e2510 30px 31px
  );
}
.nota p {
  font-family: var(--voz);
  font-style: italic;
  font-size: clamp(19px, 2vw, 27px);
  line-height: 1.55;
  margin: 0 0 20px;
}
.nota footer {
  font-family: var(--voz);
  font-size: 14px;
  color: var(--sepia-70);
  font-style: normal;
}

/* -------------------------------------------------------- mesa de trabajo */

/* El carrito de esta dirección: una mesa que sube desde abajo.
   ⭐ Cerrada NO deja nada a la vista. Antes asomaba una pestaña permanente de
   54 px, que con el carrito vacío es una franja diciendo «0 productos · $0» en
   todas las páginas y a todos los anchos. Ahora la puerta es el botón de la
   cabecera —el mismo en escritorio y en teléfono— y el panel es lo único que
   ocupa sitio, cuando lo pides.
   ⚠️ Esto obligó a devolver `.mesa-btn` a la cabecera del teléfono: era la
   pestaña la que hacía de único acceso bajo 680 px. Quitar la una sin devolver
   el otro dejaba el carrito inalcanzable con el dedo. */
.mesa {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 95;
  transform: translateY(100%);
  transition: transform 0.55s var(--ease-soft);
  /* ⚠️ NO es `--kraft`. Ver el token: con el papel de la página, sobre una banda
     kraft el panel desaparecía. */
  background: var(--mesa-papel);
  border-top: 2px solid var(--sepia);
  box-shadow: 0 -10px 34px #3a2e2524;
}
.mesa[data-open='1'] {
  transform: none;
}
.mesa__tab {
  height: var(--mesa-tab);
  display: flex;
  align-items: center;
  /* Con `space-between` y tres piezas el total se quedaba flotando en mitad de
     la barra. El hueco lo abre el total con su `margin-left: auto`, y así la
     equis viaja pegada a él en vez de repartirse el sobrante. */
  justify-content: flex-start;
  gap: 16px;
  padding-inline: var(--pad);
  width: 100%;
  font-weight: 700;
  font-size: 15px;
}
/* ⚠️ Esto era `.mesa__tab > span:last-child`, y el `>` era lo único que impedía
   que alcanzara cualquier span final de cualquier nivel: en cuanto «productos»
   pasó a vivir en su propio span dentro del primero, se llevó el tamaño y la
   letra de una cifra de dinero. Y el `>` tampoco bastaba para siempre — al
   añadir la equis de cerrar, el total dejó de ser el último hijo y se habría
   quedado sin vestir, en silencio. Un selector posicional describe el ORDEN del
   marcado, no lo que la pieza ES: con nombre propio, mover algo no la desviste. */
.mesa__tab-total {
  margin-left: auto;
  font-family: var(--voz);
  font-size: 19px;
}
.mesa__cerrar {
  width: 19px;
  height: 19px;
  flex: none;
  color: var(--mesa-tinta-70);
}
/* ⚠️ La mesa se cierra con `transform`, que mueve el píxel pero NO saca del
   orden de tabulación: sin esto el teclado sigue cayendo en el stepper y en
   «Ir a pagar» con la mesa abajo y fuera de pantalla. `visibility` sí saca del
   foco, y en transición es la única propiedad discreta que se comporta bien:
   pasa a `visible` al principio al abrir y aguanta hasta el final al cerrar,
   así que el cuerpo no se evapora a mitad del deslizamiento. La pestaña queda
   fuera —es hija de `.mesa`, no del cuerpo— y por eso sigue alcanzable. */
.mesa__body {
  padding: 6px var(--pad) calc(24px + env(safe-area-inset-bottom));
  max-height: min(58vh, 460px);
  overflow-y: auto;
  border-top: 1px dashed var(--hilo);
  visibility: hidden;
  transition: visibility 0.55s var(--ease-soft);
}
.mesa[data-open='1'] .mesa__body {
  visibility: visible;
}
.mesa__empty {
  padding: 34px 0;
  font-family: var(--voz);
  font-style: italic;
  font-size: 19px;
  color: var(--mesa-tinta-70);
}
/* La salida del carrito vacío. Un carrito sin nada y sin enlace obliga a cerrar
   el panel y buscar la tienda otra vez. */
.mesa__empty a {
  color: var(--mesa-enlace);
}

/* «Quitar» borra la línea entera; el «–» del contador baja una unidad. Llevaba
   estilos en línea y minúscula inicial, que lo hacían parecer una nota al pie y
   no el control destructivo que es. */
.mesa__quitar {
  font-size: 12.5px;
  color: var(--mesa-enlace);
  text-decoration: underline;
}
.mesa__row {
  display: grid;
  grid-template-columns: 46px 1fr auto auto;
  gap: 16px;
  align-items: center;
  padding-block: 15px;
  border-bottom: 1px dashed var(--hilo);
}
.mesa__thumb {
  aspect-ratio: 2 / 3;
  border: 1px solid #00000018;
  overflow: hidden;
  background: var(--tela, #e2d4ba);
}
.mesa__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.mesa__name {
  font-family: var(--voz);
  font-size: 19px;
}
.mesa__var {
  font-size: 13px;
  color: var(--mesa-tinta-70);
}
.stepper {
  display: inline-flex;
  align-items: center;
  border: 1.5px solid var(--sepia);
  border-radius: 3px;
  background: var(--crema);
}
.stepper button {
  width: 30px;
  height: 30px;
  font-size: 16px;
  line-height: 1;
}
.stepper span {
  min-width: 24px;
  text-align: center;
  font-weight: 700;
  font-size: 14px;
}
.mesa__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  padding-top: 20px;
}
.mesa__total b {
  font-family: var(--voz);
  font-size: 30px;
}
.mesa__ship {
  font-size: 13.5px;
  color: var(--mesa-tinta-70);
}

/* Lo que el servidor contesta cuando no se puede cobrar: casi siempre que la
   pieza se vendió mientras estaba en el carrito. Va con `--mesa-enlace`, el
   mismo token que ya usa `.mesa__quitar`, porque es el único color de acento
   que el gate ya mide contra el papel de la mesa en los DOS temas — estrenar
   un color acá sería estrenar un contraste sin medir. */
.mesa__error {
  margin: 12px 0 0;
  font-size: 14px;
  line-height: 1.45;
  color: var(--mesa-enlace);
}

/* ------------------------------------------------------------------- recibo */

/* La página de vuelta del pago. Vive acá y no incrustada en `tienda/app.py`
   porque así hereda los DOS temas sin escribir una sola regla de noche: todo
   cuelga de tokens que la noche ya remapea. Una hoja aparte habría necesitado
   su propio bloque de «LA NOCHE (2/2)», que es justo lo que este sistema evita.

   ⭐ Y es una CARTELA, no una pantalla de sistema. El recibo es el último sitio
   donde el cliente ve la marca, y una caja blanca con un tilde verde ahí borra
   de un golpe todo lo que las seis páginas anteriores construyeron. */

.recibo {
  min-height: 100vh;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 26px;
  padding: 48px 20px;
}
.recibo__marca {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--voz);
  font-size: 17px;
  color: var(--sepia);
  text-decoration: none;
}
.recibo__marca svg {
  width: 22px;
  height: 22px;
}

.recibo__cartela {
  width: min(520px, 100%);
  background: var(--kraft);
  color: var(--sepia);
  border: 1px solid var(--kraft-osc);
  border-radius: 3px;
  box-shadow: 5px 5px 0 var(--kraft-osc);
  padding: 52px 30px 30px;
  position: relative;
  text-align: center;
}

/* El espécimen cuelga sobre el borde, como la lámina en el hombro del arco de
   las cartas. Se sale de la caja a propósito: es la regla del gabinete. */
.recibo__esp {
  position: absolute;
  top: -28px;
  left: 50%;
  translate: -50% 0;
  width: 62px;
  color: var(--grabado);
}
.recibo__esp svg {
  width: 100%;
  height: auto;
  display: block;
}

.recibo__titulo {
  /* ⚠️ `clamp` y no un tamaño fijo: «Estamos confirmando tu pago» se partía en
     TRES líneas en la primera versión. El titular de un recibo no puede ser un
     rompecabezas. */
  font-family: var(--voz);
  font-size: clamp(20px, 4.4vw, 27px);
  line-height: 1.25;
  margin: 0 0 6px;
  text-wrap: balance;
}
.recibo__ref {
  font-family: var(--voz);
  font-size: 12.5px;
  letter-spacing: 0.06em;
  color: var(--sepia-70);
  margin: 0 0 22px;
}

.recibo__lineas {
  border-top: 1px solid var(--kraft-osc);
  text-align: left;
  margin-bottom: 4px;
}
.recibo__linea {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 11px 0;
  border-bottom: 1px solid var(--kraft-osc);
  font-size: 14.5px;
}
.recibo__linea b {
  font-weight: 600;
}
.recibo__linea span {
  color: var(--sepia-70);
  font-size: 13px;
}
.recibo__linea i {
  margin-left: auto;
  font-style: normal;
  font-family: var(--voz);
  white-space: nowrap;
}

.recibo__sumas {
  text-align: left;
  padding: 12px 0 4px;
  font-size: 14px;
}
.recibo__suma {
  display: flex;
  justify-content: space-between;
  padding: 3px 0;
  color: var(--sepia-70);
}
.recibo__suma--total {
  color: var(--sepia);
  font-family: var(--voz);
  font-size: 19px;
  padding-top: 10px;
  margin-top: 6px;
  border-top: 1px solid var(--kraft-osc);
}

.recibo__nota {
  font-size: 14px;
  line-height: 1.6;
  color: var(--sepia-70);
  margin: 18px 0 0;
  text-wrap: pretty;
}
.recibo__pie {
  margin-top: 24px;
}

/* Mientras se espera al banco. Late despacio para decir «esto sigue vivo» sin
   convertirse en un adorno que distraiga. */
.recibo__espera {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--voz);
  font-size: 12.5px;
  letter-spacing: 0.05em;
  color: var(--sepia-70);
  margin-top: 4px;
}
.recibo__espera::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--terracota);
  animation: latido 1.6s var(--ease-soft) infinite;
}
@keyframes latido {
  0%, 100% { opacity: 0.25; }
  50% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .recibo__espera::before { animation: none; opacity: 0.7; }
}

/* ------------------------------------------------------------------ boletín */

.news {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(22px, 4vw, 60px);
  align-items: center;
}
.news form {
  display: flex;
  gap: 10px;
  margin-top: 18px;
  flex-wrap: wrap;
}
.news input {
  flex: 1 1 220px;
  font: inherit;
  font-size: 16px;
  padding: 14px 16px;
  border: 1.5px solid var(--sepia);
  border-radius: 3px;
  background: var(--crema);
  color: var(--sepia);
}
.news input::placeholder {
  color: #3a2e2578;
}

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

.foot {
  background: var(--sepia);
  color: var(--crema);
  padding-block: clamp(48px, 6vw, 82px) 26px;
}
.foot__in {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: clamp(22px, 3vw, 44px);
}
.foot .brand {
  color: var(--crema);
  font-size: 34px;
  margin-bottom: 14px;
}
/* ⭐ El sello reemplaza al nombre escrito, y no lo repite: el anillo YA dice
   «EL MUNDO DE TERA». El nombre en texto sigue en la cabecera de todas las
   páginas, así que no se pierde de ninguna.
   El color lo pone `.foot .brand` —crema de día, sepia de noche—, y de ahí lo
   toma `currentColor`: el sello no lleva ni un color propio. */
/* El sello al cierre de la biografía. Acá la tinta es `--grabado` —el token de
   los especímenes— y no la del texto: el sello ES un grabado, así que de día
   sale en tinta sepia y de noche en latón, igual que los escarabajos.
   ⚠️ Sin `opacity`. Un sello a media opacidad se vería «discreto» y dejaría su
   contraste dependiendo de lo que tenga detrás, que es justo lo que no se puede
   medir. Lo discreto lo da el TAMAÑO. */
.bio__sello {
  display: flex;
  justify-content: center;
  /* La MISMA columna que la biografía, o el sello se centra en el `wrap`
     entero y cae a la derecha del texto. */
  max-width: var(--ancho-bio);
  margin-top: clamp(34px, 5vw, 56px);
}
.bio__sello .sello-marca {
  --sello: url('img/sello.webp');
  aspect-ratio: 424 / 401;
  width: clamp(96px, 11vw, 124px);
  color: var(--grabado);
}

.foot .brand .sello-marca {
  /* A 132 px el anillo («LIBRETAS Y ACCESORIOS · EL MUNDO DE TERA») se queda
     por debajo de lo legible, y en esta columna sobra sitio: el lema de al
     lado ya mide ~300. */
  --sello: url('img/sello.webp');
  aspect-ratio: 424 / 401;
  width: clamp(124px, 13vw, 164px);
}
.foot h4 {
  font-family: var(--voz);
  font-size: 11.5px;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  margin: 0 0 15px;
  color: #f6efe28c;
  font-weight: 700;
}
.foot a {
  display: block;
  padding-block: 5px;
  font-size: 14.5px;
  color: #f6efe2cc;
  transition: color 0.2s;
}
.foot a:hover {
  color: var(--terracota);
}
.foot__legal {
  grid-column: 1 / -1;
  display: flex;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 44px;
  padding-top: 18px;
  border-top: 1px dashed #f6efe238;
  font-size: 12.5px;
  color: #f6efe28c;
}

/* ---------------------------------------------------------------------- PDP */

.pdp {
  padding-block: 30px clamp(48px, 7vw, 92px);
}
.migas {
  font-size: 13px;
  color: var(--sepia-70);
  margin-bottom: 26px;
}
.pdp__in {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: clamp(26px, 4.5vw, 74px);
  align-items: start;
}
.pdp__stage {
  /* El marco de kraft alrededor de la foto. Va en variable porque la cinta se
     posiciona CONTRA la foto y necesita saber cuánto mide el marco: escrito dos
     veces, el día que cambie el `clamp` la cinta se queda flotando en el
     passepartout y nada avisa. */
  --marco: clamp(22px, 4vw, 60px);
  background: var(--kraft);
  border: 1px solid var(--kraft-osc);
  padding: var(--marco);
  position: relative;
}
/* ⚠️ El selector es COMPUESTO (0,2,0) y no `.pdp__flag` a secas. `.pc__flag` ya
   fija `bottom` y `left` con la misma especificidad (0,1,0), así que a secas
   ganaría el que quedara más abajo en el archivo: funcionaría hoy y se rompería
   el día que alguien reordene el bloque, moviendo la cinta a la esquina del
   marco sin que nada dé error. Con (0,2,0) el orden deja de importar — es la
   quinta vez que la especificidad muerde en este proyecto. */
.pc__flag.pdp__flag {
  bottom: calc(var(--marco) + 14px);
  left: calc(var(--marco) + 14px);
}
.pdp__stage .book-wrap {
  transform: rotate(-1.4deg);
  filter: drop-shadow(0 20px 30px #3a2e2530);
}
/* ⚠️ Las cinco telas no caben en un teléfono sin encogerse a un tamaño en que
   ya no se distingue el tejido —que es justamente lo que este selector vende—.
   Se desplaza en horizontal, con anclaje para que cada tela quede encuadrada.

   Y el `min-width: 0` no es cosmético: sin él, el ANCHO MÍNIMO de esta fila
   (5 × 66 + huecos = 370 px) se lo imponía a la columna del grid, que medía 354.
   El resultado era que toda la columna de la ficha —precio, tela, papel— caía
   16 px más a la derecha que las migas y la tabla técnica. No salía en ningún
   error: solo estaba torcido. */
.pdp__gal {
  display: flex;
  gap: 10px;
  margin-top: 14px;
  min-width: 0;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  /* El desplazamiento lateral aquí es deliberado, así que se recorta ANTES:
     esta fila no puede empujar el ancho de la página. */
  padding-bottom: 2px;
}
.pdp__gal::-webkit-scrollbar {
  display: none;
}
.pdp__gal button {
  width: 66px;
  flex: none;
  scroll-snap-align: start;
  aspect-ratio: 2 / 3;
  border: 1.5px solid var(--kraft-osc);
  background: var(--crema);
  padding: 0;
  overflow: hidden;
  transition:
    border-color 0.25s,
    transform 0.25s var(--ease);
}
.pdp__gal button img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.pdp__gal button[aria-selected='true'] {
  border-color: var(--sepia);
  transform: rotate(-2deg) translateY(-3px);
}

.pdp__info {
  position: sticky;
  top: 100px;
  /* ⚠️ Un ítem de grid tiene `min-width: auto`, o sea que NO baja de su ancho
     mínimo de contenido aunque su columna sea más estrecha. En móvil la columna
     medía 354 px y esta caja 370: se salía 16 px, y como `.pdp` recorta a esa
     altura no se veía cortada — solo se veía que el precio y las opciones
     llegaban 16 px más a la derecha que las migas y la ficha técnica. Un
     desalineado no da error, y por eso hay que medirlo. */
  min-width: 0;
}
.pdp__name {
  margin: 8px 0 10px;
}
.pdp__price {
  font-family: var(--voz);
  font-size: 38px;
  margin: 18px 0 6px;
}
.pdp__opt {
  padding-block: 20px;
  border-top: 1px dashed var(--hilo);
}
.pdp__opt h4 {
  font-family: var(--voz);
  font-size: 11.5px;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--sepia-70);
  margin: 0 0 13px;
  display: flex;
  justify-content: space-between;
}
.pdp__opt h4 b {
  color: var(--sepia);
  letter-spacing: 0;
  text-transform: none;
  font-size: 14px;
}
/* ⭐⭐⭐ Acá vivían `.tapas` y `.tapa`, el selector de telas, y se fueron en el
   bloque 6: sus cinco muestras ofrecían telas que no existen —cada libreta
   tiene una sola, la de su campo `color`— y sus miniaturas eran las fotos de
   otras cinco piezas. El sitio lo ocupa ahora el carrusel (`.pdp__gal`), que
   enseña las fotos DE ESTA pieza. */
/* La cuota, debajo del precio. Nace `hidden` y solo la enseña `app.js` cuando la
   pieza está a la venta: en una vendida o en una de muestra, ofrecer tres cuotas
   de algo que no se puede comprar es peor que no decir nada. */
.pdp__cuotas {
  margin: 0 0 6px;
  font-size: 14px;
  color: var(--sepia-70);
}

.pdp__cta {
  margin-top: 24px;
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

/* El aviso que ocupa el sitio del botón cuando la pieza no está a la venta. Lo
   que había antes era un hueco: se quitaba el botón y la ficha seguía como si
   nada, sin decir en ninguna parte por qué no se podía comprar. */
.pdp__aviso {
  margin: 0;
  padding: 14px 16px;
  border: 1px dashed var(--terracota);
  border-radius: 3px;
  font-size: 14.5px;
  color: var(--sepia);
  background: color-mix(in srgb, var(--terracota) 8%, transparent);
}
.pdp__cta .btn {
  flex: 1 1 220px;
  justify-content: center;
}
.jura {
  margin: 24px 0 0;
  padding: 18px 20px;
  background: #fdf8ec;
  border: 1px dashed var(--kraft-osc);
  font-size: 14px;
  color: var(--sepia-70);
  list-style: none;
}
.jura li {
  padding-left: 24px;
  position: relative;
  padding-block: 5px;
}
.jura li::before {
  content: '✓';
  position: absolute;
  left: 0;
  color: var(--oliva);
  font-weight: 700;
}

/* ⚠️⚠️ Las columnas las cuenta `app.js` y llegan en `--cols`; acá NO va un
   `auto-fit`. El motivo está en `columnasFicha()`: `auto-fit` reparte el ancho
   sin saber cuántos campos hay, así que metía los cinco que cabían y dejaba el
   sexto solo, con cuatro celdas vacías al lado — este mismo `background` de
   kraft, que existe para dibujar las líneas de 1 px, asomando del ancho de la
   página. El `1` de reserva es para que la ficha no se apile en una columna si
   el JS muriera antes de llegar acá; el `minmax(0, …)` es lo que impide que un
   valor largo le imponga su ancho mínimo a toda la columna. */
.ficha {
  margin-top: clamp(44px, 6vw, 84px);
  display: grid;
  grid-template-columns: repeat(var(--cols, 1), minmax(0, 1fr));
  gap: 1px;
  background: var(--kraft-osc);
  border: 1px solid var(--kraft-osc);
}
.ficha div {
  background: var(--crema);
  padding: 22px 20px;
}
.ficha dt {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sepia-70);
  font-weight: 700;
  margin-bottom: 7px;
}
.ficha dd {
  margin: 0;
  font-family: var(--voz);
  font-size: 19px;
  line-height: 1.3;
}

/* ---------------------------------------------------------------- colección */

/* ⚠️ DESBORDE HORIZONTAL EN ESCRITORIO — medido: 1346 px de ancho de scroll en
   una ventana de 1280. Venía del gabinete original y se arrastró hasta acá.
   Es el mismo fallo de siempre visto en la otra punta: el agave decorativo sale
   por la derecha (`--r: -4%`) y encima va girado 6°, lo que ensancha su caja
   más de lo que dice el `right`. Solo se veía en escritorio porque el recorte
   de móvil, que ya existía, lo tapaba por debajo de 980 px.

   `overflow: hidden` SOLO no lo arregla: sin `position: relative` el ornamento
   resuelve su posición contra el bloque inicial —el viewport— y un contenedor
   no recorta lo que no contiene. Las dos declaraciones son una sola cosa. */
.coll-hero {
  position: relative;
  overflow: hidden;
  padding-block: clamp(34px, 4.6vw, 64px) 26px;
}
.coll-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding-block: 18px;
  border-top: 1px dashed var(--hilo);
  border-bottom: 1px dashed var(--hilo);
  margin-block: 30px 34px;
}
/* Dos preguntas distintas, dos filas. El TIPO dice cómo está armada la libreta
   y la COLECCIÓN dice qué lleva grabado: apiladas en una sola fila el usuario no
   puede ver que son ejes independientes que se cruzan.
   Una fila vacía no deja hueco —`:empty` la saca del flujo—, que es lo que
   permite que las categorías sin tipos no dejen un renglón en blanco. */
.coll-bar__filters {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.coll-bar__fila {
  display: flex;
  gap: 9px;
  flex-wrap: wrap;
}
.coll-bar__fila:empty {
  display: none;
}

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

/* El WhatsApp flotante, encima de la pestaña del carrito. El offset sale del
   token, no de un 54 escrito otra vez: sin él, mover la pestaña un píxel
   desalinea el botón y nada da error.

   ⭐ Va en el VERDE de WhatsApp con el trazo en blanco, que es el par que la
   gente reconoce sin leer nada. Antes era un círculo oscuro con el icono en oro:
   combinaba con la tienda y por eso mismo no se distinguía de cualquier otro
   ornamento del jardín — un botón de contacto que hay que descifrar no sirve.

   ⚠️ Blanco sobre `--wa` da 1,98:1, por debajo del 4,5:1 que se le exige a
   cualquier texto de la tienda, y aun así es lo correcto acá: WCAG exime
   explícitamente los logotipos, y esto es el glifo de WhatsApp, no una etiqueta.
   Lo que sí se mide —y se mide en el gate— es que el CÍRCULO se recorte de la
   página: de ahí el borde `--wa-borde`, que da 3,87:1 contra el relleno. */
.flotante {
  position: fixed;
  right: 18px;
  /* Se apoyaba sobre la pestaña de la mesa. Sin pestaña baja a su esquina, y
     queda a la misma distancia de los dos bordes. */
  bottom: 18px;
  z-index: 96;
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  /* ⚠️ Fondo OPACO propio, y no por gusto: el botón flota sobre lo que haya
     debajo —una foto, el papel, el campo oscuro— así que no hay ancestro contra
     el que medir el contraste. */
  background: var(--wa);
  color: #fff;
  border: 1.5px solid var(--wa-borde);
  box-shadow: 0 8px 22px #00000030;
  transition:
    visibility 0.3s,
    opacity 0.3s,
    transform 0.3s var(--ease);
}
.flotante:hover {
  transform: translateY(-2px);
}
/* El trazo va más grueso que el de las redes de «Sobre mí»: los otros dos iconos
   viven junto a su nombre escrito y este está solo. Un logotipo que es lo único
   que identifica al botón no puede leerse como una línea fina. */
.flotante .icono-red {
  width: 26px;
  height: 26px;
  color: inherit;
  stroke-width: 1.9;
}

/* ⚠️⚠️ `visibility: hidden`, NO solo `opacity` ni `transform`. Lo que saca del
   orden de tabulación es esto; con las otras dos el teclado sigue cayendo en un
   botón invisible que está ENCIMA del carrito abierto. Es exactamente la
   lección que costó una ronda con la mesa — y `visibility` además transiciona,
   a diferencia de `display`. */
.flotante--oculto {
  visibility: hidden;
  opacity: 0;
  transform: translateY(12px);
}

/* ---------------------------------------------------------------- sobre mí */

.bio__hero {
  display: grid;
  gap: 30px;
  align-items: center;
}
@media (min-width: 820px) {
  .bio__hero {
    grid-template-columns: 300px 1fr;
    gap: 48px;
  }
}

/* El hueco de la foto. ⏳ Provisional, como el logo: hasta que llegue la de
   verdad va la lámina del ciervo volante. Un rectángulo gris diría «falta
   algo»; una lámina dice «esto es lo que hay». */
.bio__foto {
  position: relative;
  aspect-ratio: 4 / 5;
  display: grid;
  place-items: center;
  background: var(--kraft);
  border: 1px dashed var(--kraft-osc);
  border-radius: 2px;
  overflow: hidden;
}
.bio__marcador {
  width: 74%;
  color: var(--sepia-70);
  opacity: 0.5;
}
.bio__marcador .esp {
  width: 100%;
  height: auto;
}

.bio {
  display: grid;
  gap: 34px;
  max-width: var(--ancho-bio);
}
.bio__titulo {
  margin: 0 0 10px;
  font-family: var(--voz);
  font-size: 15px;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--terracota);
}
.bio__bloque p {
  margin: 0;
  font-size: 17px;
  line-height: 1.72;
}

/* -------------------------------------------------------------- contacto */

.contacto {
  display: grid;
  gap: 34px;
  align-items: center;
}
@media (min-width: 820px) {
  .contacto {
    grid-template-columns: 1fr auto;
    gap: 56px;
  }
}
.contacto__redes {
  display: grid;
  gap: 10px;
  min-width: 260px;
}
.red {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 56px;
  padding: 12px 20px;
  background: var(--crema);
  border: 1px solid var(--hilo);
  border-radius: 3px;
  color: inherit;
  text-decoration: none;
  font-family: var(--voz);
  font-size: 15px;
  letter-spacing: 0.04em;
  transition:
    border-color 0.25s,
    transform 0.25s var(--ease);
}
.red:hover {
  border-color: var(--sepia-70);
  transform: translateX(3px);
}
.icono-red {
  width: 22px;
  height: 22px;
  flex: none;
  color: var(--terracota);
}

/* ---------------------------------------------------------------- talleres */

/* La ficha de taller. NI carta NI cajón, y tiene que verse que no lo es: la
   carta significa «una pieza a la venta» y el cajón «una categoría». Esta es una
   fila con sello de fecha a la izquierda, como una ficha de préstamo. */
.talleres {
  display: grid;
  gap: 14px;
  margin-top: 24px;
}
.taller {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 20px;
  align-items: start;
  padding: 20px;
  background: var(--crema);
  border: 1px solid var(--hilo);
  border-radius: 3px;
}
@media (min-width: 820px) {
  .taller {
    grid-template-columns: auto 1fr auto;
  }
}

/* El sello: día grande, mes en minúscula y año chiquito, en tinta sobre el
   campo. `--campo` con `--oro` es la pareja ya medida —7,46:1 de día, 7,88:1 de
   noche—, la misma del dorso de la carta y del sello de vendida. */
.taller__sello {
  display: grid;
  place-items: center;
  align-content: center;
  min-width: 74px;
  padding: 12px 10px;
  background: var(--campo);
  color: var(--oro);
  border-radius: 2px;
  font-family: var(--voz);
  line-height: 1;
}
.taller__sello b {
  font-size: 27px;
  font-weight: 400;
}
.taller__sello i {
  margin-top: 5px;
  font-style: normal;
  font-size: 13px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.taller__sello span {
  margin-top: 6px;
  font-size: 11px;
  letter-spacing: 0.14em;
  opacity: 0.72;
}

.taller__nombre {
  margin: 0 0 8px;
  font-family: var(--voz);
  font-size: 18px;
  font-weight: 400;
  line-height: 1.25;
}
.taller__resumen {
  margin: 0 0 12px;
  font-size: 15px;
  line-height: 1.6;
  max-width: 62ch;
}
.taller__datos,
.taller__cuenta {
  margin: 0;
  font-family: var(--voz);
  font-size: 12.5px;
  letter-spacing: 0.08em;
  color: var(--sepia-70);
}
.taller__cuenta {
  margin-top: 5px;
  text-transform: uppercase;
  color: var(--terracota);
}

/* El espécimen se va en el teléfono. Es por ANCHO, no por tema: en 360 px la
   fila ya lleva sello y texto, y una tercera columna la parte. */
.taller__esp {
  display: none;
}
@media (min-width: 820px) {
  .taller__esp {
    display: block;
    width: 84px;
    color: var(--sepia-70);
    opacity: 0.55;
  }
  .taller__esp .esp {
    width: 100%;
    height: auto;
  }
}

/* Los pasados, apagados. ⚠️ Baja la OPACIDAD del conjunto y del espécimen, NO el
   color del texto: bajarle el contraste a un texto por debajo de 4,5:1 lo rompe,
   y «ya pasó» no es excusa para volverlo ilegible. */
.taller--pasado {
  background: transparent;
  border-style: dashed;
}
.taller--pasado .taller__sello {
  opacity: 0.78;
}
.taller--pasado .taller__cuenta {
  color: var(--sepia-70);
}

/* ---------------------------------------------------------------- gabinete */

/* Los cajones. NO son cartas de tarot y tienen que verse que no lo son: la
   carta está reservada al producto. Una gaveta es rectangular, tiene tirador y
   no lleva campo oscuro — el espécimen va grabado en el papel, no sobre la
   noche. */
/* ⚠️ Son CINCO y el reparto va a mano, no con `auto-fit`. Con `minmax` el ancho
   decide cuántas columnas caben y a 1180 px daban cuatro: el quinto cajón
   quedaba solo en su renglón, que se lee como un error de maquetación y no como
   una decisión. Cinco en fila arriba, y 3+2 en tableta —donde el renglón corto
   sí se lee intencional porque hay dos, no uno—. */
.cajones {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  margin-top: 38px;
}
@media (min-width: 700px) {
  .cajones {
    grid-template-columns: repeat(3, 1fr);
  }
}
@media (min-width: 1080px) {
  .cajones {
    grid-template-columns: repeat(5, 1fr);
  }
}
/* ⭐⭐⭐ EL CAJÓN ES UN FRENTE DE GAVETA, NO UNA TARJETA. Era `background:
   var(--crema)` sobre una pared `--crema`: 1,00:1, cero superficie, y todo el
   trabajo de separarla lo hacía un filete a 1,43:1. Se veía plano porque estaba
   plano.

   Lo que lo levanta ahora son tres cosas, y ninguna es un borde grueso de
   color —que además es el tic más delator de una interfaz hecha por IA—:

     1. su propia madera (`--cajon`), distinta de la pared Y de la mesa;
     2. un CANTO real, que es por donde se reconoce una gaveta;
     3. la sombra que proyecta sobre la pared, más el filo de luz de arriba.

   ⚠️ La sombra usa el marrón de la tinta y no negro: una sombra negra sobre
   papel ocre se ve sucia, no profunda. */
.cajon {
  position: relative;
  /* ⭐ Columna flexible para que el SELLO caiga siempre al fondo. «Accesorios de
     taller» tiene el nombre de dos líneas y empujaba su cifra 18 px por debajo
     de las otras cuatro: cinco cajones de la misma altura con los sellos a
     alturas distintas se leen como cinco cajones desalineados. Es el mismo
     `margin-top: auto` con el que los especímenes alinean su rótulo. */
  display: flex;
  flex-direction: column;
  padding: 30px 22px 22px;
  background: var(--cajon);
  border: 1px solid var(--cajon-canto);
  border-radius: 3px;
  color: inherit;
  text-decoration: none;
  overflow: hidden;
  box-shadow:
    inset 0 1px 0 var(--cajon-luz),
    0 1px 2px #33281f1f,
    0 6px 14px -8px #33281f2e;
  transition:
    border-color 0.25s,
    box-shadow 0.25s var(--ease),
    transform 0.25s var(--ease);
}

/* El tirador: una muesca en el borde de arriba, como la de una gaveta de
   herbario. Es lo que la separa de una tarjeta cualquiera.
   ⭐ Va en `--grabado` y no en `--hilo`: es la única pieza de metal del cajón, y
   `--grabado` es justo el token que de noche se vuelve latón. Antes era un hilo
   translúcido que no se veía ni de día. */
.cajon::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  translate: -50% 0;
  width: 58px;
  height: 8px;
  background: var(--grabado);
  opacity: 0.5;
  border-radius: 0 0 5px 5px;
}

/* ⭐ El cajón SE SALE. Al pasar el puntero se abre un poco y la sombra se abre
   con él —una gaveta que se tira hacia afuera proyecta más—, y el canto se
   aprieta. Es el mismo gesto del gabinete de verdad. */
.cajon:hover {
  border-color: var(--sepia-70);
  transform: translateY(-4px);
  box-shadow:
    inset 0 1px 0 var(--cajon-luz),
    0 2px 3px #33281f24,
    0 16px 26px -12px #33281f42;
}
.cajon__esp {
  height: 96px;
  color: var(--sepia-70);
  opacity: 0.72;
}
.cajon__esp .esp {
  height: 100%;
  width: auto;
  margin-inline: auto;
  display: block;
}
/* ⭐ El filete separa la LÁMINA del RÓTULO, que es como está armada una gaveta
   de museo: arriba el ejemplar, abajo la placa que lo nombra. Sin él, el
   espécimen y el texto eran una sola mancha y la tarjeta se leía como un
   bloque. */
.cajon__nombre {
  margin: 16px 0 6px;
  padding-top: 15px;
  border-top: 1px solid var(--cajon-canto);
  font-family: var(--voz);
  font-size: 17px;
  font-weight: 400;
  letter-spacing: 0.02em;
}
.cajon__linea {
  margin: 0 0 12px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--sepia-70);
}
/* La cuenta deja de ser un renglón más y pasa a ser un SELLO: la cifra escrita
   sobre la placa, encuadrada. Es un dato, no prosa — y así se distingue de la
   línea de descripción, que antes tenía exactamente el mismo peso visual. */
.cajon__cuenta {
  margin: auto 0 0;
  display: inline-block;
  align-self: flex-start;
  padding: 3px 9px;
  border: 1px solid var(--cajon-canto);
  border-radius: 2px;
  font-family: var(--voz);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sepia);
}

/* Las colecciones: más chicas y en fila, porque atraviesan los cajones en vez
   de ser uno más. La jerarquía la dice el tamaño. */
.colecciones {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 14px;
  margin-top: 30px;
}
/* ⭐⭐ La colección conserva el borde PUNTEADO y eso no es decoración: un cajón
   tiene canto sólido porque es una división fija, y una colección lo cruza. La
   línea discontinua dice justamente eso, y es lo que las distingue de un
   vistazo sin leer una palabra.
   ⚠️ Lo que estaba mal era el contraste, no la idea: sin fondo (1,00:1 contra
   la banda) y con el punteado a 1,34:1, la lámina no existía como superficie.
   Ahora tiene su papel —1,34 contra la banda— y el punteado sube a 2,4:1. */
.coleccion-lam {
  display: block;
  padding: 20px 16px;
  text-align: center;
  text-decoration: none;
  color: inherit;
  background: var(--lamina);
  border: 1px dashed var(--lamina-canto);
  border-radius: 3px;
  box-shadow: 0 1px 2px #33281f14;
  transition:
    border-color 0.25s,
    box-shadow 0.25s var(--ease),
    transform 0.25s var(--ease);
}
.coleccion-lam:hover {
  border-color: var(--sepia-70);
  transform: translateY(-2px);
  box-shadow: 0 8px 16px -10px #33281f3d;
}
.coleccion-lam__esp {
  height: 66px;
  color: var(--sepia-70);
  opacity: 0.66;
}
.coleccion-lam__esp .esp {
  height: 100%;
  width: auto;
  margin-inline: auto;
  display: block;
}
.coleccion-lam__nombre {
  margin: 12px 0 4px;
  font-family: var(--voz);
  font-size: 15px;
  font-weight: 400;
}
.coleccion-lam__n {
  margin: 0;
  font-family: var(--voz);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sepia-70);
}

/* La ficha del filtro que llegó por enlace. No es un `.gchip`: un chip es algo
   que se pulsa para ELEGIR y este se pulsa para QUITAR, así que se ve distinto
   —relleno, con su aspa— y lo dice su nombre accesible. */
.coll-fichas {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 22px;
}
.coll-fichas:empty {
  display: none;
}
.ficha-filtro {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 34px;
  padding: 6px 13px;
  border: 1px solid var(--sepia);
  border-radius: 999px;
  background: var(--sepia);
  color: var(--crema);
  font-family: var(--voz);
  font-size: 13px;
  letter-spacing: 0.02em;
  cursor: pointer;
}
.ficha-filtro span {
  font-size: 15px;
  line-height: 1;
  opacity: 0.75;
}
.ficha-filtro:hover span {
  opacity: 1;
}

/* En el dedo, el aspa necesita objetivo de verdad. */
@media (pointer: coarse) {
  .ficha-filtro {
    min-height: 44px;
    padding-inline: 16px;
  }
}
.coll-bar select {
  font: inherit;
  font-size: 14px;
  padding: 8px 10px;
  border: 1.5px solid var(--sepia);
  border-radius: 3px;
  background: var(--crema);
}
.vacio {
  padding: 74px 0;
  text-align: center;
  font-family: var(--voz);
  font-style: italic;
  font-size: 24px;
  color: var(--sepia-70);
}

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

.toast {
  position: fixed;
  left: 50%;
  top: 88px;
  /* Igual que en Pliego: el reposo se mide contra el borde propio más un
     margen fijo. Con un porcentaje, el aviso asomaba bajo la cabecera. */
  transform: translate(-50%, calc(-100% - 110px)) rotate(-1.4deg);
  background: var(--oliva);
  color: var(--crema);
  padding: 13px 22px;
  border: 1.5px solid var(--sepia);
  box-shadow: 3px 3px 0 var(--sepia);
  font-weight: 600;
  font-size: 14.5px;
  z-index: 120;
  transition: transform 0.5s var(--ease);
}
.toast[data-show='1'] {
  transform: translate(-50%, 0) rotate(-1.4deg);
}

/* ------------------------------------------------------------------ reveal */

[data-reveal] {
  opacity: 0;
  transform: translateY(26px) rotate(-0.6deg);
  transition:
    opacity 0.8s var(--ease-soft),
    transform 0.8s var(--ease-soft);
}
[data-reveal].is-in {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------------------- despacho: la ficha de envío */

/* ⭐⭐⭐ Acá la metáfora se retira. El titular y el lede son de la marca —el
   gabinete sigue siendo el gabinete— pero de las etiquetas para abajo esto es
   un formulario de tienda y nada más: campos anchos, rótulos literales, errores
   rojos al lado de su campo. Quien llega a esta página está tecleando su cédula
   con el pulgar; un adorno de más acá se paga en ventas.

   ⚠️ La página NO monta grabados ni animaciones de entrada. Los especímenes
   viven en la parte editorial de la tienda; en un checkout serían ruido sobre
   un campo obligatorio. */

/* ⚠️⚠️ Se llamaba `.ficha` — y `.ficha` YA ERA la tabla de especificaciones de
   la ficha de producto. Con el nombre repetido, esta página heredaba de ella el
   fondo `--kraft-osc`, la rejilla, el borde, un `div { background; padding }`
   que caía sobre CADA div de adentro, y `dt`/`dd` a 11 y 19 px — de ahí salían
   los rótulos diminutos del resumen. No daba error: la página se veía «casi
   bien» con estilos que no eran suyos, que es la peor manera de estar rota. */
.despacho {
  padding: clamp(26px, 5vw, 58px) 0 clamp(48px, 8vw, 96px);
}
/* ⚠️⚠️ `--sepia`, NUNCA `--tinta`, para el texto de esta zona. Los dos son «el
   color de la letra» de día, pero de noche `--tinta` se INVIERTE a oscuro —su
   trabajo es leerse sobre las superficies claras del tema oscuro— y acá el
   fondo es oscuro. Escrito con `--tinta`, las once etiquetas, el titular y el
   resumen daban **1,13:1**: invisibles, y SOLO de noche. */
.despacho__titulo {
  font-family: var(--voz);
  font-size: clamp(27px, 4.6vw, 42px);
  line-height: 1.08;
  margin: 0 0 10px;
  color: var(--sepia);
}
.despacho__lede {
  max-width: 52ch;
  color: var(--sepia-70);
  margin: 0 0 clamp(24px, 4vw, 38px);
}

/* El formulario manda y el resumen acompaña: 1,35 contra 1 y el resumen
   pegajoso, para que el total se vea mientras se llena la ficha larga. */
.despacho__cuerpo {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(22px, 3.5vw, 52px);
  align-items: start;
}

.despacho__grupo {
  border: 0;
  border-top: 1px solid var(--hilo);
  margin: 0 0 26px;
  padding: 22px 0 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px 18px;
}
.despacho__grupo:first-of-type {
  border-top: 0;
  padding-top: 0;
}
.despacho__legend {
  font-family: var(--voz);
  font-size: 13.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--sepia-70);
  padding: 0;
  margin-bottom: 4px;
  grid-column: 1 / -1;
}

/* ------------------------------------------------------------------ campos */

.campo {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.campo--ancho {
  grid-column: 1 / -1;
}
/* El documento son dos controles de un solo dato: el tipo ocupa lo justo y el
   número se lleva el resto. Partidos por la mitad, «C.C.» quedaba en un campo
   del ancho de una cédula entera. */
.campo--tipo {
  max-width: 116px;
}
.campo--num {
  grid-column: auto;
}

.campo label {
  font-family: var(--voz);
  /* Sube de 13 a 14,5 px y a semibold. Es el nombre del campo: lo que la
     persona lee para saber QUÉ escribir, y estaba más pequeño que el texto que
     iba a teclear dentro. La monoespaciada además tiene la altura-x baja, así
     que 13 px de TLWG se leen como 11,5 de una sans. */
  font-size: 14.5px;
  font-weight: 600;
  color: var(--sepia);
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.campo__opcional {
  font-family: var(--lectura);
  font-size: 13px;
  color: var(--sepia-70);
  border: 1px solid var(--hilo);
  border-radius: 999px;
  padding: 1px 8px;
}
.campo__pista {
  font-size: 13.5px;
  color: var(--sepia-70);
}

.campo input,
.campo select,
.campo textarea {
  font-family: var(--lectura);
  font-size: 16px; /* ⚠️ 16 px o menos hace que Safari en iOS haga zoom al enfocar */
  width: 100%;
  padding: 11px 13px;
  border-radius: 3px;
  /* Ver `--pozo` arriba: el relleno era el MISMO valor de la página y el borde
     daba 1,72:1 cuando la norma pide 3,0 para el contorno de un control. */
  border: 1.5px solid var(--pozo-borde);
  background: var(--pozo);
  /* ⚠️⚠️ `--sepia`, NO `--tinta`. Los dos son «el color del texto» de día, pero
     de noche `--tinta` se invierte a oscuro —porque su trabajo es leerse sobre
     las superficies CLARAS del tema oscuro, como el papel de la mesa— y el pozo
     de noche es oscuro. Puesto con `--tinta` daba 1,41:1: texto negro sobre
     campo negro, ilegible, y solo de noche. Con `--sepia` da 10,6:1 de día y
     10,8:1 de noche. Lo cazó la aserción nueva del gate. */
  color: var(--sepia);
  /* ⚠️ Sin esto, en el teléfono un input de 16 px mide 38 px de alto: por
     debajo de los 44 del objetivo táctil. */
  min-height: 46px;
}
.campo textarea {
  resize: vertical;
  line-height: 1.5;
}
.campo select:disabled {
  /* Un desplegable que todavía no tiene qué ofrecer. Se apaga a la vista, pero
     con el borde puesto: un campo sin contorno se lee como «acá no hay nada»,
     y lo que pasa es «acá todavía no». */
  opacity: 0.55;
  cursor: not-allowed;
}
.campo select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--sepia-70) 50%),
    linear-gradient(135deg, var(--sepia-70) 50%, transparent 50%);
  background-position: right 17px top 21px, right 12px top 21px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 32px;
}
.campo input:focus-visible,
.campo select:focus-visible,
.campo textarea:focus-visible {
  outline: 2px solid var(--terracota);
  outline-offset: 1px;
  border-color: var(--terracota);
}
.campo input::placeholder,
.campo textarea::placeholder {
  color: var(--sepia-70);
  opacity: 0.62;
}

/* El error va PEGADO a su campo, no en un cartel arriba. Un «revisa el
   formulario» encima de nueve campos deja a la persona buscando cuál. */
.campo__error {
  font-size: 13.5px;
  color: var(--terracota);
  font-weight: 600;
  min-height: 0;
}
.campo__error:empty {
  display: none;
}
.campo--mal input,
.campo--mal select,
.campo--mal textarea {
  border-color: var(--terracota);
  /* Además del color, un borde más grueso: el color solo no distingue para
     quien no ve bien los rojos, y este borde es la única señal del campo. */
  border-width: 2.5px;
}

/* La casilla del habeas data. Es una fila, no una columna: el cuadrito al lado
   del texto y no encima. */
.campo--casilla {
  flex-direction: row;
  align-items: flex-start;
  gap: 11px;
  flex-wrap: wrap;
}
.campo--casilla input {
  width: 22px;
  height: 22px;
  border: 1.5px solid var(--pozo-borde);
  min-height: 0;
  flex: 0 0 auto;
  margin-top: 2px;
  accent-color: var(--terracota);
}
.campo--casilla label {
  font-family: var(--lectura);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.5;
  flex: 1 1 240px;
  display: block;
}
.campo--casilla .campo__error {
  flex: 1 1 100%;
}

/* --------------------------------------------------------------- el cobro */

/* ⚠️ Llevaba un filete grueso a la izquierda —el tic más delator de una
   interfaz hecha por IA, y el detector lo caza—. Un contorno completo y fino
   dice lo mismo y además se parece a las demás superficies de la tienda, que
   son todas cajas de papel con su borde. */
.despacho__error {
  grid-column: 1 / -1;
  margin: 0;
  padding: 12px 15px;
  border-radius: 3px;
  background: #a854381f;
  border: 1.5px solid var(--terracota);
  color: var(--sepia);
  font-size: 15px;
  font-weight: 600;
}
.btn--pagar {
  grid-column: 1 / -1;
  justify-content: center;
  width: 100%;
  font-size: 17px;
  padding: 17px 27px;
}
.btn--pagar:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}
.despacho__seguro,
.despacho__recordar {
  grid-column: 1 / -1;
  margin: 0;
  font-size: 13.5px;
  color: var(--sepia-70);
  line-height: 1.55;
}
.despacho__olvidar {
  background: none;
  border: 0;
  padding: 0;
  color: var(--terracota);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

/* -------------------------------------------------------------- el resumen */

.resumen {
  background: var(--mesa-papel);
  border: 1.5px solid var(--kraft-osc);
  border-radius: 4px;
  padding: 20px 22px;
  position: sticky;
  top: 92px;
}
.resumen__titulo {
  font-family: var(--voz);
  font-size: 13.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  margin: 0 0 14px;
  color: var(--sepia);
}
.resumen__linea {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--hilo);
  font-size: 14.5px;
}
.resumen__nombre {
  color: var(--sepia);
}
.resumen__var {
  grid-column: 1;
  font-size: 13.5px;
  color: var(--mesa-tinta-70);
}
.resumen__precio {
  grid-row: 1;
  grid-column: 2;
  font-family: var(--voz);
  font-variant-numeric: tabular-nums;
  color: var(--sepia);
}
.resumen__vacio {
  margin: 0 0 4px;
  font-size: 14.5px;
  color: var(--mesa-tinta-70);
}
.resumen__vacio a {
  color: var(--mesa-enlace);
}

.resumen__sumas {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 7px 14px;
  margin: 15px 0 0;
  font-size: 14.5px;
}
.resumen__sumas dt {
  color: var(--mesa-tinta-70);
}
.resumen__sumas dd {
  margin: 0;
  text-align: right;
  font-family: var(--voz);
  font-variant-numeric: tabular-nums;
  color: var(--sepia);
}
.resumen__total {
  font-size: 19px;
  font-weight: 700;
  color: var(--sepia);
  padding-top: 9px;
  border-top: 1px solid var(--hilo);
  margin-top: 3px;
}
.resumen__zona {
  margin: 11px 0 0;
  font-size: 13.5px;
  color: var(--mesa-tinta-70);
}
.resumen__mal {
  margin: 11px 0 0;
  padding: 9px 11px;
  border-radius: 3px;
  border: 1.5px solid var(--terracota);
  background: #a854381f;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--sepia);
}
.resumen__volver {
  margin: 10px 0 0;
  font-size: 13.5px;
}
/* ⚠️ Va SOLO en su párrafo, así que no lo exime el «Inline» de WCAG 2.5.8: es
   un destino por derecho propio y el dedo tiene que alcanzarlo. Sin el alto
   mínimo medía 15 px — el texto pelado. */
.resumen__volver a {
  color: var(--mesa-enlace);
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-right: 4px;
}

@media (max-width: 980px) {
  /* El resumen se va ARRIBA del formulario, no abajo: es lo que la persona
     quiere confirmar antes de ponerse a escribir nueve campos. */
  .despacho__cuerpo {
    grid-template-columns: minmax(0, 1fr);
  }
  .resumen {
    position: static;
    order: -1;
  }
}

@media (max-width: 680px) {
  /* Una sola columna. Dos campos de 16 px en 360 px de ancho no caben, y el
     par «tipo de documento + número» partido es justo el que peor queda. */
  .despacho__grupo {
    grid-template-columns: minmax(0, 1fr);
  }
  .campo--tipo {
    max-width: none;
  }
}

/* -------------------------------------------------------------- responsive */

@media (max-width: 980px) {
  /* ⚠️ `minmax(0, 1fr)` y NO `1fr`. Un track `1fr` lleva un mínimo automático
     igual al contenido mínimo de su ítem más ancho, así que no baja de ahí
     aunque el contenedor sea más estrecho. En la ficha, las cinco telas del
     selector (5 × 66 px + huecos = 370) le imponían 370 px a una columna de
     354: toda la columna —precio, tela, papel— caía 16 px más a la derecha que
     las migas y la tabla técnica. `minmax(0, …)` quita ese mínimo y deja que la
     columna obedezca al contenedor, que es lo que se esperaba de `1fr`. */
  .hero__in,
  .probe,
  .news,
  .pdp__in,
  .band__intro {
    grid-template-columns: minmax(0, 1fr);
  }
  /* ⚠️ `width:100%` es obligatorio acá. `margin-inline:auto` en un ítem de
     grid le quita el estirado, y como TODOS los hijos del collage son
     absolutos su ancho de contenido es 0 → el aspect-ratio daba altura 0 y
     las piezas se desparramaban sobre el texto de arriba. */
  .collage {
    width: 100%;
    max-width: 420px;
    margin-inline: auto;
  }
  .pasos {
    grid-template-columns: 1fr;
  }
  .paso {
    transform: none !important;
  }
  .pdp__info {
    position: static;
  }
  .foot__in {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 680px) {
  .head__in {
    min-height: 60px; /* la cabecera es fija: en un teléfono cada píxel de alto se paga */
  }
  .burger {
    display: grid;
  }

  /* ⭐ El MISMO nav, en panel. No hay un segundo juego de enlaces: los mismos
     `href`, el mismo `aria-current`, una sola cosa que mantener. Va absoluto
     —fuera del flujo— para que abrirlo no empuje la página ni cambie el alto de
     la cabecera. */
  .nav {
    display: grid;
    position: absolute;
    top: calc(100% + 1px);
    left: 0;
    right: 0;
    gap: 0;
    padding: 4px var(--pad) 12px;
    /* ⚠️ OPACO, sin `backdrop-filter`. Con la cabecera translúcida el titular
       del hero se leía A TRAVÉS de los enlaces del menú. Una barra puede ser
       translúcida —siempre deja ver poco—, pero un panel que tapa media
       pantalla no: ahí la transparencia es solo ruido detrás del texto. */
    background: var(--crema);
    border-bottom: 1px solid var(--kraft-osc);
    box-shadow: 0 16px 26px -16px #00000040;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-10px);
    transition:
      opacity 0.22s,
      transform 0.3s var(--ease),
      visibility 0.22s;
  }
  .nav[data-open='1'] {
    opacity: 1;
    visibility: visible;
    transform: none;
  }
  /* Los enlaces son filas de 48 px: en un panel el objetivo es toda la fila, no
     el ancho de la palabra. */
  .nav a {
    padding-block: 14px;
    font-size: 17px;
    border-bottom: 1px dashed var(--hilo);
  }
  .nav a:last-child {
    border-bottom: 0;
  }
  /* El conmutador, como una fila más del panel: el objetivo es el ancho entero,
     igual que los enlaces, y el rótulo aparece porque acá sí hay sitio para él.
     Deja de ser un círculo de 38 px —eso es su forma en la cabecera— sin dejar
     de ser el mismo botón. */
  .nav .tema {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 12px;
    width: 100%;
    height: auto;
    min-height: 48px;
    border-radius: 0;
    border-color: transparent;
    color: var(--sepia);
    font-size: 17px;
    text-align: left;
  }
  .nav .tema__rotulo {
    display: inline;
  }
  .nav__cajon {
    display: block;
    padding-left: 20px;
    font-size: 16px;
    color: var(--sepia-70);
  }
  /* El subrayado dibujado se apaga acá: entre las líneas de puntos ya hay
     separación, y los dos juntos son ruido. La página actual se marca con
     color, que en una lista se lee mejor que un trazo. */
  .nav a::after {
    display: none;
  }
  .nav a[aria-current] {
    color: var(--terracota);
    font-weight: 600;
  }

  /* ⚠️ Este botón estuvo OCULTO en móvil mientras la mesa dejaba una pestaña
     asomada abajo: dos accesos a lo mismo no cabían en una cabecera de 360 px.
     Al esconder la barra del todo, la pestaña dejó de existir y este botón pasó
     a ser el ÚNICO acceso al carrito con el dedo. Volver a ocultarlo deja el
     carrito inalcanzable — que es el fallo que ya costó una ronda con «Menú».
     ⭐ Cabe porque pierde la palabra, no porque encoja: a 360 px la marca mide
     200 y quedaban 28 px libres. Icono + número son 53. */
  .mesa-btn {
    gap: 6px;
    padding: 0 9px;
    min-width: 44px;
    min-height: 44px;
    justify-content: center;
  }
  .mesa-btn__i {
    width: 21px;
    height: 21px;
  }
  /* Se recorta a la vista pero NO sale del árbol de accesibilidad: con
     `display:none` el botón se anunciaría «0» a secas. */
  .mesa-btn__rotulo {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  /* El hueco entre la marca y los botones era 20 px de mínimo, y con tres
     objetivos de 44 no sobra. */
  .head__in {
    gap: 12px;
  }
  .head__actions {
    gap: 8px;
  }

  .mesa__row {
    grid-template-columns: 40px 1fr auto;
    row-gap: 10px;
  }
  .mesa__row > :last-child {
    grid-column: 2 / -1;
    text-align: right;
  }
  .foot__in {
    grid-template-columns: 1fr;
  }
}

/* ⚠️⚠️ Por debajo de 356 px el nombre NO cabe junto a los dos botones, y el
   fallo no se VE porque `.brand` lleva `min-width: 0`: el flex la encoge por
   debajo de su contenido, el `nowrap` deja el texto SALIRSE de su caja y
   `overflow-x: hidden` recorta el sobrante. Resultado: «Tera» dibujado DEBAJO
   del botón del menú, con el `scrollWidth` diciendo que todo está bien.
   Un `min-width: 0` con `nowrap` no es «que se adapte»: es «que se salga en
   silencio». La marca tiene que ENCOGER de verdad, que es lo que `clamp()`
   prometía y el suelo de 19 px impedía.
   ⭐ El 356 está medido, no elegido: 200 de marca + 12 de hueco + 108 de los dos
   botones = 320, más los 36 del `--pad`. Y venía de antes de mudar el
   conmutador —a 360 la caja daba 160 con el texto pidiendo 200—, así que no lo
   trajo la cabecera nueva. */
@media (max-width: 355px) {
  .brand {
    font-size: 14.5px;
  }
  /* ⚠️ Acá SOLO el alto. Era `width` y `height` cuando la marca era un `<svg>`
     cuadrado; con la polilla, que es apaisada, fijar el ancho a 19 px la
     dejaría de 11 px de alto — ilegible— y además pelearía con su
     `aspect-ratio`. */
  .head .brand .sello-marca {
    height: 17px;
  }
}

/* ══════════════════════════════════════════════════════════ EL DEDO ══════════
 *
 * Lo que cambia cuando la entrada es táctil. Va por `pointer: coarse` y no por
 * ancho a propósito: **el ancho no dice cómo se toca la pantalla**. Un portátil
 * con pantalla táctil a 1280 px necesita los mismos objetivos grandes que un
 * teléfono, y una media query de ancho no lo ve.
 *
 * El mínimo es 44×44 px. Medidos antes de esto: el botón del menú 51×25, el
 * conmutador de tema 38×38, el botón de compra 93×40, las migas 34×15 y los enlaces
 * del pie 324×33 — todos por debajo.
 */

@media (pointer: coarse) {
  .tema {
    width: 44px;
    height: 44px;
  }
  .gchip {
    min-height: 44px;
  }
  /* ⭐ El control de giro ya no necesita crecer: cubre el campo entero, que a
     cualquier ancho es el objetivo táctil más grande de la página. El que sí
     crece es «Ver más», que en un teléfono carga con toda la compra. */
  .carta__ver {
    min-height: 44px;
    padding-inline: 20px;
  }
  #collSort {
    min-height: 44px;
  }
  /* Las migas y los enlaces del pie eran texto suelto: el objetivo era la altura
     de la línea. Se les da cuerpo sin moverlos de sitio, con el padding
     compensado por un margen negativo. */
  .migas a,
  .foot a {
    display: inline-block;
    padding-block: 11px;
    margin-block: -11px;
  }
  .foot a {
    display: block;
  }
  /* La marca es el enlace al inicio, y en móvil es el único: el alto de la
     línea de texto no basta como objetivo. El padding cabe dentro del
     `min-height` de la cabecera, así que no la engorda. */
  .brand {
    padding-block: 7px;
  }

  /* ⚠️ En una pantalla táctil el `:hover` se QUEDA PEGADO después de tocar: el
     dedo levanta, y la tarjeta se queda levantada y girada hasta que tocas otra
     cosa. Los realces decorativos se reservan a los punteros que de verdad
     pueden pasar por encima sin pulsar. */
  .carta:hover .carta__emblema,
  .espec:hover,
  /* ⚠️ El cajón y la lámina ya se levantaban con el puntero y NO estaban en
     esta lista: el hueco venía de antes y se notaba menos porque el gesto era
     de 3 px. Al volverse un cajón que se abre —con su sombra— quedarse abierto
     después de tocar sería mucho más raro. */
  .cajon:hover,
  .coleccion-lam:hover,
  .collage:hover .collage__piece:nth-child(1),
  .collage:hover .collage__piece:nth-child(2),
  .collage:hover .collage__piece:nth-child(3) {
    transform: none;
  }
}

/* ═════════════════════════════════════════════════════ LA CAPA DEL JARDÍN ════
 *
 * Especímenes, cajón, mural y ornamentos. Todo lo de abajo es la capa
 * entomológica y botánica; lo de arriba es el taller de encuadernación, que
 * funcionaría sin ella. Se mantienen separadas porque son dos decisiones
 * distintas: la mecánica de compra y el mundo visual.
 *
 * Salvo donde se diga, esto es el tema de DÍA. Su relectura nocturna vive en
 * «LA NOCHE (2/2)», al final del archivo.
 */

/* Los grabados no se pintan con `color` del texto: llevan su propia tinta,
   más clara, porque una lámina impresa nunca es tan negra como la tipografía.
   `--esp-relleno` es lo que hace que las patas queden TAPADAS por el cuerpo.  */
.esp {
  display: block;
  width: 100%;
  height: auto;
  color: var(--grabado);
  --esp-relleno: var(--crema);
}

/* ------------------------------------------------------------- ornamentos */

/* Espécimen suelto sobre la página. Se coloca con variables para que el HTML
   diga DÓNDE y el CSS cómo, sin estilos en línea repartidos por el marcado. */
.orn {
  position: absolute;
  left: var(--x, auto);
  right: var(--r, auto);
  top: var(--y, auto);
  bottom: var(--b, auto);
  width: var(--w, 120px);
  transform: rotate(var(--rot, 0deg));
  opacity: var(--op, 0.5);
  pointer-events: none;
  z-index: var(--z, 0);
}
/* El de fondo: muy tenue, detrás del texto, para que la página se sienta
   impresa sobre una lámina y no decorada con stickers. */
.orn--marca {
  --op: 0.13;
  --z: 0;
}

/* ------------------------------------------------------- ficha de espécimen */

/* El bloque completo: lámina + rótulo. Va ligeramente torcido y con sombra
   dura, como una cartulina montada sobre otra. */
.espec {
  position: relative;
  background: #faf4e6;
  border: 1px solid var(--kraft-osc);
  padding: 22px 18px 14px;
  box-shadow: 0 8px 20px #33281f1c;
  transform: rotate(var(--giro, -1.4deg));
  transition: transform 0.45s var(--ease-soft);
}
.espec:hover {
  transform: rotate(calc(var(--giro, -1.4deg) * 0.3)) translateY(-4px);
}
.espec .esp {
  width: 100%;
  max-width: 190px;
  margin-inline: auto;
}

/* ---------------------------------------------------------------- el hero */

.hero {
  overflow: hidden;
}
/* El ciervo volante que preside la portada.
   ⚠️ Empezó arriba a la derecha y el collage se lo comió: solo asomaban las
   antenas. Va abajo, atravesando el vacío que dejan el titular y los botones,
   y CORTADO por el borde inferior — así se lee como una lámina que sigue más
   allá de la página, que es como se comporta en la referencia. */
.hero__bicho {
  position: absolute;
  right: 16%;
  bottom: -24%;
  width: min(32vw, 330px);
  opacity: 0.22;
  transform: rotate(-13deg);
  pointer-events: none;
  z-index: 0;
}
.hero__in {
  position: relative;
  z-index: 2;
}
/* Espécimen pequeño clavado sobre el collage, encima de todo. */
.collage__bicho {
  position: absolute;
  left: -10%;
  bottom: 6%;
  width: 34%;
  z-index: 6;
  filter: drop-shadow(3px 5px 4px #33281f30);
}

/* --------------------------------------------------------- en la tarjeta */

/* Cada referencia del lote lleva SU espécimen. No es adorno: es lo que hace
   que el catálogo se lea como una colección numerada y no como una grilla.

   ⚠️⚠️ La POSICIÓN del emblema ya no vive acá, vive con la carta —arriba, en
   «catálogo»—, y no puede volver: este bloque va DESPUÉS en el archivo y con la
   misma especificidad (0,1,0), así que cualquier `top`/`right`/`width` escrito
   acá le gana al de la carta esté bien o mal. Medido: con las medidas viejas
   —66 px sueltos— el ejemplar salía al 31% del ancho del campo y le peleaba el
   sitio a la lámina; el verificador lo caza en «el ejemplar no compite».
   Lo único que queda acá es el GESTO. */

/* El ejemplar cuelga de un hilo, así que al pasar el ratón se MECE: el giro
   pivota sobre `transform-origin: top center`, que es el punto donde está
   atado. Un balanceo, no un icono que rota sobre su centro. */
.carta__emblema {
  transition: transform 0.45s var(--ease-soft);
}
.carta:hover .carta__emblema {
  transform: rotate(-9deg) scale(1.06);
}

/* ------------------------------------------------------------------ ficha */

/* En la ficha de producto el espécimen es grande y va clavado sobre el
   escenario, tapando una esquina de la foto: la regla de «siempre se sale». */
.pdp__stage {
  overflow: visible;
}
.pdp__bicho {
  position: absolute;
  right: -34px;
  bottom: -26px;
  width: clamp(90px, 13vw, 148px);
  z-index: 6;
  filter: drop-shadow(4px 6px 5px #33281f2e);
}
.pdp__reg {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0 0 4px;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sepia-70);
}
.pdp__reg i {
  font-family: var(--voz);
  font-style: italic;
  font-size: 16px;
  text-transform: none;
  letter-spacing: 0;
  color: var(--oliva);
}

/* ----------------------------------------------------------- banda rasgada */

/* Borde de papel rasgado entre secciones. Sustituye al filete de puntadas
   cuando la banda va sobre kraft: en un colage los papeles se rompen, no se
   cortan a escuadra. */
.band--kraft::before,
.band--kraft::after {
  height: 12px;
  opacity: 1;
  background:
    repeating-linear-gradient(90deg, transparent 0 7px, #00000010 7px 8px),
    var(--crema);
  -webkit-mask-image: var(--rasgado);
  mask-image: var(--rasgado);
  -webkit-mask-size: 90px 12px;
  mask-size: 90px 12px;
  -webkit-mask-repeat: repeat-x;
  mask-repeat: repeat-x;
}
.band--kraft::after {
  transform: scaleY(-1);
}
:root {
  --rasgado: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90' height='12'%3E%3Cpath d='M0 0h90v5.4c-7 .3-9 2.6-15 2.9-6 .3-9-1.9-15-1.6-6 .3-8 2.7-14 3-6 .3-10-2-16-1.7-6 .3-9 2.4-15 2.6-5 .2-8-.6-15-.4z' fill='%23000'/%3E%3C/svg%3E");
}

/* ------------------------------------------------------------------- nota */

/* La cita lleva su mariposa clavada en la esquina, como una postal vieja. */
.nota {
  overflow: visible;
}
.nota__bicho {
  position: absolute;
  right: -26px;
  top: -30px;
  width: 96px;
  z-index: 3;
  opacity: 0.85;
  transform: rotate(12deg);
  filter: drop-shadow(3px 4px 4px #33281f26);
}

/* ---------------------------------------------------------------- reducido */

@media (prefers-reduced-motion: reduce) {
  .espec:hover,
  .carta:hover .carta__emblema {
    transform: none;
  }
}

@media (max-width: 980px) {
  /* El bicho del hero pasa a marca de agua detrás del titular: en una
     columna sola, al lado del texto no le queda aire. */
  .hero__bicho {
    right: -22%;
    top: 2%;
    width: 78vw;
    opacity: 0.1;
  }
  .pdp__bicho {
    right: -14px;
    bottom: -18px;
  }
}

@media (max-width: 680px) {
  .collage__bicho {
    left: -6%;
    width: 40%;
  }
  /* El emblema de la carta NO lleva ajuste de móvil: mide 15% del campo, así
     que encoge con la carta sola. Las medidas en píxeles que había acá eran de
     cuando vivía FUERA de la tarjeta. */
}

/* ⚠️ DESBORDE HORIZONTAL EN MÓVIL — medido, no supuesto.
 *
 * La regla de la variante es que el espécimen se SALGA de su caja, y en móvil
 * eso se convierte en scroll lateral: a 390 px las tres páginas se desbordaban
 * (406, 401 y 420 px de ancho de scroll). `body{overflow-x:hidden}` no lo
 * ataja, porque el desbordamiento se propaga igual al viewport.
 *
 * No se arregla con `overflow-x: clip` en `html`: eso ya dejó un CTA
 * INALCANZABLE en otro proyecto. Se arregla donde nace — recogiendo el
 * ornamento y recortando SOLO el contenedor que lo hospeda, que además es
 * decorativo y no tiene nada que alcanzar con el dedo.
 *
 * El gesto no se pierde: el bicho sigue tapando la esquina de la foto, que es
 * lo que importa. Lo que se pierde es el trocito que sobresalía del papel.
 *
 * ⭐ La carta ya no está en esta lista, y no es un olvido: su emblema vive
 * DENTRO del campo oscuro, que recorta con su propio `overflow: hidden`. Nunca
 * llega al borde de la página, así que no hay nada que recoger.
 */
@media (max-width: 980px) {
  .coll-hero,
  .pdp,
  .nota {
    overflow: hidden;
  }
  .pdp__bicho {
    right: -8px;
  }
  .nota__bicho {
    right: -6px;
    top: -20px;
    width: 78px;
  }
}

/* ---------------------------------------------------------------- el patio */

/* La banda ancha donde el jardín se ve entero. De día es un pliego de herbario
   PRENSADO: las siete láminas apenas se adivinan bajo el papel, porque a plena
   luz lo que manda es la cita. De noche la misma composición se enciende.

   Sustituyó al helecho suelto que había detrás de la cita por una razón: un
   ornamento no se puede releer —o está o no está—, y una composición sí. Es la
   pieza que demuestra la regla de la fusión.

   ⚠️ `overflow: hidden` no es opcional. Siete láminas colocadas en porcentajes
   y con giros de hasta 22° se salen por los dos lados a propósito, y sin
   recorte eso es scroll horizontal en móvil. Se recorta acá —en el contenedor,
   que es decorativo y no tiene nada que alcanzar con el dedo— y no en `html`
   con `overflow-x: clip`, que ya dejó un CTA inalcanzable en otro proyecto. */
.mural {
  position: relative;
  background: radial-gradient(90% 120% at 50% 0%, var(--kraft), var(--crema) 78%);
  border-block: 1px solid var(--kraft-osc);
  padding-block: clamp(64px, 9vw, 128px);
  overflow: hidden;
}
.mural__fondo {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
/* La posición la manda `MURAL` en app.js a través de variables, no con
   `style="left:…"` en línea: así el `@media` de abajo puede recoger las láminas
   de los bordes. Contra un atributo `style` no podría. */
.mural__hoja {
  position: absolute;
  left: var(--x, 0);
  top: var(--y, 0);
  width: var(--w, 140px);
  transform: rotate(var(--rot, 0deg));
  /* De día el jardín está prensado bajo el papel: cada lámina se queda en un
     tercio de la opacidad que trae. De noche se le devuelve entera. */
  opacity: calc(var(--op, 0.3) * 0.34);
}
.mural .nota {
  position: relative;
  z-index: 2;
}

@media (max-width: 680px) {
  /* En una columna sola las láminas de los extremos quedan medio cortadas y el
     mural se lee como un borrón. Se achican y se recogen hacia el centro. */
  .mural__hoja {
    width: calc(var(--w, 140px) * 0.62);
  }
}

/* ============================================================== LA NOCHE (2/2)
 *
 * Todo lo que el remapeo de tokens NO arregla. Son tres familias y vale la pena
 * reconocerlas antes de agregar una regla acá, porque casi siempre la que hace
 * falta es de una de ellas:
 *
 *   1. Lo que estaba en HEX QUEMADO — no hay token que voltear.
 *   2. Lo que YA ERA OSCURO de día (el pie, el cajón entomológico): invertirlo
 *      lo ACLARARÍA, que es exactamente lo contrario de lo que se quiere.
 *   3. Lo que SIGUE SIENDO DE PAPEL (la prueba del gramaje, la nota escrita a
 *      mano): son objetos físicos y un objeto no cambia de color porque
 *      anochezca. Lo que se corrige ahí es el TEXTO, que con la inversión había
 *      quedado crema sobre crema.
 *
 * Y después la parte que no es arreglo sino tema: «la luz» y «el jardín se
 * relee». Eso es lo que separa esta noche de un modo oscuro cualquiera.
 */

/* ---------------------------------------------- 1 · lo que estaba en hex */

/* El subrayado dibujado del menú venía con el terracota metido dentro del SVG.
   Mismo trazo, en latón. */
[data-theme='noche'] .nav a::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 90 6' preserveAspectRatio='none'%3E%3Cpath d='M1 4.2C18 1.6 38 5 52 2.4 66 .2 78 4.6 89 2.2' stroke='%23C9A25A' stroke-width='1.7' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* La cinta de papel sobre fondo oscuro tiene que perder cuerpo, o parece un
   esparadrapo fluorescente. */
[data-theme='noche'] .tape {
  background: #efe7d41f;
  border-color: #ffffff14;
  box-shadow: 0 1px 3px #00000040;
}

/* El grano estaba en `multiply`, que sobre fondo oscuro solo oscurece más:
   desaparecía. De noche el grano tiene que ACLARAR, como el polvo en
   suspensión delante de una lámpara. */
[data-theme='noche'] body::before {
  mix-blend-mode: soft-light;
  opacity: 0.55;
}

/* Las rayas de la banda rasgada eran negras sobre crema. Sobre la noche hay que
   invertirlas o el papel se rompe sin que se note. */
[data-theme='noche'] .band--kraft::before,
[data-theme='noche'] .band--kraft::after {
  background:
    repeating-linear-gradient(90deg, transparent 0 7px, #ffffff0f 7px 8px),
    var(--crema);
}

/* La ficha de espécimen era una cartulina clara montada sobre otra. De noche
   sigue siendo una cartulina, pero del cajón: oscura y con el filete de latón
   que la despega del fondo. */
[data-theme='noche'] .espec {
  background: var(--kraft);
  border-color: var(--kraft-osc);
  box-shadow:
    0 -1px 0 #c9a25a26,
    0 10px 26px #00000059;
}

/* ------------------------------------------ 2 · lo que YA era oscuro de día */

/* El pie invertía los papeles: de día es la única banda oscura, y con la
   inversión sería la única CLARA — un rectángulo blanco al final de la noche.
   Se queda oscuro, apenas separado por un filete. */
/* ⚠️ El filete va como `inset box-shadow` y NO como `border-top`. Un borde ocupa
   sitio: la página medía 6098 px de día y 6097 de noche, y ese píxel es una
   sección que cambia de tamaño con el tema — justo lo que la fusión promete que
   no pasa. Una sombra interior pinta el mismo filete sin tocar el alto. */
[data-theme='noche'] .foot {
  background: var(--tinta);
  color: var(--sepia);
  box-shadow: inset 0 1px 0 var(--kraft-osc);
}
[data-theme='noche'] .foot .brand {
  color: var(--sepia);
}
[data-theme='noche'] .foot h4 {
  color: var(--laton-70);
}
[data-theme='noche'] .foot a:hover {
  color: var(--laton);
}
[data-theme='noche'] .foot__legal {
  border-top-color: var(--hilo);
  color: var(--sepia-70);
}

/* ------------------------------------- 3 · lo que sigue siendo de papel */

/* La prueba del gramaje y la nota escrita a mano son OBJETOS: una hoja pintada
   y una tarjeta. No cambian de color porque anochezca — lo que se corrige es el
   texto, que con la inversión quedó crema sobre crema. */
[data-theme='noche'] .probe__viewer,
[data-theme='noche'] .nota,
[data-theme='noche'] .jura {
  color: #2a2019;
}
[data-theme='noche'] .nota {
  background-image: repeating-linear-gradient(#fdf8ec 0 30px, #2a201914 30px 31px);
  border-color: #00000024;
}
[data-theme='noche'] .nota footer {
  color: #2a2019a8;
}
[data-theme='noche'] .jura {
  border-color: #00000026;
}
[data-theme='noche'] .jura li::before {
  color: #5e7043;
}
[data-theme='noche'] .probe__label {
  color: #2a2019;
  border-color: #00000024;
}

/* --------------------------------------------------------------- la luz */

/* ⭐ El halo tibio de arriba: la fuente de luz de la que hablan TODAS las
   sombras de la noche. Va fija, para que no “viaje” con el scroll — una luz que
   se mueve con la página es una luz que no está en ninguna parte. */
[data-theme='noche'] body::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background: radial-gradient(120% 70% at 50% -18%, #c9a25a1c, transparent 62%);
}

/* Cada pieza importante está ILUMINADA, y siempre desde arriba. Esto es lo que
   separa la noche de un modo oscuro: el filete claro del borde superior es el
   canto que devuelve la luz. */
[data-theme='noche'] .carta__ventana,
[data-theme='noche'] .pdp__stage,
[data-theme='noche'] .paso__img,
[data-theme='noche'] .collage__piece {
  box-shadow:
    0 -1px 0 #c9a25a26,
    0 18px 40px #00000059;
}

/* La fotografía es la única fuente de luz REAL de la página: se le sube el
   contraste para que el objeto se despegue de la noche. */
[data-theme='noche'] .carta__ventana img,
[data-theme='noche'] .pdp__stage img,
[data-theme='noche'] .paso__img img,
[data-theme='noche'] .swatch-box img {
  filter: brightness(1.06) contrast(1.05) saturate(0.96);
}

/* Las sombras duras del día son marrones y de noche no se ven. El relieve lo da
   el latón: mismo gesto, mismo desplazamiento al pulsar, otro material. */
[data-theme='noche'] .btn {
  box-shadow: 3px 3px 0 var(--laton);
}
[data-theme='noche'] .btn:hover {
  box-shadow: 5px 5px 0 var(--laton);
}
[data-theme='noche'] .btn:active {
  box-shadow: 0 0 0 var(--laton);
}
[data-theme='noche'] .btn--out {
  color: var(--sepia);
  border-color: var(--laton);
  box-shadow: 3px 3px 0 #c9a25a4d;
}
[data-theme='noche'] .btn--out:hover {
  box-shadow: 5px 5px 0 #c9a25a4d;
}
[data-theme='noche'] .mesa-btn {
  border-color: var(--laton);
  box-shadow: 2px 2px 0 var(--laton);
}
[data-theme='noche'] .mesa-btn:hover {
  box-shadow: 3px 3px 0 var(--laton);
}
[data-theme='noche'] .mesa-btn:active {
  box-shadow: 0 0 0 var(--laton);
}
/* ⚠️ El hundido del botón abierto necesita su gemelo de noche: la regla del día
   apaga una sombra de `--sepia`, y acá la sombra es de latón y la pinta un
   selector (0,2,0) que va MÁS ABAJO en el archivo. Sin esto el botón se
   desplaza pero conserva el relieve, que es medio gesto. */
[data-theme='noche'] .mesa-btn[aria-expanded='true'] {
  box-shadow: 0 0 0 var(--laton);
}
[data-theme='noche'] .gchip {
  border-color: var(--kraft-osc);
}
[data-theme='noche'] .gchip[aria-pressed='true'] {
  background: var(--laton);
  border-color: var(--laton);
  color: var(--tinta);
  box-shadow: none;
}
[data-theme='noche'] ::selection {
  background: var(--laton);
  color: var(--tinta);
}
[data-theme='noche'] :focus-visible {
  outline-color: var(--laton);
}

/* -------------------------------------------------- el jardín se relee */

/* ⭐⭐⭐ Acá está la fusión. NINGUNA de estas reglas agrega ni quita un
   elemento: son las mismas piezas del gabinete leídas con la otra regla. De día
   el espécimen INVADE —sombra dura, se sale de su caja—; de noche ALUMBRA
   —halo, y lo que estaba encima pasa a estar detrás—. Si alguna vez hace falta
   un `display:none` acá, la fusión se rompió. */

/* El ciervo volante pasa a ser la LUNA. Es la misma lámina: sube, crece, pierde
   el giro —una luna no está torcida— y se difumina. */
[data-theme='noche'] .hero__bicho {
  right: -4%;
  top: -34%;
  bottom: auto;
  width: min(52vw, 560px);
  opacity: 0.3;
  transform: none;
  filter: drop-shadow(0 0 26px #c9a25a24);
}

/* La sombra proyectada del collage se cambia por resplandor: de noche un objeto
   no proyecta sombra sobre el papel, se recorta contra la luz. */
[data-theme='noche'] .collage__bicho {
  filter: drop-shadow(0 0 14px #c9a25a4d);
}

/* ⭐⭐ LA CARTA NO TIENE VUELTA DE NOCHE, y eso es la decisión, no el olvido.
   Es la tercera familia de la noche llevada al extremo: como el cajón
   entomológico, la carta YA era un objeto oscuro de día —campo negro, trazo de
   oro— así que invertirla la aclararía, que es justo lo contrario.
   Desde que la carta ENTERA se pinta con `--campo` esto vale más todavía: no
   hay una sola regla de noche para la carta, ni la va a haber. `--carta-tinta`
   tampoco se remapea —la carta es oscura en los dos temas, así que se lee
   siempre con la luz— y lo único que se mueve con el tema es el valor de
   `--campo`. Lo que cambia de verdad es el PAPEL que la rodea, y eso lo
   resuelven `--kraft` y `--sepia` solos.

   ⚠️ Acá vivía la vuelta del espécimen —de clavado sobre la foto a filigrana
   detrás de la tarjeta— y con el renombrado habría sobrevivido rompiendo dos
   cosas a la vez: el emblema se habría ido al pie del campo dejando su hilo
   colgando de nada, y `.carta > *:not(.carta__emblema)` —(0,3,0) contra los
   (0,1,0) de la carta— le habría quitado el `position: absolute` al numeral,
   que es lo único que lo sostiene sobre el campo oscuro. De día se vería
   impecable. */

[data-theme='noche'] .pdp__bicho {
  filter: drop-shadow(0 0 12px #c9a25a45);
}

/* La polilla de la cita: de día está clavada sobre la tarjeta, de noche es un
   bicho que ACUDE a la única superficie iluminada de la banda. Se corre un poco
   afuera para que el latón no caiga sobre el papel claro, donde se lavaría. */
[data-theme='noche'] .nota__bicho {
  right: -34px;
  top: -38px;
  opacity: 1;
  filter: drop-shadow(0 0 12px #c9a25a4d);
}

/* El ornamento de marca de agua se apaga demasiado sobre la noche: en latón al
   13% no queda nada. */
[data-theme='noche'] .orn--marca {
  --op: 0.2;
}

/* El mural recupera la opacidad entera: de día está prensado bajo el papel, de
   noche es el patio y se ve. */
[data-theme='noche'] .mural {
  background: radial-gradient(90% 120% at 50% 0%, #1e2c24, var(--tinta) 78%);
}
[data-theme='noche'] .mural__hoja {
  opacity: var(--op, 0.3);
}

/* ------------------------------------------------------- la noche, reducida */

/* ⚠️⚠️ DESBORDE HORIZONTAL — el mismo de siempre, y de noche hay que volver a
 * resolverlo entero. No basta con las medidas del día: `[data-theme='noche']
 * .hero__bicho` tiene MÁS especificidad (0,2,0) que la regla de móvil
 * `.hero__bicho` (0,1,0), así que la gana esté donde esté en el archivo. Una
 * media query no suma especificidad — solo condiciona. Sin estas reglas, la
 * tienda medía bien de día y se desbordaba de noche, que es justo el fallo que
 * nadie va a mirar.
 *
 * Y ojo con los halos: un `drop-shadow` ENSANCHA la caja de desbordamiento
 * igual que si el elemento fuera más grande, y acá hay halos de hasta 26 px que
 * cuentan por los dos lados.
 *
 * ⭐ La carta salió de esta lista al volverse carta: su emblema no tiene medidas
 * de noche que corregir, porque no tiene medidas de noche.
 */
@media (max-width: 980px) {
  [data-theme='noche'] .hero__bicho {
    right: -22%;
    top: 2%;
    width: 78vw;
    opacity: 0.16;
  }
  [data-theme='noche'] .pdp__bicho {
    right: -8px;
    bottom: -18px;
  }
  [data-theme='noche'] .nota__bicho {
    right: -6px;
    top: -20px;
  }
}

/* ═══════════════════════════════════════════════ LEGIBILIDAD EN EL TELÉFONO ══
 *
 * ⚠️ Este bloque va AL FINAL del archivo por una razón, no por descuido. Todos
 * estos selectores tienen especificidad (0,1,0) igual que los que ajustan, así
 * que gana el que aparezca después. Puesto junto al resto de lo responsive
 * —antes de «LA CAPA DEL JARDÍN», que es donde se definen— no hacía nada:
 * medía 11 px igual que antes.
 *
 * Son tamaños que en escritorio son etiqueta de museo y en un teléfono son
 * simplemente letra pequeña. Suben lo justo para leerse sin perder el registro:
 * siguen siendo los textos menores de su tarjeta.
 */
@media (max-width: 680px) {
  /* La frase del volteo hereda el ajuste que tenía el binomio de la carta, que
     es a quien reemplaza en ese sitio: en un teléfono la carta llena el ancho
     entero y once píxeles en versalitas debajo de una foto a sangre son el
     único texto que cuesta leer. */
  .carta__pista {
    font-size: 12px;
    min-height: calc(18px + 3px + 2 * 12px * 1.3);
  }
  .migas {
    font-size: 14px;
  }
  .foot__legal {
    font-size: 13.5px;
  }
}

/* ------------------------------------------------- el cajón, en el teléfono */

/* ⭐ Un cajón de dos columnas en 390 px no es un cajón: es una rejilla donde la
   ETIQUETA pesa más que el ejemplar. Medido: el dibujo ocupa 110 px de alto y su
   rótulo llegaba a 162, porque «ESCARABAJO RINOCERONTE · LÁM. IX» en una columna
   de 127 px se parte en cuatro líneas.
   Así que en el teléfono el cajón deja de ser vitrina y pasa a ser REGISTRO: una
   fila por ejemplar, el dibujo a la izquierda y su ficha al lado, alineada a la
   izquierda como en un libro de entradas. Cabe todo en una línea o dos, se lee
   de corrido, y el conjunto ocupa MENOS alto que la rejilla que reemplaza. */
@media (max-width: 680px) {
  /* El alfiler y la cinta se posicionan contra el dibujo, que sigue siendo su
     contenedor: en fila caen igual de bien que en rejilla. */
}

/* ------------------------------------------------------------------ legal */

/* La política de datos y lo que venga detrás (términos, retracto). Una columna
   angosta y nada más: son textos que se LEEN de corrido, así que van en
   `--lectura` y con medida de lectura de verdad. */

.legal {
  padding: clamp(26px, 5vw, 58px) 0 clamp(48px, 8vw, 96px);
}
.legal__in {
  max-width: 74ch;
}
.legal__titulo {
  font-family: var(--voz);
  font-size: clamp(27px, 4.4vw, 40px);
  line-height: 1.08;
  margin: 0 0 10px;
  color: var(--sepia);
}
.legal__meta {
  font-family: var(--voz);
  font-size: 13px;
  color: var(--sepia-70);
  margin: 0 0 26px;
}
.legal__lede {
  font-size: 17px;
  line-height: 1.6;
  color: var(--sepia);
  margin: 0 0 34px;
}
.legal h2 {
  font-family: var(--voz);
  font-size: 19px;
  margin: 34px 0 10px;
  color: var(--sepia);
}
.legal h3 {
  font-family: var(--voz);
  font-size: 15px;
  margin: 22px 0 8px;
  color: var(--sepia);
}
.legal p {
  margin: 0 0 14px;
  line-height: 1.65;
  color: var(--sepia);
}
.legal__lista {
  margin: 0 0 16px;
  padding-left: 20px;
  line-height: 1.65;
  color: var(--sepia);
}
.legal__lista li {
  margin-bottom: 7px;
}
/* ⚠️⚠️ El `:not(.btn)` no es cosmético. `.legal a` tiene especificidad (0,1,1)
   y `.btn` (0,1,0), así que este selector le ganaba al botón y «Volver a la
   tienda» salía en terracota sobre su propio fondo oscuro: **2,73:1**. Un botón
   con el color del texto de otra cosa no da error, solo se lee mal. */
.legal a:not(.btn) {
  color: var(--enlace);
}
.legal__volver {
  margin-top: 38px;
}

/* ⚠️⚠️ MARCADOR DEL OWNER. Amarillo chillón y con la palabra FALTA adentro, a
   propósito: un marcador que se lee como texto normal es PEOR que un hueco,
   porque el hueco sí avisa. Esto tiene que doler a la vista hasta que se
   reemplace — y como es un documento legal, publicarlo con un marcador puesto
   es publicar una política que no identifica al responsable.

   ✅ Desde el 2026-08-04 **no lo usa ninguna página**: los tres datos del
   vendedor llegaron y viven en `<b class="vendedor">`. La regla se queda
   escrita porque el patrón sigue siendo el correcto para el siguiente dato que
   falte, y borrarla invitaría a improvisar otro marcador más discreto. */
.falta {
  background: #ffe066;
  color: #4a3200;
  padding: 1px 7px;
  border-radius: 2px;
  border: 1px dashed #a8791b;
  font-family: var(--voz);
  font-size: 0.88em;
}
