/* ============================================================
   BAJAJ RIDER DISTRICT — sistema visual
   Base: premium-ui-system (tokens, motion, a11y).

   La paleta NO se invento: se muestreo pixel a pixel del arte del cliente.
     neon    #0167FD  <- bordes con glow, "DISTRICT", iconos de campo
     profundo#0023A2  <- salpicaduras del fondo, relleno de botones
     negro   #00030A  <- base de las pantallas (negro con tinte azul, no gris)
     blanco  #FEFEFE  <- titulares y texto

   El lenguaje de formas del arte es CHAFLAN + BORDE NEON: cada caja tiene las cuatro
   esquinas cortadas en diagonal y un contorno azul que brilla hacia afuera. Aqui se
   reproduce con clip-path (la forma) + drop-shadow (el brillo). No con border-radius:
   una pildora redondeada seria de otra marca.

   Contrastes verificados (WCAG 2.2) sobre el negro base #00030A:
     blanco #FEFEFE ......... 19.9:1
     texto  #E8EDF7 ......... 16.8:1
     apoyo  #93A9CE .......... 7.6:1
     neon   #0167FD .......... 3.4:1  -> SOLO para bordes, iconos y texto grande (>=24px),
                                         nunca para texto corrido. Los textos azules del
                                         arte usan #5B9BFF (6.1:1).
   ============================================================ */

