/* =========================================================
   A TODO TERRENO 2026 — SHINERAY
   Paleta y tipografía extraídas del brief visual (Paso 0)
   ========================================================= */

/* .woff2 primero (mismo glifo, contenedor mucho mas liviano) con el
   .otf original como respaldo para el puñado de navegadores que
   todavia no entienden woff2 -- no cambia una sola letra en pantalla. */
@font-face {
  font-family: "Discota";
  src: url("../assets/fonts/Discota-CondensedRough.woff2") format("woff2"),
       url("../assets/fonts/Discota-CondensedRough.otf") format("opentype");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "DIN Pro Black";
  src: url("../assets/fonts/DINPro-Black.woff2") format("woff2"),
       url("../assets/fonts/DINPro-Black.otf") format("opentype");
  font-weight: 900;
  font-display: swap;
}

:root {
  --arena-100: #f3ead5;
  --arena-300: #e4cb98;
  --arena-500: #d3ac66;
  --tinta: #14110d;
  --tinta-soft: #241f18;
  --rojo: #c41e1e;
  --rojo-dark: #8f1414;
  /* El rojo de marca sobre el fondo tinta da 3.18:1 — suficiente para
     titulares grandes, insuficiente (WCAG AA pide 4.5:1) para textos
     chicos. Esta variante aclarada es solo para texto sobre oscuro; el
     rojo de marca se mantiene intacto sobre fondos claros. */
  --rojo-sobre-oscuro: #e84545;
  --hueso: #f3eee2;
  --dorado: #b98a3a;

  /* Únicas dos fuentes de marca en todo el sitio: Discota para
     titulares de impacto, DIN Pro Black para todo lo demás (texto,
     etiquetas, botones). Las variables font-mono y font-serif se
     mantienen para no reescribir cada regla, pero ya no apuntan a
     JetBrains Mono ni Playfair Display. */
  --font-display: "Discota", "Arial Narrow", sans-serif;
  --font-heavy: "DIN Pro Black", Arial, sans-serif;
  --font-mono: "DIN Pro Black", Arial, sans-serif;
  --font-serif: "Discota", "Arial Narrow", sans-serif;

  /* ---- Escala tipográfica ----
     Había 17 tamaños distintos solo entre .55 y 1.3rem, elegidos uno a
     uno. Estos seis peldaños cubren todo el texto que no es titular, con
     saltos suficientes para que dos niveles contiguos se distingan de
     verdad (si dos tamaños difieren en 1px, no son dos niveles: son
     ruido). */
  --t-micro:     .625rem;   /* letra chica legal, MRZ */
  --t-etiqueta:  .6875rem;  /* rótulos, overlines, versalitas */
  --t-apoyo:     .8125rem;  /* pies, notas */
  --t-cuerpo:    .9375rem;  /* texto corrido */
  --t-destacado: 1.0625rem; /* entradilla, botones */
  --t-subtitulo: 1.25rem;

  /* ---- Tracking ----
     El principio: el espaciado va al revés del tamaño. La letra chica en
     mayúsculas necesita aire para no empastarse; el titular grande
     necesita cerrarse, porque a ese cuerpo el espacio entre letras se
     agranda ópticamente y el conjunto se desarma. */
  --track-micro:    .18em;
  --track-etiqueta: .12em;
  --track-cuerpo:   .01em;
  --track-titulo:   -.015em;

  /* ---- Interlineado ----
     También inverso al tamaño, y más generoso de lo normal en el cuerpo
     porque la única fuente de texto disponible es un peso Black: sin
     aire entre líneas, un 900 se convierte en un muro. */
  --lh-titulo: .92;
  --lh-medio:  1.25;
  --lh-cuerpo: 1.65;

  --ease: cubic-bezier(.22,.68,0,1);

  /* Sistema de curvas. Un solo --ease para todo aplanaba el
     movimiento: todo entraba con el mismo carácter. Estas cuatro
     cubren los papeles distintos que necesita la pieza. */
  --ease-salida: cubic-bezier(.16, 1, .3, 1);        /* entradas: rápido y frena suave */
  --ease-resorte: cubic-bezier(.34, 1.56, .64, 1);   /* rebote corto, para lo que "aterriza" */
  --ease-peso: cubic-bezier(.6, .04, .3, 1.2);       /* caída con masa, para el wordmark */
  --ease-suave: cubic-bezier(.4, 0, .2, 1);          /* micro-interacciones */
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; scroll-behavior: auto !important; }
}

body {
  margin: 0;
  background: var(--tinta);
  color: var(--hueso);
  font-family: var(--font-mono);
  overflow-x: hidden;
  position: relative;
}

/* Topografía de fondo, fija y sutil, cosiendo visualmente toda la
   experiencia (bienvenida, bitácora, pasaporte, confirmación) con el
   mismo relieve de "terreno" en vez de un fondo plano. */
body::before {
  content: "";
  position: fixed; inset: 0; z-index: -1;
  background: var(--tinta) url("../assets/brand/montanas-topografia.webp") center 12% / 140% auto no-repeat;
  opacity: .16;
  pointer-events: none;
}

