/**
 * components.css — Sistema de componentes reutilizables.
 * Button · Badge · Card · GameCard · SportCard · ProviderCard · Carousel
 * Marquee · Navigation · BottomNav · Accordion · AgeGate · Footer
 *
 * Regla transversal: nada accionable mide menos de var(--tap) (44px).
 * Y ningún estado se revela SOLO en hover — en táctil el primer toque se
 * consumiría revelando en vez de ejecutar la acción.
 */

/* ============================================================
   BUTTON
   ============================================================ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: var(--tap);
  padding: 0 var(--s-5);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  font-family: var(--f-body);
  font-weight: 700;
  font-size: var(--fs-sm);
  line-height: 1;
  text-align: center;
  white-space: nowrap;
  transition: background var(--d-fast) var(--ease-std),
              border-color var(--d-fast) var(--ease-std),
              color var(--d-fast) var(--ease-std),
              transform var(--d-fast) var(--ease-std);
  /* El toque no espera delay de 300ms ni dispara zoom accidental. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

/* Oro = ÚNICO color de acción. Solo los CTA de conversión lo usan. */
.btn--gold {
  background: var(--grad-cta);
  color: var(--cta-ink);
  box-shadow: var(--elev-cta);
}
.btn--gold:hover { background: var(--cta-hover); }
.btn--gold:active { transform: translateY(1px); }

.btn--ghost {
  background: var(--bg-surface);
  border-color: var(--border);
  color: var(--text-primary);
}
.btn--ghost:hover { background: var(--bg-elevated); border-color: var(--violet-accent); }
.btn--ghost:active { transform: translateY(1px); }

.btn--link {
  min-height: var(--tap);
  padding: 0;
  background: none;
  color: var(--cta);
  font-weight: 600;
}
.btn--link:hover { text-decoration: underline; }

.btn--lg { min-height: 52px; font-size: var(--fs-body); padding-inline: var(--s-6); }
.btn--block { width: 100%; }

.btn__icon { width: 18px; height: 18px; flex: 0 0 auto; }

/* ============================================================
   BADGE
   ============================================================ */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: var(--r-xs);
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.6;
}
.badge--gold { background: var(--cta); color: var(--cta-ink); }
.badge--violet { background: var(--violet-primary); color: #fff; }
.badge--outline { border: 1px solid var(--border); color: var(--text-secondary); }
/* Pasa a --live: el badge dejo de tomar prestado el rojo de error y usa
   el token semantico de "en vivo". Ver tokens.css. */
.badge--live { background: var(--live); color: var(--live-ink); }
.badge--live::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

/* ============================================================
   CARD
   ============================================================ */

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-5);
  background: var(--bg-surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
  transition: border-color var(--d-mid) var(--ease-std),
              transform var(--d-mid) var(--ease-out);
}
@media (hover: hover) {
  .card:hover { border-color: var(--border); transform: translateY(-3px); }
}

.card__icon {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: rgba(138, 43, 226, 0.16);
  color: var(--cta);
  flex: 0 0 auto;
}
.card__icon svg { width: 22px; height: 22px; }

.card__title { font-size: var(--fs-h3); font-weight: 700; }
.card__text { font-size: var(--fs-sm); color: var(--text-body); }

/* ============================================================
   GAME CARD — cuadrada, radio 10px como el lobby real
   ============================================================ */

.game-card {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--bg-elevated);
  border: 1px solid var(--border-soft);
  transition: transform var(--d-mid) var(--ease-out),
              border-color var(--d-mid) var(--ease-std);
}
@media (hover: hover) {
  .game-card:hover { transform: translateY(-4px); border-color: var(--violet-accent); }
}

.game-card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* Placeholder: patrón diagonal + nombre. Se ve claramente que falta. */
.game-card__ph {
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  padding: var(--s-3);
  text-align: center;
  background:
    repeating-linear-gradient(45deg, rgba(138, 43, 226, 0.1), rgba(138, 43, 226, 0.1) 8px, transparent 8px, transparent 16px),
    var(--bg-elevated);
  color: var(--text-muted);
  font-size: 10px;
  font-weight: 500;
  line-height: 1.4;
  /* El nombre del juego NO va aca: lo pinta .game-card__veil. */
  align-content: center;
}
.game-card__ph span { display: block; }
.game-card__ph-dim { font-size: 9px; opacity: 0.7; margin-top: 2px; }

.game-card__veil {
  position: absolute;
  inset: auto 0 0 0;
  padding: var(--s-5) var(--s-3) var(--s-3);
  background: var(--grad-card-veil);
}
.game-card__name {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 12px;
  color: #fff;
  line-height: 1.2;
}

/* Con 4 tarjetas por fila la tarjeta baja a ~57-93px de lado segun el
   viewport. A 12px un nombre largo ("Gates of Olympus 1000") envolvia a 5
   lineas y el velo (113px) terminaba mas alto que la propia tarjeta (75px):
   el texto se montaba sobre el placeholder.
   La tipografia y los paddings del interior se escalan con la tarjeta —
   con clamp, para que sigan el mismo ancho en vez de saltar por
   breakpoint. No se recorta ningun nombre. */
@media (max-width: 1023px) {
  .game-card__veil { padding: var(--s-4) 6px 6px; }
  .game-card__name {
    font-size: clamp(8px, 1.9vw, 11px);
    line-height: 1.15;
    /* Tope de 2 lineas con puntos suspensivos. Con 4 tarjetas por fila la
       tarjeta mide ~75px de lado, y un nombre de 33 caracteres ("John
       Hunter and the Aztec Treasure") necesita 99px aun a 8px: no entra
       por geometria, no por estilo. Es ademas el tratamiento habitual de
       una ficha de juego — el nombre completo sigue en el alt/DOM. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .game-card__ph { font-size: clamp(7px, 1.7vw, 10px); padding: 4px; }
  .game-card__ph-dim { display: none; }
  .game-card__badge { top: 4px; left: 4px; }
  .badge { padding: 2px 5px; font-size: 8px; letter-spacing: 0.06em; }
}
.game-card__badge { position: absolute; top: var(--s-2); left: var(--s-2); }

/* ============================================================
   SPORT CARD — cada deporte con su color real
   ============================================================ */

.sport-card {
  position: relative;
  display: flex;
  align-items: flex-end;
  /* Retrato 2:3. No es un numero de gusto: los 8 assets vienen en
     vertical, seis a 3:4 (0.75) y dos a 2:3 (0.667). Elegido 2:3 porque
     el recorte cae donde menos duele — un 3:4 dentro de un 2:3 pierde
     ~6% por cada lado, mientras que al reves perderia ~11% arriba y
     abajo, o sea cabezas y pies de las figuras. */
  aspect-ratio: 2 / 3;
  min-height: 0;
  padding: var(--s-3);
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--bg-elevated);
  border: 1px solid var(--border-soft);
  transition: transform var(--d-mid) var(--ease-out);
}
/* Contorno neon permanente (Desktop y Mobile). Se cambia el COLOR del
   borde que la tarjeta ya tenia — no se agrega uno nuevo — asi que la
   caja no cambia ni un pixel: mismo ancho, alto, aspect-ratio y gap.
   El halo va en box-shadow exterior, que tampoco ocupa layout. */
.sport-card {
  border-color: rgba(151, 71, 255, 0.5);
  box-shadow: var(--neon-glow);
}

/* La imagen ocupa la tarjeta entera: sin padding, sin marco interior.
   Va en position:absolute y no como background para que el navegador la
   trate como imagen real — lazy loading, decodificacion asincrona y
   soporte de srcset si mas adelante hace falta.
   z-index 0 la deja por DEBAJO del degradado de color (::after) y del
   nombre (z-index 1), que es lo que mantiene el texto legible sobre
   cualquier foto. */
.sport-card__img {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

/* Degradado to top desde el color del deporte: sistema real heredado.
   Con imagen detras deja de ser solo decoracion y pasa a ser el velo que
   garantiza el contraste del nombre — por eso sube de 0.85 a 0.92. */
.sport-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top,
    var(--sport) 0%,
    rgba(0, 0, 0, 0) 78%);
  opacity: 0.92;
}
@media (hover: hover) {
  .sport-card:hover { transform: translateY(-3px); }
}
.sport-card__name {
  position: relative;
  z-index: 1;
  font-family: var(--f-display);
  font-weight: 800;
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.65);
}
.sport-card__ico {
  position: absolute;
  top: var(--s-3);
  right: var(--s-3);
  z-index: 1;
  width: 24px;
  height: 24px;
  color: #fff;
  opacity: 0.9;
}

