

/* Dos familias variables, servidas desde el propio dominio.
   Saira pone la voz de carrera: se abre a lo ancho (eje wdth hasta 125) como
   el rotulado de un monoplaza, y se usa para titulares, cifras y rótulos.
   Sora lleva el texto corrido: geométrica, abierta y cómoda a cualquier
   tamaño, con el aire justo entre letras para que nada se empaste. */
@font-face {
  font-family: 'Saira';
  src: url('../fonts/saira-var.woff2') format('woff2');
  font-weight: 300 900;
  font-stretch: 100% 125%;
  font-display: swap;
}

@font-face {
  font-family: 'Sora';
  src: url('../fonts/sora-var.woff2') format('woff2');
  font-weight: 100 800;
  font-display: swap;
}

:root {
  /* --- Lienzo ----------------------------------------------------------- */
  /* El negro de la marca es el fondo; encima, dos superficies apenas más
     claras ordenan la profundidad sin introducir ningún gris nuevo. */
  --fondo: #000000;
  --fondo-2: #0b0c0d;
  --superficie: #0e1011;
  --superficie-2: #16191b;

  --borde: #25292b;
  --borde-fuerte: #454b4f;
  /* Contorno de los campos y de los botones: llega solo a 3,1:1 sobre la
     superficie para que se vea dónde se escribe. */
  --borde-campo: #5e6469;

  /* --- Tipos ------------------------------------------------------------ */
  --texto: #f4f6f3;
  --texto-2: #b4babd;
  /* 5,4:1 sobre el negro: el texto de apoyo también se lee a pleno sol. */
  --texto-3: #8b9296;

  /* --- Acento ----------------------------------------------------------- */
  /* El verde de referencia del logo oficial. Sobre el negro llega a 12:1, así que sirve
     igual para un rótulo pequeño que para el relleno de una acción. */
  --acento: #93d241;
  --acento-2: #93d241;
  --acento-suave: rgba(147, 210, 65, .1);
  --acento-borde: rgba(147, 210, 65, .38);
  /* Lo que se escribe encima del verde macizo: el negro del lienzo. */
  --sobre-acento: #05090a;

  --ok: #93d241;
  --ok-suave: rgba(147, 210, 65, .1);
  --alerta: #ffc53d;
  --alerta-suave: rgba(255, 197, 61, .1);
  --error: #ff6f68;
  --error-suave: rgba(255, 111, 104, .12);
  --info: #93d241;

  /* --- Forma ------------------------------------------------------------ */
  --radio: 12px;
  --radio-s: 9px;
  --radio-xs: 6px;
  /* Las piezas diminutas —una etiqueta, una cuenta— no se redondean del todo:
     una esquina apenas insinuada lee como pieza mecanizada; el pastillero
     completo lee como pegatina. */
  --radio-micro: 5px;

  /* Filo: la línea de luz del canto superior y la sombra que asienta el
     inferior. Un píxel cada una. No es relieve simulado, es el canto de una
     pieza: sin difuminado, sin degradado, sin volumen. */
  --filo: inset 0 1px 0 rgba(255, 255, 255, .055), inset 0 -1px 0 rgba(0, 0, 0, .45);

  /* Sobre negro una sombra casi no se ve: lo que separa una capa de la de
     abajo es su línea. La sombra solo acompaña a lo que de verdad flota. */
  --sombra-baja: none;
  --sombra: 0 18px 40px -24px rgba(0, 0, 0, .9);
  --sombra-alta: 0 30px 70px -20px rgba(0, 0, 0, .95);

  /* --- Movimiento ------------------------------------------------------- */
  --curva: cubic-bezier(0.22, 1, 0.36, 1);
  --curva-entrada: cubic-bezier(0.4, 0, 0.2, 1);
  --t-rapida: 140ms;
  --t-media: 260ms;
  --t-lenta: 460ms;
  --transicion: var(--t-rapida) var(--curva);
  /* Un único ritmo para las respuestas al puntero: un poco más pausado para
     que el hover se sienta intencional y no nervioso. */
  --t-hover: 220ms;
  --curva-hover: cubic-bezier(0.16, 1, 0.3, 1);
  --sombra-hover: 0 18px 42px -24px rgba(147, 210, 65, .52);

  /* --- Ritmo ------------------------------------------------------------ */
  --e1: 6px;
  --e2: 10px;
  --e3: 16px;
  --e4: 24px;
  --e5: 40px;
  --e6: 72px;

  --fuente: 'Sora', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
  /* La voz de pista: titulares, cifras, botones y rótulos. */
  --display: 'Saira', 'Sora', system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

  /* Rótulo micro: el tamaño más pequeño del sistema —lo que nombra un dato sin
     competir con él—. Va en Saira ancha y no en la mono, porque la mono la pone
     cada dispositivo y ningún rótulo debería cambiar de forma según el
     teléfono. Abierto de interletraje: en versalitas a 11px, las letras
     pegadas se leen como una mancha. */
  --micro-tam: .69rem;
  --micro-track: .12em;
  /* Un rótulo de dos palabras aguanta el aire; una fila de tres botones no: se
     estiran hasta partirse en dos líneas y dejan de leerse como una sola orden.
     Lo que se pulsa y lo que va apretado en una celda llevan menos de la mitad
     de interletraje que lo que solo nombra. */
  --micro-track-2: .055em;
  --micro-peso: 650;

  /* Los controles que dibuja el navegador —el calendario de una fecha, la
     lista de un desplegable, la barra de desplazamiento— también en oscuro. */
  color-scheme: dark;
}

* { box-sizing: border-box; }

/* El atributo `hidden` tiene que ganar siempre: varias clases de este archivo
   fijan `display` y, al ser estilos de autor, pisarían la regla del navegador
   y dejarían visible algo oculto. */
[hidden] { display: none !important; }

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

body {
  margin: 0;
  min-height: 100dvh;
  background-color: var(--fondo);
  color: var(--texto);
  font-family: var(--fuente);
  font-size: 16px;
  line-height: 1.58;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-kerning: normal;
  /* El archivo variable cubre de 100 a 900: si aun así falta un peso, se toma
     el vecino real antes que una negrita falsa, que sobre negro se empasta. */
  font-synthesis-weight: none;
}

h1, h2, h3 {
  margin: 0 0 .5em;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: 0;
  color: var(--texto);
}
/* Cuanto mayor es el cuerpo, más sobra el espacio entre letras: el titular se
   cierra hasta -0,033em y el h3, que casi es texto, se queda casi en cero. */
h1 { font-size: clamp(1.9rem, 4vw, 2.6rem); letter-spacing: 0; line-height: 1.04; }
h2 { font-size: clamp(1.2rem, 2.2vw, 1.45rem); letter-spacing: 0; }
h3 { font-size: 1.02rem; letter-spacing: 0; }

/* Rótulo micro. Nombra sin pesar: versalitas abiertas, un punto por encima del
   gris de apoyo para que el interletraje no lo desangre. */
.micro,
.seccion-marca,
.metrica__etiqueta,
.campo__etiqueta,
.selector-cantidad__etiqueta,
.etiqueta,
thead th,
.campo > label {
  font-size: var(--micro-tam);
  font-weight: var(--micro-peso);
  letter-spacing: var(--micro-track);
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  line-height: 1.35;
}
p  { margin: 0 0 1em; }

a { color: var(--acento); text-underline-offset: 3px; text-decoration-thickness: 1px; transition: color var(--t-hover) var(--curva-hover); }
a:hover { color: var(--acento-2); }

::selection { background: var(--acento); color: var(--sobre-acento); }

* { scrollbar-width: thin; scrollbar-color: var(--borde-fuerte) transparent; }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-thumb { background: var(--borde-fuerte); border-radius: 999px; border: 3px solid transparent; background-clip: content-box; transition: background-color var(--t-hover) var(--curva-hover); }
*::-webkit-scrollbar-thumb:hover { background: var(--acento-borde); background-clip: content-box; }

/* --------------------------------------------------------------------------
   Estructura
   -------------------------------------------------------------------------- */

.contenedor { width: min(1140px, 100%); margin-inline: auto; padding-inline: clamp(16px, 4vw, 32px); }
.contenedor--angosto { width: min(460px, 100%); }

.barra {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(0, 0, 0, .94);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--borde);
}
.barra__interior {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 62px;
  padding-block: 10px;
  flex-wrap: wrap;
}
.barra__marca {
  display: flex; align-items: center; gap: 10px;
  margin-right: auto;
  flex: 0 0 auto;
  font-weight: 600;
  letter-spacing: 0;
  white-space: nowrap;
}
.barra__marca span { font-size: .98rem; }
.marca__sello { display: grid; flex: none; place-items: center; height: 26px; }
.marca__logo { display: block; width: auto; height: 26px; object-fit: contain; }
.barra__nav { display: flex; gap: 2px; flex-wrap: wrap; }

/* Encabezado de pantalla: un rótulo pequeño, el título y una línea que cierra
   el bloque. Sin trazados animados ni fondos. */
.encabezado-pista {
  padding: clamp(22px, 4vw, 44px) 0 clamp(16px, 2.4vw, 24px);
  border-bottom: 1px solid var(--borde);
}
.encabezado-pista--simple { display: flex; align-items: flex-end; }
.encabezado-pista h1 { margin-bottom: 0; }
.encabezado-pista p { margin-bottom: 0; color: var(--texto-2); }

.brand-lockup { display: inline-grid; place-items: center; }
.brand-lockup__logo { display: block; width: min(190px, 52vw); height: auto; }

main { padding-block: clamp(16px, 3vw, 28px) clamp(72px, 10vh, 120px); }

.rejilla { display: grid; gap: clamp(16px, 2.4vw, 28px); }
/* Los elementos de una rejilla no encogen por debajo de su contenido salvo que
   se les permita: sin esto, una tabla ancha estira la página entera. */
.rejilla > * { min-width: 0; }
.rejilla--2 { grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); }
.rejilla--3 { grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); }
.rejilla--metricas { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 12px; }
.rejilla--resumen { grid-template-columns: minmax(0, 1.25fr) minmax(300px, 1fr); }
@media (max-width: 860px) { .rejilla--resumen { grid-template-columns: 1fr; } }
.rejilla--ajustes { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 0 14px; }

.fila { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.fila--entre { justify-content: space-between; }
.crece { flex: 1 1 auto; min-width: 0; }

/* --------------------------------------------------------------------------
   Rótulos de sección
   -------------------------------------------------------------------------- */

/* Sobre el título de cada pantalla: dice en qué parte del sistema está la
   persona. Pequeño, en versalitas suaves y sin barras ni corchetes. */
.seccion-marca {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 8px;
  color: var(--acento);
}
/* Una raya corta delante del rótulo: ancla la columna de texto y da al bloque
   un punto de partida visible sin añadir ni un color más. */
.seccion-marca::before,
.centrado .seccion-marca::after {
  content: '';
  width: 18px; height: 1px;
  background: currentColor;
  opacity: .85;
}
/* Centrado, una sola raya cuelga del lado izquierdo y descuadra el rótulo:
   cuando el bloque va al centro, la raya va a los dos lados. */
/* --------------------------------------------------------------------------
   Tarjetas
   -------------------------------------------------------------------------- */

.tarjeta {
  min-width: 0;
  padding: clamp(18px, 2.4vw, 26px);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--superficie);
  box-shadow: var(--sombra-baja);
}
.tarjeta--atencion { border-color: rgba(255, 111, 104, .4); background: var(--error-suave); }

.tarjeta__titulo {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin-bottom: var(--e3);
  flex-wrap: wrap;
}
.tarjeta__titulo h2, .tarjeta__titulo h3 { margin: 0; }

.metrica { display: grid; gap: 2px; }
.metrica__valor {
  font-size: clamp(1.7rem, 3vw, 2.1rem);
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.metrica__etiqueta {
  color: var(--texto-3);
}
.metrica--acento .metrica__valor { color: var(--acento); }
.metrica--ok .metrica__valor { color: var(--ok); }

/* Contador principal del saldo del cliente: el dato más grande de la pantalla
   y el único que puede permitirse ese tamaño. */
.saldo {
  display: grid;
  place-items: center;
  gap: 2px;
  padding: clamp(26px, 4vw, 44px) var(--e3);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--superficie);
  box-shadow: var(--sombra-baja);
  text-align: center;
}
.saldo__numero {
  font-size: clamp(4.4rem, 17vw, 7rem);
  font-weight: 600;
  line-height: .95;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  color: var(--acento);
}
.saldo__texto {
  color: var(--texto-3);
  font-size: .92rem;
}
.saldo--vacio .saldo__numero { color: var(--error); }