.skip-link {
  position: absolute; left: -999px; top: 0;
  background: var(--rojo); color: #fff; padding: .75rem 1rem; z-index: 100;
}
.skip-link:focus { left: 0; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

[hidden] { display: none !important; }

/* =========== Slides: scroll-snap + navegación por pasos =========== */

html { scroll-snap-type: y proximity; }
.hero, .bitacora, .explicador, .manifiesto, .confirmacion, .pistas {
  scroll-snap-align: start;
}

.slide-nav {
  position: fixed; right: 1.25rem; top: 50%; transform: translateY(-50%);
  z-index: 40;
  display: flex; flex-direction: column; gap: .9rem;
}
.slide-nav a {
  display: block; width: 1rem; height: 1rem; padding: .3rem;
}
.slide-nav a span {
  display: block; width: 100%; height: 100%;
  border: 2px solid #888;
  border-radius: 50%;
  mix-blend-mode: difference;
  transition: transform .25s var(--ease);
}
.slide-nav a:hover span { transform: scale(1.2); }
.slide-nav a.is-active span { background: #888; }
.slide-nav a[hidden] { display: none; }

@media (max-width: 56rem) {
  .slide-nav { display: none; }
}

.overline {
  font-family: var(--font-mono);
  letter-spacing: .35em;
  font-size: .72rem;
  color: var(--rojo);
  text-transform: uppercase;
  margin: 0 0 .5rem;
}

html.no-scroll { overflow: hidden; height: 100%; }

/* =========== Bienvenida: tapa de arena a pantalla completa ===========
   Antes era un fondo tinta con cinco masas de polvo animadas en bucle
   infinito (filter:blur de gran radio, siempre en movimiento): costoso
   de componer en GPU y la causa de la lentitud reportada en esta
   pantalla. Se reemplaza por el mismo tratamiento fijo de textura de
   arena + dunas de semitono que usa la tapa del pasaporte (.paso--cover
   / .cover-dunes), sin animación continua. */

.welcome {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  text-align: center;
  overflow: hidden;
  background:
    radial-gradient(circle at 28% 18%, rgba(255,255,255,.14), transparent 55%),
    radial-gradient(circle at 75% 80%, rgba(120,90,50,.12), transparent 50%),
    linear-gradient(rgba(203,180,148,.72), rgba(203,180,148,.72)),
    url("../assets/brand/textura-arena.jpg");
  background-size: auto, auto, cover, cover;
  background-position: center;
  cursor: pointer;
}
.welcome[hidden] { display: none; }

.welcome__grain {
  position: absolute; inset: 0;
  filter: url(#grain);
  opacity: .35;
  mix-blend-mode: overlay;
  pointer-events: none;
}

.welcome__dunes {
  position: absolute; z-index: 0;
  left: 0; right: 0; bottom: 0;
  width: 100%; height: min(46%, 22rem);
  pointer-events: none;
  overflow: hidden;
}
.welcome__dunes-back,
.welcome__dunes-front {
  position: absolute; left: 0; right: 0; bottom: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: bottom;
  transform: scale(1.12);
  transform-origin: bottom center;
}
.welcome__dunes-back { opacity: .72; }
.welcome__dunes-ruta {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 62%;
  opacity: .42;
  background: #cbb494;
  -webkit-mask: url("../assets/brand/ruta.webp") bottom center / contain no-repeat;
  mask: url("../assets/brand/ruta.webp") bottom center / contain no-repeat;
}

.welcome__canvas {
  position: absolute; inset: 0; z-index: 2;
  pointer-events: none;
}

.welcome__content {
  position: relative; z-index: 3;
  padding: 2rem 1.5rem;
  max-width: 34rem;
  transition: opacity .5s var(--ease), transform .5s var(--ease);
}

.welcome__brand {
  display: block;
  width: clamp(12.4rem, 44vw, 16.9rem); /* x1.3 sobre el tamaño anterior */
  height: auto;
  margin: 0 auto 1.75rem;
}

.welcome .overline { color: var(--rojo); }

.welcome__title {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 11vw, 5rem);
  line-height: .95;
  letter-spacing: .01em;
  color: var(--tinta);
  margin: 0 0 1.4rem;
}
/* Regla retirada: apuntaba al <span> que envolvía "A TODO TERRENO"
   cuando el título era texto. Ahora el wordmark es una imagen y el único
   span que queda es "BIENVENIDO", al que esta regla le ganaba en
   especificidad y lo pintaba de rojo. */


.welcome__cta {
  position: relative; z-index: 3;
  font-family: var(--font-display);
  font-size: 1.05rem;
  letter-spacing: .06em;
  background: var(--rojo);
  color: #fff;
  border: 0;
  border-radius: 3px;
  padding: .8rem 2.1rem;
  cursor: pointer;
  box-shadow: 0 6px 16px rgba(120,30,20,.4), inset 0 1px 0 rgba(255,255,255,.18);
  transition: background .2s var(--ease), transform .15s var(--ease), box-shadow .2s var(--ease);
}
.welcome__cta:hover {
  background: var(--rojo-dark);
  transform: translateY(-2px);
  box-shadow: 0 10px 22px rgba(120,30,20,.5), inset 0 1px 0 rgba(255,255,255,.18);
}
.welcome__cta:active { transform: scale(.97); }
.welcome__cta:focus-visible { outline: 3px solid var(--tinta); outline-offset: 3px; }

/* Al hacer clic, el contenido se desvanece hacia arriba antes de dar paso
   a la tapa del pasaporte. */
.welcome.is-dispersing .welcome__content {
  opacity: 0;
  transform: scale(.94) translateY(-8px);
}
.welcome.is-dispersing .welcome__dunes {
  transition: opacity 1.1s ease;
  opacity: 0;
}

/* =========== Topbar de marca persistente =========== */

.topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  display: flex; align-items: center; justify-content: space-between;
  padding: .9rem 1.5rem;
  background: rgba(20,17,13,.85);
  backdrop-filter: blur(6px);
  border-bottom: 1px solid rgba(243,238,226,.08);
  transform: translateY(-100%);
  transition: transform .4s var(--ease);
}
.topbar.is-visible { transform: translateY(0); }

.topbar__wordmark {
  font-family: var(--font-display);
  font-size: .95rem;
  letter-spacing: .04em;
}
.topbar__wordmark em {
  font-style: normal;
  font-family: var(--font-mono);
  font-size: .65rem;
  letter-spacing: .25em;
  opacity: .6;
  margin-right: .4rem;
}
.topbar__event {
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .2em;
  color: var(--rojo-sobre-oscuro);
  display: none;
}
.topbar__brand {
  font-family: var(--font-mono);
  font-size: .7rem;
  letter-spacing: .15em;
  color: var(--arena-500);
}
@media (min-width: 36rem) {
  .topbar__event { display: inline; }
}

/* =========== Grain / halftone textures (no image assets) =========== */

.hero__grain {
  position: absolute; inset: 0;
  background-image:
    radial-gradient(circle at 20% 30%, rgba(0,0,0,.05) 0, transparent 40%),
    radial-gradient(circle at 80% 70%, rgba(0,0,0,.06) 0, transparent 45%);
  background-color: var(--arena-300);
  filter: url(#grain);
  opacity: .9;
}

.hero__dune {
  position: absolute; left: 0; right: 0; bottom: 0; height: 42%;
  background-image: url("../assets/brand/montanas-halftone.webp");
  background-repeat: no-repeat;
  background-position: bottom center;
  background-size: cover;
  will-change: transform;
}

.hero__dune--back {
  height: 52%;
  opacity: .6;
  background-image: url("../assets/brand/montanas-halftone-alt.webp");
}

/* Viñeta sutil de cohesión visual, presente en todo el sitio */
body::after {
  content: "";
  position: fixed; inset: 0; z-index: 60;
  pointer-events: none;
  background: radial-gradient(ellipse at center, transparent 55%, rgba(0,0,0,.16) 100%);
  mix-blend-mode: multiply;
}

/* =========================== HERO =========================== */

.hero {
  position: relative;
  min-height: 100svh;
  display: flex; align-items: center; justify-content: center;
  text-align: center;
  overflow: hidden;
  color: var(--tinta);
}

.hero__content {
  position: relative; z-index: 2;
  padding: 2rem 1.5rem;
  max-width: 40rem;
}

.brand-mark {
  display: inline-block;
  width: clamp(11rem, 22vw, 16rem);
  height: auto;
  margin-bottom: 2rem;
}

.hero__title {
  font-family: var(--font-display);
  font-size: clamp(3.2rem, 14vw, 8rem);
  line-height: .88;
  margin: 0 0 .5rem;
  letter-spacing: .01em;
  color: var(--tinta);
  text-shadow:
    2px 0 0 rgba(20,17,13,.15),
    -1px 1px 0 rgba(20,17,13,.1),
    0 3px 12px rgba(20,17,13,.25);
}

.hero__sub {
  font-family: var(--font-mono);
  letter-spacing: .3em;
  font-size: clamp(.75rem, 2vw, 1rem);
  color: var(--rojo-dark);
  margin: 0 0 2rem;
  font-weight: 700;
}

.hero__hint {
  font-size: .95rem;
  line-height: 1.6;
  opacity: .85;
  margin: 0 0 2.5rem;
}

.scroll-cue {
  background: none; border: 2px solid var(--tinta);
  border-radius: 50%; width: 2.75rem; height: 2.75rem;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.scroll-cue__line {
  width: 2px; height: 1rem; background: var(--tinta);
  animation: scrollpulse 1.6s ease-in-out infinite;
}
@keyframes scrollpulse {
  0%, 100% { transform: translateY(-3px); opacity: .4; }
  50% { transform: translateY(3px); opacity: 1; }
}

/* ========================= BITÁCORA ========================= */

.bitacora {
  background: var(--tinta);
  min-height: 100svh;
  padding: 6rem 1.5rem;
  display: flex; align-items: center; justify-content: center;
}

.bitacora__linea {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 4vw, 2.4rem);
  line-height: 1.25;
  text-align: center;
  color: var(--arena-500);
  max-width: 44rem;
  opacity: 0;
  transform: translateY(24px);
  transition: opacity .9s var(--ease), transform .9s var(--ease);
}
.bitacora__linea.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* ========================= EXPLICADOR ========================= */

.explicador {
  position: relative;
  min-height: 100svh;
  background: #fff;
  color: var(--tinta);
  padding: 5rem 1.5rem 6rem;
  overflow: hidden;
  display: flex; flex-direction: column; justify-content: center;
}

.explicador__bleed {
  position: absolute; bottom: 0; width: 42%; height: 30%;
  background-image: radial-gradient(circle, var(--rojo) 1.6px, transparent 1.8px);
  background-size: 8px 8px;
  opacity: .55;
  pointer-events: none;
}
.explicador__bleed--left {
  left: 0;
  clip-path: polygon(0 40%, 60% 100%, 0 100%);
}
.explicador__bleed--right {
  right: 0;
  clip-path: polygon(100% 30%, 100% 100%, 30% 100%);
}

.explicador__head {
  position: relative; z-index: 1;
  text-align: center;
  max-width: 36rem;
  margin: 0 auto 3rem;
}
.explicador__head h2 {
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 4.5vw, 2.4rem);
  margin: 0 0 .75rem;
}
.explicador__sub { opacity: .7; font-size: .92rem; margin: 0; }

.explicador__grid {
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.5rem;
  max-width: 64rem;
  margin: 0 auto;
}

.explicador__card {
  background: var(--hueso);
  border: 1px solid rgba(20,17,13,.1);
  padding: 1.75rem 1.5rem;
  box-shadow: 0 12px 30px rgba(20,17,13,.06);
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
.explicador__card:hover {
  transform: translateY(-4px);
  box-shadow: 0 18px 36px rgba(20,17,13,.12);
}

.explicador__num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.5rem; height: 2.5rem;
  background: var(--rojo);
  color: #fff;
  font-family: var(--font-display);
  font-size: 1.15rem;
  border-radius: 50%;
  margin-bottom: 1.25rem;
}

.explicador__card h3 {
  font-size: 1.05rem;
  margin: 0 0 .6rem;
}

.explicador__card p {
  font-size: .88rem;
  line-height: 1.55;
  opacity: .75;
  margin: 0;
}

.explicador__cta {
  position: relative; z-index: 1;
  text-align: center;
  font-family: var(--font-mono);
  font-size: .78rem;
  letter-spacing: .1em;
  color: var(--rojo-dark);
  margin: 3rem 0 0;
}

/* ========================= MANIFIESTO ========================= */

/* Escenario del pasaporte.
   Era un plano de color arena, que a pantalla completa se leía como una
   hoja en blanco. Ahora es un paisaje: cielo cálido arriba, arena real
   abajo y la cordillera de la marca en el horizonte. El pasaporte queda
   apoyado sobre un lugar en vez de flotar sobre nada. */
.manifiesto {
  position: relative;
  min-height: 100svh;
  color: var(--tinta);
  padding: 5rem 1.25rem 6rem;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  isolation: isolate;
  background:
    linear-gradient(
      to bottom,
      #f6e4c4 0%,
      #f2d9b0 32%,
      #e8c894 58%,
      #dcb87e 100%
    );
}

/* Arena real, difuminada hacia arriba para que funda con el cielo. */
.manifiesto::before {
  content: "";
  position: absolute; inset: 0; z-index: -2;
  background: url("../assets/brand/textura-arena.jpg") center bottom / cover no-repeat;
  opacity: .55;
  mix-blend-mode: multiply;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 45%, #000 100%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 45%, #000 100%);
  pointer-events: none;
}

/* Cordillera en el horizonte, detrás del documento. Muy tenue: es
   profundidad de escena, no un elemento que compita con el pasaporte. */
.manifiesto::after {
  content: "";
  position: absolute; left: -5%; right: -5%; bottom: 0; z-index: -1;
  height: 38%;
  background: url("../assets/brand/montanas-halftone-alt.webp") bottom center / 110% auto no-repeat;
  opacity: .17;
  pointer-events: none;
}

/* Cuerpo del documento.
   Era un plano casi blanco (#f3eee2) con unas líneas tenues: a pantalla
   completa se leía como una hoja de oficina. Ahora es papel envejecido —
   base cálida, sombreado hacia los bordes como el de un pliego que no
   apoya del todo plano, y fibra visible. El guilloché de seguridad, que
   es lo que tiene un pasaporte de verdad, va en la capa de textura. */
.pasaporte {
  position: relative; z-index: 2;
  width: 100%; max-width: 31rem;
  background-color: #efe3c8;
  background-image:
    /* Sombra de los bordes: el pliego se curva hacia afuera. */
    radial-gradient(120% 100% at 50% 0%, rgba(255,252,240,.55), transparent 58%),
    radial-gradient(100% 70% at 0% 100%, rgba(150,110,60,.16), transparent 60%),
    radial-gradient(100% 70% at 100% 100%, rgba(150,110,60,.14), transparent 60%),
    /* Guilloché: retícula fina en diagonal, como el fondo de seguridad
       impreso en las hojas internas de un pasaporte. */
    repeating-linear-gradient(58deg, rgba(150,110,60,.055) 0 1px, transparent 1px 7px),
    repeating-linear-gradient(-58deg, rgba(150,110,60,.045) 0 1px, transparent 1px 7px),
    /* Renglones del documento. */
    linear-gradient(rgba(20,17,13,.022) 1px, transparent 1px);
  background-size: auto, auto, auto, auto, auto, 100% 2rem;
  outline: 1px solid rgba(185,138,58,.5);
  outline-offset: -8px;
  border: 1px solid rgba(120,90,50,.28);
  box-shadow:
    0 25px 60px rgba(20,17,13,.28),
    0 2px 0 rgba(185,138,58,.5) inset,
    0 0 60px rgba(150,110,60,.12) inset;
  overflow: hidden;
  transition: opacity .6s var(--ease), transform .6s var(--ease), filter .6s var(--ease);
}

.pasaporte__watermark {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  color: var(--tinta);
  opacity: .035;
  pointer-events: none;
}

.pasaporte__texture {
  position: absolute; inset: 0; z-index: 0;
  filter: url(#grain);
  opacity: .05;
  mix-blend-mode: multiply;
  pointer-events: none;
}

/* Sombra de lomo: sugiere que el documento es un cuadernillo encuadernado, no una tarjeta plana */
.pasaporte__spine {
  position: absolute; top: 0; bottom: 0; left: 0; width: 2.75rem; z-index: 1;
  background: linear-gradient(to right, rgba(20,17,13,.16), transparent);
  pointer-events: none;
}

/* Patrón fino tipo guilloché, característico de las páginas internas de un pasaporte real */
.pasaporte__header {
  position: relative; z-index: 1;
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; flex-wrap: wrap;
  padding: .9rem 1.75rem;
  background: var(--tinta);
  color: var(--arena-500);
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .12em;
}
.pasaporte__serial { color: var(--hueso); font-weight: 700; white-space: nowrap; }
/* Texto chico en rojo sobre tinta: necesita la variante aclarada. */
.pasaporte__serial span { color: var(--rojo-sobre-oscuro); }

/* En pantallas angostas el nombre del emisor partía en dos líneas y
   empujaba el serial; se acorta el tracking y se baja un punto. */
@media (max-width: 26rem) {
  .pasaporte__header { padding-inline: 1.1rem; font-size: .62rem; letter-spacing: .08em; }
  .pasaporte__body { padding-inline: 1.1rem; }
  .pasaporte__progress { padding-inline: 1.1rem; }
}

.pasaporte__body { position: relative; z-index: 1; padding: 1.5rem 1.75rem 2.25rem; }

.pasaporte__body .overline { font-family: var(--font-serif); font-style: italic; font-weight: 500; letter-spacing: .08em; font-size: .85rem; color: var(--rojo-dark); text-transform: none; }

.manifiesto__intro { margin: 0 0 1.5rem; opacity: .75; font-size: .85rem; text-align: center; min-height: 2.6em; }

/* ---- Progreso del stepper ---- */

.pasaporte__progress {
  position: relative; z-index: 1;
  display: flex; align-items: center; justify-content: space-between;
  padding: .85rem 1.75rem 0;
}
.pasaporte__progress-label {
  font-family: var(--font-mono);
  font-size: .65rem; letter-spacing: .16em;
  opacity: .55;
}
.step-dots { display: flex; gap: .4rem; }
.step-dot {
  width: .45rem; height: .45rem; border-radius: 50%;
  background: rgba(20,17,13,.2);
  transition: background .3s var(--ease), transform .3s var(--ease);
}
.step-dot.is-active { background: var(--rojo); transform: scale(1.3); }
.step-dot.is-done { background: var(--dorado); }

/* ---- Pasos (stepper): se hojean como páginas reales de un pasaporte ---- */

/* El formulario da la perspectiva desde la que se ve el libro inclinarse */
#passportForm { perspective: 1200px; }

/* Marco: tiene el tamaño y la forma de una página de pasaporte y recibe el
   tilt 3D al pasar el mouse. Lo que gira adentro son las .paso apiladas
   en la misma celda. Si una hoja necesita más alto, el marco crece: nunca
   hay scroll interno. */
.pasaporte__pageframe {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  container-type: inline-size;
  width: min(24rem, 100%);
  /* Antes la altura la fijaba `aspect-ratio: .72`, que ademas de dar la
     proporcion la CAPABA: cuando el paso 3 crecio con los datos del
     visado, el contenido sobrante quedaba recortado por el overflow del
     panel y el boton de sellar desaparecia — el formulario dejaba de
     poder enviarse. Ahora la proporcion es un piso, no un techo: las
     hojas cortas conservan la forma de pasaporte y las largas crecen. */
  min-height: min(33rem, 128vw);
  margin: 0 auto 1.5rem;
  perspective: 1600px;
  transform-style: preserve-3d;
  will-change: transform;
  /* Suaviza el ruido del giroscopio (el mouse ya se sentia bien sin
     esto, pero el sensor entrega lecturas mas nerviosas). */
  transition: transform .15s ease-out;
}

.paso {
  position: relative;
  grid-column: 1;
  grid-row: 1;
  width: 100%;
  min-height: 100%;
  min-width: 0;
  box-sizing: border-box;
  overflow: hidden;
  padding: 1.5rem 1.4rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  transform-origin: left center;
  backface-visibility: hidden;
  border: 1px solid rgba(20,17,13,.15);
  background-color: var(--hueso);
  background-image:
    repeating-linear-gradient(115deg, rgba(20,17,13,.035) 0 1px, transparent 1px 6px),
    repeating-linear-gradient(25deg, rgba(20,17,13,.025) 0 1px, transparent 1px 7px);
}

.btn-paso {
  font-family: var(--font-display);
  letter-spacing: .06em;
  font-size: 1rem;
  background: var(--rojo);
  color: #fff;
  border: 0;
  padding: .85rem 1.5rem;
  cursor: pointer;
  transition: background .2s var(--ease), transform .15s var(--ease);
}
.btn-paso:hover { background: var(--rojo-dark); transform: translateY(-2px); }
.btn-paso:active { transform: scale(.97); }
.btn-paso:focus-visible { outline: 3px solid var(--tinta); outline-offset: 3px; }

.btn-paso--ghost {
  background: transparent;
  color: var(--tinta);
  border: 1.5px solid rgba(20,17,13,.3);
}
.btn-paso--ghost:hover { background: rgba(20,17,13,.05); }

.paso__nav {
  display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; margin-top: 1.5rem;
}
.paso__nav .btn-sellar { flex: 1; }

/* ---- Paso 1: portada del pasaporte, réplica del cuadernillo kraft físico ---- */

.paso--cover {
  position: relative;
  overflow: hidden;
  justify-content: flex-start;
  text-align: center;
  background:
    radial-gradient(circle at 28% 18%, rgba(255,255,255,.14), transparent 55%),
    radial-gradient(circle at 75% 80%, rgba(120,90,50,.12), transparent 50%),
    linear-gradient(rgba(203,180,148,.72), rgba(203,180,148,.72)),
    url("../assets/brand/textura-arena.jpg");
  background-size: auto, auto, cover, cover;
  background-position: center;
  color: var(--rojo);
  padding: 1.6rem 1.25rem 1.1rem;
  border: 0;
  border-radius: 6px;
  transform-style: preserve-3d;
  will-change: transform;
  box-shadow:
    0 10px 30px rgba(0,0,0,.3),
    -4px 0 8px rgba(0,0,0,.18),
    inset 0 0 0 1px rgba(90,65,35,.18);
  transition: box-shadow .35s var(--ease);
}
.paso--cover:hover,
.paso--cover:focus-visible {
  box-shadow:
    0 22px 44px rgba(0,0,0,.38),
    -4px 0 8px rgba(0,0,0,.18),
    inset 0 0 0 1px rgba(90,65,35,.18);
}

/* Botón de registro dentro de la propia tapa */
/* CTA principal de la tapa. Va en tinta, no en rojo: cae sobre las
   montañas de semitono rojo, y un botón rojo sobre fondo rojo pierde
   toda la afordancia. El negro tinta es el mismo del wordmark
   TERRENO, así que sigue en paleta y es el elemento de mayor
   contraste de la tapa — que es justo lo que debe ser. */
.cover-cta {
  position: relative; z-index: 3;
  align-self: center;
  font-family: var(--font-display);
  font-size: 1.15rem;
  letter-spacing: .06em;
  background: var(--tinta);
  color: var(--hueso);
  border: 0;
  border-radius: 3px;
  padding: .95rem 2.2rem;
  min-height: 48px; /* objetivo táctil mínimo recomendado */
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(0,0,0,.35), inset 0 1px 0 rgba(255,255,255,.12);
  transition: background .2s var(--ease), transform .15s var(--ease), box-shadow .2s var(--ease);
  margin-bottom: .9rem;
}
.cover-cta:hover {
  background: var(--tinta-soft);
  transform: translateY(-2px);
  box-shadow: 0 12px 26px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.12);
}
.cover-cta:active { transform: scale(.97); }
.cover-cta:focus-visible { outline: 3px solid var(--tinta); outline-offset: 3px; }

.pasaporte__cover-grain {
  position: absolute; inset: 0; z-index: 2;
  filter: url(#grain);
  opacity: .3;
  mix-blend-mode: overlay;
  pointer-events: none;
}

/* Rastro de arena: un dedo arrastrandose por la tapa deja granos que se
   asientan, como trazar en arena de verdad. pointer-events:none para
   que nunca robe el toque al boton de la propia tapa -- el listener
   real vive en .paso--cover, que sigue recibiendo el gesto igual. */
.cover-arena {
  position: absolute; inset: 0; z-index: 2;
  width: 100%; height: 100%;
  pointer-events: none;
}

/* Dunas de semitono rojo con camino de arena, ancladas al pie de la tapa */
.cover-dunes {
  position: absolute; z-index: 0;
  left: 0; right: 0; bottom: 0;
  width: 100%; height: 46%;
  pointer-events: none;
  overflow: hidden;
}
/* Las capas conservan su caja (100% del contenedor, que es lo que da la
   silueta correcta de dos picos) y se agrandan con un escalado del 12%.
   El parallax las desplaza hasta 30px: sin ese excedente, al moverse
   hacia un lado el borde de la imagen se despegaba del borde de la tapa
   y dejaba ver el fondo. El overflow del contenedor recorta lo que sobra.
   Escala y desplazamiento se componen en el mismo transform, porque una
   segunda declaración de transform pisaría a la anterior: por eso el
   parallax escribe --px/--py en vez de transform. */
.cover-dunes img,
.cover-dunes__ruta {
  --px: 0px;
  --py: 0px;
  transform: translate3d(var(--px), var(--py), 0) scale(1.12);
  transform-origin: bottom center;
}
.cover-dunes img {
  position: absolute; left: 0; right: 0; bottom: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: bottom;
}
.cover-dunes__back { opacity: .72; }
/* La ruta viene como trazo gris claro; puesta tal cual sobre el
   semitono rojo se leía como rayones/daño en la imagen. Se usa como
   máscara y se rellena con el arena de la tapa, así se lee como un
   camino abriéndose entre las montañas. */
.cover-dunes__ruta {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 62%;
  opacity: .42;
  background: #cbb494;
  -webkit-mask: url("../assets/brand/ruta.webp") bottom center / contain no-repeat;
  mask: url("../assets/brand/ruta.webp") bottom center / contain no-repeat;
}

.cover-brand {
  position: relative; z-index: 1;
  display: block;
  width: clamp(10.5rem, 62%, 15rem);
  height: auto;
  margin: .4rem auto 0;
}

.cover-pasaporte {
  position: relative; z-index: 1;
  align-self: center;
  color: var(--tinta);
  border: 1.5px solid rgba(20,17,13,.55);
  font-family: var(--font-mono);
  font-size: .7rem;
  letter-spacing: .5em;
  text-indent: .5em;
  padding: .35rem .7rem .35rem 1rem;
  margin: .9rem 0 .3rem;
}

.cover-title {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center;
  margin: auto 0;
  text-shadow: 0 2px 10px rgba(20,17,13,.25);
}
.cover-atodo {
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 11cqw, 2.3rem);
  letter-spacing: .48em;
  text-indent: .48em;
  color: var(--rojo);
  line-height: 1;
  /* Sin margen negativo: con la Discota real, -.48em hacía que las
     astas de TERRENO chocaran contra "A TODO" y se leyera mal. */
  margin-bottom: .06em;
}
.cover-terreno {
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 19cqw, 4.2rem);
  letter-spacing: .01em;
  color: var(--tinta);
  line-height: 1;
  transform: rotate(-1.5deg);
}