/* ============================================================
   PROVIDER CARD
   ============================================================ */

.provider-card {
  display: grid;
  place-items: center;
  min-width: 134px;
  height: 62px;
  padding: var(--s-3) var(--s-4);
  background: var(--bg-surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-sm);
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--text-secondary);
  text-align: center;
  line-height: 1.2;
  flex: 0 0 auto;
  transition: color var(--d-fast) var(--ease-std), border-color var(--d-fast) var(--ease-std);
}
/* El logo ocupa la caja de contenido del chip — el padding que ya tenía
   la ficha para el texto es justamente el aire que un logo necesita, así
   que no se agrega ninguno nuevo.
   contain y no cover: los assets son 400x160 (2.5) y la caja es 102x38
   (2.68). Con cover se recortarían los lados del logo, que en una marca
   es exactamente lo que no se puede hacer. Con contain entra entero,
   centrado y sin deformar. */
/* Ancho FIJO en el chip con logo, y no el min-width de siempre.
   El chip es display:grid con place-items:center, asi que su item no
   recibe un ancho definido: un <img> con width:100% ahi dentro cae a su
   ancho intrinseco (400px del PNG) y el chip se estiraba a 434px en vez
   de 134. Medido. Fijando el ancho, el area de grid pasa a ser definida,
   el 100% resuelve contra los 102px de la caja de contenido y el chip
   vuelve a medir exactamente lo que median los de texto. */
/* El chip con logo ES la imagen: sin padding, sin borde y sin fondo
   propio, para que no quede ni un pixel de marco alrededor.

   - padding 0 y border 0: son lo que hacia que la imagen midiera 132x60
     dentro de un chip de 134x62. Sin ellos, la caja de contenido coincide
     exactamente con el chip y la imagen mide 134x62 clavados.
   - background none: no hay nada detras que pueda asomar.
   - overflow hidden: recorta la imagen contra el radio del chip, asi las
     esquinas quedan perfectas y no sobresale nada.
   - width fija: el chip es display:grid con place-items:center, y sin un
     ancho definido un <img width:100%> cae a su ancho intrinseco y estira
     el chip. Con el ancho fijo el 100% resuelve contra los 134px.

   Los chips SIN logo conservan su borde, su padding y su fondo: siguen
   siendo los mismos de siempre. */
.provider-card--logo {
  width: 134px;
  padding: 0;
  border: 0;
  background: none;
  overflow: hidden;
}

/* Contorno neon permanente en TODOS los chips (Desktop y Mobile).
   Va como box-shadow y nunca como border: un border de 1px le comeria
   2px de ancho y alto a la imagen y romperia la regla de imagen = chip
   (134x62 exactos). El ring de box-shadow se pinta fuera de la caja,
   no ocupa layout y no introduce padding interno.

   El overflow:hidden del chip recorta la IMAGEN contra el radio, pero
   no recorta su propio box-shadow, asi que el halo sale entero.

   En los chips de texto se apaga su borde propio: sin eso quedarian con
   dos lineas (su borde mas el ring) y se verian mas gruesos que los de
   logo. Transparent y no `border:0` — el pixel se conserva y la caja
   sigue midiendo igual. */
.provider-card {
  box-shadow: var(--neon-line), var(--neon-glow);
}
.provider-card:not(.provider-card--logo) { border-color: transparent; }

/* Los assets ya vienen recortados a 2.1613, la proporcion exacta del
   chip, asi que cover no recorta nada: llena la caja completa sin
   deformar. Se deja cover y no fill por seguridad — si algun dia un asset
   entra con otra proporcion, prefiere recortar antes que estirar. */
.provider-card__logo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

@media (hover: hover) {
  .provider-card:hover { color: var(--text-primary); border-color: var(--violet-accent); }
}

/* ============================================================
   CAROUSEL — scroll-snap NATIVO
   proximity (nunca mandatory): mandatory es lo que traba el scroll
   vertical cuando el dedo arrastra en diagonal. Sin scroll jail.
   ============================================================ */

.carousel { position: relative; }