@keyframes latido { 0% { transform: scale(1); } 42% { transform: scale(1.06); } 100% { transform: scale(1); } }
.saldo__numero.pulso { animation: latido 520ms var(--curva); }

/* --------------------------------------------------------------------------
   Botones y formularios
   -------------------------------------------------------------------------- */

.boton {
  --bg: var(--superficie);
  --fg: var(--texto);
  --bd: var(--borde-fuerte);
  appearance: none;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 42px;
  padding: 10px 18px;
  border-radius: var(--radio-s);
  border: 1px solid var(--bd);
  background: var(--bg);
  color: var(--fg);
  font-family: inherit;
  font-size: .92rem;
  font-weight: 550;
  letter-spacing: 0;
  line-height: 1.2;
  cursor: pointer;
  text-decoration: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  box-shadow: var(--filo);
  transition:
    background-color var(--transicion),
    border-color var(--transicion),
    color var(--transicion),
    box-shadow var(--transicion),
    transform var(--transicion),
    opacity var(--transicion);
  touch-action: manipulation;
}
.boton:hover:not(:disabled) { --bg: var(--superficie-2); --bd: var(--borde-campo); }
/* Un pulsador se hunde. Un píxel basta: más es un salto, menos no se siente. */
.boton:active:not(:disabled) { --bg: var(--fondo-2); transform: translateY(1px); box-shadow: inset 0 1px 2px rgba(0, 0, 0, .5); }
.boton:disabled { opacity: .5; cursor: not-allowed; box-shadow: none; }

/* Acción principal: el verde de la marca, macizo y sin degradado. */
.boton--principal {
  --bg: var(--acento);
  --fg: var(--sobre-acento);
  --bd: var(--acento);
  font-weight: 600;
  position: relative;
  overflow: hidden;
  /* Sobre el verde macizo el filo se invierte: la luz va abajo y el canto
     oscuro arriba, como una tecla iluminada desde dentro. */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .28), inset 0 -1px 0 rgba(0, 0, 0, .22);
}
.boton--principal:hover:not(:disabled) { --bg: var(--acento-2); --bd: var(--acento-2); }
.boton--principal:active:not(:disabled) { box-shadow: inset 0 2px 4px rgba(0, 0, 0, .28); }

/* Un solo barrido al pasar por encima: dice que el control está vivo y se
   acaba. La banda es el negro de la marca y no un brillo blanco, porque el
   blanco sobre el verde claro del hover no se distingue —y porque un barrido
   oscuro cruzando una tecla encendida es lo que hace un instrumento, no lo que
   hace un anuncio. Va a velocidad constante: un barrido con aceleración
   parece un rebote. Quien pide menos movimiento lo tiene anulado más abajo. */
.boton--principal::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(104deg, transparent 38%, rgba(5, 9, 10, .22) 50%, transparent 62%);
  transform: translateX(-130%);
  pointer-events: none;
}
.boton--principal:hover:not(:disabled)::after { animation: filoBarrido 620ms linear; }
@keyframes filoBarrido { to { transform: translateX(130%); } }
.boton--fantasma { --bg: transparent; --bd: var(--borde-fuerte); --fg: var(--texto-2); box-shadow: none; }
.boton--fantasma:active:not(:disabled) { box-shadow: none; }
.boton--fantasma:hover:not(:disabled) { --bg: var(--superficie-2); --bd: var(--borde-campo); --fg: var(--texto); }
.boton--peligro { --bg: transparent; --fg: var(--error); --bd: rgba(255, 111, 104, .4); box-shadow: none; }
.boton--peligro:hover:not(:disabled) { --bg: var(--error-suave); --bd: var(--error); }
.boton--ok { --bg: transparent; --fg: var(--ok); --bd: var(--acento-borde); box-shadow: none; }
.boton--ok:hover:not(:disabled) { --bg: var(--ok-suave); --bd: var(--ok); }
.boton--bloque { width: 100%; }
.boton--grande { min-height: 52px; padding-inline: 26px; font-size: 1rem; letter-spacing: 0; }
/* El botón chico casi nunca lleva una frase: lleva un verbo. En versalitas
   ocupa lo mismo y se distingue del texto que tiene al lado. */
.boton--chico {
  min-height: 34px; padding: 6px 11px;
  font-size: .705rem; font-weight: var(--micro-peso);
  letter-spacing: var(--micro-track-2); text-transform: uppercase;
}

/* Acción secundaria que no compite con nada: se lee como un enlace, pero
   sigue siendo un botón para el teclado y el lector de pantalla. */
.boton--enlace {
  --bg: transparent; --bd: transparent;
  min-height: 34px; padding: 4px 2px;
  color: var(--texto-2);
  font-size: .9rem; font-weight: 500;
  text-decoration: underline; text-underline-offset: 4px; text-decoration-color: var(--borde-fuerte);
  box-shadow: none;
}
.boton--enlace:hover:not(:disabled) { --bg: transparent; color: var(--acento); text-decoration-color: var(--acento); }

.boton--nav {
  --bg: transparent;
  --bd: transparent;
  min-height: 36px;
  padding: 6px 12px;
  font-size: .92rem;
  font-weight: 500;
  color: var(--texto-2);
  box-shadow: none;
}
.boton--nav:hover { --bg: var(--fondo-2); --bd: transparent; color: var(--texto); }
.boton--nav { position: relative; box-shadow: none; }
.boton--nav:active:not(:disabled) { box-shadow: none; }
.boton--nav[aria-current="page"] { color: var(--texto); font-weight: 600; background: var(--fondo-2); }
/* Dónde estoy no se dice solo con un fondo apenas más claro: se subraya. */
.boton--nav[aria-current="page"]::after {
  content: '';
  position: absolute; left: 12px; right: 12px; bottom: 3px;
  height: 2px; border-radius: 2px;
  background: var(--acento);
}

.campo { display: grid; gap: 5px; margin-bottom: var(--e4); }
.campo > label,
.campo__etiqueta {
  color: var(--texto-2);
}
.campo__ayuda { font-size: .82rem; color: var(--texto-3); }
.campo__error { font-size: .84rem; color: var(--error); }
.campo__error:empty { display: none; }

input, select, textarea {
  width: 100%;
  min-height: 44px;
  padding: 10px 13px;
  border: 1px solid var(--borde-campo);
  border-radius: var(--radio-s);
  background: var(--superficie);
  color: var(--texto);
  font-family: inherit;
  font-size: 1rem;
  line-height: 1.4;
  /* Hundido, no elevado: un campo es un hueco donde se escribe, y el canto de
     luz va abajo —al revés que en un botón, que sobresale. */
  box-shadow: inset 0 1px 0 rgba(0, 0, 0, .35);
  transition: border-color var(--transicion), box-shadow var(--transicion);
}
input:hover:not(:disabled), select:hover:not(:disabled), textarea:hover:not(:disabled) { border-color: var(--texto-3); }
textarea { min-height: 96px; resize: vertical; padding-top: 11px; }

/* Desplegable con la flecha de la casa en vez de la del sistema. */
/* El galón va dibujado con trazo redondeado, como el resto de iconos de la
   casa. Los dos triángulos de antes dejaban una punta cuadrada que no casaba
   con ninguna otra pieza. El color va escrito porque un fondo de CSS no puede
   heredar `currentColor`: si cambia --texto-2, cambia también aquí. */
select {
  appearance: none;
  padding-right: 40px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.6 6 6.4 11 1.6' stroke='%23b4babd' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-position: calc(100% - 14px) 50%;
  background-size: 12px 8px;
  background-repeat: no-repeat;
}

input:focus, select:focus, textarea:focus { outline: none; }
input:focus-visible, select:focus-visible, textarea:focus-visible,
input:focus, select:focus, textarea:focus {
  border-color: var(--acento);
  box-shadow: 0 0 0 3px var(--acento-suave), inset 0 1px 0 rgba(0, 0, 0, .35);
}
/* Doble anillo: el hueco negro separa el verde del control aunque el control
   ya sea verde, así que el foco nunca se empasta contra su propio fondo. */
.boton:focus-visible, a:focus-visible, [tabindex]:focus-visible, .pestana:focus-visible {
  outline: 2px solid var(--acento);
  outline-offset: 3px;
  box-shadow: 0 0 0 3px var(--fondo), var(--filo);
}
input[aria-invalid="true"] { border-color: var(--error); }
input[aria-invalid="true"]:focus { box-shadow: 0 0 0 3px var(--error-suave); }
input::placeholder, textarea::placeholder { color: var(--texto-3); }

/* 24 px, no 20: es el mínimo que pide WCAG 2.2 para un objetivo táctil.
   Se dibuja entera en vez de pintar la del sistema con `accent-color`: así el
   radio, el canto y la curva del tic son los mismos que en todo lo demás, en
   lugar de cambiar de forma entre un teléfono y un escritorio. */
input[type="checkbox"] {
  appearance: none;
  display: inline-grid;
  place-content: center;
  width: 24px; height: 24px; min-height: 0;
  flex: none;
  padding: 0;
  border: 1px solid var(--borde-campo);
  border-radius: var(--radio-micro);
  background: var(--superficie);
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(0, 0, 0, .35);
  transition: background-color var(--transicion), border-color var(--transicion);
}
input[type="checkbox"]:hover:not(:disabled) { border-color: var(--texto-3); }
input[type="checkbox"]:checked {
  background: var(--acento);
  border-color: var(--acento);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .28);
}
/* El tic va enmascarado, no recortado: un `clip-path` dibuja un polígono, y un
   polígono cambia de grosor cuando cambia de pendiente —el brazo corto salía
   más gordo que el largo—. La máscara lleva un trazo de verdad, con la misma
   punta redonda y el mismo grosor relativo que los iconos de `.icono`, así que
   la casilla pertenece a la misma familia que el resto de dibujos. El color lo
   pone el fondo, que sigue saliendo del token.
   Crece desde el centro al marcarse: 140 ms, lo justo para que se vea que fue
   esta casilla y no la de al lado. */
input[type="checkbox"]::before {
  content: '';
  width: 14px; height: 14px;
  background: var(--sobre-acento);
  --tic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14' fill='none'%3E%3Cpath d='M2.6 7.3 5.7 10.4 11.4 3.9' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  -webkit-mask: var(--tic) center / contain no-repeat;
  mask: var(--tic) center / contain no-repeat;
  transform: scale(0);
  transition: transform var(--t-rapida) var(--curva);
}
input[type="checkbox"]:checked::before { transform: scale(1); }
input[type="checkbox"]:disabled { opacity: .5; cursor: not-allowed; }
input[type="checkbox"]:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; }

.campo--linea { display: flex; align-items: center; gap: 10px; }
/* Junto a una casilla no hay un rótulo, hay una frase: se lee como texto
   corrido y no como la etiqueta de un campo. */
.opcion-aviso label,
.campo--linea > label,
.campo--linea > span {
  font-size: .95rem;
  font-weight: 400;
  color: var(--texto);
  letter-spacing: normal;
  text-transform: none;
}
.opcion-aviso label .tenue-2 { font-size: .86rem; }

fieldset { border: 0; margin: 0; padding: 0; }

/* --------------------------------------------------------------------------
   Avisos, etiquetas y estados
   -------------------------------------------------------------------------- */