/* Etiqueta informativa, no interactiva: antes tenía relleno sólido y
   sombra, así que competía con el CTA y parecía el botón principal.
   Ahora es un sello de contorno, claramente subordinado. */
.cover-label {
  position: relative; z-index: 1;
  align-self: center;
  background: transparent;
  color: var(--hueso);
  border: 1.5px solid rgba(243,238,226,.65);
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .18em;
  padding: .4rem .9rem;
  border-radius: 3px;
  transform: rotate(-1deg);
  margin-bottom: 1.1rem;
}

/* ---- Paso 2: página de datos ---- */

/* Fechas de emisión/expiración: decorativas, no editables, mismo trazo que un input real */
.field__readonly {
  font-family: var(--font-mono);
  font-size: .95rem;
  margin: 0;
  padding: .3rem .1rem .35rem;
  border-bottom: 1.5px dotted rgba(20,17,13,.55);
}
.field--dates-row { flex-direction: row; gap: .8rem; }
.field--dates-row > div { flex: 1; min-width: 0; }

/* Página de datos: réplica del cuadernillo "Pasaporte de Aventura" físico,
   fondo kraft con venas rojas de mapa en vez del papel hueso de las demás
   hojas, y más compacta para que quepan campos + fechas + pie sin desbordar. */
.paso--datapage {
  position: relative;
  padding-top: .85rem; padding-bottom: .6rem;
  justify-content: flex-start;
  background-color: #ddcda3;
  background-image:
    repeating-linear-gradient(115deg, rgba(20,17,13,.035) 0 1px, transparent 1px 6px),
    repeating-linear-gradient(25deg, rgba(20,17,13,.025) 0 1px, transparent 1px 7px);
}
.paso--datapage .field { margin-bottom: .2rem; }
.paso--datapage label { margin-bottom: .1rem; }
.paso--datapage input[type="text"],
.paso--datapage input[type="email"],
.paso--datapage input[type="tel"],
.paso--datapage .field__readonly { padding-top: .15rem; padding-bottom: .2rem; }
.paso--datapage .field--dp input,
.paso--datapage input {
  border-bottom-style: dotted;
  border-bottom-color: rgba(20,17,13,.55);
}
/* La etiqueta es metadato, el valor que escribe la persona es el
   contenido. Antes ambos iban en DIN Black al mismo peso visual, así
   que la jerarquía quedaba plana; se baja el tamaño y la opacidad de
   la etiqueta para que el dato mande. */