@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 800;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url("/fonts/archivo-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
    U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 800;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url("/fonts/archivo-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
    U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
    U+2C60-2C7F, U+A720-A7FF;
}

:root {
  color-scheme: dark;

  /* ---------- TIER 1: primitivos (muestreados del arte) ---------- */
  --neon: #0167fd;
  --profundo: #0023a2;
  --negro: #00030a;
  --blanco: #fefefe;

  --azul-texto: #5b9bff; /* el azul del arte, subido de luminancia hasta ser legible */
  --azul-tenue: #93a9ce;
  --superficie: #04070f;
  --superficie-alta: #060b16;
  --rojo: #ff5a67;
  --verde: #2fd07a;

  /* Espaciado — base 4px, ritmo 8px */
  --space-1: 4px;   --space-2: 8px;   --space-3: 12px;  --space-4: 16px;
  --space-5: 24px;  --space-6: 32px;  --space-7: 48px;  --space-8: 64px;

  /* Tipografia fluida (360 -> 480, que es el rango real de un celular) */
  --text--1: clamp(0.8125rem, 0.77rem + 0.19vw, 0.875rem);
  --text-0:  clamp(0.9375rem, 0.87rem + 0.31vw, 1.0625rem);
  --text-1:  clamp(1.0625rem, 0.96rem + 0.47vw, 1.25rem);
  --text-2:  clamp(1.25rem, 1.08rem + 0.78vw, 1.5625rem);
  --text-3:  clamp(1.75rem, 1.4rem + 1.56vw, 2.375rem);
  --text-4:  clamp(2.5rem, 1.9rem + 2.7vw, 3.5rem);

  --font-body: "Archivo", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Mono", "Segoe UI Mono", Menlo, monospace;

  /* Chaflan: el corte de esquina del arte. Un solo sistema, dos tamaños. */
  --corte: 11px;
  --corte-grande: 17px;

  /* Motion — valores de casa, no se inventan otros */
  --dur-instant: 120ms;
  --dur-toggle: 240ms;
  --dur-modal: 400ms;
  --dur-page: 500ms;
  --ease-out: cubic-bezier(0.33, 1, 0.68, 1);
  --ease-out-strong: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in: cubic-bezier(0.32, 0, 0.67, 0);
  --ease-in-out: cubic-bezier(0.45, 0, 0.55, 1);

  /* ---------- TIER 2: semanticos ---------- */
  --texto: #e8edf7;
  --texto-fuerte: var(--blanco);
  --texto-apoyo: var(--azul-tenue);
  --borde: color-mix(in srgb, var(--neon) 55%, transparent);

  /* El brillo del neon. Dos capas: una cerrada que define el filo y otra abierta que
     tiñe el aire alrededor, igual que en el arte. */
  --glow: drop-shadow(0 0 3px color-mix(in srgb, var(--neon) 70%, transparent))
          drop-shadow(0 0 14px color-mix(in srgb, var(--neon) 45%, transparent));
  --glow-fuerte: drop-shadow(0 0 4px color-mix(in srgb, var(--neon) 85%, transparent))
                 drop-shadow(0 0 20px color-mix(in srgb, var(--neon) 60%, transparent));
}

/* ---------------------------------------------------------------- reset */

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

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

body {
  min-height: 100svh;
  background: var(--negro);
  color: var(--texto);
  font-family: var(--font-body);
  font-size: var(--text-0);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  /* La experiencia es una pila de pantallas, no un documento: no debe hacer scroll de
     rebote ni tirar hacia abajo para refrescar en mitad de un formulario. */
  overscroll-behavior: none;
}

img, video, canvas { display: block; max-width: 100%; }
button, input, select { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }
:focus-visible { outline: 2px solid var(--neon); outline-offset: 3px; border-radius: 2px; }

.oculto-visual {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
/* Fuera del flujo y fuera del foco, pero enviable: es la trampa de bots y el input file. */
.trampa { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; pointer-events: none; }

.noscript {
  position: fixed; inset: auto 0 0; padding: var(--space-4);
  background: var(--profundo); color: var(--blanco); text-align: center; font-size: var(--text--1);
}

/* ---------------------------------------------------------------- marco 9:16 */

.marco {
  /* El arte es 1080x1920 exacto. En un monitor o una tablet no se estira: se encierra a
     su proporcion y el resto queda negro, como una vertical de verdad. */
  width: min(100vw, calc(100svh * 9 / 16));
  height: 100svh;
  margin-inline: auto;
  position: relative;
  overflow: hidden;
  background: var(--negro);
}

.escenario { position: absolute; inset: 0; }

/* ---------------------------------------------------------------- pantallas */

.pantalla {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  padding: max(var(--space-5), env(safe-area-inset-top)) var(--space-5)
           max(var(--space-5), env(safe-area-inset-bottom));
  /* Cada pantalla es su propio ambito de scroll. El titular no se va: solo el contenido. */
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;

  /* Fondo de marca: la textura del cliente bajo un velo que la vuelve legible. Sin el
     velo, el azul saturado del arte deja los textos ilegibles; con el, se lee como los
     mockups del cliente, donde la salpicadura solo asoma en los bordes. */
  background-color: var(--negro);
  background-image:
    radial-gradient(120% 70% at 50% 0%, rgba(0, 3, 10, 0.55) 0%, rgba(0, 3, 10, 0.86) 55%, var(--negro) 100%),
    url("/brand/fondo-1080.webp");
  background-size: auto, cover;
  background-position: center, center top;
  background-repeat: no-repeat;

  opacity: 0;
  transform: translate3d(22px, 0, 0);
  pointer-events: none;
  transition: opacity var(--dur-toggle) var(--ease-out),
              transform var(--dur-page) var(--ease-out-strong);
}
.pantalla[hidden] { display: none; }
.pantalla.is-activa { opacity: 1; transform: none; pointer-events: auto; }
.pantalla.is-saliendo {
  opacity: 0;
  transform: translate3d(-14px, 0, 0);
  transition-timing-function: var(--ease-in);
}

/* Entrada escalonada de los bloques de cada pantalla. Solo transform y opacity. */
.pantalla.is-activa > * {
  animation: sube var(--dur-modal) var(--ease-out-strong) both;
}
.pantalla.is-activa > *:nth-child(1) { animation-delay: 40ms; }
.pantalla.is-activa > *:nth-child(2) { animation-delay: 90ms; }
.pantalla.is-activa > *:nth-child(3) { animation-delay: 130ms; }
.pantalla.is-activa > *:nth-child(4) { animation-delay: 170ms; }
.pantalla.is-activa > *:nth-child(5) { animation-delay: 210ms; }
.pantalla.is-activa > *:nth-child(6) { animation-delay: 240ms; }

@keyframes sube {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: none; }
}

/* ---------------------------------------------------------------- 1. inicio */

.pantalla--inicio {
  padding: 0;
  background-image: none; /* el arte de inicio ya trae su propio fondo completo */
  justify-content: flex-end;
  overflow: hidden;
}

/* El arte cubre TODA la pantalla y el pie va superpuesto encima. Antes se usaba contain
   para no recortar nada, pero dejaba franjas negras arriba y abajo y la portada no se veia
   completa. Con cover se recorta un 9% por lado en un celular 9:19.5, y ahi el titular
   "RIDER DISTRICT" (que llega casi al borde del lienzo) todavia entra: es el elemento que
   marca cuanto recorte se puede permitir. */
.inicio__arte {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
}

.inicio__pie {
  position: relative; /* por encima del arte */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-5) max(var(--space-5), env(safe-area-inset-bottom));
  /* Velo de abajo hacia arriba: el arte termina en una zona con brillo azul y sin esto el
     enlace de recuperar se pierde sobre el. */
  background: linear-gradient(180deg, rgba(0, 3, 10, 0) 0%, rgba(0, 3, 10, 0.72) 45%, rgba(0, 3, 10, 0.94) 100%);
}