.aviso {
  display: block;
  margin-bottom: var(--e3);
  padding: 12px 16px;
  border: 1px solid var(--borde);
  border-left: 3px solid var(--borde-fuerte);
  border-radius: var(--radio-s);
  background: var(--superficie-2);
  color: var(--texto);
  font-size: .94rem;
}
.aviso:empty { display: none; }
.aviso--error  { border-color: rgba(255, 111, 104, .35); border-left-color: var(--error); background: var(--error-suave); color: #ffc9c5; }
.aviso--ok     { border-color: var(--acento-borde); border-left-color: var(--ok); background: var(--ok-suave); color: #93d241; }
.aviso--alerta { border-color: rgba(255, 197, 61, .35); border-left-color: var(--alerta); background: var(--alerta-suave); color: #ffe6a6; }

.etiqueta {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 9px;
  border: 1px solid var(--borde);
  border-radius: var(--radio-micro);
  background: var(--superficie-2);
  color: var(--texto-2);
  letter-spacing: var(--micro-track-2);
  white-space: nowrap;
}
.etiqueta--ok     { color: var(--ok); border-color: var(--acento-borde); background: var(--ok-suave); }
.etiqueta--alerta { color: var(--alerta); border-color: rgba(255, 197, 61, .35); background: var(--alerta-suave); }
.etiqueta--error  { color: var(--error); border-color: rgba(255, 111, 104, .35); background: var(--error-suave); }
.etiqueta--info   { color: var(--acento); border-color: var(--acento-borde); background: var(--acento-suave); }

.punto { position: relative; width: 8px; height: 8px; border-radius: 50%; background: var(--borde-fuerte); flex: none; }
.punto--vivo { background: var(--ok); }
/* El estado "en vivo" es el único dato de la barra que cambia solo: un anillo
   que sale cada dos segundos y medio lo dice sin ocupar sitio ni texto. */
.punto--vivo::after {
  content: '';
  position: absolute; inset: -3px;
  border: 1px solid var(--ok);
  border-radius: 50%;
  opacity: 0;
  animation: pulsoPunto 2.5s var(--curva-entrada) infinite;
}
@keyframes pulsoPunto {
  0%   { opacity: .6; transform: scale(.55); }
  70%, 100% { opacity: 0; transform: scale(1.35); }
}
.punto--caido { background: var(--error); }

.estado-conexion {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--texto-3);
  font-size: .82rem;
}

.vacio { text-align: center; padding: 36px 18px; color: var(--texto-3); }
.vacio__icono { display: inline-flex; margin-bottom: 10px; opacity: .45; font-size: 1.8rem; }

/* Espera con forma: ocupa el sitio que ocupará el contenido real. */
.esqueleto { display: grid; gap: 8px; }
.esqueleto__linea {
  height: 13px;
  border-radius: var(--radio-xs);
  background: linear-gradient(90deg, var(--fondo-2) 0%, var(--superficie-2) 50%, var(--fondo-2) 100%);
  background-size: 200% 100%;
  animation: esqueletoOnda 1.4s var(--curva-entrada) infinite;
}
@keyframes esqueletoOnda { from { background-position: 100% 0; } to { background-position: -100% 0; } }

.cargando {
  width: 18px; height: 18px;
  border: 2px solid var(--borde);
  border-top-color: var(--acento);
  border-right-color: var(--acento-borde);
  border-radius: 50%;
  display: inline-block;
  animation: girar 800ms linear infinite;
}
@keyframes girar { to { transform: rotate(360deg); } }
.cargando--grande { width: 28px; height: 28px; border-width: 3px; }

/* --------------------------------------------------------------------------
   Iconos
   -------------------------------------------------------------------------- */

.icono {
  width: 1.15em; height: 1.15em;
  vertical-align: -0.18em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.icono--grande { width: 1.5em; height: 1.5em; }

/* --------------------------------------------------------------------------
   Packs y QR
   -------------------------------------------------------------------------- */

.pack {
  display: grid;
  gap: 12px;
  padding: 18px;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--superficie);
  box-shadow: var(--sombra-baja);
  transition: border-color var(--transicion), box-shadow var(--transicion);
}
.pack--inactivo { opacity: .6; }
.pack__cabecera { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.pack__codigo { font-family: var(--mono); font-size: .92rem; font-weight: 600; letter-spacing: .04em; color: var(--texto-2); }
.pack__restantes { font-size: 1.9rem; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; letter-spacing: 0; }

.barra-progreso {
  height: 6px;
  border-radius: 999px;
  background: var(--fondo-2);
  overflow: hidden;
}
.barra-progreso__relleno {
  height: 100%;
  /* El extremo que avanza va a pleno verde y la cola se apaga: se ve hacia
     dónde crece la barra incluso en una captura quieta. */
  background: linear-gradient(90deg, rgba(147, 210, 65, .45), var(--acento));
  border-radius: 999px;
  transition: width var(--t-lenta) var(--curva);
}

/* Programa de fidelidad: la tarjeta de sellos del cliente. Cada entrada usada
   llena un sello, y el último es el que la casa invita. */
.fidelidad { border-color: var(--acento-borde); }
.fidelidad__sellos {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 14px 0 4px;
}
.sello {
  width: 20px; height: 20px;
  border-radius: 999px;
  border: 1px solid var(--borde-fuerte);
  background: var(--fondo-2);
  transition: background var(--transicion), border-color var(--transicion);
}
.sello--lleno { background: var(--acento); border-color: var(--acento); }
.sello--premio {
  border: 1px dashed var(--acento);
  background: var(--acento-suave);
}
.fidelidad--completa { border-color: var(--acento-borde); background: var(--ok-suave); }

.qr-caja {
  position: relative;
  display: grid; place-items: center; gap: 12px;
  padding: 18px;
  background: #fff;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  min-height: 210px;
  width: fit-content;
  min-width: min(300px, 100%);
  max-width: 100%;
  margin-inline: auto;
}
.qr-caja svg { display: block; width: min(264px, 62vw); height: auto; }
.qr-caja--cargando { background: var(--superficie-2); }
.qr-pie { text-align: center; color: var(--texto-3); font-size: .86rem; }
.qr-cuenta { font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 600; color: var(--texto); }

.qr-temporizador {
  width: 100%;
  max-width: 264px;
  height: 3px;
  background: var(--fondo-2);
  border-radius: 999px;
  margin: 10px auto 0;
  overflow: hidden;
}
.qr-temporizador__barra {
  height: 100%;
  width: 100%;
  background: var(--acento);
  border-radius: 999px;
  transition: width 1s linear;
}

/* --------------------------------------------------------------------------
   Guardar el pase en la cartera del teléfono

   Va dentro de la tarjeta del pase, así que se separa con un recuadro propio
   en vez de con otra tarjeta: anidar tarjetas hace que ninguna de las dos se
   lea como el borde de nada.
   -------------------------------------------------------------------------- */

.cartera {
  padding: 16px;
  border: 1px solid var(--borde);
  border-radius: var(--radio-s);
  background: var(--fondo-2);
  text-align: center;
}
.cartera__titulo {
  margin: 0 0 4px;
  font-size: .95rem;
  letter-spacing: .02em;
}
.cartera .fila { flex-wrap: wrap; }

/* En el mostrador: el QR que el cliente escanea para guardar su pase. Fondo
   blanco siempre: un QR sobre el lienzo negro no lo lee ninguna cámara. */
.cartera-qr {
  width: min(232px, 60vw);
  margin: 0 auto;
  padding: 10px;
  border-radius: var(--radio-s);
  background: #fff;
}
.cartera-qr svg { display: block; width: 100%; height: auto; }

/* --------------------------------------------------------------------------
   Escáner
   -------------------------------------------------------------------------- */

/* Lo único oscuro del sistema, y por un motivo: es una imagen de cámara. */
.escaner {
  position: relative;
  border-radius: var(--radio);
  overflow: hidden;
  background: #16181a;
  aspect-ratio: 4 / 3;
  max-height: 62vh;
  border: 1px solid var(--borde);
}
.escaner video { width: 100%; height: 100%; object-fit: cover; display: block; }
.escaner__marco {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  pointer-events: none;
}
.escaner__mira {
  position: relative;
  width: min(64%, 300px); aspect-ratio: 1;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .55);
  border-radius: var(--radio-s);
  --mira: rgba(255, 255, 255, .92);
}
.escaner__mira::before,
.escaner__mira::after {
  content: '';
  position: absolute;
  width: 34px; height: 34px;
  border: 3px solid var(--mira);
  transition: border-color var(--t-media) var(--curva);
}
.escaner__mira::before { top: 0; left: 0; border-right: 0; border-bottom: 0; border-radius: var(--radio-s) 0 0 0; }
.escaner__mira::after { bottom: 0; right: 0; border-left: 0; border-top: 0; border-radius: 0 0 var(--radio-s) 0; }
.escaner__mira--ok { --mira: var(--acento); }
.escaner__mira--error { --mira: var(--error); }

/* El resultado de la puerta: se lee a un brazo de distancia y con prisa, así
   que manda el color de fondo y el tamaño del número. */
.resultado {
  position: relative;
  overflow: hidden;
  padding: clamp(22px, 4vw, 32px);
  text-align: center;
  display: grid;
  gap: 6px;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--superficie);
  transition: border-color var(--t-media) var(--curva), background-color var(--t-media) var(--curva);
}
.resultado--ok       { background: var(--ok-suave); border-color: var(--acento-borde); }
.resultado--error    { background: var(--error-suave); border-color: rgba(255, 111, 104, .4); }
.resultado--alerta   { background: var(--alerta-suave); border-color: rgba(255, 197, 61, .4); }
.resultado--guardada { background: var(--superficie-2); border-color: var(--borde-fuerte); border-style: dashed; }
.resultado__icono { display: grid; place-items: center; font-size: 2.1rem; line-height: 1; color: var(--texto-3); }
.resultado--ok .resultado__icono       { color: var(--ok); }
.resultado--error .resultado__icono    { color: var(--error); }
.resultado--alerta .resultado__icono   { color: var(--alerta); }
.resultado--guardada .resultado__icono { color: var(--texto-2); }
.resultado__titulo { font-size: clamp(1.15rem, 3.2vw, 1.4rem); font-weight: 600; letter-spacing: 0; }
.resultado__detalle { color: var(--texto-2); }
.resultado__restantes {
  font-size: clamp(3rem, 11vw, 4.2rem);
  font-weight: 600; line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

/* Selector de cantidad para escaneo en grupo. */
.selector-cantidad {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 0;
  border: 0;
}
.selector-cantidad__etiqueta { color: var(--texto-2); }
.selector-cantidad__opciones { display: flex; gap: 6px; }
.btn-cantidad {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; height: 44px;
  padding: 0 10px;
  border: 1px solid var(--borde-campo);
  border-radius: var(--radio-s);
  background: var(--superficie);
  color: var(--texto-2);
  font: inherit;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  box-shadow: var(--filo);
  transition: border-color var(--transicion), color var(--transicion), background-color var(--transicion), transform var(--transicion);
}
.btn-cantidad:hover { border-color: var(--texto-3); color: var(--texto); }
.btn-cantidad:active { transform: translateY(1px); box-shadow: inset 0 1px 2px rgba(0, 0, 0, .5); }
/* La cantidad elegida se rellena: en la puerta se ve de un vistazo cuántas
   entradas va a descontar el siguiente escaneo. */
.btn-cantidad.activo {
  background: var(--acento); border-color: var(--acento); color: var(--sobre-acento);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .28);
}

/* --------------------------------------------------------------------------
   Tablas y listas
   -------------------------------------------------------------------------- */

.tabla-envoltura { overflow-x: auto; min-width: 0; max-width: 100%; }
table { width: 100%; border-collapse: collapse; font-size: .92rem; }
thead th {
  text-align: left; padding: 0 12px 10px;
  color: var(--texto-3);
  border-bottom: 1px solid var(--borde);
  white-space: nowrap;
}
tbody td { padding: 13px 12px; border-bottom: 1px solid var(--borde); vertical-align: middle; }
/* La bitácora se mide en cientos de renglones: ahí el aire de las demás tablas
   convertía la pantalla en un desierto. */
#tabla-auditoria tbody td { padding-block: 9px; }
thead th:first-child, tbody td:first-child { padding-left: 2px; }
thead th:last-child, tbody td:last-child { padding-right: 2px; }
tbody tr:last-child td { border-bottom: 0; }
td.mono, .mono { font-family: var(--mono); font-size: .88em; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }

.lista { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.lista__item {
  display: flex; gap: 14px; align-items: center;
  padding: 13px 4px;
  border-top: 1px solid var(--borde);
  transition: background-color var(--t-rapida) var(--curva);
}
.lista__item:first-child { border-top: 0; }
.opcion-lista:hover { background: var(--superficie-2); }
.lista__item--rechazada { background: var(--error-suave); }
.aviso--sin-conexion { margin-bottom: var(--e3); }
.lista__item--nuevo { animation: aparecer var(--t-lenta) var(--curva); }
@keyframes aparecer { from { opacity: 0; transform: translateY(-7px); } to { opacity: 1; transform: none; } }

/* Una lista larga dentro de un bloque ancho se lee en dos columnas. Son dos
   listas de verdad (ver admin.js), así que cada columna empieza sin línea
   encima sin tener que contar elementos desde el CSS. */
.columnas-lista { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(330px, 100%), 1fr)); gap: 0 clamp(20px, 3.4vw, 40px); }
.columnas-lista > * { min-width: 0; }