.paso--datapage label {
  color: var(--tinta);
  opacity: .6;
  font-size: .62rem;
  letter-spacing: .14em;
}
.paso--datapage .overline {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: .5rem;
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  letter-spacing: .03em;
  font-size: clamp(.72rem, 4.4cqw, .95rem);
  line-height: 1.2;
  margin-bottom: .7rem;
  color: var(--tinta);
}
.datapage__globe {
  flex-shrink: 0;
  width: 1.3rem; height: 1.3rem;
  margin-top: .1rem;
  color: var(--tinta);
  opacity: .7;
}

/* Venas rojas tipo mapa/capilar de fondo, como en la ilustración de referencia */
.datapage__veins {
  position: absolute; inset: 0; z-index: 0;
  opacity: .32;
  pointer-events: none;
}
.datapage__veins svg { width: 100%; height: 100%; }
.paso--datapage > *:not(.datapage__veins) { position: relative; z-index: 1; }

/* En marcos angostos no entran las dos líneas del rótulo bilingüe: se
   conserva solo el español y el inglés queda como title/atributo visual. */
@container (max-width: 22rem) {
  .paso--datapage label em { display: none; }
}

/* Pie de la página de datos: código de barras, moto, rosa de los vientos y sello */
.datapage__foot {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  align-items: end;
  gap: .4rem;
  margin-top: auto;
  padding-top: .3rem;
  color: var(--tinta);
}
.datapage__barcode {
  grid-column: 1 / -1;
  width: 100%;
  height: 1.3rem;
  color: var(--tinta);
}
.datapage__barcode-serial {
  grid-column: 1 / -1;
  font-family: var(--font-mono);
  font-size: .58rem;
  letter-spacing: .25em;
  opacity: .7;
  margin-top: -.25rem;
  margin-bottom: .1rem;
}
.datapage__moto,
.datapage__compass {
  width: 1.7rem; height: 1.7rem;
  color: var(--tinta);
  opacity: .75;
}

/* La aguja gira con el sensor real del telefono (compas.js); el
   transform-origin en el centro del viewBox (32,32 en un SVG de 64x64
   = 50%) es lo que la hace girar sobre su propio eje en vez de barrer
   un arco. La transicion suaviza el ruido del sensor entre lecturas. */
#compassAguja {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform .4s var(--ease, ease-out);
}
.datapage__stamp {
  width: 2.3rem; height: 2.3rem;
  color: var(--rojo);
  opacity: .85;
  justify-self: end;
}
.datapage__stamp svg { width: 100%; height: 100%; }

/* ---- Paso 4: resumen y MRZ ---- */

.pasaporte__resumen {
  display: grid; grid-template-columns: 1fr; gap: .85rem;
  margin: 0 0 1.5rem;
  padding: 1rem 1.25rem;
  background: rgba(20,17,13,.03);
  border: 1px solid rgba(20,17,13,.12);
}
.pasaporte__resumen dt {
  font-family: var(--font-mono);
  font-size: .62rem; letter-spacing: .12em; text-transform: uppercase; opacity: .55;
  margin-bottom: .2rem;
}
.pasaporte__resumen dd {
  margin: 0; font-weight: 700; font-family: var(--font-mono);
}

.pasaporte__mrz {
  font-family: var(--font-mono);
  font-size: clamp(.4rem, 2vw, .62rem);
  letter-spacing: .02em;
  line-height: 1.7;
  color: rgba(35,55,75,.65);
  background: linear-gradient(rgba(215,227,238,.7), rgba(215,227,238,.7)), var(--hueso);
  border-top: 2px solid rgba(20,17,13,.15);
  border-bottom: 1px solid rgba(20,17,13,.1);
  padding: .85rem .8rem;
  margin: 0 0 1.25rem;
  white-space: pre;
  overflow: hidden;
}

.pasaporte__fineprint {
  font-size: .68rem; letter-spacing: .04em; opacity: .5;
  text-align: center; margin: 1rem 0 0;
}

.field { margin-bottom: 1rem; display: flex; flex-direction: column; }

label { font-size: .68rem; letter-spacing: .12em; text-transform: uppercase; margin-bottom: .25rem; opacity: .65; }
label em { text-transform: none; letter-spacing: 0; opacity: .8; font-style: normal; }

input[type="text"],
input[type="email"],
input[type="tel"] {
  font-family: var(--font-mono);
  font-size: 1rem; /* 16px: evita el zoom automático de iOS al enfocar */
  padding: .3rem .1rem .35rem;
  border: 0;
  border-bottom: 1.5px solid rgba(20,17,13,.3);
  background: transparent;
  color: var(--tinta);
  border-radius: 0;
  appearance: none;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}
input[type="text"]:focus,
input[type="email"]:focus,
input[type="tel"]:focus {
  outline: none;
  border-bottom-color: var(--rojo);
  box-shadow: 0 1.5px 0 0 var(--rojo);
}
/* El placeholder por defecto del navegador es un gris azulado fuera de
   paleta; se lleva al marrón tinta de la marca. */
input::placeholder { color: rgba(20,17,13,.38); opacity: 1; }
input.invalid { border-bottom-color: var(--rojo); }

.field--codigo {
  align-self: center;
  width: 100%;
  max-width: 220px;
  margin-bottom: 1rem;
}
.field--codigo label { color: var(--rojo); opacity: .75; }
.field--codigo input {
  text-align: center;
  text-transform: uppercase;
  color: var(--rojo-dark, var(--rojo));
  border-bottom-color: rgba(90,30,20,.35);
}
.field--codigo .field__error { text-align: center; }

.field__error {
  color: var(--rojo);
  font-size: .78rem;
  min-height: 1.1em;
  margin-top: .3rem;
}

.field--consentimiento { margin-top: .3rem; }
.consentimiento__label {
  display: flex;
  align-items: flex-start;
  gap: .55rem;
  cursor: pointer;
}
.consentimiento__label input[type="checkbox"] {
  /* 20px propio + el padding del label le da al toque un area cercana
     a los 44px recomendados, sin agrandar la caja visualmente. */
  width: 20px; height: 20px;
  flex: none;
  margin-top: .1rem;
  accent-color: var(--rojo);
}
.consentimiento__label span {
  font-family: var(--font-mono);
  font-size: .78rem;
  line-height: 1.45;
  text-transform: none;
  letter-spacing: 0;
  color: var(--tinta);
  opacity: .85;
}
.field--consentimiento.invalid .consentimiento__label span { color: var(--rojo); opacity: 1; }

.btn-sellar {
  position: relative;
  overflow: hidden;
  width: 100%;
  background: var(--rojo);
  color: #fff;
  font-family: var(--font-display);
  letter-spacing: .08em;
  font-size: 1.15rem;
  padding: 1rem;
  border: 0;
  cursor: pointer;
  box-shadow: 0 10px 24px rgba(196,30,30,.25);
  transition: transform .15s var(--ease), background .2s var(--ease), box-shadow .2s var(--ease);
}
.btn-sellar::before {
  content: "";
  position: absolute; top: 0; bottom: 0; left: -60%;
  width: 40%;
  background: linear-gradient(115deg, transparent, rgba(255,255,255,.35), transparent);
  transform: skewX(-20deg);
  transition: left .6s var(--ease);
}
.btn-sellar:hover::before { left: 130%; }
.btn-sellar:hover {
  background: var(--rojo-dark);
  transform: translateY(-2px);
  box-shadow: 0 14px 30px rgba(196,30,30,.32);
}
.btn-sellar:active { transform: scale(.97); }
.btn-sellar:focus-visible { outline: 3px solid var(--tinta); outline-offset: 3px; }