/* El boton del cliente, tal cual. Es un <button> de verdad y no un <img> con click: asi
   tiene foco visible, respuesta tactil y lo anuncia un lector de pantalla. */
/* El boton del cliente, tal cual, pero contenido: al 88% del ancho competia con el titular
   del arte y quedaba a 19 px de el. Al 74% baja a ~72 px de alto, deja unos 32 px de aire
   bajo "DISTRICT" y se lee como un boton, no como otra franja del cartel. */
.boton-arte {
  width: min(66%, 268px);
  filter: var(--glow);
  transition: transform var(--dur-instant) var(--ease-out), filter var(--dur-toggle) var(--ease-out);
}
.boton-arte:active { transform: scale(0.975); filter: var(--glow-fuerte); }
.boton-arte img { width: 100%; height: auto; }

.enlace {
  color: var(--azul-texto);
  font-size: var(--text--1);
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: var(--space-2) var(--space-3);
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 1px;
  transition: color var(--dur-instant) var(--ease-out);
}
.enlace:active { color: var(--blanco); }

/* ---------------------------------------------------------------- retroceso */

/* Va absoluto y no en el flujo: asi el titular sigue centrado en la pantalla y no se
   descoloca por tener un boton a un lado. */
.volver {
  position: absolute;
  top: max(var(--space-4), env(safe-area-inset-top));
  left: var(--space-3);
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  color: var(--texto-apoyo);
  transition: color var(--dur-instant) var(--ease-out), transform var(--dur-instant) var(--ease-out);
}
.volver:active { color: var(--blanco); transform: translateX(-2px); }

/* Cuando el titular va justo detras del boton (pantallas sin logo, como FOTOGRAFÍA) hay
   que bajarlo o la flecha queda pegada a la primera letra. */
.volver + .titular { margin-top: var(--space-6); }

/* ---------------------------------------------------------------- marca y titulares */

.marca {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}
.marca__logo { width: 132px; height: auto; }

/* Lockup "RIDER DISTRICT": blanco + azul en caja, como en el arte. */
.marca__evento {
  display: flex;
  align-items: stretch;
  gap: 5px;
  font-size: var(--text--1);
  font-weight: 800;
  font-stretch: 78%;
  letter-spacing: 0.05em;
  transform: skewX(-9deg);
}
.marca__evento span { color: var(--blanco); }
.marca__evento em {
  font-style: normal;
  color: var(--blanco);
  background: var(--neon);
  padding: 0 6px;
  filter: var(--glow);
}

/* Titular grunge del arte: condensado, muy pesado, inclinado y en mayusculas.
   En los mockups del cliente el titulo ocupa ~86% del ancho de la pantalla, asi que va
   dimensionado en vw y muy condensado (62% es el minimo de la Archivo variable). Con un
   tamaño en rem se quedaba en la mitad de ancho y la pantalla perdia toda su fuerza. */
.titular {
  font-size: clamp(3rem, var(--fs, 15.5vw), 5.5rem);
  font-weight: 800;
  font-stretch: 62%;
  line-height: 0.92;
  letter-spacing: 0.005em;
  text-align: center;
  color: var(--texto-fuerte);
  transform: skewX(-9deg);
  text-shadow: 0 0 24px rgba(1, 103, 253, 0.35);
  /* Los titulos largos ("FOTOGRAFÍA", "RECUPERAR") no deben partirse en dos lineas ni
     desbordar el marco: se encogen solos si hace falta. */
  white-space: nowrap;
  max-width: 100%;
}