/* --------------------------------------------------------------------------
   Pestañas, diálogos y avisos flotantes
   -------------------------------------------------------------------------- */

.pestanas {
  display: flex; gap: clamp(14px, 2.4vw, 28px);
  border-bottom: 1px solid var(--borde);
  margin-bottom: var(--e5);
  overflow-x: auto;
}
.pestana {
  position: relative;
  flex: 0 0 auto; min-width: max-content;
  padding: 12px 2px;
  border: 0; border-radius: 0;
  background: transparent; color: var(--texto-3);
  font-family: inherit; font-size: .94rem; font-weight: 550;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--transicion);
}
.pestana:hover { color: var(--texto-2); }
.pestana[aria-selected="true"] { color: var(--texto); }
.pestana[aria-selected="true"]::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: -1px;
  height: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--acento);
  /* Se traza al cambiar de pestaña: el ojo sigue la raya hasta el contenido
     nuevo en vez de tener que buscar cuál se encendió. */
  transform-origin: left;
  animation: trazarPestana var(--t-media) var(--curva);
}
@keyframes trazarPestana { from { transform: scaleX(0); } }

.pestanas--grupos { margin-bottom: var(--e3); }
.pestana__cuenta {
  display: inline-block; min-width: 1.7em; margin-left: 8px; padding: 1px 6px;
  border-radius: var(--radio-micro);
  background: var(--fondo-2);
  font-size: .72rem; font-weight: 650; font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
  color: var(--texto-3);
}
.pestana[aria-selected="true"] .pestana__cuenta { background: var(--acento-suave); color: var(--acento); }

dialog {
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--superficie);
  color: var(--texto);
  padding: 0;
  width: min(520px, calc(100vw - 26px));
  max-height: calc(100dvh - 40px);
  box-shadow: var(--sombra-alta);
}
dialog[open] { animation: entrarModal var(--t-media) var(--curva); }
@keyframes entrarModal {
  from { opacity: 0; transform: translateY(8px) scale(.99); }
  to { opacity: 1; transform: none; }
}
dialog::backdrop { background: rgba(0, 0, 0, .72); backdrop-filter: blur(3px); }
.dialogo-ancho { width: min(720px, calc(100vw - 26px)); }
.modal__cuerpo { padding: clamp(18px, 3vw, 26px); overflow-y: auto; max-height: calc(100dvh - 120px); }
.modal__cuerpo > h2:first-child { margin-bottom: var(--e3); }
.modal__pie {
  display: flex; gap: 9px; justify-content: flex-end;
  padding: 14px clamp(18px, 3vw, 26px);
  border-top: 1px solid var(--borde);
  background: var(--superficie-2);
  border-radius: 0 0 var(--radio) var(--radio);
  flex-wrap: wrap;
}