/* Entre el click en "Sellar mi lugar" y la respuesta del servidor puede
   pasar más de un instante (red lenta, servidor recién despertando):
   sin nada visible ahí, la persona no sabe si el click funcionó y
   vuelve a tocar el botón, disparando un segundo registro. El spinner +
   texto "Sellando..." confirma que el click se registró; :disabled ya
   bloquea el segundo tap mientras tanto. */
.btn-sellar:disabled {
  cursor: not-allowed;
  opacity: .85;
}
.btn-sellar.is-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .65rem;
}
.btn-sellar__spinner {
  display: none;
  width: 1.1rem; height: 1.1rem;
  border: 2px solid rgba(255,255,255,.35);
  border-top-color: #fff;
  border-radius: 50%;
  flex-shrink: 0;
}
.btn-sellar.is-loading .btn-sellar__spinner {
  display: inline-block;
  animation: girar-spinner .7s linear infinite;
}
@keyframes girar-spinner {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .btn-sellar.is-loading .btn-sellar__spinner { animation: none; }
}

.pasaporte.is-stamped {
  animation: stamp-hit .5s var(--ease) forwards;
}
@keyframes stamp-hit {
  0% { transform: scale(1); }
  40% { transform: scale(1.04) rotate(-1deg); }
  60% { transform: scale(.98) rotate(.5deg); }
  100% { transform: scale(1); }
}

/* ---- Sello de tinta que cae sobre la hoja al confirmar ---- */

.sello-stamp {
  position: absolute;
  top: 42%; left: 50%;
  z-index: 6;
  display: inline-flex; flex-direction: column; align-items: center; gap: .3rem;
  color: var(--rojo);
  transform: translate(-50%, -50%) rotate(-20deg) scale(2.8);
  opacity: 0;
  pointer-events: none;
  mix-blend-mode: multiply;
}
.sello-stamp img {
  display: block;
  width: clamp(5.5rem, 20vw, 8.75rem);
  height: auto;
}
.sello-stamp small {
  font-family: var(--font-mono);
  font-size: .55rem;
  letter-spacing: .22em;
  font-weight: 700;
}
.sello-stamp.is-landed {
  animation: sello-drop .45s cubic-bezier(.2, .9, .3, 1.1) forwards;
}
@keyframes sello-drop {
  /* El desenfoque solo existe mientras el sello todavia esta cayendo
     rapido (0-55%): es lo que vende la velocidad del golpe. Para el
     instante del impacto ya esta nitido, como una foto que congela el
     momento exacto en que toca el papel. */
  0% { transform: translate(-50%, -50%) rotate(-20deg) scale(2.8); opacity: 0; filter: blur(5px); }
  40% { filter: blur(3px); }
  55% { transform: translate(-50%, -50%) rotate(-11deg) scale(.93); opacity: 1; filter: blur(0); }
  75% { transform: translate(-50%, -50%) rotate(-13deg) scale(1.05); opacity: .92; filter: blur(0); }
  100% { transform: translate(-50%, -50%) rotate(-12deg) scale(1); opacity: .9; filter: blur(0); }
}

/* Destello del impacto: un flash breve de luz justo cuando el sello
   toca el papel, como si el propio golpe encendiera una luz por un
   instante. Es un elemento hermano del sello, no un pseudo-elemento
   suyo: .sello-stamp tiene mix-blend-mode: multiply (solo puede
   oscurecer), asi que un blanco brillante metido ADENTRO de ese grupo
   se multiplicaria contra la pagina y nunca llegaria a "encender" nada
   -- probado, no se veia. Como hermano, compone normal contra la pagina. */
.sello-flash {
  position: absolute;
  top: 42%; left: 50%;
  z-index: 7;
  width: clamp(5.5rem, 20vw, 8.75rem);
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  background: radial-gradient(circle, #fff, rgba(255,255,255,0) 70%);
  transform: translate(-50%, -50%) scale(.5);
  opacity: 0;
  pointer-events: none;
}
#selloStamp.is-landed ~ .sello-flash {
  animation: destello-impacto .3s ease-out .2s forwards;
}
@keyframes destello-impacto {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(.5); }
  30%  { opacity: .95; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.5); }
}
.pasaporte.is-dissolving {
  opacity: 0;
  transform: translateY(10px) scale(.98);
  filter: blur(6px);
  pointer-events: none;
}

/* ---- Acabado holografico del sello ----
   Un laminado de seguridad real cambia de color segun el angulo desde
   el que se lo mira; esto imita eso con un barrido de tono continuo
   enmascarado por la silueta del propio sello, asi que el brillo solo
   aparece sobre la tinta roja y nunca se sale del dibujo.

   .sello-stamp ya usa su propio ::after para el anillo de onda
   (onda-sello, mas abajo en este archivo) -- por eso el holograma va en
   un span propio (.sello-stamp__ink) alrededor de la imagen, en vez de
   pisar ese pseudo-elemento. */
.sello-stamp__ink { position: relative; display: block; }

.sello-stamp__ink::after,
.sello::after {
  content: "";
  position: absolute;
  inset: 0;
  background: conic-gradient(from 0deg,
    #ff5da2, #ffb45e, #f4e26b, #6effc2, #5ec8ff, #b98bff, #ff5da2);
  -webkit-mask-image: url("../assets/brand/sello-aventura-garantizada.png");
  -webkit-mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-image: url("../assets/brand/sello-aventura-garantizada.png");
  mask-size: contain;
  mask-repeat: no-repeat;
  mask-position: center;
  mix-blend-mode: color-dodge;
  opacity: .5;
  pointer-events: none;
  animation: holograma-giro 7s linear infinite;
}
@keyframes holograma-giro {
  to { filter: hue-rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .sello-stamp__ink::after, .sello::after { animation: none; }
}

.dust-canvas {
  position: absolute; inset: 0; z-index: 3;
  pointer-events: none;
}

/* ========================= CONFIRMACIÓN ========================= */

/* Contraportada del pasaporte: solo arena + logo, sin la duna de
   semitono rojo de las demás pantallas -- aquí compite con el sello y
   el titular en un espacio ya cargado. */
.confirmacion {
  position: relative;
  overflow: hidden;
  min-height: 100svh;
  background:
    radial-gradient(circle at 66% 46%, rgba(255,255,255,.6), rgba(255,255,255,0) 55%),
    linear-gradient(rgba(243,234,213,.35), rgba(243,234,213,.35)),
    url("../assets/brand/textura-arena.jpg");
  background-size: auto, auto, cover;
  background-position: center;
  color: var(--tinta);
  text-align: center;
  /* Esta pantalla la va a abrir casi todo el mundo desde el celular, en
     el momento, parado en algún lado -- no es un documento para leer con
     scroll, es la confirmación de "ya quedaste". Tiene que entrar
     completa de una, en el celular más chico razonable, sin que nadie
     tenga que arrastrar el dedo para verla entera. Por eso CADA medida
     de acá para abajo (sello, título, separadores, tarjetas) usa clamp()
     atado a svh: en un teléfono bajo se comprime sola; en uno alto o en
     desktop, respira. */
  padding: clamp(1rem, 4svh, 2.75rem) 1.25rem clamp(.75rem, 3svh, 1.75rem);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0;
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .8s var(--ease) .3s, transform .8s var(--ease) .3s;
}
.confirmacion.is-visible { opacity: 1; transform: translateY(0); }

/* En los pasos 1-3 el contenido vive dentro de la hoja (.pasaporte,
   max-width: 31rem) sobre un fondo de arena a todo lo ancho: por eso
   se leen bien en cualquier tamaño de pantalla. La confirmación no
   tenía ese marco -- el texto quedaba suelto en todo el viewport y en
   pantallas anchas se veía perdido, flotando en un campo de arena
   vacío. Se repite el mismo max-width para que sea, visualmente, la
   pagina siguiente del mismo documento. */
.confirmacion__content {
  width: 100%;
  max-width: 31rem;
}

.confirmacion__logo {
  position: absolute; z-index: -1;
  top: 1.5rem; left: 1.5rem;
  width: clamp(10rem, 34vw, 13rem);
  height: auto;
}

/* Sello de la pantalla de confirmación: es el remate emocional del
   flujo, tiene que verse. El filtro #inkstamp a este tamaño no leía
   como textura de tinta sino que borraba el sello entero, así que se
   quita y se sostiene el efecto solo con el multiply. */
.sello {
  position: relative; z-index: 1;
  display: inline-block;
  transform: rotate(-6deg);
  margin-bottom: clamp(.4rem, 1.8svh, 1rem);
  mix-blend-mode: multiply;
}
.sello img {
  display: block;
  width: clamp(3.5rem, 12vw, 5.5rem);
  height: auto;
}

.confirmacion h2 {
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 5vw, 2.6rem);
  margin: 0 0 .4rem;
}

.confirmacion p { max-width: 30rem; margin: 0 auto .35rem; line-height: 1.5; }

/* La pantalla mezclaba titular, dato practico y cierre todo pegado,
   uno atras del otro sin aire -- con todo el texto en el mismo peso
   de fuente (Black), sin esa separacion se leia como un solo bloque
   apretado. Un divisor fino entre cada grupo (emocion / dato / cierre)
   hace el trabajo que en otro sitio haria el cambio de peso. */
.confirmacion__divisor {
  display: block;
  width: 3rem;
  height: 1.5px;
  margin: clamp(.4rem, 1.6svh, 1rem) auto;
  background: rgba(20,17,13,.18);
}

.confirmacion__accion { margin: 0 auto; }

.confirmacion__datos {
  display: inline-flex; gap: 2.5rem; flex-wrap: wrap; justify-content: center;
  margin: 0;
  padding: .5rem 1.25rem;
  background: var(--hueso);
  border: 1px solid rgba(20,17,13,.15);
}
.confirmacion__datos > div { text-align: left; }
.confirmacion__datos dt {
  font-family: var(--font-mono);
  font-size: clamp(.6rem, 2.6vw, .65rem);
  white-space: nowrap;
  letter-spacing: .12em; text-transform: uppercase; opacity: .55;
  margin-bottom: .25rem;
}
.confirmacion__datos dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: clamp(.95rem, 5vw, 1.1rem);
  white-space: nowrap;
  font-weight: 700;
  color: var(--rojo-dark);
  letter-spacing: .04em;
}