/* Cada titulo lleva su tamaño calibrado para que TODOS ocupen ~85% del ancho, como en los
   mockups. Con un solo tamaño para los cuatro, "REGISTRO" (8 letras) llenaba el 66% y
   "FOTOGRAFÍA" (10) el 84%, y las pantallas no parecian de la misma familia. Son cuatro
   titulos fijos, asi que se calibran a mano en vez de medirlos con JS en cada carga. */
[data-pantalla="registro"]  .titular { --fs: 19.1vw; }
[data-pantalla="foto"]      .titular { --fs: 15.7vw; }
/* "QR PERSONAL" va en UNA linea, asi que necesita bastante menos cuerpo que el resto para
   ocupar el mismo 85%: en dos lineas cabia a 18.3vw, en una se desbordaba al 109%. */
[data-pantalla="qr"]        .titular { --fs: 14.3vw; }
[data-pantalla="recuperar"] .titular { --fs: 16.3vw; }

/* Variante de dos palabras: la segunda en azul. Va en UNA sola linea. */
.titular--doble {
  display: flex;
  flex-direction: row;
  align-items: baseline;
  justify-content: center;
  gap: 0.28em;
  white-space: nowrap;
}
.titular--doble em {
  font-style: normal;
  color: var(--neon);
  text-shadow: 0 0 18px rgba(1, 103, 253, 0.75);
}

.sub {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
  margin-bottom: var(--space-5);
  font-size: var(--text--1);
  font-weight: 600;
  color: var(--texto);
  text-align: center;
}
/* Las barras "//" del arte, dibujadas con CSS en vez de con texto: asi no las lee un
   lector de pantalla ni se rompen al cambiar de fuente. */
.sub__barra {
  flex: 0 0 auto;
  width: 14px;
  height: 12px;
  background: var(--neon);
  clip-path: polygon(38% 0, 100% 0, 62% 100%, 0 100%);
  filter: var(--glow);
}
.sub--fuerte {
  font-size: var(--text-1);
  font-weight: 800;
  font-stretch: 84%;
  letter-spacing: 0.04em;
  color: var(--texto-fuerte);
}
/* Sin las barras "//" del arte: es una nota informativa, no un rotulo. */
.sub--simple {
  margin-top: var(--space-2);
  margin-bottom: var(--space-4);
  font-weight: 600;
  color: var(--texto-apoyo);
}

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

/* El formulario ocupa el alto sobrante y se reparte: sin esto quedaba un tercio de
   pantalla negro debajo del boton y la composicion se veia caida hacia arriba. */
.forma {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  flex: 1 1 auto;
  justify-content: center;
  padding-bottom: var(--space-4);
}
.forma > .boton--primario { margin-top: var(--space-3); }

/* .campo es solo el grupo: marco + mensaje de error.
   El mensaje tiene que quedar FUERA del marco, no dentro: el clip-path recorta todo su
   subarbol y el fondo del borde lo tiñe, asi que un error dentro del marco se veia como
   una barra roja sin texto legible. */
.campo { display: flex; flex-direction: column; }

/* Dos capas para dibujar el borde neon con esquinas cortadas: .campo__marco es la capa de
   color (hace de trazo) y .campo__caja la interior (el relleno). Las dos llevan el mismo
   clip-path y los 2px de diferencia son el grosor.
   No se puede hacer con border + border-radius porque el arte no tiene esquinas redondas,
   y un box-shadow quedaria recortado por el clip-path: de ahi el drop-shadow. */
.campo__marco {
  --c: var(--corte);
  background: var(--borde);
  padding: 2px;
  clip-path: polygon(
    var(--c) 0, 100% 0, 100% calc(100% - var(--c)),
    calc(100% - var(--c)) 100%, 0 100%, 0 var(--c)
  );
  filter: var(--glow);
  transition: filter var(--dur-toggle) var(--ease-out), background var(--dur-toggle) var(--ease-out);
}
.campo__marco:focus-within { background: var(--neon); filter: var(--glow-fuerte); }
.campo.is-mal .campo__marco { background: var(--rojo); filter: drop-shadow(0 0 10px rgba(255, 90, 103, 0.5)); }

.campo__caja {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 0 var(--space-4);
  min-height: 58px; /* objetivo tactil holgado; el minimo accesible es 44 */
  background: var(--superficie);
  clip-path: polygon(
    var(--c) 0, 100% 0, 100% calc(100% - var(--c)),
    calc(100% - var(--c)) 100%, 0 100%, 0 var(--c)
  );
  position: relative;
}