.brindis-zona {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 20px; z-index: 90;
  display: grid; gap: 8px;
  width: min(430px, calc(100vw - 22px));
  pointer-events: none;
}
.brindis {
  pointer-events: auto;
  padding: 13px 16px;
  border: 1px solid var(--borde);
  border-left: 3px solid var(--borde-fuerte);
  border-radius: var(--radio-s);
  background: var(--superficie);
  box-shadow: var(--sombra);
  font-size: .94rem;
  animation: subir var(--t-media) var(--curva);
}
.brindis--ok { border-left-color: var(--ok); }
.brindis--error { border-left-color: var(--error); }
.brindis--alerta { border-left-color: var(--alerta); }
.brindis--saliendo { animation: bajar 200ms var(--curva-entrada) forwards; }
@keyframes subir { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@keyframes bajar { to { opacity: 0; transform: translateY(8px); } }

/* --------------------------------------------------------------------------
   Utilidades
   -------------------------------------------------------------------------- */

.tenue { color: var(--texto-2); }
.tenue-2 { color: var(--texto-3); }
.pequeno { font-size: .88rem; }
.centrado { text-align: center; }
.sin-margen { margin: 0; }
.mt { margin-top: var(--e3); }
.mt-mini { margin-top: var(--e1); }
.mt-2 { margin-top: var(--e4); }
.ancho-auto { width: auto; }
.sin-margen-todo { margin: 0; }
.mb { margin-bottom: var(--e3); }
.mb-2 { margin-bottom: 18px; }
.mb-3 { margin-bottom: 26px; }
.centro-flex { justify-content: center; }
.alinea-arriba { align-items: start; }
.sin-salto { white-space: nowrap; }
.min-200 { min-width: 200px; }
.ancho-puesto { width: 140px; }
.columna { display: grid; gap: var(--e3); min-width: 0; }
.columna > * { min-width: 0; }
.lista-scroll { max-height: 190px; overflow-y: auto; }
.brand-lockup--entrada { display: grid; margin: 0 auto 18px; }
.separador { border: 0; border-top: 1px solid var(--borde); margin: var(--e4) 0; }
.subrayado-no { text-decoration: none; color: inherit; }
.oculto-visual { position: fixed; opacity: 0; pointer-events: none; }
.contenido-qr { display: contents; }
.resalte { color: var(--acento); font-weight: 600; }
.opcion-lista { text-align: left; cursor: pointer; width: 100%; font: inherit; color: inherit; }
.icono-lista { display: inline-flex; font-size: 1.05rem; color: var(--texto-3); }
.icono-lista--grande { display: inline-flex; font-size: 1.25rem; color: var(--texto-3); }
.lista__item--rechazada .icono-lista,
.lista__item--rechazada .icono-lista--grande { color: var(--error); }

.codigo-grande { font-family: var(--mono); font-size: 1.05rem; letter-spacing: .08em; color: var(--texto); }
.entrada-codigo { font-family: var(--mono); letter-spacing: .08em; text-transform: uppercase; }

/* Un error, un enlace caducado, una contraseña nueva: pantallas de una sola
   cosa, centradas en el alto. */
.pagina-sola {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 100dvh;
  padding-block: clamp(36px, 8vh, 90px);
}
.pagina-sola > .seccion-marca,
.pagina-sola > .boton { align-self: center; }

.grafico { display: flex; align-items: flex-end; gap: 5px; height: 104px; padding-bottom: 1px; border-bottom: 1px solid var(--borde); }
.grafico__barra {
  flex: 1;
  background: rgba(147, 210, 65, .45);
  border-radius: 3px 3px 0 0;
  min-height: 2px;
  transform-origin: bottom;
  animation: crecerBarra var(--t-lenta) var(--curva) backwards;
  transition: background-color var(--transicion);
}
@keyframes crecerBarra { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.grafico__barra:nth-child(1) { animation-delay: 20ms; }
.grafico__barra:nth-child(2) { animation-delay: 40ms; }
.grafico__barra:nth-child(3) { animation-delay: 60ms; }
.grafico__barra:nth-child(4) { animation-delay: 80ms; }
.grafico__barra:nth-child(5) { animation-delay: 100ms; }
.grafico__barra:nth-child(6) { animation-delay: 120ms; }
.grafico__barra:nth-child(7) { animation-delay: 140ms; }
.grafico__barra:nth-child(8) { animation-delay: 160ms; }
.grafico__barra:nth-child(9) { animation-delay: 180ms; }
.grafico__barra:nth-child(10) { animation-delay: 200ms; }
.grafico__barra:nth-child(11) { animation-delay: 220ms; }
.grafico__barra:nth-child(12) { animation-delay: 240ms; }
.grafico__barra:nth-child(13) { animation-delay: 260ms; }
.grafico__barra:nth-child(n+14) { animation-delay: 280ms; }

/* Entrada de los bloques al asomar en pantalla. La clase la pone JavaScript
   (ver shell.js), nunca el HTML: sin JavaScript todo se ve igual. */
@keyframes entrarBloque { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
.revelar { opacity: 0; }
.revelar--visible { opacity: 1; animation: entrarBloque var(--t-lenta) var(--curva); }

@keyframes entrarPanel { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
[role="tabpanel"]:not([hidden]),
#ficha-panel > * { animation: entrarPanel var(--t-media) var(--curva); }

/* Primera columna de una tabla clave/valor. */
.celda-clave { text-align: left; white-space: nowrap; color: var(--texto-3); font-size: .84rem; }
/* Celda con datos técnicos en crudo: se parte en vez de estirar la tabla. */
.celda-json { max-width: 46ch; overflow-wrap: anywhere; word-break: break-word; }

/* ==========================================================================
   Ficha del cliente
   ========================================================================== */

.ficha { display: grid; gap: var(--e4); min-width: 0; }
.ficha > * { min-width: 0; }

.ficha__volver {
  display: inline-flex; align-items: center; gap: 8px;
  align-self: start;
  background: none; border: 0; padding: 6px 0;
  color: var(--texto-2); font: inherit; font-weight: 500;
  font-size: .9rem;
  cursor: pointer;
  transition: color var(--transicion);
}
.ficha__volver:hover { color: var(--acento); }

.ficha__cabecera {
  display: flex; gap: 18px; align-items: flex-start; flex-wrap: wrap;
  padding: clamp(18px, 2.6vw, 24px);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--superficie);
  box-shadow: var(--sombra-baja);
}

.avatar {
  width: 58px; height: 58px; flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  font-size: 1.25rem; font-weight: 600; letter-spacing: 0;
  color: var(--acento-2);
  background: var(--acento-suave);
}
.avatar--staff { background: var(--superficie-2); color: var(--texto-2); }
.avatar--master { background: var(--acento); color: var(--sobre-acento); }

.ficha__identidad { display: grid; gap: 4px; min-width: 220px; flex: 1 1 260px; }
.ficha__nombre { font-size: clamp(1.3rem, 3vw, 1.6rem); font-weight: 600; letter-spacing: 0; line-height: 1.15; }
.ficha__contacto { color: var(--texto-2); font-size: .92rem; display: flex; gap: 6px 16px; flex-wrap: wrap; }
.ficha__contacto a { color: inherit; text-decoration: none; }
.ficha__contacto a:hover { color: var(--acento); text-decoration: underline; }
.ficha__etiquetas { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.ficha__acciones { display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-start; }

.habitos {
  display: flex; gap: 8px 26px; flex-wrap: wrap;
  color: var(--texto-3);
  font-size: .86rem;
}
.habitos strong { color: var(--texto); font-weight: 600; font-size: .92rem; }

.semana { display: grid; gap: 8px; }
.semana__fila { display: grid; grid-template-columns: 78px 1fr 30px; align-items: center; gap: 12px; font-size: .86rem; }
.semana__nombre { color: var(--texto-3); }
.semana__barra { height: 8px; border-radius: 999px; background: var(--fondo-2); overflow: hidden; }
.semana__relleno { height: 100%; background: rgba(147, 210, 65, .5); border-radius: 999px; transition: width var(--t-lenta) var(--curva); }
.semana__valor { text-align: right; font-variant-numeric: tabular-nums; color: var(--texto-2); font-size: .84rem; }

.tiempo { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.tiempo__item { position: relative; display: grid; grid-template-columns: 32px 1fr; gap: 14px; padding: 13px 0; }
.tiempo__item::before {
  content: ''; position: absolute; left: 15px; top: 0; bottom: 0;
  width: 1px; background: var(--borde);
}
.tiempo__item:first-child::before { top: 22px; }
.tiempo__item:last-child::before { bottom: calc(100% - 22px); }
.tiempo__icono {
  position: relative; z-index: 1;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--superficie);
  border: 1px solid var(--borde);
  color: var(--texto-3);
  font-size: .88rem;
}
.tiempo__icono--suma { border-color: var(--acento-borde); background: var(--ok-suave); color: var(--ok); }
.tiempo__icono--resta { border-color: var(--borde-fuerte); background: var(--fondo-2); color: var(--texto-2); }
.tiempo__icono--aviso { border-color: rgba(255, 197, 61, .4); background: var(--alerta-suave); color: var(--alerta); }
.tiempo__cuerpo { display: grid; gap: 3px; align-content: start; min-width: 0; }
.tiempo__titulo { font-weight: 600; }
.tiempo__detalle { color: var(--texto-2); font-size: .88rem; }
.tiempo__meta { color: var(--texto-3); font-size: .8rem; }
.tiempo__saldo {
  justify-self: start; margin-top: 4px;
  font-family: var(--mono);
  font-size: .76rem; font-weight: 600;
  padding: 2px 8px; border-radius: 999px;
  background: var(--fondo-2); color: var(--texto-2);
}

.mini-pack {
  display: grid; gap: 10px;
  padding: 15px;
  border: 1px solid var(--borde);
  border-radius: var(--radio-s);
  background: var(--superficie);
  transition: border-color var(--transicion);
}
.mini-pack--inactivo { opacity: .6; }
.mini-pack__fila { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.mini-pack__codigo { font-family: var(--mono); font-weight: 600; letter-spacing: .04em; color: var(--texto-2); }
.mini-pack__saldo { font-size: 1.5rem; font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1; letter-spacing: 0; }

.dispositivo {
  display: grid; grid-template-columns: auto 1fr auto; gap: 12px; align-items: center;
  padding: 13px 15px;
  border: 1px solid var(--borde); border-radius: var(--radio-s);
  background: var(--superficie);
}
.dispositivo--revocada { opacity: .55; }

.ficha__vacio { text-align: center; padding: 40px 20px; color: var(--texto-3); }

/* ==========================================================================
   Avisos a clientes y clientes por recuperar
   ========================================================================== */

.recuperar { align-items: flex-start; }
.recuperar__nombre { font-weight: 600; color: var(--texto); text-decoration: none; }
.recuperar__nombre:hover { color: var(--acento); text-decoration: underline; }
.recuperar__contacto { margin-top: 3px; color: var(--acento); font-size: .84rem; }
.recuperar__acciones { flex: none; justify-content: flex-end; }
/* Quien ya fue contactado hace poco sigue a la vista, pero no llama la atención. */
.recuperar--contactado { opacity: .62; }
.recuperar--contactado .recuperar__contacto { color: var(--texto-3); }

.ajustes-grupo { display: grid; gap: 4px; margin: 6px 0 var(--e4); }
.ajustes-grupo legend { margin-bottom: 8px; font-size: .88rem; font-weight: 600; color: var(--texto-2); }
.opcion-aviso {
  display: grid; grid-template-columns: 24px 1fr; gap: 12px; align-items: start;
  padding: 13px 2px;
  border-bottom: 1px solid var(--borde);
}
.opcion-aviso:last-of-type { border-bottom: 0; }
.opcion-aviso input { margin-top: 1px; }
.opcion-aviso__nombre { font-weight: 600; }

/* Opciones de pack en el diálogo de recarga */
.opcion-pack {
  display: flex;
  flex-direction: column;
  padding: 12px 14px;
  border: 2px solid var(--borde);
  border-radius: var(--radio);
  background: var(--superficie);
  cursor: pointer;
  text-align: left;
  transition: border-color var(--t-rapida) var(--curva), background-color var(--t-rapida) var(--curva);
}
.opcion-pack:hover {
  border-color: var(--borde-fuerte);
}
.opcion-pack.activo {
  border-color: var(--acento);
  background: var(--acento-suave);
}
.opcion-pack__cabecera {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 4px;
}
.opcion-pack__entradas {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--texto);
}
.opcion-pack__precio {
  font-size: 1rem;
  font-weight: 600;
  color: var(--acento);
}
.opcion-pack__unitario {
  font-size: .82rem;
  color: var(--texto-3);
}

.caja-pago {
  padding: 12px 14px;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--fondo-2);
  margin-bottom: 14px;
}
.caja-pago__linea {
  display: flex;
  justify-content: space-between;
  padding-block: 3px;
}

/* ==========================================================================
   Capa de movimiento

   Lo poco que se mueve por cuenta propia. Las clases las pone `movimiento.js`,
   nunca el HTML: sin JavaScript la página se ve entera y en su sitio.
   ========================================================================== */
.barra.esta-desplazada { border-bottom-color: var(--borde-fuerte); }

/* Subrayado que viaja entre pestañas. */
.pestanas--con-indicador { position: relative; }
.pestanas__indicador {
  position: absolute;
  bottom: 0;
  left: 0;
  width: var(--ancho, 0);
  height: 2px;
  opacity: 0;
  pointer-events: none;
  background: var(--acento);
  transform: translateX(var(--x, 0));
  transition:
    transform 340ms var(--curva),
    width 340ms var(--curva),
    opacity var(--t-rapida) var(--curva);
}
.pestanas__indicador--visible { opacity: 1; }
.pestanas--con-indicador .pestana[aria-selected="true"]::after { opacity: 0; }

/* Tiras de pestañas que se desplazan de lado: el degradado de los bordes avisa
   de que hay más a los lados. Las clases las pone `movimiento.js`. */
.pestanas--desplazable { scroll-behavior: smooth; }
.pestanas--desplazable.hay-antes.hay-despues {
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 22px, #000 calc(100% - 22px), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 22px, #000 calc(100% - 22px), transparent 100%);
}
.pestanas--desplazable.hay-antes:not(.hay-despues) {
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 22px);
  mask-image: linear-gradient(90deg, transparent 0, #000 22px);
}
.pestanas--desplazable:not(.hay-antes).hay-despues {
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 22px), transparent 100%);
  mask-image: linear-gradient(90deg, #000 calc(100% - 22px), transparent 100%);
}

/* Entrada del código QR: se anima el marco, nunca el dato. Una línea cruzando
   el código arruinaría lecturas en la puerta. */
@keyframes entrarQr { from { opacity: 0; transform: scale(.97); } to { opacity: 1; transform: none; } }
.qr-caja svg { animation: entrarQr var(--t-media) var(--curva) both; }

/* Filas y packs entran escalonados. */
@keyframes entrarFila { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
tbody tr { animation: entrarFila var(--t-media) var(--curva) backwards; }
tbody tr:nth-child(1) { animation-delay: 0ms; }
tbody tr:nth-child(2) { animation-delay: 24ms; }
tbody tr:nth-child(3) { animation-delay: 48ms; }
tbody tr:nth-child(4) { animation-delay: 72ms; }
tbody tr:nth-child(5) { animation-delay: 96ms; }
tbody tr:nth-child(6) { animation-delay: 120ms; }
tbody tr:nth-child(7) { animation-delay: 144ms; }
tbody tr:nth-child(8) { animation-delay: 168ms; }
tbody tr:nth-child(n+9) { animation-delay: 192ms; }

.pack { animation: entrarFila var(--t-media) var(--curva) backwards; }
.pack:nth-child(1) { animation-delay: 0ms; }
.pack:nth-child(2) { animation-delay: 60ms; }
.pack:nth-child(3) { animation-delay: 120ms; }
.pack:nth-child(n+4) { animation-delay: 180ms; }

/* El número que queda tras un escaneo entra con un golpe corto: es el dato que
   la persona de la puerta necesita leer sin pensar. */
@keyframes golpeRestantes {
  from { opacity: 0; transform: scale(1.12); }
  to { opacity: 1; transform: none; }
}
.resultado__restantes { animation: golpeRestantes 300ms var(--curva) both; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  /* Quien pide menos movimiento no puede quedarse con bloques invisibles. */
  .revelar { opacity: 1 !important; }
  .pestanas--desplazable { scroll-behavior: auto; }
}

/* --------------------------------------------------------------------------
   Adaptaciones generales
   -------------------------------------------------------------------------- */

@media (max-width: 620px) {
  /* Cuatro métricas a pantalla completa ocupaban media pantalla: en móvil van
     de dos en dos. */
  .rejilla--metricas { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .rejilla--metricas .tarjeta { padding: 14px; }
  .rejilla--metricas .metrica__valor { font-size: 1.45rem; }

  .ficha__cabecera { gap: 14px; }
  .avatar { width: 48px; height: 48px; font-size: 1.05rem; }
  .ficha__acciones { width: 100%; }
  .ficha__acciones .boton { flex: 1 1 auto; }
  .semana__fila { grid-template-columns: 64px 1fr 26px; }
}

@media (max-width: 480px) {
  .lista__item { flex-wrap: wrap; }
  .lista__item > .crece { flex: 1 1 62%; }
  .recuperar__acciones { width: 100%; }
  .recuperar__acciones .boton { flex: 1 1 auto; }
}

@media (max-width: 560px) {
  /* En un teléfono no caben en una línea la marca, tres destinos y dos
     acciones. La navegación baja a su propia línea, que se desplaza de lado. */
  .barra__interior { flex-wrap: wrap; row-gap: 6px; padding-block: 8px; }
  .barra__nav {
    order: 3;
    flex: 1 0 100%;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    min-width: 0;
  }
  .barra__nav::-webkit-scrollbar { display: none; }
  .barra__nav .boton { white-space: nowrap; }

  /* Se ocultan a la vista pero siguen anunciándose en el lector de pantalla:
     con display:none el estado de conexión sería un punto de color sin nombre. */
  .estado-conexion span:not(.punto),
  .barra__marca span:last-child {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* --------------------------------------------------------------------------
   Pase físico (QR impreso)
   -------------------------------------------------------------------------- */

.pase {
  width: 86mm;
  margin: 0 auto;
  padding: 0 6mm 7mm;
  overflow: hidden;
  border: 1px solid #111;
  border-radius: 2mm;
  background: #fff;
  color: #000;
  text-align: center;
  font-family: var(--fuente);
}
.pase__cabecera {
  margin: 0 -6mm 5mm;
  padding: 5mm 6mm 4mm;
  background: #111;
  /* El filete verde de la marca: lo único de color que lleva la hoja. */
  border-bottom: 1.5mm solid #93d241;
}
.pase__marca { display: grid; place-items: center; }
.pase__logo { display: block; width: 100%; max-width: 50mm; height: auto; }
.pase__titulo { margin-top: 3mm; color: #fff; font-size: 11pt; font-weight: 600; letter-spacing: .01em; }
.pase__qr svg { width: 55mm; height: 55mm; display: block; margin: 0 auto; }
.pase__codigo { font-family: var(--mono); font-size: 13pt; font-weight: 600; letter-spacing: .08em; margin-top: 3mm; }
.pase__cliente { font-size: 10pt; margin-top: 1mm; }
.pase__pie { font-size: 8pt; margin-top: 3mm; color: #555; }

/* ==========================================================================
   PIT LANE EDITORIAL — capa visual unificada
   ========================================================================== */

:root {
  --fondo: #000000;
  --fondo-2: #080b0c;
  --superficie: #0d1214;
  --superficie-2: #151c1e;
  --borde: rgba(226, 240, 231, .12);
  --borde-fuerte: rgba(226, 240, 231, .28);
  --borde-campo: rgba(226, 240, 231, .4);
  --texto: #f3f7f4;
  --texto-2: #b7c4bc;
  --texto-3: #7e8d84;
  --acento: #93d241;
  --acento-2: #93d241;
  --acento-suave: rgba(147, 210, 65, .1);
  --acento-borde: rgba(147, 210, 65, .42);
  --sobre-acento: #041006;
  --ok: #93d241;
  --ok-suave: rgba(147, 210, 65, .1);
  --alerta: #ffd166;
  --alerta-suave: rgba(255, 209, 102, .1);
  --error: #ff746d;
  --error-suave: rgba(255, 116, 109, .1);
  --radio: 16px;
  --radio-s: 11px;
  --radio-xs: 7px;
  --sombra-baja: 0 18px 50px -38px rgba(0, 0, 0, .9);
  --sombra: 0 26px 70px -38px rgba(0, 0, 0, .95);
  --sombra-alta: 0 38px 100px -42px rgba(0, 0, 0, .98);
  --curva: cubic-bezier(.22, 1, .36, 1);
  --curva-entrada: cubic-bezier(.4, 0, .2, 1);
  --transicion: 180ms var(--curva);
}

html {
  background: var(--fondo);
  scroll-padding-top: 84px;
}

body {
  background:
    radial-gradient(circle at 88% -8%, rgba(147, 210, 65, .065), transparent 28rem),
    radial-gradient(circle at 8% 96%, rgba(147, 210, 65, .035), transparent 24rem),
    var(--fondo);
  color: var(--texto);
}

body::before {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  content: '';
  opacity: .2;
  background-image:
    linear-gradient(rgba(255, 255, 255, .022) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, .022) 1px, transparent 1px);
  background-size: 76px 76px;
  mask-image: linear-gradient(to bottom, #000, transparent 78%);
}

.contenedor { width: min(1240px, 100%); padding-inline: clamp(18px, 4vw, 42px); }
main { padding-block: clamp(20px, 4vw, 42px) clamp(82px, 12vh, 140px); }

.barra {
  background: rgba(4, 7, 8, .78);
  border-bottom-color: rgba(226, 240, 231, .16);
  box-shadow: 0 16px 36px -28px rgba(0, 0, 0, .95);
}
.barra::after {
  display: block;
  height: 1px;
  content: '';
  background: linear-gradient(90deg, transparent, rgba(147, 210, 65, .55), transparent);
  opacity: .55;
}
.barra__interior {
  min-height: 72px;
  gap: 8px;
  padding-block: 11px;
}
.barra__marca {
  gap: 11px;
  color: var(--texto);
  letter-spacing: 0;
}
.barra__marca::after {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  content: '';
  background: var(--acento);
  box-shadow: 0 0 0 5px rgba(147, 210, 65, .08), 0 0 18px rgba(147, 210, 65, .55);
}
.marca__logo { height: 28px; }
.barra__nav { gap: 4px; }
.boton--nav {
  position: relative;
  min-height: 38px;
  padding-inline: 13px;
  color: var(--texto-3);
  border-radius: 999px;
  transition: color var(--transicion), background-color var(--transicion), transform var(--transicion);
}
.boton--nav:hover { color: var(--texto); background: rgba(226, 240, 231, .06); }
.boton--nav[aria-current="page"] {
  color: var(--texto);
  background: rgba(147, 210, 65, .09);
}
.boton--nav[aria-current="page"]::after {
  position: absolute;
  right: 14px;
  bottom: 4px;
  left: 14px;
  height: 2px;
  border-radius: 999px;
  content: '';
  background: var(--acento);
  box-shadow: 0 0 14px rgba(147, 210, 65, .7);
}
.estado-conexion {
  margin-inline: 6px;
  padding: 6px 10px;
  border: 1px solid var(--borde);
  border-radius: 999px;
  background: rgba(226, 240, 231, .035);
  font-size: .74rem;
}
.estado-conexion .punto { width: 6px; height: 6px; }

.encabezado-pista {
  position: relative;
  padding: clamp(24px, 5vw, 54px) 0 clamp(22px, 3vw, 34px);
  border-bottom-color: rgba(226, 240, 231, .2);
}
.encabezado-pista::after {
  position: absolute;
  right: 0;
  bottom: -1px;
  width: min(180px, 28%);
  height: 2px;
  content: '';
  background: var(--acento);
  box-shadow: 0 0 18px rgba(147, 210, 65, .35);
}
.encabezado-pista h1 {
  max-width: 15ch;
  font-size: clamp(2.3rem, 5vw, 4.6rem);
  letter-spacing: 0;
  line-height: .96;
}
.encabezado-pista p { max-width: 58ch; margin-top: 10px; color: var(--texto-2); }
.seccion-marca {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 12px;
  color: var(--acento);
  font-family: var(--mono);
  font-size: .67rem;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.seccion-marca::before {
  width: 20px;
  height: 1px;
  content: '';
  background: currentColor;
  box-shadow: 0 0 10px currentColor;
}

.rejilla { gap: clamp(14px, 2.2vw, 24px); }
.tarjeta {
  position: relative;
  overflow: hidden;
  padding: clamp(20px, 3vw, 30px);
  border-color: var(--borde);
  border-radius: var(--radio);
  background:
    linear-gradient(135deg, rgba(255, 255, 255, .028), transparent 38%),
    var(--superficie);
  box-shadow: var(--sombra-baja);
  transition: border-color var(--t-hover) var(--curva-hover), box-shadow var(--t-hover) var(--curva-hover);
}
.tarjeta::before {
  position: absolute;
  top: 0;
  right: 20px;
  left: 20px;
  height: 1px;
  content: '';
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .14), transparent);
}
.tarjeta__titulo { margin-bottom: clamp(16px, 2.4vw, 24px); }
.tarjeta__titulo h2,
.tarjeta__titulo h3 { font-size: clamp(1.12rem, 1.8vw, 1.42rem); letter-spacing: 0; }
.metrica {
  position: relative;
  min-height: 118px;
  align-content: end;
  padding: 18px;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: rgba(13, 18, 20, .72);
}
.metrica::before {
  position: absolute;
  top: 16px;
  left: 18px;
  width: 28px;
  height: 2px;
  content: '';
  background: var(--borde-fuerte);
}
.metrica__valor { font-size: clamp(1.8rem, 3.4vw, 2.6rem); letter-spacing: 0; }
.metrica__etiqueta { color: var(--texto-3); }

.saldo {
  position: relative;
  min-height: 250px;
  overflow: hidden;
  place-items: start;
  justify-items: start;
  align-content: center;
  gap: 8px;
  padding: clamp(30px, 6vw, 64px);
  border-color: rgba(147, 210, 65, .34);
  border-radius: calc(var(--radio) + 4px);
  background:
    radial-gradient(circle at 88% 18%, rgba(147, 210, 65, .2), transparent 19rem),
    linear-gradient(115deg, rgba(147, 210, 65, .055), transparent 42%),
    var(--superficie);
  text-align: left;
  box-shadow: 0 28px 90px -44px rgba(147, 210, 65, .35), var(--sombra);
}
.saldo::before {
  position: absolute;
  top: 26px;
  left: clamp(30px, 6vw, 64px);
  content: 'PASE EN VIVO';
  color: var(--acento);
  font-family: var(--mono);
  font-size: .64rem;
  letter-spacing: .18em;
}
.saldo::after {
  position: absolute;
  right: clamp(26px, 6vw, 64px);
  bottom: 28px;
  width: 96px;
  height: 96px;
  border: 1px solid rgba(147, 210, 65, .26);
  border-radius: 50%;
  content: '';
  opacity: .75;
  box-shadow: 0 0 0 12px rgba(147, 210, 65, .025), 0 0 0 24px rgba(147, 210, 65, .02);
}
.saldo__numero {
  position: relative;
  z-index: 1;
  font-size: clamp(5.2rem, 15vw, 10rem);
  font-weight: 620;
  letter-spacing: 0;
  text-shadow: 0 0 30px rgba(147, 210, 65, .23);
}
.saldo__texto { position: relative; z-index: 1; color: var(--texto-2); font-size: 1rem; }

.qr-caja {
  padding: clamp(20px, 3vw, 32px);
  border-color: rgba(0, 0, 0, .45);
  border-radius: var(--radio);
  box-shadow: 0 20px 44px -30px rgba(0, 0, 0, .8);
}
.qr-caja::after {
  position: absolute;
  inset: 10px;
  border: 1px solid rgba(0, 0, 0, .08);
  border-radius: calc(var(--radio) - 4px);
  pointer-events: none;
  content: '';
}
.qr-caja svg { width: min(294px, 66vw); }
.qr-pie { color: var(--texto-2); }
.codigo-grande { color: var(--texto); letter-spacing: .08em; }

.pack {
  padding: 20px;
  border-color: var(--borde);
  border-radius: var(--radio);
  background: var(--superficie);
}
.pack__restantes { font-size: 2.15rem; color: var(--acento); }

.boton {
  min-height: 44px;
  border-radius: 999px;
  box-shadow: none;
  transition: background-color var(--transicion), border-color var(--transicion), color var(--transicion), box-shadow var(--transicion), transform var(--transicion);
}
.boton:hover:not(:disabled) { transform: translateY(-1px); }
.boton:active:not(:disabled) { transform: translateY(1px); }
.boton--principal {
  position: relative;
  overflow: hidden;
  background: var(--acento);
  border-color: var(--acento);
  color: var(--sobre-acento);
  box-shadow: 0 12px 28px -18px rgba(147, 210, 65, .9);
}
.boton--principal::after {
  position: absolute;
  inset: 0;
  content: '';
  pointer-events: none;
  background: linear-gradient(110deg, transparent 32%, rgba(255, 255, 255, .36) 50%, transparent 68%);
  transform: translateX(-125%);
}
.boton--principal:hover:not(:disabled) { background: var(--acento-2); border-color: var(--acento-2); color: var(--sobre-acento); box-shadow: 0 14px 34px -16px rgba(147, 210, 65, .9); }
.boton--principal:hover:not(:disabled)::after { animation: barrido-control 650ms var(--curva); }
.boton--fantasma { background: rgba(226, 240, 231, .025); border-color: var(--borde-fuerte); }
.boton--fantasma:hover:not(:disabled) { background: rgba(226, 240, 231, .08); border-color: var(--texto-2); }
.boton--chico { min-height: 38px; padding: 8px 14px; font-size: .72rem; letter-spacing: .06em; text-transform: uppercase; }
.boton--grande { min-height: 54px; padding-inline: 28px; }

.campo { gap: 7px; margin-bottom: 22px; }
.campo > label,
.campo__etiqueta {
  color: var(--texto-2);
  font-size: .7rem;
  font-weight: 650;
  letter-spacing: .1em;
  text-transform: uppercase;
}
input, select, textarea {
  min-height: 48px;
  border-color: rgba(226, 240, 231, .24);
  border-radius: var(--radio-s);
  background: rgba(0, 0, 0, .24);
  transition: border-color var(--transicion), box-shadow var(--transicion), background-color var(--transicion);
}
input:hover:not(:disabled), select:hover:not(:disabled), textarea:hover:not(:disabled) { border-color: var(--borde-campo); background: rgba(0, 0, 0, .36); }
input:focus, select:focus, textarea:focus { background: rgba(0, 0, 0, .42); box-shadow: 0 0 0 4px rgba(147, 210, 65, .1), 0 0 24px -10px rgba(147, 210, 65, .7); }
.aviso { border-radius: var(--radio-s); box-shadow: var(--sombra-baja); }
.etiqueta { padding: 5px 10px; border-radius: 999px; font-size: .68rem; letter-spacing: .08em; text-transform: uppercase; }
.vacio { padding: 48px 22px; }
.cargando { filter: drop-shadow(0 0 8px rgba(147, 210, 65, .45)); }

.pestanas {
  gap: 6px;
  margin-bottom: clamp(22px, 3vw, 34px);
  padding: 5px;
  border: 1px solid var(--borde);
  border-radius: 999px;
  background: rgba(226, 240, 231, .035);
}
.pestana {
  min-height: 40px;
  padding: 8px 16px;
  border-radius: 999px;
  transition: color var(--transicion), background-color var(--transicion), transform var(--transicion);
}
.pestana:hover { background: rgba(226, 240, 231, .06); }
.pestana[aria-selected="true"] { background: var(--acento); color: var(--sobre-acento); }
.pestana[aria-selected="true"]::after { display: none; }
.dialogo-ancho { border-color: var(--borde-fuerte); border-radius: calc(var(--radio) + 4px); background: #0b1012; box-shadow: var(--sombra-alta); }
dialog::backdrop { background: rgba(0, 0, 0, .74); backdrop-filter: blur(8px); }

.escaner {
  border-color: rgba(147, 210, 65, .28);
  border-radius: var(--radio);
  background: #020303;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .05), 0 24px 60px -34px rgba(147, 210, 65, .35);
}
.escaner__mira {
  width: min(68%, 320px);
  border-radius: var(--radio);
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .66), 0 0 48px -8px rgba(147, 210, 65, .5);
}
.escaner__mira::before,
.escaner__mira::after { width: 42px; height: 42px; border-color: var(--mira); filter: drop-shadow(0 0 6px var(--mira)); }
.resultado {
  min-height: 220px;
  align-content: center;
  border-radius: var(--radio);
  background:
    radial-gradient(circle at 50% 0, rgba(147, 210, 65, .11), transparent 18rem),
    var(--superficie);
}
.resultado__icono { font-size: 2.6rem; filter: drop-shadow(0 0 14px currentColor); }
.resultado__titulo { font-size: clamp(1.45rem, 3vw, 2rem); letter-spacing: 0; }
.resultado__restantes { font-size: clamp(4rem, 13vw, 6rem); color: var(--acento); text-shadow: 0 0 26px rgba(147, 210, 65, .35); }
.selector-cantidad { padding: 10px 0; }
.btn-cantidad { min-width: 46px; height: 46px; border-radius: 999px; }
.btn-cantidad.activo { box-shadow: 0 0 0 5px rgba(147, 210, 65, .1), 0 0 20px -5px rgba(147, 210, 65, .6); }

.tabla-envoltura { border: 1px solid var(--borde); border-radius: var(--radio); }
table { font-size: .9rem; }
thead th { padding-top: 14px; background: rgba(226, 240, 231, .03); }
.lista__item { padding-block: 16px; }
.opcion-pack {
  min-height: 102px;
  justify-content: space-between;
  padding: 16px;
  border: 1px solid var(--borde);
  border-radius: var(--radio-s);
  background: var(--superficie);
}
.opcion-pack:hover { border-color: var(--borde-fuerte); background: var(--superficie-2); }
.opcion-pack.activo { border-color: var(--acento); background: var(--acento-suave); box-shadow: 0 0 0 4px rgba(147, 210, 65, .08); }

.revelar { opacity: 0; transform: translateY(16px); }
.revelar--visible { opacity: 1; transform: none; transition: opacity 620ms var(--curva) var(--animation-delay, 0ms), transform 720ms var(--curva) var(--animation-delay, 0ms); }

@keyframes barrido-control { to { transform: translateX(125%); } }

@media (max-width: 900px) {
  .encabezado-pista h1 { font-size: clamp(2.2rem, 8vw, 3.8rem); }
  .estado-conexion { display: none; }
}
@media (max-width: 620px) {
  .contenedor { padding-inline: 16px; }
  main { padding-top: 14px; }
  .barra__interior { min-height: 62px; }
  .barra__marca::after { display: none; }
  .barra__nav { gap: 2px; }
  .boton--nav { padding-inline: 11px; }
  .encabezado-pista { padding-block: 24px 20px; }
  .encabezado-pista h1 { font-size: clamp(2.1rem, 12vw, 3.1rem); }
  .encabezado-pista::after { width: 92px; }
  .tarjeta { padding: 18px; }
  .saldo { min-height: 224px; padding: 44px 24px 30px; }
  .saldo::before { left: 24px; }
  .saldo::after { right: 20px; bottom: 20px; width: 72px; height: 72px; }
  .saldo__numero { font-size: clamp(5rem, 25vw, 7.4rem); }
  .rejilla--2,
  .rejilla--resumen { grid-template-columns: 1fr; }
  .pestanas { justify-content: flex-start; overflow-x: auto; border-radius: var(--radio); }
  .pestana { flex: 0 0 auto; }
  .resultado { min-height: 196px; }
  .resultado__titulo { font-size: 1.42rem; }
  .escaner__mira { width: min(76%, 300px); }
}

@media (prefers-reduced-motion: reduce) {
  .revelar,
  .revelar--visible { opacity: 1 !important; transform: none !important; transition: none !important; }
  .boton:hover:not(:disabled),
  .opcion-pack:hover { transform: none; }
  .boton--principal:hover:not(:disabled)::after { animation: none; }
}

/* ==========================================================================
   Sistema de interacción

   La interfaz responde como una pieza de pit lane: el hover prepara, el clic
   confirma y las superficies activas ganan un filo de luz. Los cambios de
   posición se reservan a dispositivos que realmente tienen puntero para que
   tocar una tarjeta no produzca estados pegajosos en móvil.
   ========================================================================== */

.boton {
  --hover-shadow: var(--sombra-hover);
  transition:
    background-color var(--t-hover) var(--curva-hover),
    border-color var(--t-hover) var(--curva-hover),
    color var(--t-hover) var(--curva-hover),
    box-shadow var(--t-hover) var(--curva-hover),
    transform var(--t-hover) var(--curva-hover),
    opacity var(--t-hover) var(--curva-hover);
}
.boton--peligro { --hover-shadow: 0 18px 42px -24px rgba(255, 111, 104, .58); }
.boton--ok { --hover-shadow: 0 18px 42px -24px rgba(147, 210, 65, .58); }
.boton:active:not(:disabled) {
  transform: translateY(1px) scale(.985);
  transition-duration: 90ms;
}

input, select, textarea {
  transition:
    border-color var(--t-hover) var(--curva-hover),
    box-shadow var(--t-hover) var(--curva-hover),
    background-color var(--t-hover) var(--curva-hover),
    transform var(--t-hover) var(--curva-hover);
}
.opcion-pack {
  transition:
    border-color var(--t-hover) var(--curva-hover),
    background-color var(--t-hover) var(--curva-hover),
    box-shadow var(--t-hover) var(--curva-hover),
    transform var(--t-hover) var(--curva-hover);
}
.pestana,
.lista__item,
.ficha__volver,
.grafico__barra {
  transition:
    background-color var(--t-hover) var(--curva-hover),
    border-color var(--t-hover) var(--curva-hover),
    color var(--t-hover) var(--curva-hover),
    box-shadow var(--t-hover) var(--curva-hover),
    transform var(--t-hover) var(--curva-hover);
}

@media (hover: hover) {
  .boton:hover:not(:disabled) {
    transform: translateY(-2px);
    box-shadow: var(--hover-shadow);
  }
  .boton--enlace:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: none;
  }
  .boton--nav:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: inset 0 -2px 0 var(--acento);
  }

  .opcion-pack:hover {
    transform: translateY(-3px);
    border-color: var(--acento-borde);
    background: var(--superficie-2);
    box-shadow: 0 16px 38px -26px rgba(147, 210, 65, .42);
  }

  /* Un campo no se mueve bajo el puntero: solo se ilumina. Si saltara, el
     texto que se está escribiendo bailaría con cada pasada del ratón. */
  input:hover:not(:disabled),
  select:hover:not(:disabled),
  textarea:hover:not(:disabled) {
    box-shadow: 0 12px 28px -24px rgba(147, 210, 65, .78);
  }
  .pestana:hover {
    color: var(--texto);
    transform: translateY(-2px);
  }
  .pestana[aria-selected="true"]:hover {
    box-shadow: 0 10px 24px -18px rgba(147, 210, 65, .9);
  }
  .btn-cantidad:hover {
    transform: translateY(-2px) scale(1.06);
    border-color: var(--acento);
    color: var(--texto);
    box-shadow: 0 12px 26px -20px rgba(147, 210, 65, .84);
  }
  .opcion-lista:hover {
    transform: translateX(3px);
    box-shadow: inset 3px 0 0 var(--acento);
  }
  .ficha__volver:hover { transform: translateX(4px); }
}

@media (prefers-reduced-motion: reduce) {
  .boton:hover:not(:disabled),
  .boton:active:not(:disabled),
  .opcion-pack:hover,
  input:hover:not(:disabled),
  select:hover:not(:disabled),
  textarea:hover:not(:disabled),
  .pestana:hover,
  .btn-cantidad:hover,
  .opcion-lista:hover,
  .ficha__volver:hover { transform: none !important; }
}
/* ---------------------------------------------------------------------------
   Verificación en dos pasos
   El QR se dibuja en el servidor y llega como imagen: se le pone fondo blanco
   propio porque un QR sobre el negro de la marca no lo lee ninguna cámara.
   --------------------------------------------------------------------------- */
.qr-dos-factores {
  display: block;
  width: min(220px, 60vw);
  height: auto;
  margin: var(--e3) auto;
  padding: 10px;
  border-radius: var(--radio);
  background: #fff;
  border: 1px solid var(--borde);
}

/* La clave escrita a mano: en grupos de cuatro y con espacio entre caracteres,
   que es lo que hace que no se confunda una letra al teclearla. */
.clave-manual {
  display: block;
  margin-top: 6px;
  padding: 10px 12px;
  border: 1px dashed var(--borde-fuerte);
  border-radius: var(--radio);
  background: var(--superficie-2);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 1rem;
  letter-spacing: .12em;
  word-break: break-all;
  user-select: all;
}

.lista-codigos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 6px 12px;
  margin: var(--e3) 0;
  padding: 0;
  list-style: none;
}
.lista-codigos code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .95rem;
  letter-spacing: .08em;
  user-select: all;
}

.tarjeta--suave { background: var(--superficie-2); border-color: var(--borde); }

.fila-acciones { display: flex; flex-wrap: wrap; gap: 8px; margin-top: var(--e3); }

.pasos { margin: var(--e3) 0; padding-left: 1.2em; display: grid; gap: 6px; color: var(--texto-2); }

/* ==========================================================================
   Tipografía de pista y hovers de alto voltaje

   La última palabra sobre cómo se lee y cómo responde la interfaz.

   Tipos. Saira ancha (wdth 125) es la voz de carrera: titulares en versales,
   cifras y rótulos, siempre con aire positivo entre letras —ninguna letra
   toca a su vecina—. Sora lleva todo el texto corrido. La mono queda solo
   para lo que se teclea o se compara carácter a carácter: códigos y claves.

   Hovers. Cada control reacciona como un coche en parrilla: se inclina un
   poco más hacia delante, sube un par de píxeles y un brillo lo cruza una
   sola vez. Nada parpadea en bucle ni cambia de ancho al pasar por encima:
   un botón que se estira mueve el texto de alrededor. Lo intenso vive dentro
   de `(hover: hover)`; en táctil queda la respuesta al toque, y quien pide
   menos movimiento recibe los estados finales sin viaje.
   ========================================================================== */

:root {
  --track-display: .018em;
  --track-titular: .012em;
  --track-rotulo: .2em;
  --track-boton: .11em;
  --curva-turbo: cubic-bezier(.19, 1, .22, 1);
  --curva-resorte: cubic-bezier(.34, 1.56, .64, 1);
  /* Los movimientos de hover comparten el mismo tiempo de llegada. */
  --t-turbo: var(--t-hover);
  --inclinacion: -13deg;
  --estela: rgba(147, 210, 65, .9);
}

/* --- Texto corrido ------------------------------------------------------ */

body {
  font-family: var(--fuente);
  font-weight: 400;
  letter-spacing: .004em;
  line-height: 1.62;
  font-optical-sizing: auto;
  font-synthesis: none;
}

p, li, td, dd { text-wrap: pretty; }

/* Los controles del navegador no heredan la letra por defecto: sin esto, un
   <button> que no es `.boton` —la opción de un pack, por ejemplo— sale en
   la fuente del sistema. */
button, input, select, textarea { font-family: inherit; }

.opcion-pack__entradas {
  font-family: var(--display);
  font-stretch: 118%;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.opcion-pack__precio {
  font-family: var(--display);
  font-stretch: 112%;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
}

/* --- Titulares: la voz de carrera ----------------------------------------- */

h1,
h2,
h3,
.encabezado-pista h1,
.tarjeta__titulo h2,
.tarjeta__titulo h3,
.ficha__nombre,
.resultado__titulo,
.barra__marca {
  font-family: var(--display);
  font-stretch: 118%;
  font-weight: 700;
  letter-spacing: var(--track-titular);
  line-height: 1.04;
  font-kerning: normal;
  /* Saira se escribe en versales: en caja baja su «y» parece una «u» con
     cola, y en mayúsculas todas sus letras son limpias y de pista. */
  text-transform: uppercase;
}

h2,
h3,
.tarjeta__titulo h2,
.tarjeta__titulo h3,
.resultado__titulo { letter-spacing: .04em; }

.tarjeta__titulo h2,
.tarjeta__titulo h3 { font-size: clamp(1rem, 1.45vw, 1.18rem); }

.encabezado-pista h1 {
  font-stretch: 125%;
  font-weight: 800;
  line-height: .96;
  letter-spacing: var(--track-display);
  text-transform: uppercase;
}

/* --- Cifras: dígitos anchos, iguales y alineados -------------------------- */

.saldo__numero,
.metrica__valor,
.pack__restantes,
.mini-pack__saldo,
.resultado__restantes {
  font-family: var(--display);
  font-stretch: 125%;
  font-weight: 700;
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: .01em;
}

.saldo__numero { font-weight: 800; line-height: .9; }

/* En la rejilla de métricas un importe como «$1.250,00» tiene que caber en
   una tarjeta estrecha: se estrecha el ancho de la letra antes que el tamaño. */
.metrica__valor {
  font-stretch: 106%;
  font-size: clamp(1.4rem, 2.1vw, 1.95rem);
  line-height: 1.05;
  white-space: nowrap;
  overflow-wrap: normal;
}

/* --- Rótulos: versales anchas con mucho aire ------------------------------ */

.campo > label,
.campo__etiqueta,
.seccion-marca,
.etiqueta,
.saldo::before,
th {
  font-family: var(--display);
  font-stretch: 122%;
  font-weight: 600;
  letter-spacing: var(--track-rotulo);
  text-transform: uppercase;
}

.campo > label,
.campo__etiqueta { font-size: .68rem; letter-spacing: .16em; }

/* --- Botones: chasis inclinado ------------------------------------------- */

/* El botón deja de ser una pastilla y pasa a ser un chasis: el fondo se
   dibuja en `::before`, inclinado hacia delante como el número de un coche
   de carreras, y el texto queda recto encima. Así el halo no se recorta y la
   inclinación no deforma las letras.

   Los colores del chasis se declaran con la especificidad mínima de `.boton`:
   así cada variante (`.boton.boton--principal`, `--fantasma`…) los pisa. Si
   vivieran en la regla de abajo, sus dos :not() les darían más peso que a
   cualquier variante y todos los botones saldrían grises. */
.boton {
  --chasis: var(--superficie-2);
  --chasis-borde: var(--borde-fuerte);
  --chasis-halo: 0 0 0 0 transparent;
  --texto-boton: var(--texto);
}
.boton:not(.boton--enlace):not(.boton--nav) {
  position: relative;
  isolation: isolate;
  overflow: visible;
  border-color: transparent;
  border-radius: 0;
  background: transparent;
  color: var(--texto-boton);
  box-shadow: none;
  font-family: var(--display);
  font-stretch: 116%;
  font-weight: 650;
  font-size: .8rem;
  letter-spacing: var(--track-boton);
  text-transform: uppercase;
  padding-inline: 26px;
  transition:
    color var(--t-hover) var(--curva-hover),
    transform var(--t-turbo) var(--curva-turbo),
    opacity var(--t-hover) var(--curva-hover);
}

.boton:not(.boton--enlace):not(.boton--nav)::before {
  position: absolute;
  /* La inclinación saca las esquinas unos 6 px por cada lado: se recogen
     aquí para que el chasis respete el margen de la página. */
  inset: 0 6px;
  z-index: -1;
  border-radius: 4px;
  content: '';
  pointer-events: none;
  background:
    linear-gradient(104deg, transparent 30%, rgba(255, 255, 255, .5) 47%, rgba(255, 255, 255, 0) 60%) -160% 0 / 60% 100% no-repeat,
    var(--chasis);
  box-shadow: inset 0 0 0 1px var(--chasis-borde), var(--chasis-halo);
  transform: skewX(var(--inclinacion));
  transition:
    background-color var(--t-hover) var(--curva-hover),
    box-shadow var(--t-turbo) var(--curva-turbo),
    transform var(--t-turbo) var(--curva-turbo);
}

/* El ::after de las capas anteriores (el barrido del botón principal) no
   vale para el chasis: el brillo ya lo lleva el ::before. */
.boton:not(.boton--enlace):not(.boton--nav)::after { content: none; }

.boton.boton--principal {
  --chasis: var(--acento);
  --chasis-borde: rgba(255, 255, 255, .22);
  --chasis-halo: 0 10px 26px -16px rgba(147, 210, 65, .7);
  --texto-boton: var(--sobre-acento);
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  color: var(--sobre-acento);
  font-weight: 750;
}

.boton.boton--fantasma { --chasis: rgba(226, 240, 231, .03); --chasis-borde: var(--borde-fuerte); --texto-boton: var(--texto-2); }
.boton.boton--peligro { --chasis: rgba(255, 116, 109, .05); --chasis-borde: rgba(255, 116, 109, .45); --texto-boton: var(--error); --estela: var(--error); --estela-2: rgba(255, 116, 109, .45); }
.boton.boton--ok { --chasis: rgba(147, 210, 65, .05); --chasis-borde: var(--acento-borde); --texto-boton: var(--ok); }
.boton.boton--chico { min-height: 36px; padding-inline: 16px; font-size: .68rem; letter-spacing: .12em; }
.boton.boton--grande { min-height: 54px; padding-inline: 34px; font-size: .86rem; }
.boton.boton--bloque { width: 100%; }

.boton:not(.boton--enlace):not(.boton--nav):disabled::before { background: var(--superficie-2); box-shadow: inset 0 0 0 1px var(--borde); }
.boton:not(.boton--enlace):not(.boton--nav):disabled { color: var(--texto-3); }

.boton:not(.boton--enlace):not(.boton--nav):focus-visible { outline: none; }
.boton:not(.boton--enlace):not(.boton--nav):focus-visible::before {
  box-shadow: inset 0 0 0 1px var(--chasis-borde), 0 0 0 2px var(--fondo), 0 0 0 4px var(--acento);
}

.boton:not(.boton--enlace):not(.boton--nav):active:not(:disabled) {
  transform: translateY(1px) scale(.97);
  transition-duration: 90ms;
}

.boton--enlace,
.boton--nav {
  font-family: var(--fuente);
  letter-spacing: .01em;
}

/* --- Pestañas del acceso -------------------------------------------------- */

.pestana {
  font-family: var(--display);
  font-stretch: 118%;
  font-weight: 650;
  font-size: .76rem;
  letter-spacing: .12em;
  text-transform: uppercase;
}

/* --- Campos: el rótulo se enciende con el foco ---------------------------- */

.campo > label { transition: color 240ms var(--curva-hover); }
.campo:focus-within > label { color: var(--acento); }
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  box-shadow: 0 0 0 1px var(--acento), 0 0 0 4px rgba(147, 210, 65, .14);
}

/* La pestaña activa es una píldora verde. Con movimiento, la píldora es el
   indicador que pone movimiento.js y viaja de una pestaña a otra en vez de
   apagarse aquí y encenderse allá; sin él, cada pestaña pinta la suya. */
.pestanas--con-indicador .pestanas__indicador {
  top: 5px;
  bottom: 5px;
  z-index: 0;
  height: auto;
  border-radius: 999px;
  box-shadow: 0 8px 22px -14px rgba(147, 210, 65, .8);
}
.pestanas--con-indicador .pestana {
  position: relative;
  z-index: 1;
  /* La pestaña que deja de estar activa suelta su verde al instante: la
     píldora sale de debajo. */
  transition: color 340ms var(--curva), background-color 0s;
}
/* La nueva activa pinta su propio verde cuando la píldora termina de llegar:
   mientras viaja, se ve la píldora; al llegar, la pestaña ya es legible por sí
   misma (texto oscuro sobre su propio fondo verde) sin depender de lo que
   tenga detrás. */
.pestanas--con-indicador .pestana[aria-selected="true"] { transition: color 340ms var(--curva), background-color 0s linear 340ms; }
/* La píldora no sube con el puntero: el texto tampoco, o se separarían. */
.pestanas--con-indicador .pestana:hover { transform: none; box-shadow: none; }

/* ==========================================================================
   Estados de hover (solo con puntero real)
   ========================================================================== */

@media (hover: hover) {
  /* Botones: sube, se inclina un poco más y un brillo lo cruza una vez. */
  .boton:not(.boton--enlace):not(.boton--nav):hover:not(:disabled) {
    transform: translateY(-2px);
    color: var(--texto-boton-hover, var(--texto-boton));
  }
  .boton:not(.boton--enlace):not(.boton--nav):hover:not(:disabled)::before {
    transform: skewX(-16deg) scaleX(1.02);
    background-position: 260% 0, 0 0;
    transition:
      background-position var(--t-hover) var(--curva-hover),
      box-shadow var(--t-hover) var(--curva-hover),
      transform var(--t-hover) var(--curva-hover);
  }
  .boton.boton--principal:hover:not(:disabled) {
    --chasis: #93d241;
    --chasis-halo: 0 0 0 1px rgba(147, 210, 65, .45), 0 16px 36px -14px rgba(147, 210, 65, .75);
    color: var(--sobre-acento);
    background: transparent;
    box-shadow: none;
  }
  .boton.boton--fantasma:hover:not(:disabled) {
    --chasis: rgba(147, 210, 65, .1);
    --chasis-borde: var(--acento);
    --chasis-halo: 0 0 28px -12px rgba(147, 210, 65, .55);
    --texto-boton-hover: var(--texto);
    background: transparent;
  }
  .boton.boton--peligro:hover:not(:disabled) {
    --chasis: rgba(255, 116, 109, .14);
    --chasis-borde: var(--error);
    --chasis-halo: 0 0 34px -10px rgba(255, 116, 109, .75);
    background: transparent;
  }
  .boton.boton--ok:hover:not(:disabled) {
    --chasis: rgba(147, 210, 65, .14);
    --chasis-borde: var(--acento);
    --chasis-halo: 0 0 34px -10px rgba(147, 210, 65, .7);
    background: transparent;
  }
  .boton:not(.boton--enlace):not(.boton--nav):not(.boton--principal):not(.boton--fantasma):not(.boton--peligro):not(.boton--ok):hover:not(:disabled) {
    --chasis-borde: var(--acento);
    --chasis-halo: 0 0 30px -12px rgba(147, 210, 65, .7);
  }

  .boton--nav:hover:not(:disabled) { color: var(--acento); }

  /* Pestañas */
  .pestana:hover { color: var(--texto); }
  .pestana[aria-selected="true"]:hover { color: var(--sobre-acento); }

}

@media (max-width: 620px) {
  /* Una palabra larga como «Administración» no se puede partir: en el
     teléfono la letra se recoge a lo ancho y baja de tamaño antes que
     desbordar la pantalla. */
  .encabezado-pista h1 {
    font-size: clamp(1.6rem, 7.4vw, 2.6rem);
    font-stretch: 108%;
    overflow-wrap: break-word;
  }
  h1, h2, h3 { overflow-wrap: break-word; }
  .boton.boton--grande { padding-inline: 28px; }
}

/* --- Menos movimiento: estados finales, sin viaje ------------------------- */

@media (prefers-reduced-motion: reduce) {
  .boton:not(.boton--enlace):not(.boton--nav):hover:not(:disabled),
.boton:not(.boton--enlace):not(.boton--nav):hover:not(:disabled)::before { transform: none !important; }
  .boton:not(.boton--enlace):not(.boton--nav)::before { transform: skewX(var(--inclinacion)) !important; }
  .pestanas--con-indicador .pestana { transition: none; }
}

@media print {
  /* En papel no hay lienzo negro: los tipos vuelven a la tinta y las
     superficies al blanco, o la hoja saldría en negativo. */
  :root {
    --fondo: #fff;
    --fondo-2: #fff;
    --superficie: #fff;
    --superficie-2: #fff;
    --texto: #000;
    --texto-2: #333;
    --texto-3: #555;
    --borde: #ccc;
    --borde-fuerte: #999;
    --acento: #93d241;
    --sombra: none;
    --sombra-alta: none;
  }
  body { background: #fff; color: #000; }
  /* El velo del diálogo es una mancha de tinta en papel. */
  dialog::backdrop { background: transparent; backdrop-filter: none; }
  /* Nada de lo que espera a entrar en pantalla puede salir en blanco en papel. */
  .revelar { opacity: 1 !important; }
  /* La portada tiene su propia cabecera y su propio pie, que no se llaman
     `.barra`: en papel tampoco pintan nada. */
  .barra,
.boton,
.brindis-zona { display: none !important; }
  .tarjeta, .pack { border: 1px solid #ccc; box-shadow: none; background: #fff; color: #000; }
  .qr-caja { min-height: auto; border: 0; }

  /* Al imprimir un pase, solo sale el pase: sin cabecera, panel ni diálogos. */
  .imprimiendo-pase > *:not(#pase-impreso) { display: none !important; }
  .imprimiendo-pase #pase-impreso { display: block !important; }
  .imprimiendo-pase dialog { display: none !important; }

  @page { margin: 10mm; }
}