.boton-calendario {
  display: block;
  width: fit-content;
  font-family: var(--font-display);
  letter-spacing: .04em;
  font-size: .92rem;
  background: transparent;
  color: var(--tinta);
  border: 1.5px solid rgba(20,17,13,.3);
  padding: .5rem 1.2rem;
  margin: .5rem auto 0;
  cursor: pointer;
  transition: background .2s var(--ease), transform .15s var(--ease);
}

/* "Consulta con tu asesor..." tiene que ser siempre una sola línea. La
   regla general de texto corrido (más abajo, ".confirmacion p") le pone
   max-width: 34ch y le gana en especificidad a una clase sola por venir
   después en el archivo -- por eso el selector repite ".confirmacion p"
   acá, para ganarle de verdad. nowrap + clamp() achica la letra en vez
   de dejar que se parta a media palabra. */
.confirmacion p.confirmacion__embarque {
  max-width: none;
  white-space: nowrap;
  font-size: clamp(.62rem, 4.2vw, .9375rem);
  letter-spacing: .01em;
}

/* El aviso de notificaciones es el dato accionable de toda la pantalla
   -- si se pierde entre el resto del texto corrido, nadie activa las
   notificaciones y las pistas de ruta caen en spam o pasan sin verse.
   Se arma como la misma tarjeta-notificación push que usa .notif en el
   countdown (icono en chip rojo + entrada animada): mismo lenguaje de
   marca en las dos pantallas, y de paso se lee como una alerta real, no
   como una nota al pie más. Es un <div>, no un <p>, así no compite con
   la regla general ".confirmacion p" de más abajo. Reemplaza al divisor
   que separaba este bloque del anterior: su propio fondo + sombra ya
   marcan el corte, un divisor encima era espacio de sobra que esta
   pantalla, pensada ante todo para el celular, no tiene para regalar. */
.confirmacion__aviso {
  display: flex;
  align-items: center;
  gap: .55rem;
  max-width: 26rem;
  margin: clamp(.5rem, 1.8svh, 1rem) auto 0;
  text-align: left;
  background: var(--hueso);
  border-radius: .7rem;
  border-left: 3px solid var(--rojo);
  box-shadow: 0 8px 20px rgba(20,17,13,.1);
  padding: .5rem .75rem;
  animation: notif-in .5s var(--ease) .1s both;
}
.confirmacion__aviso-icon {
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  width: 1.6rem; height: 1.6rem;
  border-radius: .45rem;
  background: var(--rojo);
  color: #fff;
  animation: aviso-pulse 2.4s ease-in-out 1s infinite;
}
.confirmacion__aviso-icon svg { width: 14px; height: 14px; }
@keyframes aviso-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.1) rotate(-8deg); }
}
@media (prefers-reduced-motion: reduce) {
  .confirmacion__aviso-icon { animation: none; }
}
.confirmacion__aviso-texto {
  font-size: .74rem;
  line-height: 1.35;
}
.confirmacion__aviso strong { color: var(--rojo-dark); }

.confirmacion p.confirmacion__despedida {
  font-size: .78rem;
  opacity: .85;
  margin-top: .4rem;
}

/* En una pantalla de PC sobra ancho: la columna angosta de 31rem (pensada
   para que el texto no se sintiera perdido en un mar de arena vacío en
   mobile/tablet) en un monitor grande se ve amontonada, todo pegado en
   el centro con espacio de sobra a los costados sin usar. Desde 64rem
   (~1024px) se le da más aire: columna más ancha y más separación entre
   bloques, sin tocar nada por debajo de ese punto. */
@media (min-width: 64rem) {
  .confirmacion__content { max-width: 42rem; }
  .confirmacion { padding: clamp(2.5rem, 8svh, 4rem) 2rem clamp(1.5rem, 5svh, 2.5rem); }
  .confirmacion__divisor { margin: clamp(1.2rem, 3.5svh, 2.2rem) auto; }
  .confirmacion__aviso { max-width: 34rem; padding: .9rem 1.3rem; }
  .confirmacion__aviso-texto { font-size: .95rem; }
  .confirmacion__datos { padding: 1rem 2rem; gap: 3rem; }
}
.boton-calendario:hover { background: rgba(20,17,13,.05); transform: translateY(-1px); }
.boton-calendario:active { transform: scale(.97); }
.boton-calendario:focus-visible { outline: 3px solid var(--tinta); outline-offset: 3px; }

.confirmacion__sellos {
  display: inline-flex; flex-direction: column; gap: .5rem;
  list-style: none;
  margin: 1rem auto 0;
  padding: 1rem 1.75rem;
  background: var(--hueso);
  border: 1px solid rgba(20,17,13,.15);
  text-align: left;
  font-family: var(--font-mono);
  font-size: .85rem;
}
.confirmacion__sellos strong { color: var(--rojo-dark); }

/* ========================= AVISO DE CUENTA REGRESIVA (notificación flotante) ========================= */

/* Ya no es una pantalla mas del documento: es una notificacion que
   "llega" flotando encima de lo que sea que la persona este mirando en
   ese momento, igual que una notificacion real de telefono -- no hay
   scroll que la revele, aparece sola. pointer-events va en none en el
   contenedor y en auto en la tarjeta: el area vacia alrededor de la
   tarjeta no debe bloquear clics en lo que hay debajo. */
.countdown {
  position: fixed;
  left: 0; right: 0;
  bottom: max(1.25rem, env(safe-area-inset-bottom));
  z-index: 70;
  display: flex; justify-content: center;
  padding: 0 1.25rem;
  pointer-events: none;
}

/* Tarjeta estilo notificación push, como si el teléfono avisara los días
   que faltan para el evento en vez de mostrar un contador de dígitos. */