.campo__icono { flex: 0 0 auto; color: var(--neon); display: flex; }
.campo.is-mal .campo__icono { color: var(--rojo); }

.campo input,
.campo select {
  flex: 1 1 auto;
  min-width: 0;
  background: none;
  border: 0;
  padding: var(--space-4) 0;
  font-size: var(--text-1);
  font-weight: 700;
  color: var(--texto-fuerte);
  /* 16px reales como minimo: por debajo de eso, Safari en iOS hace zoom al enfocar el
     campo y descoloca toda la pantalla. --text-1 ya arranca en 17px. */
  appearance: none;
}
.campo input::placeholder { color: var(--texto-apoyo); font-weight: 600; opacity: 1; }
.campo select { cursor: pointer; }
.campo select:invalid { color: var(--texto-apoyo); font-weight: 600; }
.campo select option { background: var(--superficie); color: var(--texto-fuerte); }
/* La flecha se dibuja aparte porque appearance:none quita la nativa. */
.campo__flecha { flex: 0 0 auto; color: var(--neon); pointer-events: none; display: flex; }

.campo__error {
  font-size: var(--text--1);
  font-weight: 600;
  color: var(--rojo);
  padding: 6px var(--space-2) 0;
  min-height: 0;
}
.campo__error:empty { display: none; }

.forma__error,
.aviso {
  font-size: var(--text--1);
  font-weight: 600;
  color: var(--rojo);
  text-align: center;
  padding: var(--space-2);
}
.forma__error:empty { display: none; }
.aviso--suave { color: var(--texto-apoyo); }

.nota {
  font-size: var(--text--1);
  color: var(--texto-apoyo);
  text-align: center;
  padding: 0 var(--space-2);
  line-height: 1.5;
}

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

.acciones { display: flex; flex-direction: column; gap: var(--space-3); margin-top: auto; padding-top: var(--space-5); }

.boton {
  --c: var(--corte-grande);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  min-height: 62px;
  padding: var(--space-3) var(--space-5);
  clip-path: polygon(
    var(--c) 0, calc(100% - var(--c)) 0, 100% var(--c), 100% calc(100% - var(--c)),
    calc(100% - var(--c)) 100%, var(--c) 100%, 0 calc(100% - var(--c)), 0 var(--c)
  );
  font-weight: 800;
  font-stretch: 80%;
  font-size: var(--text-1);
  letter-spacing: 0.06em;
  color: var(--blanco);
  transform: skewX(-9deg);
  transition: transform var(--dur-instant) var(--ease-out), filter var(--dur-toggle) var(--ease-out),
              opacity var(--dur-toggle) var(--ease-out);
}
/* El texto se des-inclina para que solo la caja quede en diagonal, como en el arte:
   el chaflan es de la forma, no de la tipografia... salvo el titulo, que si es italico. */
.boton__txt { transform: skewX(9deg) skewX(-6deg); display: inline-block; }
.boton__ico { transform: skewX(9deg); display: flex; flex: 0 0 auto; }

.boton--primario { background: linear-gradient(180deg, var(--neon) 0%, var(--profundo) 100%); filter: var(--glow); }
.boton--linea { background: var(--borde); padding: 2px; filter: var(--glow); }
/* En el boton de linea el relleno lo pone un pseudo-elemento para no meter otro div. */
.boton--linea::before {
  content: "";
  position: absolute;
  inset: 2px;
  background: var(--superficie-alta);
  clip-path: inherit;
  z-index: -1;
}
.boton--linea .boton__ico { color: var(--neon); }
.boton--fantasma {
  background: none;
  min-height: 52px;
  font-size: var(--text-0);
  color: var(--texto-apoyo);
  clip-path: none;
}
.boton--fantasma .boton__ico { color: var(--texto-apoyo); }

.boton:active { transform: skewX(-9deg) scale(0.978); }
.boton[disabled] { opacity: 0.55; pointer-events: none; }
.boton[hidden] { display: none; }

/* Estado de carga: el giro aparece y el texto se va. Sin esto, el doble toque en celular
   crea dos registros (y el segundo choca contra el indice unico con un 409 desconcertante). */