.carousel__track {
  display: flex;
  gap: var(--c-gap);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x proximity;
  scroll-behavior: smooth;
  /* Evita que el swipe horizontal encadene al documento y dispare el
     gesto de "atras" del navegador al llegar al extremo del carrusel. */
  overscroll-behavior-x: contain;
  /* SIN sangrado: el track ocupa exactamente el content box del container,
     asi que sus dos bordes caen sobre las mismas lineas verticales que el
     resto de la pagina. Antes sangraba hasta el borde de pantalla con
     margin negativo + padding, y eso hacia que la pista de la tarjeta
     siguiente se derramara fuera del grid por la derecha.
     La pista ahora sale del ANCHO de las tarjetas (ver la formula mas
     abajo), no de correr el track: el sobrante lo recorta el propio
     overflow del scroller, justo sobre la linea derecha del contenido. */

  /* Ancho de la pista de la 5a tarjeta y separacion entre tarjetas.
     Estos son los valores de DESKTOP y no cambian: en mobile se aprietan
     unos pixeles mas (ver el bloque <=559px). */
  --c-peek: 12px;
  --c-gap: var(--s-3);
  padding-block: var(--s-2);
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.carousel__track::-webkit-scrollbar { display: none; }
.carousel__track > * { scroll-snap-align: start; flex: 0 0 auto; }

@media (prefers-reduced-motion: reduce) {
  .carousel__track { scroll-behavior: auto; }
}

/* Anchos por tipo de fila. El peek nace de que 100/n no da entero:
   a 390px, 30% deja ~14% de la siguiente asomando. */
/* 4 tarjetas completas + la pista de la 5a, en CUALQUIER viewport.
   4 tarjetas + 4 gaps + pista = 100% del ancho util, asi que:
     tarjeta = (100% - 4*gap - pista) / 4
   El 100% es el content box del track, que ahora coincide con el del
   container: por eso el resultado queda alineado a izquierda y derecha
   sin ningun offset manual. Una sola regla, sin valores por breakpoint. */
.carousel__track--games > *,
.carousel__track--sports > * {
  flex: 0 0 calc((100% - (4 * var(--c-gap)) - var(--c-peek)) / 4);
  width: auto;
  min-width: 0;
  max-width: none;
}

/* Mobile: se recuperan 18px apretando gap (12 -> 8) y pista (12 -> 10).
   Esos 18px se reparten entre las cuatro tarjetas, que crecen ~6% sin
   tocar la formula ni romper la composicion: siguen entrando 4 completas
   y sigue asomando la quinta. Medido de 320 a 430: 4 visibles y 10px de
   pista en los siete viewports. */
@media (max-width: 559px) {
  .carousel__track { --c-peek: 10px; --c-gap: var(--s-2); }
}

/* Mobile: Apuestas deportivas un poco mas grande que el resto.
   La formula compartida no se toca — solo cambian sus dos variables.
   Con gap 8 y pista 10 la tarjeta media 79.0; con gap 5 y pista 6 pasa a
   83.0, un +5.1% que cae dentro del 5-8% pedido. Los 16px que se le
   quitan al aire van integros al ancho de las cuatro tarjetas, asi que
   se mantiene el patron: 4 completas + una franja fina de la quinta, y
   los dos bordes siguen al ras del container. */
@media (max-width: 559px) {
  .carousel__track--sports { --c-gap: 5px; --c-peek: 6px; }
}

/* Mismo problema que en el marquee: el track tiene overflow-y hidden
   (y overflow-x auto lo obliga a computar hidden tambien cuando el otro
   eje es visible), asi que cortaba el halo de las tarjetas arriba y
   abajo. Padding para abrir sitio dentro del recorte, margen negativo
   para no alterar el alto. Solo --sports: el track de Casino no lleva
   contorno y no se toca. */
.carousel__track--sports {
  padding-block: 12px;
  margin-block: -12px;
}

/* Desktop: las 8 tarjetas de Apuestas deportivas, todas a la vez.
   La seccion tiene OCHO deportes, no siete (ver informe). Ocho columnas
   sobre los 1216 de contenido, con el gap de 12 que ya usaba:

       (1216 - 7 x 12) / 8 = 141.5 por tarjeta

   No hay scroll ni pista: entran las ocho enteras y la ultima cierra al
   ras del borde derecho. El alto lo pone el aspect-ratio 2:3 de la
   tarjeta (212px), no un min-height, asi que ninguna imagen se deforma. */
@media (min-width: 1024px) {
  .carousel__track--sports {
    --c-gap: var(--s-3);
    --c-peek: 0px;
    /* Sin arrastre: ya no hay nada fuera de la vista que alcanzar. */
    overflow-x: visible;
  }
  .carousel__track--sports > * {
    flex: 0 0 calc((100% - (7 * var(--c-gap))) / 8);
  }
}

/* ---------- Desktop: Casino y Casino en vivo a 9 tarjetas ----------
   La medida de la tarjeta NO es una eleccion nuestra: es la de
   Juegos > Destacados de Premioplus, medida en vivo con
   getBoundingClientRect() sobre el proyecto real. Alli la fila es un
   grid de repeat(9, 1fr) con gap 16 dentro de un contenedor FIJO de
   1232px, asi que la tarjeta mide 122.667 x 122.667 (1:1) identica en
   1280, 1366, 1440, 1600 y 1920 — no es fluida, es una constante.

   Aca el contenedor de contenido mide 1216 (container 1280 menos 32 de
   padding a cada lado). De ahi sale el gap, que no es un numero
   elegido a ojo sino el unico que cierra la cuenta:

       9 x 122.667 + 8 x gap = 1216   ->   gap = 14px exacto

   Por eso el gap cambia y la tarjeta no: el pedido era conservar la
   medida de referencia y llenar el ancho util, y el gap es la unica
   variable libre que queda. Como la formula se escribe sobre 100% del
   track (que ES el content box del container), los dos bordes quedan
   al ras solos, sin offsets.

   Va a partir de 1280 y no de 1024: entre 1024 y 1279 el contenedor
   todavia es mas angosto que 1280 y las tarjetas saldrian por debajo
   de la medida de referencia. Ahi se conserva el carrusel actual.

   Solo --games: Apuestas deportivas usa --sports y no se toca. */
@media (min-width: 1280px) {
  .carousel__track--games {
    /* La medida de referencia, escrita como la cuenta que la produce en
       Premioplus en vez de como un numero suelto: contenedor 1232, gap
       16, 9 columnas -> 1104 / 9 = 122.667px. */
    --pp-card: calc((1232px - (8 * 16px)) / 9);

    /* La tarjeta es FIJA y el gap es el que flexiona. Al principio estaba
       al reves (gap fijo en 14, tarjeta en 1fr) y a 1440 daba exacto, pero
       a 1280 fallaba: ahi el contenedor no llega a su max-width porque la
       barra de scroll deja 1265 de viewport util, el contenido baja a 1201
       y la tarjeta caia a 121.00 — un 1.3% por debajo de la referencia.

       Invertido, la prioridad pedida se respeta en todo el rango: la
       tarjeta mide 122.667 SIEMPRE y el gap absorbe la diferencia
       (14.0px con 1216 de contenido, 12.1px con 1201). Las dos puntas
       siguen al ras porque el 100% del calc ES el content box del
       container.

       max(0px, ...) es solo seguro: el gap no puede volverse negativo y
       encimar tarjetas si el contenedor se achicara de forma imprevista. */
    gap: max(0px, calc((100% - (9 * var(--pp-card))) / 8));
    /* Sin pista: las 9 llenan el ancho y la 10a queda entera fuera del
       viewport del track, no asomando. */
    --c-peek: 0px;
  }
  .carousel__track--games > * {
    flex: 0 0 var(--pp-card);
    width: var(--pp-card);
  }

  /* El interior se escala con la tarjeta. Es el mismo tratamiento que
     ya existe por debajo de 1024, pero con valores FIJOS en vez de vw:
     aca la tarjeta mide siempre 122.667 pase lo que pase con el
     viewport, asi que hacer depender la tipografia del ancho de
     pantalla no tendria sentido. */
  .carousel__track--games .game-card__veil { padding: var(--s-4) 6px 6px; }
  .carousel__track--games .game-card__name {
    font-size: 11px;
    line-height: 1.15;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .carousel__track--games .game-card__ph { font-size: 9px; padding: 4px; }
  .carousel__track--games .game-card__ph-dim { display: none; }
  .carousel__track--games .game-card__badge { top: 4px; left: 4px; }
  .carousel__track--games .badge { padding: 2px 5px; font-size: 8px; letter-spacing: 0.06em; }
}

/* Encaje vertical de Casino + Casino en vivo en una sola pantalla.
   A 1440x900 quedan 824px utiles (viewport menos header). Con las
   tarjetas ya en su medida obligatoria, la unica variable que queda es
   el espacio muerto ENTRE las dos secciones: eran 88 + 88 = 176px.

   Se recorta SOLO ese limite interior — el padding-bottom de Casino y
   el padding-top de Casino en vivo. Los bordes que dan a las secciones
   vecinas (Por que aca arriba, Apuestas deportivas abajo) conservan sus
   88px, asi que el ritmo del resto de la pagina no cambia y ninguna
   otra seccion se toca.

   Se probo primero con 32+32 y entraba con 106px de sobra: demasiada
   holgura para el recorte aplicado. 48+48 = 96px deja 74px de aire
   igual y conserva mejor la jerarquia — es la mitad del ritmo normal
   de la pagina, no un cuarto. Las dos secciones siguen leyendose como
   bloques separados en vez de quedar pegadas. */
@media (min-width: 1280px) {
  #casino { padding-bottom: var(--s-7); }
  #en-vivo { padding-top: var(--s-7); }
}
.carousel__track--cards > * { width: 78%; min-width: 232px; max-width: 340px; }

@media (min-width: 640px) {
  .carousel__track--cards > * { width: 46%; }
}
@media (min-width: 1024px) {
  .carousel__track--cards > * { width: 30.5%; max-width: none; }
}

.carousel__nav { display: none; gap: var(--s-2); }
@media (min-width: 1024px) {
  .carousel__nav { display: flex; }
}
.carousel__btn {
  width: var(--tap);
  height: var(--tap);
  display: grid;
  place-items: center;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  color: var(--text-primary);
  transition: background var(--d-fast) var(--ease-std), opacity var(--d-fast) var(--ease-std);
}
.carousel__btn:hover:not(:disabled) { background: var(--bg-elevated); border-color: var(--violet-accent); }
.carousel__btn:disabled { opacity: 0.3; cursor: not-allowed; }
.carousel__btn svg { width: 18px; height: 18px; }

/* ============================================================
   MARQUEE — movimiento continuo, sin saltos
   El contenido se duplica y se traslada exactamente -50%: el bucle cierra
   sobre una copia idéntica, así que no hay salto visible.
   ============================================================ */

.marquee {
  /* El halo de los chips se salia por arriba y por abajo y este
     overflow lo cortaba en seco. El padding abre esos 12px DENTRO de la
     caja de recorte (overflow recorta contra el padding box, no contra
     el content box) y el margen negativo los devuelve al layout: la
     franja ocupa exactamente el mismo alto que antes. */
  padding-block: 12px;
  margin-block: -12px;
  overflow: hidden;
  margin-inline: calc(var(--pad-x) * -1);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
/* Mobile: el marquee vuelve al eje del contenido.
   Traia margin-inline negativo para sangrar a pantalla completa, y con
   los chips llegando al borde fisico del telefono quedaba como la unica
   franja que se salia de la guia lateral que respetan titulos, textos,
   banners y el resto de los carruseles.

   Se corrige quitando el margen, no agregando padding: `overflow`
   recorta contra el PADDING BOX, asi que un padding solo habria movido
   el arranque de la cinta sin impedir que los chips siguieran
   dibujandose hasta el borde. Sin el margen, la caja de recorte pasa a
   ser el content box del container y los chips entran y salen justo en
   la guia.

   No se toca nada del movimiento: la animacion traslada el track un
   -50% y es independiente del ancho de la ventana, asi que velocidad,
   direccion, bucle, pausa al hover, mascara de bordes y tamano de los
   chips quedan igual. */
@media (max-width: 1023px) {
  .marquee { margin-inline: 0; }
}

.marquee__track {
  display: flex;
  gap: var(--marquee-gap, var(--s-3));
  width: max-content;
  animation: marquee-scroll var(--marquee-dur, 48s) linear infinite;
  will-change: transform;
}
.marquee:hover .marquee__track,
.marquee__track.is-paused,
.marquee__track.editix-manual-pause { animation-play-state: paused; }
/* Infinite Marquee — Carousel Editor (Ronda 43): "Pausar con el mouse
   encima" desactivado explícitamente desde Editix. Misma especificidad
   que la regla de arriba (clase + :hover) — gana por orden de cascada
   (esta va después), sin necesitar !important. */
.marquee.editix-no-hover-pause:hover .marquee__track { animation-play-state: running; }
.marquee__track.editix-marquee-reverse { animation-direction: reverse; }

/* El desplazamiento es -50% MAS medio gap, y ese medio gap no es un
   retoque a ojo: es la unica distancia que hace que el bucle cierre.

   Con 39 chips duplicados y separacion g, el ancho total es
   2S + 77g, asi que el 50% vale S + 38.5g. Pero la copia empieza
   despues de 39 separaciones, o sea en S + 39g. La diferencia es
   exactamente g/2 — 6px con el gap de 12 — y era el arrastre que el
   carrusel acumulaba en cada vuelta: un salto chico pero real cada
   ciclo. Medido: la copia arrancaba en 5852 y la animacion solo
   recorria 5847.

   Escrito como g/2 y no como "6px" para que siga siendo correcto si
   alguna vez cambia el gap. */
@keyframes marquee-scroll {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(calc(-50% - (var(--marquee-gap, var(--s-3)) / 2)), 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; }
  .marquee { overflow-x: auto; }
}

/* ============================================================
   NAVIGATION — header
   ============================================================ */

.header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 90;
  height: var(--header-h);
  background: rgba(19, 5, 22, 0.88);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  border-bottom: 1px solid var(--border-soft);
}
.header__inner {
  height: 100%;
  display: flex;
  align-items: center;
  gap: var(--s-4);
}
.header__logo {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  /* El area tactil no la define la imagen (30px) sino el minimo de 44. */
  min-height: var(--tap);
  min-width: var(--tap);
}
.header__logo img { width: auto; }

/* El MISMO wordmark en mobile y en desktop: un solo asset de marca en la
   cabecera, y solo cambia la altura. Antes mobile mostraba el monograma;
   ese monograma ahora vive en la barra inferior como boton Home, que es
   el unico lugar donde tiene sentido una version reducida de la marca.

   Solo se fija la ALTURA. El ancho queda en auto y la imagen conserva su
   proporcion 120x15 — nunca se estira para entrar. */
.header__logo img { height: 15px; object-fit: contain; }
@media (min-width: 380px) { .header__logo img { height: 16px; } }
@media (min-width: 640px) { .header__logo img { height: 18px; } }

.nav { display: none; }
@media (min-width: 1024px) {
  .nav {
    display: flex;
    align-items: center;
    gap: var(--s-5);
    margin-inline: auto;
  }
  .nav a {
    min-height: var(--tap);
    display: inline-flex;
    align-items: center;
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--text-body);
    transition: color var(--d-fast) var(--ease-std);
  }
  .nav a:hover,
  .nav a.is-current { color: var(--cta); }
}

.header__actions { margin-left: auto; display: flex; align-items: center; gap: var(--s-2); }
@media (min-width: 1024px) { .header__actions { margin-left: 0; } }

.header__cta { padding-inline: var(--s-4); font-size: 13px; }
@media (min-width: 400px) { .header__cta { padding-inline: var(--s-5); } }

/* ============================================================
   BOTTOM NAV — mobile
   7 accesos: 3 + Home + 3. Columnas iguales con min-width:0. Sin ese
   min-width cada 1fr es minmax(auto,1fr) y la etiqueta más larga empuja
   su columna: "Deportes" se comería el ancho de "Casino".

   El centrado del Home no se calcula ni se compensa: con SIETE columnas
   iguales, la cuarta es el centro exacto de la barra por aritmética. Da
   igual lo que midan los iconos o las etiquetas de los lados.
   ============================================================ */

.bottom-nav { display: none; }

@media (max-width: 1023px) {
  .bottom-nav {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 88;
    display: grid;
    /* Al salir Club VIP la barra pasa de 7 items a 6: quedan TRES a la
       izquierda del PG (Casino, En vivo, Deportes) y DOS a la derecha
       (Registro, Ayuda).

       Con columnas iguales el PG deja de estar centrado: seria la
       columna 4 de 6, o sea su centro caeria en el 58.3% del ancho —
       unos 32px corrido a la derecha en un telefono de 390. Y no es
       ajustable con repeat(6, 1fr): para que la columna del medio quede
       centrada, los dos grupos laterales tienen que PESAR lo mismo, y
       con 5 items no hay reparto par posible.

       La solucion es hacer que pesen lo mismo aunque tengan distinta
       cantidad. Con la salida de "En vivo" ya no hace falta: quedan DOS
       items de cada lado (Casino, Deportes | Registro, Ayuda), asi que
       la simetria vuelve a ser exacta y los cuatro miden igual. El PG
       queda centrado por geometria, sin posicionamiento absoluto ni
       offsets, y sin celdas vacias.

       La columna del PG va en `auto`: se ajusta al diametro real del
       circulo, que es variable (clamp de 54 a 66px).

       Efecto lateral util: los tres items de la izquierda conservan
       practicamente su ancho actual (44.3px a 320 contra los 45.7 de
       antes), asi que Casino y Deportes no se mueven de sitio. */
    grid-template-columns: repeat(2, 1fr) auto repeat(2, 1fr);
    align-items: center;

    /* Diametro del boton Home: +22% sobre el tamaño anterior en todo el
       rango (44->54 a 320px, 54->66 a 430px). Ya no cabe dentro de su
       columna, y no hace falta: el circulo sale por arriba de la barra. */
    --nav-home-d: clamp(54px, 15.9vw, 66px);

    /* Cuanto se levanta el circulo respecto de la fila. Sumado a lo que
       mide de mas que la fila, es lo que asoma por encima del borde
       superior de la barra: entre 6px a 320 y 18px a 430, o sea crece
       junto con el boton en vez de ser un desplazamiento fijo. */
    --nav-home-lift: 14px;

    background: rgba(24, 13, 29, 0.95);
    backdrop-filter: blur(18px) saturate(150%);
    -webkit-backdrop-filter: blur(18px) saturate(150%);
    border-top: 1px solid var(--border-soft);
    /* Explicito: el circulo del Home cruza el borde superior y ni el, ni
       su aro, ni su glow pueden quedar recortados. */
    overflow: visible;
    /* El inset inferior va SUMADO al padding, no sustituyendolo: en un
       iPhone la barra crece hacia abajo y el contenido conserva sus 5px
       de aire sobre el borde. En Android el inset es 0 y no cambia nada. */
    padding: 5px 0 calc(5px + env(safe-area-inset-bottom, 0px));
  }
  .bottom-nav a {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    /* 56 y no 48: es la altura que la fila ya tenia, cuando la marcaba la
       pastilla dorada del registro. La vista Casino calcula su primera
       pantalla restando el alto real de esta barra (67px), asi que si la
       fila encogiera, esa pantalla se descuadraria. Ahora la altura la
       fija el item lateral y deja de depender de la decoracion del CTA. */
    min-height: 56px;
    min-width: 0;
    padding: 4px 1px;
    border-radius: var(--r-md);
    color: var(--text-secondary);
    font-size: 9px;
    font-weight: 500;
    line-height: 1.1;
    text-align: center;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    transition: color var(--d-fast) var(--ease-std), background var(--d-fast) var(--ease-std);
  }
  .bottom-nav a svg { width: 20px; height: 20px; flex: 0 0 auto; }
  @media (min-width: 380px) { .bottom-nav a { font-size: 10px; } }
  .bottom-nav a span {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .bottom-nav a:active { background: var(--bg-elevated); }
  .bottom-nav a.is-current { color: var(--cta); }

  /* --- Home: el monograma PG ---
     Es el unico elemento circular y relleno de la barra, y el unico con
     glow propio: eso, no el tamaño solo, es lo que lo vuelve el centro
     de gravedad visual.

     El fondo es oscuro y NO el degradado dorado del CTA: el monograma ya
     es dorado, asi que sobre oro desapareceria. El oro va en el aro y en
     el resplandor, que es el mismo sistema de neon que ya usa la barra. */
  .bottom-nav a.bottom-nav__home {
    justify-self: center;
    width: var(--nav-home-d);
    height: var(--nav-home-d);
    min-height: 0;
    padding: 0;

    /* El circulo mide mas que la fila y ademas sube, pero su CAJA DE
       MARGEN sigue midiendo exactamente los 56px de la fila:

           (56 - D - lift) + D + lift = 56

       Da igual cuanto valgan D y lift. Por eso la barra sigue midiendo
       67px, la safe-area no se mueve, el body no cambia de padding y el
       calculo del primer viewport de Casino —que resta esos 67— sigue
       cuadrando. Lo unico que pasa es que el borde del circulo se sale
       hacia ARRIBA, que es justo lo que se busca. */
    margin-top: calc(56px - var(--nav-home-d) - var(--nav-home-lift));
    margin-bottom: var(--nav-home-lift);

    border-radius: 50%;
    background: var(--bg-elevated);
    /* Aro y glow suben con el diametro para no quedar finos alrededor de
       un circulo mas grande. Mismo color y misma difuminacion: es el
       mismo efecto a otra escala, no uno nuevo. */
    border: 2px solid rgba(255, 210, 0, 0.5);
    box-shadow: 0 7px 24px rgba(255, 210, 0, 0.26);
    /* Por encima de sus vecinos para que el aro y el glow no queden
       cortados; el circulo nunca excede su columna, asi que estar arriba
       no le roba superficie tactil a nadie. */
    position: relative;
    z-index: 1;
    transition: border-color var(--d-fast) var(--ease-std),
                box-shadow var(--d-fast) var(--ease-std),
                background var(--d-fast) var(--ease-std);
  }
  /* El monograma ocupa el 75% del diametro INTERIOR (el diametro menos
     los dos bordes). Como el aro dorado del asset llena su lienzo de lado
     a lado, ese 75% es literalmente lo que ocupa dentro del circulo, y
     deja un 12.5% de aire a cada lado: lleno pero sin tocar el borde.

     Se fija el ANCHO y la altura queda en auto: la proporcion 37x34 la
     mantiene el propio archivo, no un segundo numero que pueda
     desincronizarse. */
  .bottom-nav a.bottom-nav__home img {
    width: calc((var(--nav-home-d) - 4px) * 0.75);
    height: auto;
    object-fit: contain;
    display: block;
  }
  .bottom-nav a.bottom-nav__home:active {
    background: #30183f;
    box-shadow: 0 0 0 5px rgba(255, 210, 0, 0.12),
                0 7px 24px rgba(255, 210, 0, 0.26);
  }
  /* Estado activo con las mismas piezas que ya usa la barra —oro de
     --cta y el glow de --elev-cta—, solo reforzadas. */
  .bottom-nav a.bottom-nav__home.is-current {
    border-color: var(--cta);
    background: rgba(255, 210, 0, 0.1);
    box-shadow: 0 0 0 4px rgba(255, 210, 0, 0.14),
                0 8px 28px rgba(255, 210, 0, 0.38);
  }

  /* El registro sigue destacado en oro, pero pierde la pastilla: dos
     circulos rellenos competirian entre si y el centro dejaria de leerse
     como el acceso principal. */
  .bottom-nav a.bottom-nav__cta { color: var(--cta); }
  .bottom-nav__cta span { color: var(--cta); font-weight: 700; }
}

/* Por debajo de 1024 el envoltorio desaparece con display:contents y sus
   hijos vuelven a ser hijos directos del contenedor: la cabecera sigue
   siendo una sola columna, como estaba.

   El unico efecto del envoltorio seria mover el banner al final, asi que
   se restituye la secuencia original con `order`. Para que `order`
   aplique hace falta que el contenedor sea flex — y como ningun par de
   hermanos adyacentes tiene margenes en AMBOS lados, la separacion no
   cambia respecto al flujo en bloque (donde colapsarian): verificado
   contra las medidas previas, pixel a pixel.

   Secuencia que se conserva:
     Casino     eyebrow, titulo, claim, BANNER, descripcion
     Sportbook  eyebrow, titulo, claim, descripcion, BANNER, CTA */
@media (max-width: 1023px) {
  .view-hero > .container { display: flex; flex-direction: column; }
  .view-hero__text { display: contents; }
  /* Selector de tres clases a proposito: el banner de Casino reutiliza
     .hero__media, y la Home le pone `order: 3` en su bloque mobile de
     sections.css — que carga DESPUES de este archivo y ganaria a igual
     especificidad. Con el descendiente explicito manda esta regla, y la
     de la Home sigue intacta para su propio hero. */
  .view-hero > .container > .view-hero__media { order: 1; }
  .view-hero > .container > .view-hero__text > .casino-top__lede,
  .view-hero > .container > .view-hero__text > .sb-top__cta { order: 2; }
}

/* ============================================================
   HERO DE VISTA — estructura compartida por Casino y Sportbook
   ============================================================
   UNA sola definicion para las dos cabeceras. Antes cada vista tenia la
   suya: Sportbook ya iba a dos columnas y Casino seguia en una sola, con
   el banner acotado a 900px y centrado debajo del titulo. Al alternar
   entre las dos paginas el salto era evidente.

   Vive en components.css —que cargan las tres paginas— y no en
   casino.css/sportbook.css a proposito: esos dos se cargan DESPUES, asi
   que a igual especificidad le ganarian. Con la estructura aca y las
   reglas propias retiradas de alli, hay una sola fuente de verdad y las
   dos vistas no pueden desalinearse.

   El reparto de columnas (1fr / 1.15fr), el gap y el centrado vertical
   son los que ya tenia Sportbook: se conservan tal cual para que esa
   vista no se mueva y Casino se alinee con ella.

   Cada cabecera tiene EXACTAMENTE dos celdas: .view-hero__text y
   .view-hero__media. Es la clave de que funcione, y por eso se envolvio
   el texto en las dos paginas.

   El primer intento fue dejar los textos sueltos en la rejilla y darle
   al banner `grid-row: 1 / -1`. No funciona: el `-1` apunta al final de
   la rejilla EXPLICITA, y como no hay `grid-template-rows` declarado,
   resolvia a la fila 1 sola. El banner inflaba esa fila a sus 403px y el
   titulo de Casino terminaba 519px por debajo del borde, con el eyebrow
   flotando centrado en una fila vacia.

   Tampoco sirve declarar filas y hacer que el banner las abarque: cuando
   un item ocupa varias pistas auto y mide mas que ellas, el sobrante se
   REPARTE entre esas pistas, y el texto queda desperdigado. Con una sola
   fila y dos celdas no hay reparto posible: align-items:center enfrenta
   los dos bloques y ya.

   Solo >=1024px. Por debajo cada vista conserva exactamente su
   composicion actual en una columna. */
@media (min-width: 1024px) {
  /* section.view-hero y no .view-hero a secas: cada vista trae su propio
     padding-top base (.casino-top usa --s-6, .sb-top usa --s-5) y esos
     archivos cargan DESPUES, asi que a igual especificidad ganaban y las
     dos cabeceras arrancaban a distinta altura (108 contra 100). Con el
     tipo delante gana esta, y las reglas propias siguen mandando por
     debajo de 1024, donde este bloque no aplica. */
  section.view-hero { padding-top: calc(var(--header-h) + var(--s-8)); }

  .view-hero > .container {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    /* start y no center: con `center` cada celda se centraba contra la
       otra, asi que el borde superior del banner caia a media altura del
       texto — y a distinta altura en cada vista, porque los textos miden
       distinto. Con `start` las dos celdas arrancan en la misma linea de
       la fila, que es la alineacion pedida, y sale del layout: no hay un
       solo offset ni un valor por pagina. */
    align-items: start;
    column-gap: var(--s-8);
  }

  /* El margen superior del primer elemento del texto se anula: si no, el
     bloque izquierdo empieza mas abajo que su celda y la linea superior
     dejaria de coincidir con la del banner. Se hace sobre :first-child y
     no sobre una clase concreta para que valga en las dos vistas. */
  .view-hero__text > :first-child { margin-top: 0; }

  .view-hero__text { grid-column: 1; }

  .view-hero__media {
    grid-column: 2;
    /* Anula cualquier acotado o centrado propio de cada vista: dentro de
       la columna el banner ocupa el ancho completo, que es lo que hace
       que las dos paginas empiecen y terminen en el mismo pixel. */
    max-width: none;
    margin-inline: 0;
  }
}

/* La bottom-nav tapa el final del documento: se compensa en el body. */
@media (max-width: 1023px) {
  /* Se suma el inset de safe-area igual que hace la propia barra: sin
     esto, en un iPhone la barra crece hacia abajo pero el body seguia
     reservando solo su alto nominal. */
  body { padding-bottom: calc(var(--bottomnav-h) + env(safe-area-inset-bottom, 0px)); }
}

/* ============================================================
   ACCORDION — FAQ
   <details>/<summary> nativo: teclado y lector de pantalla gratis,
   y cero JS para abrir/cerrar.
   ============================================================ */

.acc {
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
  background: var(--bg-surface);
  overflow: hidden;
}
.acc + .acc { margin-top: var(--s-3); }

.acc__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  min-height: var(--tap);
  padding: var(--s-4);
  font-family: var(--f-display);
  font-weight: 700;
  font-size: var(--fs-sm);
  color: var(--text-primary);
  cursor: pointer;
  list-style: none;
  touch-action: manipulation;
}
.acc__q::-webkit-details-marker { display: none; }
.acc__q:hover { background: var(--bg-elevated); }

.acc__chev {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  color: var(--cta);
  transition: transform var(--d-mid) var(--ease-out);
}
.acc[open] .acc__chev { transform: rotate(180deg); }

.acc__a {
  padding: 0 var(--s-4) var(--s-4);
  font-size: var(--fs-sm);
  color: var(--text-body);
}

/* ============================================================
   AGE GATE
   ============================================================ */

.age-gate__backdrop {
  position: fixed;
  inset: 0;
  z-index: 400;
  background: rgba(10, 3, 12, 0.93);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.age-gate {
  position: fixed;
  inset: 0;
  z-index: 401;
  display: grid;
  place-items: center;
  padding: var(--s-4);
  overflow-y: auto;
}
.age-gate__panel {
  width: 100%;
  max-width: 420px;
  padding: var(--s-6) var(--s-5);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--elev-3);
  text-align: center;
}
.age-gate__logo { height: 19px; width: auto; margin: 0 auto var(--s-5); }
.age-gate__badge {
  display: inline-grid;
  place-items: center;
  width: 56px;
  height: 56px;
  margin-bottom: var(--s-4);
  border-radius: 50%;
  background: var(--grad-cta);
  color: var(--cta-ink);
  font-family: var(--f-display);
  font-weight: 800;
  font-size: 17px;
}
.age-gate__title {
  font-size: 1.3rem;
  font-weight: 800;
  text-transform: uppercase;
  margin-bottom: var(--s-3);
}
.age-gate__text { font-size: var(--fs-sm); color: var(--text-body); margin-bottom: var(--s-5); }
.age-gate__actions { display: flex; flex-direction: column; gap: var(--s-3); }
.age-gate__note { margin-top: var(--s-4); font-size: var(--fs-xs); color: var(--text-secondary); }

/* ============================================================
   FOOTER
   ============================================================ */

.footer {
  border-top: 1px solid var(--border-soft);
  /* Mismo criterio que la franja de pagos: translucida sobre el fondo
     global, sin rectangulo propio. */
  background: rgba(19, 5, 22, 0.42);
  padding-block: var(--s-7) var(--s-5);
}
.footer__grid {
  display: grid;
  gap: var(--s-6);
  grid-template-columns: 1fr;
  margin-bottom: var(--s-6);
}

/* Mobile: las tres columnas de enlaces (Casino / Deportes / Ayuda) van una
   al lado de la otra en vez de apiladas. El bloque de marca ocupa la fila
   completa arriba. */
@media (max-width: 639px) {
  .footer__grid {
    /* minmax(0,1fr) y no 1fr: "1fr" es en realidad minmax(auto,1fr), y ese
       "auto" toma el min-content de la columna. El enlace
       support@progambling.bet es una cadena sin espacios, asi que estiraba
       su columna a 187px contra 81 de la vecina — y de paso generaba
       scroll horizontal en la pagina. Medido antes del arreglo. */
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s-5) var(--s-3);
  }
  /* El correo puede cortarse dentro de su columna en vez de empujarla. */
  .footer__col a { overflow-wrap: anywhere; }
  .footer__grid > div:first-child { grid-column: 1 / -1; }
  /* Con tres columnas en ~110px cada una, el alto tactil de 44px por enlace
     separaba demasiado los items: se baja a 32 manteniendo el area tactil
     por encima del minimo gracias al padding vertical. */
  .footer__col a { min-height: 32px; padding-block: 6px; font-size: 13px; line-height: 1.3; }
  .footer__col h3 { font-size: 10px; letter-spacing: 0.1em; }
}
@media (min-width: 640px) { .footer__grid { grid-template-columns: 1.5fr 1fr 1fr; } }
@media (min-width: 1024px) { .footer__grid { grid-template-columns: 2fr 1fr 1fr 1fr; } }