.notif {
  display: flex; align-items: flex-start; gap: .9rem;
  width: min(26rem, 100%);
  background: var(--hueso);
  color: var(--tinta);
  border-radius: 1.1rem;
  padding: 1.1rem 1.25rem;
  box-shadow: 0 18px 40px rgba(0,0,0,.35);
  animation: notif-in .5s var(--ease) both;
  pointer-events: auto;
}
@keyframes notif-in {
  from { opacity: 0; transform: translateY(14px) scale(.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

.notif__icon {
  flex-shrink: 0;
  width: 2.5rem; height: 2.5rem;
  display: flex; align-items: center; justify-content: center;
  background: var(--rojo);
  color: #fff;
  border-radius: .6rem;
}

.notif__body { flex: 1; min-width: 0; }
.notif__app {
  display: flex; justify-content: space-between; align-items: baseline; gap: .5rem;
  font-family: var(--font-mono);
  font-size: .68rem; letter-spacing: .1em; text-transform: uppercase;
  opacity: .55; margin: 0 0 .3rem;
}
.notif__now { opacity: .7; text-transform: none; letter-spacing: 0; }
.notif__msg {
  margin: 0 0 .2rem;
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 4vw, 1.3rem);
  line-height: 1.25;
}
.notif__msg strong { color: var(--rojo-dark); font-size: 1.3em; }
.notif__sub {
  margin: 0;
  font-family: var(--font-mono);
  font-size: .78rem;
  opacity: .55;
  font-variant-numeric: tabular-nums;
}

/* ========================= PISTAS ========================= */

.pistas {
  min-height: 100svh;
  background: var(--arena-100);
  color: var(--tinta);
  padding: 4rem 1.5rem 5rem;
  display: flex; flex-direction: column; justify-content: center;
}

.pistas__intro { max-width: 34rem; margin: 0 auto 2.5rem; text-align: center; opacity: .75; font-size: .9rem; }

.pistas__lista {
  list-style: none; margin: 0 auto; padding: 0;
  max-width: 34rem;
  display: flex; flex-direction: column; gap: 1rem;
}

.pista {
  border: 1px solid rgba(20,17,13,.2);
  padding: 1.1rem 1.25rem;
  display: flex; gap: 1rem; align-items: flex-start;
  background: var(--hueso);
}

.pista__num {
  font-family: var(--font-display);
  color: var(--rojo);
  font-size: 1.3rem;
  flex-shrink: 0;
}

.pista.is-locked {
  background: repeating-linear-gradient(135deg, rgba(20,17,13,.06) 0 8px, transparent 8px 16px);
  color: rgba(20,17,13,.55);
}
.pista.is-locked .pista__num { color: rgba(20,17,13,.35); }

.pista.is-unlocked {
  animation: reveal-pista .7s var(--ease);
}
@keyframes reveal-pista {
  from { opacity: 0; transform: translateX(-8px); }
  to { opacity: 1; transform: translateX(0); }
}

/* ========================= FOOTER ========================= */

.footer {
  background: var(--tinta);
  color: rgba(243,238,226,.4);
  text-align: center;
  font-size: .7rem;
  letter-spacing: .15em;
  padding: 1.5rem;
}

/* =========================================================
   CAPA DE MOVIMIENTO
   Coreografía de entrada de la tapa, profundidad de las
   montañas y micro-interacciones. Todo se activa solo si
   motion.js puso la clase `js-motion` en el <html>: sin JS,
   nada queda oculto esperando una animación que no llega.
   ========================================================= */

/* ---- Entrada escenificada de la tapa ----
   El orden cuenta una historia: primero el terreno (montañas),
   después quién invita (logo), después a qué (título), y al
   final qué hacer (CTA). No todo a la vez. */

.js-motion .cover-dunes,
.js-motion .cover-brand,
.js-motion .cover-pasaporte,
.js-motion .cover-title .ltr,
.js-motion .cover-cta,
.js-motion .cover-label {
  opacity: 0;
}

.js-motion.has-entered .cover-dunes {
  animation: subir-terreno 1.1s var(--ease-salida) forwards;
}
@keyframes subir-terreno {
  from { opacity: 0; transform: translateY(26%) scale(1.04); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.js-motion.has-entered .cover-brand {
  animation: bajar-logo .8s var(--ease-salida) .25s forwards;
}
@keyframes bajar-logo {
  from { opacity: 0; transform: translateY(-14px); }
  to   { opacity: 1; transform: translateY(0); }
}

.js-motion.has-entered .cover-pasaporte {
  animation: bajar-logo .8s var(--ease-salida) .38s forwards;
}

/* "A TODO": las letras se abren en abanico, una tras otra. */
.js-motion.has-entered .cover-atodo .ltr {
  animation: abrir-letra .5s var(--ease-salida) forwards;
  animation-delay: calc(.5s + var(--i, 0) * .045s);
}
@keyframes abrir-letra {
  from { opacity: 0; transform: translateY(-10px) rotate(-8deg); }
  to   { opacity: 1; transform: translateY(0) rotate(0); }
}

/* "TERRENO": cae con peso y rebota una vez, como un sello de
   goma golpeando el papel. Arranca cuando "A TODO" ya terminó. */
.js-motion.has-entered .cover-terreno .ltr {
  animation: caer-letra .62s var(--ease-peso) forwards;
  animation-delay: calc(.82s + var(--i, 0) * .05s);
}
@keyframes caer-letra {
  0%   { opacity: 0; transform: translateY(-38px) scaleY(1.25); }
  70%  { opacity: 1; transform: translateY(3px) scaleY(.94); }
  100% { opacity: 1; transform: translateY(0) scaleY(1); }
}

.cover-title .ltr { display: inline-block; will-change: transform; }
.cover-title .ltr--espacio { width: .28em; }

.js-motion.has-entered .cover-cta {
  animation: entrar-cta .6s var(--ease-resorte) 1.35s forwards;
}
@keyframes entrar-cta {
  from { opacity: 0; transform: translateY(16px) scale(.94); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.js-motion.has-entered .cover-label {
  animation: sellar-etiqueta .55s var(--ease-resorte) 1.55s forwards;
}
@keyframes sellar-etiqueta {
  from { opacity: 0; transform: rotate(-14deg) scale(1.3); }
  to   { opacity: 1; transform: rotate(-1deg) scale(1); }
}

/* ---- Vida de las montañas: dos técnicas, nunca a la vez ----
   Una animación CSS sobre `transform` gana siempre sobre el estilo
   inline que escribe el parallax, así que las dos no pueden convivir
   en la misma capa (pausarla tampoco libera la propiedad: la mantiene
   congelada en el valor animado). Se reparten por tipo de puntero, que
   además es lo que cada dispositivo puede aprovechar: en escritorio el
   parallax responde al mouse; en táctil, donde no hay puntero que
   seguir, las capas respiran solas. */
@media (hover: none), (pointer: coarse) {
  .js-motion .cover-dunes__front { animation: respirar 13s ease-in-out 2.4s infinite; }
  .js-motion .cover-dunes__back  { animation: respirar-lento 17s ease-in-out 2.4s infinite; }
}
/* Llevan el mismo scale(1.12) que la regla base: una animación sobre
   transform reemplaza el valor entero, así que omitir la escala aquí
   haría que las capas encogieran al arrancar la respiración. */
@keyframes respirar {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1.12); }
  50%      { transform: translate3d(-1.1%, -.7%, 0) scale(1.12); }
}
@keyframes respirar-lento {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1.12); }
  50%      { transform: translate3d(1.4%, -.5%, 0) scale(1.12); }
}

/* ---- Botones: barrido de luz + onda de tinta ---- */

.cover-cta, .btn-paso, .btn-sellar, .welcome__cta {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

/* Un destello diagonal cruza el botón al pasar el mouse. */
.cover-cta::before, .btn-sellar::before, .welcome__cta::before {
  content: "";
  position: absolute; top: 0; bottom: 0; left: -60%;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.28), transparent);
  transform: skewX(-18deg);
  pointer-events: none;
  transition: left .55s var(--ease-suave);
}
.cover-cta:hover::before, .btn-sellar:hover::before, .welcome__cta:hover::before {
  left: 125%;
}

.onda {
  position: absolute;
  border-radius: 50%;
  background: rgba(255,255,255,.32);
  transform: scale(0);
  pointer-events: none;
  animation: onda-expandir .55s var(--ease-salida) forwards;
}
@keyframes onda-expandir {
  to { transform: scale(1); opacity: 0; }
}

/* ---- Realce del logo al pasar por la tapa ---- */
.cover-brand { transition: transform .5s var(--ease-resorte); }
.paso--cover:hover .cover-brand { transform: scale(1.04); }

/* ---- Sello: impacto con onda expansiva ----
   Al aterrizar, el sello empuja un anillo de tinta hacia afuera.
   Es el remate del flujo, merece un golpe real. */
.sello-stamp::after {
  content: "";
  position: absolute; inset: -8%;
  border: 3px solid var(--rojo);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
}
.sello-stamp.is-landed::after {
  animation: onda-sello .7s var(--ease-salida) .3s forwards;
}
@keyframes onda-sello {
  0%   { opacity: .55; transform: scale(.75); }
  100% { opacity: 0;   transform: scale(1.75); }
}

/* ---- Nada de lo anterior corre si se pidió menos movimiento ----
   La regla global ya colapsa las duraciones, pero estos elementos
   arrancan en opacity:0, así que hay que devolverlos a la vista
   explícitamente o quedarían invisibles. */
@media (prefers-reduced-motion: reduce) {
  .js-motion .cover-dunes,
  .js-motion .cover-brand,
  .js-motion .cover-pasaporte,
  .js-motion .cover-title .ltr,
  .js-motion .cover-cta,
  .js-motion .cover-label {
    opacity: 1;
    animation: none;
    transform: none;
  }
  .js-motion .cover-dunes__front,
  .js-motion .cover-dunes__back { animation: none !important; }
  .cover-cta::before, .btn-sellar::before, .welcome__cta::before { display: none; }
}

/* =========================================================
   MATERIALIDAD: que se sienta un documento, no una tarjeta
   ========================================================= */

/* ---- Canto de las páginas ----
   Un pasaporte es un cuadernillo: se le ven los cantos de las hojas
   por debajo de la tapa. Dos capas apenas rotadas y desplazadas
   bastan para leerlo como volumen en vez de una sola lámina. */
.pasaporte__pageframe::before,
.pasaporte__pageframe::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 6px;
  background: linear-gradient(160deg, #efe7d6, #d9cdb4);
  pointer-events: none;
}
.pasaporte__pageframe::before {
  transform: translate(4px, 5px) rotate(.5deg);
  box-shadow: 0 6px 16px rgba(20,17,13,.16);
}
.pasaporte__pageframe::after {
  transform: translate(8px, 10px) rotate(1.1deg);
  background: linear-gradient(160deg, #e7dcc6, #cbbb9c);
  box-shadow: 0 10px 24px rgba(20,17,13,.18);
}

/* ---- Tipografía grabada en el papel ----
   La tapa de un pasaporte lleva el título estampado en seco, hundido
   en el material. Una luz arriba y una sombra abajo (invertidas
   respecto a una sombra normal) leen como relieve, no como texto
   flotando sobre un fondo. */
.cover-terreno {
  text-shadow:
    0 1px 0 rgba(255,255,255,.34),
    0 -1px 1px rgba(20,17,13,.34);
}
.cover-atodo {
  text-shadow:
    0 1px 0 rgba(255,255,255,.3),
    0 -1px 1px rgba(120,25,25,.3);
}
/* Reemplaza la sombra de caída genérica que traía el contenedor. */
.cover-title { text-shadow: none; }

/* ---- Fibra del papel ----
   Grano fino y direccional sobre la tapa kraft: es lo que separa un
   fondo de color de una superficie con material. */
.paso--cover::after {
  content: "";
  position: absolute; inset: 0; z-index: 1;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(93deg, rgba(120,90,50,.05) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(3deg,  rgba(255,255,255,.05) 0 1px, transparent 1px 4px);
  mix-blend-mode: overlay;
}

/* ---- Luz cálida en la tapa ----
   Una fuente de luz alta a la izquierda, coherente con la dirección
   del grabado de arriba, y un oscurecimiento en los bordes: el papel
   deja de verse plano. */
.paso--cover::before {
  content: "";
  position: absolute; inset: 0; z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(120% 80% at 22% 8%, rgba(255,246,224,.3), transparent 55%),
    radial-gradient(130% 100% at 50% 100%, transparent 60%, rgba(60,40,20,.22));
}

/* ---- Esquina que invita a tocar ----
   Si nadie interactua, la esquina inferior derecha se despega un
   instante y vuelve a su lugar: el gesto universal de "esto se puede
   tocar", sin decir una palabra. .paso--cover tiene overflow:hidden,
   asi que en vez de sacarla de la caja se simula el despegue con
   escala + sombra, anclado en la propia esquina. */
.cover-esquina {
  position: absolute;
  right: 0; bottom: 0; z-index: 3;
  width: 2.6rem; height: 2.6rem;
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
  background: linear-gradient(135deg, rgba(224,205,172,.95), rgba(120,90,50,.65));
  transform-origin: bottom right;
  pointer-events: none;
}
.cover-esquina.is-inviting {
  animation: despegar-esquina 1.8s var(--ease-salida);
}
@keyframes despegar-esquina {
  0%, 100% {
    transform: scale(1) rotate(0deg);
    filter: drop-shadow(0 0 0 rgba(0,0,0,0));
  }
  35% {
    transform: scale(1.2) rotate(-7deg) translate(-4px, -4px);
    filter: drop-shadow(-3px -3px 5px rgba(0,0,0,.35));
  }
  62% {
    transform: scale(1.06) rotate(-2deg) translate(-1px, -1px);
    filter: drop-shadow(-2px -2px 3px rgba(0,0,0,.22));
  }
}
@media (prefers-reduced-motion: reduce) {
  .cover-esquina { display: none; }
}

/* ---- Control de sonido ambiente ----
   Tres barras que quedan quietas y bajas cuando está apagado, y suben
   ondulando cuando suena: el estado se lee sin texto y sin iconos de
   altavoz genéricos. */
.ambiente {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 70;
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  gap: 3px;
  background: rgba(20,17,13,.55);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(243,238,226,.22);
  border-radius: 50%;
  cursor: pointer;
  transition: background .25s var(--ease-suave), border-color .25s var(--ease-suave), transform .25s var(--ease-resorte);
}
.ambiente:hover { background: rgba(20,17,13,.78); transform: scale(1.06); }
.ambiente:focus-visible { outline: 3px solid var(--hueso); outline-offset: 3px; }
.ambiente.is-on { border-color: var(--rojo-sobre-oscuro); }

.ambiente__ondas { display: flex; align-items: center; gap: 3px; height: 16px; }
.ambiente__ondas span {
  display: block; width: 3px; height: 4px;
  border-radius: 2px;
  background: var(--arena-300);
  transition: background .25s var(--ease-suave);
}
.ambiente.is-on .ambiente__ondas span {
  background: var(--rojo-sobre-oscuro);
  animation: ondear 1.5s ease-in-out infinite;
}
.ambiente.is-on .ambiente__ondas span:nth-child(2) { animation-delay: .22s; }
.ambiente.is-on .ambiente__ondas span:nth-child(3) { animation-delay: .44s; }
@keyframes ondear {
  0%, 100% { height: 4px; }
  50%      { height: 15px; }
}

@media (prefers-reduced-motion: reduce) {
  /* Sin animación las barras se quedan altas: el estado "encendido"
     tiene que seguir siendo visible. */
  .ambiente.is-on .ambiente__ondas span { animation: none; height: 12px; }
}

/* =========================================================
   JERARQUÍA TIPOGRÁFICA
   Aplica la escala y el tracking definidos arriba. Va al
   final para prevalecer sobre los valores sueltos previos
   sin tener que reescribir cada regla histórica.
   ========================================================= */

/* ---- Titulares ----
   Cierre del tracking y del interlineado: a estos cuerpos el espacio
   sobra, no falta. */
.welcome__title,
.hero__title,
.cover-terreno,
.confirmacion h2 {
  letter-spacing: var(--track-titulo);
  line-height: var(--lh-titulo);
}

/* "A TODO" es la excepción deliberada: el tracking abierto no es un
   descuido sino el recurso que lo separa del bloque macizo de TERRENO
   y arma el contraste de la tapa. */
.cover-atodo { line-height: 1; }

/* ---- Overline / versalitas ----
   Texto chico en mayúsculas: necesita aire o se empasta. */
.overline,
.cover-label,
.pasaporte__progress-label,
.topbar__event,
.topbar__brand {
  font-size: var(--t-etiqueta);
  letter-spacing: var(--track-etiqueta);
  line-height: var(--lh-medio);
}

/* La overline del cuerpo del pasaporte es un rótulo de sección, no un
   titular: se le baja el cuerpo y se le sube el tracking para que no
   compita con el dato que anuncia. */
.pasaporte__body .overline {
  font-size: var(--t-apoyo);
  letter-spacing: .06em;
}

/* ---- Texto corrido ----
   La única fuente de texto disponible es un peso Black. A 900, el
   interlineado normal produce un muro: se abre a 1.65 y se recorta el
   contraste con una opacidad leve, que es lo que devuelve la sensación
   de "texto" frente a "titular pequeño". */
.manifiesto__intro,
.confirmacion p,
.hero__hint {
  font-size: var(--t-cuerpo);
  line-height: var(--lh-cuerpo);
  letter-spacing: var(--track-cuerpo);
  max-width: 34ch;              /* medida de lectura: más ancho cansa */
  margin-inline: auto;
}

/* ---- Rótulos de campo ----
   Son metadato: el dato que escribe la persona manda. */
label {
  font-size: var(--t-etiqueta);
  letter-spacing: var(--track-etiqueta);
}

/* ---- Letra chica ---- */
.pasaporte__fineprint,
.pasaporte__mrz {
  font-size: var(--t-micro);
  letter-spacing: var(--track-micro);
}
.pasaporte__mrz { letter-spacing: .02em; } /* el MRZ imita ancho fijo */

/* ---- Botones ----
   Un botón es una orden: cuerpo estable y tracking corto. Antes iban de
   1rem a 1.15rem sin criterio. */
.cover-cta,
.welcome__cta,
.btn-sellar,
.btn-paso {
  font-size: var(--t-destacado);
  letter-spacing: .04em;
  line-height: 1.1;
}

/* ---- Números del pasaporte ----
   El serial y las fechas son datos de documento: tabulares y con aire,
   como en un pasaporte real. */
.pasaporte__serial,
.confirmacion__datos dd,
.field__readonly {
  font-variant-numeric: tabular-nums;
  letter-spacing: .06em;
}

/* ---- Titular de confirmación en dos alturas ----
   Antes era una sola línea larga ("¡Estás listo para la aventura a todo
   terreno! 🤘") que a este cuerpo se partía en dos renglones apretados y
   dejaba el emoji solo en el segundo, huérfano. Partirlo en grito +
   bajada da la jerarquía que la línea única no tenía: primero la
   emoción, después el dato. */
.confirmacion h2 {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .25rem;
  margin: 0 0 .4rem;
}
/* Antes clamp(2.6rem, 12vw, 4rem): el grito real de la pantalla no
   necesita ser el elemento más grande del documento -- solo el más
   protagonista. Esta pantalla la abre casi todo el mundo desde el
   celular: tiene que entrar completa, sin scroll, en el teléfono más
   chico razonable -- por eso el mínimo del clamp es tan bajo. En
   desktop/tablet (más vw, más aire) sigue leyendo como titular. */
.confirmacion__grito {
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 6.2vw, 2.35rem);
  line-height: .98;
  letter-spacing: var(--track-titulo);
  color: var(--tinta);
}
.confirmacion__bajada {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .05rem;
  font-family: var(--font-mono);
  letter-spacing: var(--track-etiqueta);
  text-transform: uppercase;
  line-height: 1.3;
  color: var(--rojo-dark);
}
/* "¿El destino?" y "Secreto hasta tu llegada." tienen que ser cada una
   una sola línea, sin importar el ancho de pantalla -- por eso
   white-space: nowrap en vez de max-width. clamp() achica la letra en
   pantallas angostas en vez de dejar que el texto se desborde o se
   parta en una tercera línea. */
.confirmacion__bajada-linea {
  white-space: nowrap;
  font-size: clamp(.56rem, 4vw, .75rem);
}

/* ---- Campo validado ----
   Una marca discreta cuando el dato está bien. No es decoración: en un
   formulario de cuatro campos donde el error antes aparecía dos pasos
   después, confirmar en el momento es lo que da confianza para seguir. */
.field { position: relative; }
.field__error {
  display: block;
  font-size: var(--t-micro);
  letter-spacing: .04em;
  line-height: 1.35;
  color: var(--rojo-dark);
  min-height: 1.1em;      /* reserva el alto: sin esto el formulario salta
                             cada vez que aparece o desaparece un error */
  margin-top: .2rem;
}
input.is-ok {
  border-bottom-color: rgba(30,110,60,.5);
}
input.is-ok + .field__error::after {
  content: "✓";
  color: rgba(30,110,60,.85);
  font-size: .8rem;
  position: absolute;
  right: .1rem;
  bottom: 1.35em;
}

/* =========================================================
   WORDMARK OFICIAL
   "A TODO TERRENO" deja de componerse con la fuente y pasa
   a ser el lockup real de marca. Una fuente aproxima; el
   wordmark tiene el peso, el kerning y el desgaste exactos
   del original, e iguales en todos los navegadores.
   ========================================================= */

.cover-wordmark {
  display: block;
  width: min(94%, 22rem);
  height: auto;
  margin: 0 auto;
  /* Grabado en seco sobre el papel kraft: el relieve va al contorno de
     la imagen, no a una caja rectangular. */
  filter:
    drop-shadow(0 1px 0 rgba(255,255,255,.32))
    drop-shadow(0 -1px 1px rgba(20,17,13,.28));
}

.welcome__title {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .35rem;
  margin: 0 0 1.6rem;
}
.welcome__bienvenido {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 6vw, 2.4rem);
  letter-spacing: .16em;
  text-indent: .16em;
  line-height: 1;
  color: var(--rojo);
}
.welcome__wordmark {
  display: block;
  width: min(88%, 24rem);
  height: auto;
  filter: drop-shadow(0 2px 10px rgba(20,17,13,.2));
}

/* Las reglas de texto del título de tapa quedan sin uso al pasar a
   imagen; se anulan aquí para que no dejen restos de estilo. */
.cover-title { display: block; text-shadow: none; }

/* =========================================================
   PASO 3 · HOJA DE VISADO
   Era un resumen de dos datos sobre fondo liso: no se
   parecía a un pasaporte, se parecía a la pantalla de
   confirmación de un formulario. Ahora es la hoja de visado
   del documento, con sus dos bloques (titular y viaje),
   guilloché propio y el sello cayendo encima.
   ========================================================= */

.paso--visado {
  justify-content: flex-start;
  gap: .9rem;
  /* Retícula de seguridad más marcada que la del resto del cuadernillo:
     en un pasaporte real las hojas de visado llevan su propio fondo. */
  background-image:
    repeating-linear-gradient(32deg, rgba(150,110,60,.06) 0 1px, transparent 1px 6px),
    repeating-linear-gradient(-32deg, rgba(150,110,60,.05) 0 1px, transparent 1px 6px);
}

.visado__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: .75rem;
  border-bottom: 1.5px solid rgba(120,90,50,.3);
  padding-bottom: .45rem;
  margin-bottom: .3rem;
}
.visado__head .overline { margin: 0; }
.visado__tipo {
  font-family: var(--font-mono);
  font-size: var(--t-micro);
  letter-spacing: var(--track-micro);
  color: rgba(20,17,13,.55);
  white-space: nowrap;
}