.boton__giro { display: none; transform: skewX(9deg); }
.boton.is-cargando .boton__txt,
.boton.is-cargando .boton__ico { display: none; }
.boton.is-cargando .boton__giro { display: flex; animation: gira 900ms linear infinite; }
@keyframes gira { to { transform: skewX(9deg) rotate(360deg); } }

/* ---------------------------------------------------------------- visor de foto */

.visor { display: flex; justify-content: center; }

.visor__caja {
  --c: var(--corte-grande);
  position: relative;
  width: 100%;
  aspect-ratio: 3 / 4; /* el encuadre del arte, y el que se recorta al capturar */
  background: var(--borde);
  padding: 2px;
  clip-path: polygon(
    var(--c) 0, calc(100% - var(--c)) 0, 100% var(--c), 100% calc(100% - var(--c)),
    calc(100% - var(--c)) 100%, var(--c) 100%, 0 calc(100% - var(--c)), 0 var(--c)
  );
  filter: var(--glow);
  overflow: hidden;
}
.visor__caja > * { clip-path: inherit; }

.visor__vacio,
.visor__video,
.visor__previa {
  position: absolute;
  inset: 2px;
  width: calc(100% - 4px);
  height: calc(100% - 4px);
  background: var(--superficie);
}
/* cover para que lo que se ve en el visor sea exactamente lo que se captura despues. */
.visor__video, .visor__previa { object-fit: cover; }
.visor__video[hidden], .visor__previa[hidden] { display: none; }

.visor__vacio { display: flex; align-items: center; justify-content: center; }
/* La silueta es el fondo del encuadre: nace del borde inferior y llena la caja, como en el
   arte. Dimensionada en % del visor y no en px, porque el visor es fluido. */
.visor__silueta {
  position: absolute;
  bottom: 0;
  left: 50%;
  translate: -50% 0;
  width: 76%;
  height: auto;
  color: rgba(1, 103, 253, 0.17);
}
/* La camara va encima y algo mas abajo del centro: sobre el pecho de la silueta, como en
   el arte, no flotando encima de la cabeza. */
.visor__camara {
  position: relative;
  z-index: 1;
  translate: 0 16%;
  color: var(--neon);
  filter: var(--glow);
  display: flex;
}

/* Esquinas de encuadre, como las del marco del arte. */
.visor__esq {
  position: absolute;
  width: 34px; height: 34px;
  border: 2px solid var(--neon);
  filter: var(--glow);
  z-index: 2;
  pointer-events: none;
  /* Sin esto heredan el chaflan octogonal del contenedor y en vez de corchetes salen
     cuatro rombos: el recorte se come justo las dos aristas que forman la escuadra. */
  clip-path: none;
}
.visor__esq--tl { top: 16px; left: 16px; border-right: 0; border-bottom: 0; }
.visor__esq--tr { top: 16px; right: 16px; border-left: 0; border-bottom: 0; }
.visor__esq--bl { bottom: 16px; left: 16px; border-right: 0; border-top: 0; }
.visor__esq--br { bottom: 16px; right: 16px; border-left: 0; border-top: 0; }

/* Tache para descartar la foto (tomada o subida) o cancelar la camara abierta. */
.visor__tache {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 999px; /* unico circulo del sistema: es un control flotante, no una caja */
  background: rgba(0, 3, 10, 0.72);
  border: 2px solid var(--neon);
  color: var(--blanco);
  clip-path: none;
  filter: var(--glow);
  transition: transform var(--dur-instant) var(--ease-out), background var(--dur-instant) var(--ease-out);
}
.visor__tache:active { transform: scale(0.9); background: var(--neon); }
.visor__tache[hidden] { display: none; }

/* Cuenta atras 3-2-1 sobre el visor. */
.cuenta {
  position: absolute;
  inset: 2px;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 3, 10, 0.45);
  clip-path: none;
  pointer-events: none;
}
.cuenta[hidden] { display: none; }
.cuenta span {
  font-size: clamp(6rem, 34vw, 11rem);
  font-weight: 800;
  font-stretch: 70%;
  line-height: 1;
  color: var(--blanco);
  text-shadow: 0 0 40px rgba(1, 103, 253, 0.9);
  transform: skewX(-9deg);
}
/* Un ciclo por numero: entra grande y se encoge. La animacion se reinicia desde JS
   quitando y volviendo a poner esta clase con un reflow en medio. */