.footer__logo { height: 17px; width: auto; margin-bottom: var(--s-4); }
.footer__about { font-size: var(--fs-sm); color: var(--text-body); max-width: 42ch; }

.footer__col h3 {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin-bottom: var(--s-2);
}
.footer__col a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  font-size: var(--fs-sm);
  color: var(--text-body);
  transition: color var(--d-fast) var(--ease-std);
}
.footer__col a:hover { color: var(--cta); }

.footer__legal {
  padding-top: var(--s-5);
  border-top: 1px solid var(--border-soft);
  font-size: var(--fs-xs);
  color: var(--text-secondary);
  line-height: 1.65;
}
.footer__legal p + p { margin-top: var(--s-3); }

.footer__age {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-block: var(--s-4);
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--bg-surface);
}
.footer__age b {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--cta);
  color: var(--cta-ink);
  font-family: var(--f-display);
  font-weight: 800;
  font-size: 12px;
}
.footer__age span { font-size: var(--fs-xs); color: var(--text-body); }

/* ============================================================
   CAPA DE CURSOR — SOLO DESKTOP
   ============================================================
   Todo lo de acá abajo vive dentro de @media (hover:hover) and
   (pointer:fine). No es cosmético: en un touchscreen el navegador
   emula :hover al tocar y lo deja pegado hasta el toque siguiente,
   que es el origen clásico del bug del doble tap — el primer toque
   "hoverea", el segundo activa. Encapsulado así, en mobile estas
   reglas directamente no existen.

   Se anima sólo transform, opacity, box-shadow y color de borde:
   ninguna de las cuatro dispara reflow. Nada toca width, height,
   margin ni padding en hover.
   ============================================================ */