.visado__datos {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .55rem .9rem;
  margin: 0;
}
.visado__dato--ancho { grid-column: 1 / -1; }

.visado__dato dt {
  font-family: var(--font-mono);
  font-size: var(--t-micro);
  letter-spacing: var(--track-etiqueta);
  text-transform: uppercase;
  color: rgba(20,17,13,.55);
  margin-bottom: .1rem;
}
.visado__dato dt em {
  font-style: normal;
  text-transform: none;
  letter-spacing: .02em;
  opacity: .7;
}
.visado__dato dd {
  margin: 0;
  font-size: var(--t-apoyo);
  line-height: 1.25;
  color: var(--tinta);
  /* El dato se apoya en una línea, como un campo rellenado a máquina
     sobre un formulario impreso. */
  border-bottom: 1px dotted rgba(20,17,13,.35);
  padding-bottom: .15rem;
  overflow-wrap: anywhere;
}
.visado__mono { font-variant-numeric: tabular-nums; letter-spacing: .06em; }

/* El destino es sorpresa: se muestra tachado como un dato censurado,
   que es la manera de decirlo sin dejar el campo vacío. */
.visado__clasificado {
  color: var(--rojo-dark);
  letter-spacing: .16em;
  position: relative;
}

.visado__datos--viaje {
  border-top: 1.5px solid rgba(120,90,50,.3);
  padding-top: .7rem;
  margin-top: .2rem;
}

.visado__nota {
  font-size: var(--t-micro);
  line-height: 1.45;
  letter-spacing: .04em;
  color: rgba(20,17,13,.5);
  margin: .1rem 0 0;
  max-width: none;
}

/* En pantallas muy angostas los dos bloques a dos columnas aprietan
   demasiado los correos largos. */
@media (max-width: 22rem) {
  .visado__datos { grid-template-columns: 1fr; }
}

/* ---- Bienvenida: una sola entrada, siempre con sonido ----
   El navegador solo permite reproducir audio dentro de un gesto del
   usuario: este clic hace de permiso. Ya no se ofrece la eleccion
   sonido/silencio -- un solo boton, sin pregunta. */
.welcome__acciones {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .7rem;
}