.cuenta span.is-late { animation: late 700ms var(--ease-out) both; }
@keyframes late {
  0%   { opacity: 0; transform: skewX(-9deg) scale(1.5); }
  18%  { opacity: 1; transform: skewX(-9deg) scale(1); }
  100% { opacity: 0.85; transform: skewX(-9deg) scale(0.92); }
}

.visor__barra {
  position: absolute; left: 2px; right: 2px; bottom: 2px; height: 5px;
  background: rgba(255, 255, 255, 0.12); z-index: 3; clip-path: none;
}
.visor__barra i {
  display: block; height: 100%; width: var(--progreso, 0%);
  background: var(--neon);
  transition: width var(--dur-toggle) var(--ease-out);
}

/* ---------------------------------------------------------------- QR */

/* Ancho del bloque del QR: acotado en px para que en pantallas grandes no crezca hasta
   ocupar media pagina y para que en el celular quepan debajo el folio, la leyenda y los
   dos botones sin obligar a hacer scroll. */
/* Aire generoso alrededor del codigo: el QR, el folio y la leyenda son tres cosas
   distintas y pegadas se leian como un bloque. */
.qr {
  display: flex;
  justify-content: center;
  margin-top: var(--space-4);
  margin-bottom: var(--space-6);
}
.qr__marco { width: min(100%, 250px); }

.qr__marco {
  --c: var(--corte-grande);
  position: relative;
  padding: 14px;
  background: var(--borde);
  clip-path: polygon(
    var(--c) 0, calc(100% - var(--c)) 0, 100% var(--c), 100% calc(100% - var(--c)),
    calc(100% - var(--c)) 100%, var(--c) 100%, 0 calc(100% - var(--c)), 0 var(--c)
  );
  filter: var(--glow-fuerte);
}
.qr__marco .visor__esq { width: 26px; height: 26px; top: 6px; left: 6px; }
.qr__marco .visor__esq--tr { left: auto; right: 6px; }
.qr__marco .visor__esq--bl { top: auto; bottom: 6px; }
.qr__marco .visor__esq--br { top: auto; bottom: 6px; left: auto; right: 6px; }

/* Placa BLANCA bajo el QR. No es una decision estetica: los lectores fallan con codigos
   sobre fondo oscuro o transparente.
   El tamaño se controla desde el contenedor y el canvas va al 100%. Dandole el ancho al
   propio canvas no funciona: es un elemento reemplazado con tamaño intrinseco (624 px) y
   acaba mandando el `max-width: 100%` del reset, no el ancho que se le pide. */
/* El cuadrado lo impone la PLACA, no el canvas.
   En un <canvas>, ni height:auto ni aspect-ratio conservan la proporcion como en un <img>:
   gana el alto intrinseco del atributo (624 px) y el codigo sale estirado en vertical. Con
   una placa de proporcion fija y el canvas a 100%/100% el resultado es exacto siempre. */
.qr__placa {
  background: #ffffff;
  padding: 10px;
  line-height: 0; /* si no, el line-height del contenedor añade una franja bajo la imagen */
}
.qr__lienzo {
  display: block;
  width: 100%;
  height: auto; /* en un <img> esto SI conserva la proporcion; en un <canvas> no */
}

/* Nombre del visitante, con el mismo tratamiento que en el pase: condensado, muy pesado,
   inclinado y en mayusculas. Se encoge solo si el nombre es largo. */
.qr__nombre {
  text-align: center;
  font-size: clamp(1.5rem, 7.4vw, 2.25rem);
  font-weight: 800;
  font-stretch: 70%;
  line-height: 1.05;
  color: var(--texto-fuerte);
  text-transform: uppercase;
  transform: skewX(-9deg);
  margin-bottom: var(--space-2);
  overflow-wrap: anywhere;
}
.qr__nombre:empty { display: none; }

.qr__folio {
  text-align: center;
  font-family: var(--font-mono);
  font-size: var(--text-1);
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--azul-tenue);
  margin-bottom: var(--space-6);
}
.qr__folio strong {
  color: var(--texto-fuerte);
  user-select: all; /* un toque largo lo selecciona entero para dictarlo o copiarlo */
}

/* En rojo por decision del cliente: es la instruccion que no se puede pasar por alto.
   Se usa el rojo del sistema y en negrita, para que sobre el fondo negro llegue a 6.4:1 de
   contraste y no se lea como un error de formulario. */