@media (hover: hover) and (pointer: fine) {

  /* Un único juego de variables para toda la capa: si mañana hay que
     subir o bajar la intensidad general, se toca acá y no en veinte
     reglas sueltas. */
  :root {
    --hov-lift: -4px;
    --hov-scale: 1.012;
    --hov-ring: 0 0 0 1px rgba(138, 43, 226, 0.34);
    --hov-halo: 0 10px 30px -12px rgba(138, 43, 226, 0.5);
    --hov-halo-gold: 0 10px 28px -12px rgba(255, 210, 0, 0.42);
    --hov-t: 260ms;
  }

  /* --- Tarjetas ---------------------------------------------------
     Elevación corta + escala mínima + halo violeta + borde más vivo.
     La escala es 1.012 y no 1.05 a propósito: por encima de ~1.02 el
     texto se re-rasteriza visiblemente y la tarjeta se lee "saltona"
     en vez de premium. */
  .card,
  .game-card,
  .sport-card,
  .provider-card,
  .trust__item,
  .market,
  .step {
    transition:
      transform var(--hov-t) var(--ease-out),
      box-shadow var(--hov-t) var(--ease-out),
      border-color var(--hov-t) var(--ease-out),
      background-color var(--hov-t) var(--ease-out);
  }

  /* .step se suma a la MISMA regla que ya usaban .card, .trust__item y
     .market — no a una copia con valores parecidos. Las cuatro tarjetas
     de "Como empezar" heredan asi color, ring, halo, transicion,
     duracion y easing identicos al resto de la pagina, y si manana se
     ajusta el sistema se ajustan todas juntas. */
  .card:hover,
  .trust__item:hover,
  .market:hover,
  .step:hover {
    transform: translateY(var(--hov-lift)) scale(var(--hov-scale));
    border-color: var(--violet-accent);
    box-shadow: var(--hov-ring), var(--hov-halo);
  }

  .game-card:hover {
    transform: translateY(var(--hov-lift)) scale(var(--hov-scale));
    border-color: var(--violet-accent);
    box-shadow: var(--hov-ring), var(--hov-halo);
  }
  /* La imagen acompaña con un acercamiento propio, contenido por el
     overflow de la tarjeta. Da profundidad sin mover el marco. */
  .game-card__media img,
  .game-card img { transition: transform 420ms var(--ease-out); }
  .game-card:hover img { transform: scale(1.06); }

  .sport-card:hover {
    transform: translateY(-3px) scale(var(--hov-scale));
    box-shadow: var(--hov-halo);
  }

  .provider-card:hover {
    transform: translateY(-2px);
    border-color: var(--violet-accent);
    box-shadow: var(--hov-ring);
  }

  /* --- Botones ----------------------------------------------------
     Nada de cambio de color radical: el amarillo sigue siendo el
     amarillo. Sube el halo, se eleva 2px y el borde se refuerza. */
  .btn {
    transition:
      transform var(--hov-t) var(--ease-out),
      box-shadow var(--hov-t) var(--ease-out),
      border-color var(--hov-t) var(--ease-out),
      background-color var(--hov-t) var(--ease-out);
  }
  .btn:hover { transform: translateY(-2px); }
  .btn--gold:hover { box-shadow: var(--hov-halo-gold); }
  .btn--ghost:hover { box-shadow: var(--hov-ring), var(--hov-halo); }
  /* :active devuelve el botón a su sitio: el clic tiene que sentirse
     como que algo se hunde, no como que sigue flotando. */
  .btn:active { transform: translateY(0); }

  .carousel__btn { transition: transform var(--hov-t) var(--ease-out), box-shadow var(--hov-t) var(--ease-out), background-color var(--hov-t) var(--ease-out), border-color var(--hov-t) var(--ease-out); }
  .carousel__btn:hover:not(:disabled) { transform: scale(1.08); box-shadow: var(--hov-ring); }
  .carousel__btn:active:not(:disabled) { transform: scale(0.96); }

  /* Chips del lobby y links del footer: sólo respuesta de superficie. */
  .cat { transition: background-color var(--hov-t) var(--ease-out), border-color var(--hov-t) var(--ease-out), color var(--hov-t) var(--ease-out); }
  .cat:hover:not(.is-active) { background: var(--bg-elevated); border-color: var(--violet-accent); }
  .footer__col a { transition: color var(--hov-t) var(--ease-out); }
  .acc__q { transition: background-color var(--hov-t) var(--ease-out); }
}