/* En rojo por decision del cliente: es la instruccion que no se puede pasar por alto.
   Se usa el rojo del sistema, en cuerpo pequeño para que no compita con el folio. */
.qr__leyenda {
  text-align: center;
  font-size: var(--text--1);
  font-weight: 700;
  line-height: 1.45;
  color: var(--rojo);
  padding: 0 var(--space-3);
  max-width: 34ch;
  margin-inline: auto;
}

.pase { margin-top: var(--space-5); text-align: center; }
.pase img { width: 100%; height: auto; border: 1px solid var(--borde); }
.pase figcaption {
  margin-top: var(--space-2);
  font-size: var(--text--1);
  color: var(--texto-apoyo);
}

/* ---------------------------------------------------------------- confirmacion */

.confirma {
  --c: var(--corte-grande);
  width: min(92vw, 380px);
  max-height: 88svh;
  overflow-y: auto;
  /* margin auto explicito: al cambiar el display a flex en [open], el centrado que trae el
     navegador para un dialogo modal deja de aplicarse y la caja se pega arriba. */
  margin: auto;
  padding: 2px; /* el trazo del marco neon */
  border: 0;
  background: var(--borde);
  color: var(--texto);
  clip-path: polygon(
    var(--c) 0, calc(100% - var(--c)) 0, 100% var(--c), 100% calc(100% - var(--c)),
    calc(100% - var(--c)) 100%, var(--c) 100%, 0 calc(100% - var(--c)), 0 var(--c)
  );
}
/* El relleno va en un pseudo-elemento para no meter otro div en el markup. */
.confirma::before {
  content: "";
  position: absolute;
  inset: 2px;
  background: var(--superficie);
  clip-path: inherit;
  z-index: -1;
}
.confirma::backdrop { background: rgba(0, 3, 10, 0.82); }
.confirma[open] { display: flex; flex-direction: column; gap: var(--space-3); }

.confirma__titulo {
  font-size: var(--text-2);
  font-weight: 800;
  font-stretch: 74%;
  letter-spacing: 0.02em;
  text-align: center;
  color: var(--texto-fuerte);
  transform: skewX(-9deg);
  padding: var(--space-5) var(--space-5) 0;
}
.confirma__nota {
  font-size: var(--text--1);
  color: var(--texto-apoyo);
  text-align: center;
  padding: 0 var(--space-5);
}

.confirma__lista { display: flex; flex-direction: column; padding: var(--space-2) var(--space-5); }
.confirma__lista > div {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-bottom: 1px solid color-mix(in srgb, var(--neon) 22%, transparent);
}
.confirma__lista > div:last-child { border-bottom: 0; }
.confirma__lista dt {
  flex: 0 0 auto;
  font-size: var(--text--1);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--texto-apoyo);
}
.confirma__lista dd {
  flex: 1 1 auto;
  min-width: 0;
  text-align: right;
  font-weight: 700;
  color: var(--texto-fuerte);
  /* Un correo largo no debe ensanchar el dialogo ni salirse. */
  overflow-wrap: anywhere;
}

.confirma__acciones {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-5) var(--space-5);
}

/* ---------------------------------------------------------------- exito */

.exito { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); text-align: center; padding-top: var(--space-6); }
.exito[hidden] { display: none; }
.exito__ico { color: var(--neon); filter: var(--glow); display: flex; }
.exito__titulo { font-size: var(--text-2); font-weight: 800; font-stretch: 82%; color: var(--texto-fuerte); }
.exito__txt { font-size: var(--text-0); color: var(--texto); }
.exito__nota { font-size: var(--text--1); color: var(--texto-apoyo); max-width: 30ch; }
.exito .boton { margin-top: var(--space-4); align-self: stretch; }

/* ---------------------------------------------------------------- accesibilidad */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Pantallas muy bajas (iPhone SE apaisado, teclado abierto): se recorta el aire, no el
   contenido. El titular es lo primero que sobra cuando no cabe todo. */
@media (max-height: 700px) {
  .titular { font-size: var(--text-3); }
  .sub { margin-bottom: var(--space-4); }
  .marca__logo { width: 108px; }
  .campo__caja { min-height: 52px; }
  .boton { min-height: 56px; }
}