/* --- Halo ambiental que sigue al cursor --------------------------
   No es una "linterna": no hay círculo con borde. Es un degradado
   radial muy abierto y de baja opacidad que se mueve con el puntero
   dentro del contenedor, así que se percibe como que la superficie
   responde a la luz, no como un foco encima.

   El JS sólo escribe dos custom properties (--gx, --gy) y un 0/1.
   Ningún estilo se recalcula desde JS y no se lee layout en el
   movimiento: el trabajo por frame es escribir dos strings.

   Va en ::after y no en un div extra para no tocar el marcado.
   border-radius:inherit lo mantiene dentro de la forma del contenedor
   y pointer-events:none evita que se coma los clics de lo que hay
   debajo (los CTA, sin ir más lejos). */
@media (hover: hover) and (pointer: fine) {
  /* Reset LOCAL de las tres variables en cada contenedor con halo.
     Sin esto hay un bug garantizado: las custom properties se HEREDAN,
     y los contenedores estan anidados (seccion > carrusel > tarjeta).
     Al pasar el cursor por el fondo de una seccion, el --gon:1 que le
     escribe el JS bajaba a todas sus tarjetas y se encendian las diez
     a la vez, cada una con las coordenadas de la seccion. Verificado:
     las tarjetas heredaban --gon 1 sin que nadie las tocara.

     Una declaracion en el propio elemento le gana al valor heredado,
     asi que cada contenedor arranca apagado y solo se enciende el que
     el JS marca por estilo inline. */
  [data-fx-glow] {
    position: relative;
    --gon: 0;
    --gx: 50%;
    --gy: 50%;
  }
  [data-fx-glow]::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    border-radius: inherit;
    background: radial-gradient(
      var(--fx-r, 260px) circle at var(--gx, 50%) var(--gy, 50%),
      rgba(151, 71, 255, 0.15),
      rgba(151, 71, 255, 0.05) 42%,
      rgba(151, 71, 255, 0) 68%
    );
    opacity: var(--gon, 0);
    transition: opacity 320ms var(--ease-out);
  }
  /* --- Nivel AMBIENTAL: el halo va DETRAS del contenido ------------
     En secciones, carruseles y el panel VIP hay texto largo e
     imagenes: teñirlos por encima se leeria como una veladura sucia.
     Ahi el halo tiene que ser luz de fondo.

     La combinacion es isolation:isolate + z-index:-1. El isolate crea
     un contexto de apilamiento en el propio contenedor, asi que el -1
     queda ATRAPADO adentro: pinta sobre el fondo del contenedor pero
     debajo de todo su contenido, y no se escapa detras de la pagina.

     Esto reemplaza al truco habitual de ponerle position:relative a
     los hijos, que aca NO se puede usar: el hijo directo de .ptrack es
     el pin del carrusel pinneado, que es position:sticky. Pisarlo con
     relative mataria el recorrido horizontal entero en cualquier
     ventana angosta con mouse. isolation no toca el position de nadie
     y tampoco crea bloque contenedor, asi que el sticky sigue intacto. */
  .vip__panel[data-fx-glow],
  .carousel[data-fx-glow],
  .section[data-fx-glow] { isolation: isolate; }

  .vip__panel[data-fx-glow]::after,
  .carousel[data-fx-glow]::after,
  .section[data-fx-glow]::after { z-index: -1; }

  .vip__panel[data-fx-glow]::after { --fx-r: 460px; }
  .carousel[data-fx-glow]::after { --fx-r: 380px; }

  /* Respuesta ambiental de seccion: la seccion no se mueve ni cambia
     de tamaño — solo sube apenas la luz de fondo bajo el cursor. Es
     deliberadamente mas tenue y mas abierta que la de las tarjetas:
     tiene que percibirse como atmosfera, no como un elemento. */
  .section[data-fx-glow]::after {
    --fx-r: 620px;
    background: radial-gradient(
      var(--fx-r) circle at var(--gx, 50%) var(--gy, 50%),
      rgba(138, 43, 226, 0.075),
      rgba(138, 43, 226, 0) 70%
    );
  }

  /* prefers-reduced-motion: se apaga el halo y se dejan sólo los
     cambios de color. Sin movimiento, sin seguimiento. */
  @media (prefers-reduced-motion: reduce) {
    [data-fx-glow]::after { display: none; }
    .card:hover, .game-card:hover, .sport-card:hover,
    .provider-card:hover, .trust__item:hover, .market:hover,
    .step:hover, .btn:hover,
    .carousel__btn:hover:not(:disabled) { transform: none; }
    .game-card:hover img { transform: none; }
  }
}
