/* =============================================================================
   ClaveGTA — base.css   ·   lo que comparten TODAS las páginas
   -----------------------------------------------------------------------------
   Tipografía, paleta, reset y las piezas que se repiten sin cambiar: botón de
   compra, barra de consentimiento, pie, foco visible.

   POR QUÉ EXISTE ESTE ARCHIVO
   La home y la tienda son páginas distintas con hojas distintas. Si cada una
   lleva su copia de la paleta, tarde o temprano una cambia y la otra no, y
   nadie lo ve: el sitio se queda con dos magentas parecidos. Es el mismo fallo
   silencioso que el `slug()` duplicado entre app.js y measure.js. Aquí la
   paleta se declara UNA vez.

   Orden de carga: base.css primero, luego la hoja de la página.
   ========================================================================== */

@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-latin-var.woff2') format('woff2-variations'),
       url('../fonts/archivo-latin-var.woff2') format('woff2');
  font-weight: 100 900;
  font-stretch: 100%;
  font-style: normal;
  font-display: swap;
}

/* ---------- Paleta ---------------------------------------------------------
   Cada color tiene una función y solo una:
     magenta = comprar          cian = dato comprobado
     ámbar   = léelo antes      violeta = ambiente
   Nada es decorativo por serlo. */
:root {
  /* FONDO. El purpura del marco de la caratula oficial, no un negro generico.
     `--ink-2` es exactamente el color que Rockstar usa para enmarcar la portada. */
  --ink:        #14001F;
  --ink-2:      #1D002E;
  --panel:      #290A40;
  --panel-2:    #371452;
  --line:       #4C2570;
  --line-soft:  #331050;

  /* TEXTO. Crema calida del arte oficial, no blanco violaceo. */
  --fg:         #FFF2E6;
  --fg-dim:     #CBAEC0;
  --fg-faint:   #9C8299;

  /* ACENTOS. Muestreados del degradado del logotipo VI de la caratula:
     azul #3E60CE -> purpura #B537BF -> coral #FF6B7B -> naranja #FF9152.
     Se conserva la semantica anterior; solo cambian los tonos. */
  --magenta:    #FF6B7B;
  --magenta-hi: #FF8E70;
  --magenta-ink:#2B0413;
  --cyan:       #4FC9D6;
  /* Variante clara del cian, SOLO para texto sobre imagen. El cian normal tiene
     luminancia media (~0.52): sobre un fondo plano oscuro cumple de sobra, pero
     sobre el arte oficial —que es un atardecer claro— no llega a 4,5 ni con el
     velo al 95%. El problema no era el velo: era el color. */
  --cyan-hi:    #A6EFF6;
  --violet:     #B537BF;
  --amber:      #FF9152;
  --blue:       #3E60CE;

  --display: 'Archivo', ui-sans-serif, system-ui, "Segoe UI", Roboto, Arial, sans-serif;
  --body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;

  --r:   14px;
  --r-s: 10px;
  --wrap: 720px;

  /* ===========================================================================
     ESCALA TIPOGRAFICA — CUATRO NIVELES, NO UNA LISTA DE TAMANOS
     ---------------------------------------------------------------------------
     Antes cada tamano se decidia en su sitio y el resultado era incoherente: el
     H3 estaba fijo en 22px, o sea POR DEBAJO del cuerpo de escritorio (23px), y
     el CTA —el elemento que gana el dinero— era el texto mas pequeno del
     sistema con 13px. No era timidez de diseno: era falta de sistema.

     (Correccion sobre la auditoria: el «CTA a 13px» que se reporto era la
     pildora del nav, no el boton de compra, que siempre estuvo en 17px. Un
     enlace de cabecera a 13px es correcto. Lo que si estaba mal era el H3.)

     Los cuatro niveles responden a cuatro trabajos distintos:

       1. TITULAR    el nombre del juego. Manda en el primer viewport.
       2. EDITORIAL  lo que se lee: H2, cuerpo, entradillas.
       3. PRODUCTO   lo que se compra: nombre de la ficha, cifras, datos.
       4. ACCION     el boton. Se lee de un vistazo o no sirve.

     Todos escalan con el viewport. Un nivel que no escala rompe la relacion
     con los demas en cuanto cambia el ancho, que es exactamente lo que pasaba.
     ======================================================================== */
  --t-accion:   clamp(17px, .4vw + 15.5px, 18.5px);
  --t-producto: clamp(19px, 1.5vw + 14px, 25px);
  /* Sube a 26px: a 23 empataba EXACTAMENTE con el cuerpo de la portada, y un
     encabezado del mismo tamaño que su texto no es jerarquía, solo un cambio
     de peso. Arreglar que no escalara dejó el empate a medias. */
  --t-h3:       clamp(18.5px, 1.4vw + 13.5px, 26px);
  /* Encabezado de sub-bloque: el título de un aviso, de una tarjeta o de un
     apartado dentro de una sección que ya tiene su H2. Existía tres veces con
     tres tamaños distintos (15,5 · 16 · 17 px) para el mismo trabajo, y dos de
     ellos quedaban a un pelo de su propio cuerpo. Uno solo, y por encima. */
  --t-bloque:   17px;
  --t-sub:      19px;
}

/* ---------- Reset ---------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

/* EL ATRIBUTO `hidden` TIENE QUE GANAR SIEMPRE.
   `hidden` vale `display:none` en la hoja del NAVEGADOR, y eso lo pisa
   cualquier regla de autor con `display`. En este sitio lo pisaban cuatro:
   .consent, .stickybuy, .lsticky y .trailerband, todas con `display:flex`.

   El síntoma que lo destapó: pulsar «Aceptar medición» guardaba el
   consentimiento correctamente —localStorage, data-consent, carga de la
   analítica, todo bien— pero la barra NO desaparecía, porque `el.hidden = true`
   no podía contra `display:flex`. Para el visitante, el botón no hacía nada.

   El `!important` está justificado: `hidden` significa «esto no es relevante
   ahora», y no hay ningún caso en el que un `display` de componente deba
   ganarle. Sin esta línea, cualquier `hidden` futuro es una trampa. */
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--ink);
  color: var(--fg);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
img, svg, video, iframe { max-width: 100%; display: block; }
a { color: var(--magenta-hi); }
h1, h2, h3, h4 { font-family: var(--display); margin: 0; }
p { margin: 0; }
button { font: inherit; color: inherit; }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--magenta); color: var(--magenta-ink);
  padding: 10px 16px; border-radius: 0 0 var(--r-s) 0; font-weight: 700;
}
.skip-link:focus { left: 0; }

:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ---------- Botón de compra -------------------------------------------------
   Un solo tratamiento en todo el sitio. Si algún día hay dos botones magenta
   compitiendo en la misma pantalla, es que la página está mal, no el CSS. */
.cta {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 56px; padding: 14px 22px;
  background: var(--magenta); color: var(--magenta-ink);
  font-family: var(--display); font-weight: 800; font-size: var(--t-accion);
  letter-spacing: .04em; text-transform: uppercase;
  text-decoration: none; border-radius: var(--r-s);
  transition: background .16s ease, transform .16s ease;
}
.cta:hover { background: var(--magenta-hi); }
.cta:active { transform: translateY(1px); }
.cta::after { content: '→'; font-size: 18px; }

/* ---------- Marca ---------------------------------------------------------- */
.brand { display: flex; align-items: center; gap: 9px; text-decoration: none; color: var(--fg); }
/* MARCA — variante C. «Clave» manda: es lo que vendes y es lo que te separa
   del resto de sitios sobre GTA. Va en coral, el mismo color del botón de
   compra, para que marca y CTA hablen el mismo idioma. «GTA» queda en crema:
   identifica el producto sin robar el protagonismo. */
.brand__name { font-family: var(--display); font-weight: 600; font-size: 17px; letter-spacing: -.01em; }
.brand__name b { font-weight: 800; color: var(--magenta); }

/* ---------- Barra superior --------------------------------------------------
   La comparten la tienda y las páginas de aterrizaje. Estaba en store.css
   cuando solo la usaba la tienda; en cuanto la usan cuatro páginas, tenerla en
   una hoja concreta es pedir que se dupliquen tres variantes parecidas. */
.topbar {
  position: relative; z-index: 3;
  border-bottom: 1px solid var(--line-soft);
  background: rgba(20, 0, 31, .74);
  backdrop-filter: blur(10px);
}
.topbar__in {
  max-width: var(--wrap); margin: 0 auto;
  padding: 12px 20px;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.topbar__tag {
  font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--fg-faint); white-space: nowrap;
}

/* ---------- ESCENARIO: el atardecer de Vice City -----------------------------
   El fondo cinematográfico del sitio, en UN solo sitio. Lo usan la portada, la
   tienda y las tres páginas de aterrizaje.

   POR QUÉ AQUÍ Y NO EN CADA HOJA
   El recorrido de usuario dejó claro el problema: la landing, que es la puerta
   de entrada desde Google, era la única página sin escenario — texto sobre
   fondo oscuro. La página que recibe el tráfico era la menos reconocible del
   sitio. Copiar el degradado a landing.css lo habría arreglado esa tarde y
   habría dejado tres copias divergiendo desde el día siguiente.

   Todo el escenario se ajusta con dos variables que pone la página:
     --ground   alto de la banda de suelo (horizonte, skyline y retícula)
     --sun-w    tamaño del sol

   El contenido de la página debe reservar `--ground` por abajo. En porcentajes
   el horizonte cruzaba la base del título como un subrayado accidental, y en un
   punto distinto según el ancho.

   Arte propio: gradientes y SVG. Ni un archivo de Rockstar. */
.scene {
  --ground: 120px;
  --sun-w: min(170vw, 1100px);
  position: absolute; inset: 0; z-index: 0;
  pointer-events: none; overflow: hidden;
}

.scene__sun {
  position: absolute; left: 50%;
  bottom: calc(var(--ground) - (var(--sun-w) / 2.6));
  width: var(--sun-w); aspect-ratio: 1; transform: translateX(-50%);
  background: radial-gradient(circle at 50% 50%,
    rgba(255, 107, 123, .58) 0%,
    rgba(255, 106, 61, .30) 22%,
    rgba(139, 92, 246, .19) 44%,
    rgba(139, 92, 246, 0) 68%);
}

/* La línea del horizonte: el detalle que convierte un degradado en un
   atardecer. Sin ella, cielo y suelo son la misma mancha. */
.scene__horizon {
  position: absolute; left: 0; right: 0; bottom: var(--ground); height: 2px;
  background: linear-gradient(to right,
    transparent 0%, rgba(255, 106, 61, 0) 8%,
    rgba(255, 145, 82, .85) 34%, rgba(255, 107, 123, .95) 50%,
    rgba(255, 145, 82, .85) 66%, rgba(255, 106, 61, 0) 92%, transparent 100%);
  box-shadow: 0 0 34px 10px rgba(255, 92, 60, .32);
}

.scene__grid {
  position: absolute; left: -40%; right: -40%; bottom: 0;
  height: calc(var(--ground) + 40px);
  background:
    repeating-linear-gradient(to right, rgba(79, 201, 214, .22) 0 1px, transparent 1px 88px),
    repeating-linear-gradient(to bottom, rgba(79, 201, 214, .15) 0 1px, transparent 1px 38px);
  transform: perspective(360px) rotateX(64deg);
  transform-origin: bottom center;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 58%);
          mask-image: linear-gradient(to bottom, transparent, #000 58%);
}

/* Los edificios se apoyan en el horizonte, no flotan. */
.scene__skyline {
  position: absolute; left: 0; right: 0; bottom: 0; width: 100%;
  height: calc(var(--ground) + 2px);
}

.scene__veil {
  position: absolute; inset: 0;
  background: linear-gradient(to bottom,
    rgba(20, 0, 31, .18) 0%, rgba(20, 0, 31, .06) 38%, rgba(20, 0, 31, .94) 100%);
}

.scene__grain {
  position: absolute; inset: 0; opacity: .55; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.34'/%3E%3C/svg%3E");
}

/* Si algún día hay arte con base de uso decidida, entra por aquí y tapa el
   dibujo propio sin tocar nada más. Ver config.media. */
.scene__key {
  position: absolute; inset: 0; z-index: 0;
  object-fit: cover;
  /* Encuadre: los personajes se llevan a la derecha para que el titular tenga
     su propia mitad. Un titular cruzando una cara es un collage, no un hero. */
  object-position: 70% 38%;
  width: 100%; height: 100%;
}
@media (min-width: 900px) { .scene__key { object-position: 78% 36%; } }

/* CON FOTO REAL, EL DIBUJO PROPIO SE APAGA.
   Sol, horizonte, retícula y skyline son el escenario de respaldo: siguen en el
   DOM y vuelven solos si algún día se vacía `config.media.keyArt`. Superponer
   los dos solo ensucia la imagen. */
.scene--photo .scene__sun,
.scene--photo .scene__horizon,
.scene--photo .scene__grid,
.scene--photo .scene__skyline { display: none; }

/* El velo pasa por encima de la foto: es lo que hace legible el titular.
   Más denso abajo, donde vive el texto, y con una pizca de color de marca
   arriba para que la foto no choque contra el fondo de la página. */
/* EL VELO ES LO QUE HACE LEGIBLE EL TEXTO, Y TIENE QUE MEDIRSE.
   El arte oficial es un atardecer: melocotón, oro y lavanda, todo de luminancia
   ALTA. Encima va texto crema. Medido sobre los píxeles del render, el titular
   de la portada daba 1,30 de contraste sobre un mínimo de 3, y la cuenta atrás
   de la tienda 1,01 —o sea, invisible—.

   El `text-shadow` no arregla esto: da sensación de profundidad, no contraste.
   Por eso el problema pasó desapercibido hasta que se midió el píxel real en
   vez de buscar un background-color subiendo por el DOM, que sobre una foto
   devuelve el color del contenedor y no lo que se ve.

   Tres capas, cada una con su trabajo:
     1. una base uniforme que baja la luminancia de toda la imagen;
     2. una vertical que oscurece arriba (titular) y funde con el fondo abajo;
     3. una horizontal que protege la mitad donde vive el texto y deja
        respirar la mitad donde están los personajes. */
.scene--photo .scene__veil {
  z-index: 1;
  /* MÓVIL. El texto ocupa TODO el ancho, así que una cortina lateral no lo
     cubre: hace falta oscurecer de forma pareja. Se paga en color, y se paga a
     conciencia: un titular a 1,3 de contraste no es un titular. */
  background:
    linear-gradient(to bottom,
      rgba(20, 0, 31, .86) 0%, rgba(20, 0, 31, .72) 40%,
      rgba(20, 0, 31, .80) 78%, var(--ink) 100%),
    rgba(20, 0, 31, .22);
}

/* ESCRITORIO. Aquí el texto vive en la mitad izquierda y la imagen tiene sitio
   propio a la derecha, así que la cortina puede ser direccional: densa donde
   hay letras, transparente donde están los personajes. El atardecer conserva
   su color justo donde se ve. */
@media (min-width: 900px) {
  .scene--photo .scene__veil {
    background:
      linear-gradient(to right,
        rgba(20, 0, 31, .95) 0%, rgba(20, 0, 31, .90) 40%,
        rgba(20, 0, 31, .50) 62%, rgba(20, 0, 31, .04) 86%),
      /* La banda de arriba va algo más densa: ahí vive el eyebrow, que es el
         texto más pequeño del encabezado. Las caras están más abajo en el
         encuadre, así que no pierden luz por esto. */
      linear-gradient(to bottom,
        rgba(20, 0, 31, .52) 0%, rgba(20, 0, 31, .12) 38%,
        rgba(20, 0, 31, .70) 80%, var(--ink) 100%);
  }
}

/* Las landings y la tienda centran su columna de texto, así que una cortina
   lateral no la cubre: ahí manda la vertical. Pero NO pueden compartir la misma
   densidad, porque no comparten imagen: la landing lleva una calle de noche y
   la tienda el arte de la playa, que es un atardecer claro. Aligerar el velo
   para la landing —correcto ahí— sacó a la tienda de la norma al momento.
   Cada una con la suya, y las dos medidas. */
.lhero .scene--photo .scene__veil {
  background:
    /* Aquí el texto va centrado, así que una cortina lateral no lo cubre: manda
       la vertical. Aun así se deja respirar la franja media, que es donde la
       imagen tiene el horizonte. */
    /* Con una imagen de noche debajo el velo puede ser MUCHO más ligero y
       aun así pasar la medición: antes iba a .88 arriba porque la captura
       elegida era una vista diurna, la más clara de las 42 del paquete. La
       imagen se cambió; el velo la acompaña y ahora se ve el juego. */
    linear-gradient(to bottom,
      rgba(20, 0, 31, .70) 0%, rgba(20, 0, 31, .52) 40%,
      rgba(20, 0, 31, .38) 64%, rgba(20, 0, 31, .82) 88%, var(--ink) 100%);
}
.scene--photo .scene__grain { z-index: 2; opacity: .30; }

.scene__credit {
  position: absolute; right: 12px; bottom: 10px; z-index: 3;
  font-size: 10px; letter-spacing: .02em;
  color: rgba(255, 242, 230, .52);
}

/* La tienda: imagen clara debajo, así que velo más denso. Medido: con el de
   la landing, «Vice City vuelve.» caía a 3,51 y la línea de la cuenta atrás a
   4,01, ambas por debajo del 4,5 que pide AA. */
.stage .scene--photo .scene__veil {
  background:
    linear-gradient(to bottom,
      rgba(20, 0, 31, .86) 0%, rgba(20, 0, 31, .72) 40%,
      rgba(20, 0, 31, .58) 64%, rgba(20, 0, 31, .88) 88%, var(--ink) 100%);
}

/* ---------- Pie ------------------------------------------------------------ */
.foot { border-top: 1px solid var(--line-soft); padding: 30px 0 34px; }
.foot__in {
  max-width: var(--wrap); margin: 0 auto; padding: 0 20px;
  display: flex; flex-direction: column; gap: 14px;
}
.foot p { font-size: 12.5px; color: var(--fg-faint); line-height: 1.65; }
.foot b { color: var(--fg-dim); }
/* Los enlaces del pie median 21px de alto: por debajo de los 44px que necesita
   un dedo. El padding vertical los lleva a 44 sin cambiar como se ven, y el
   margen negativo compensa para que la fila no crezca. */
.foot__links { display: flex; flex-wrap: wrap; gap: 0 18px; margin: -11px 0; }
.foot__links a {
  font-size: 13px; color: var(--fg-dim); text-decoration: none;
  display: inline-flex; align-items: center; min-height: 44px;
}
.foot__links a:hover { color: var(--fg); text-decoration: underline; }

/* ---------- Consentimiento --------------------------------------------------
   VA EN EL FLUJO, ARRIBA. No es una superposición fija abajo, y la razón es
   concreta: siéndolo, tapaba el botón de compra. En móvil caía justo encima del
   CTA de /comprar; en escritorio, la tarjeta de abajo a la derecha se cruzaba
   con la tarjeta de compra centrada. Se intentó arreglar haciéndola más baja y
   reservando hueco por abajo, y no sirve: una barra fija se ancla al viewport y
   tapa lo que caiga a esa altura, sea cual sea el scroll. Era ajustar píxeles
   contra un problema estructural.

   En el flujo no puede solapar nada por construcción: empuja el contenido
   mientras está y desaparece al decidir. Además se ve antes, que es justo lo
   que debe hacer una petición de consentimiento. Lo mide I10, comparando
   rectángulos de verdad. */
.consent {
  position: relative; z-index: 60;
  background: var(--panel); border-bottom: 1px solid var(--line);
  padding: 10px 16px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px;
}
.consent p { flex: 1 1 240px; font-size: 12.5px; color: var(--fg-dim); line-height: 1.45; }
.consent__actions { display: flex; gap: 8px; flex: 0 0 auto; }
.btn-ghost, .btn-solid {
  /* 44 px es el mínimo táctil y el QA (I3) lo mide de verdad. */
  min-height: 44px; padding: 9px 15px; border-radius: var(--r-s);
  font-family: var(--display); font-weight: 700; font-size: 13.5px; cursor: pointer;
  white-space: nowrap;
}
.btn-ghost { background: transparent; border: 1px solid var(--line); color: var(--fg-dim); }
.btn-ghost:hover { color: var(--fg); border-color: var(--fg-faint); }
.btn-solid { background: var(--magenta); border: 1px solid var(--magenta); color: var(--magenta-ink); }
.btn-solid:hover { background: var(--magenta-hi); }

/* ---------- noscript ------------------------------------------------------- */
.noscript {
  max-width: var(--wrap); margin: 0 auto; padding: 16px 20px;
  border-top: 1px solid var(--line-soft);
  display: flex; flex-direction: column; gap: 8px;
}
.noscript p { font-size: 13.5px; color: var(--fg-dim); }

/* ---------- Fachada de vídeo ------------------------------------------------
   No se contacta con YouTube hasta que el visitante pulsa. Sin esto, entrar en
   la home cargaría scripts de un tercero antes de decidir nada sobre cookies,
   que es justo lo que el banner de consentimiento promete que no pasa. */
.facade {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--ink-2); overflow: hidden; cursor: pointer;
  /* Pila centrada, no rejilla: con `grid` los tres hijos ocupaban una fila
     cada uno y se repartían el alto, así que en escritorio el botón quedaba
     arriba y el texto abajo, separados por medio contenedor. */
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; padding: 16px; text-align: center;
}
/* EL FOTOGRAMA DE LA FACHADA.
   Va al fondo y oscurecido: es contexto, no protagonista. El botón y el texto
   tienen que seguir leyéndose encima sin dudarlo. */
.facade__still {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover;
  filter: brightness(.62) saturate(1.05);
  transition: filter .22s ease, transform .5s ease;
}
.facade > :not(.facade__still) { position: relative; z-index: 1; }
.facade:hover .facade__still { filter: brightness(.74) saturate(1.1); transform: scale(1.02); }
.facade.is-playing .facade__still { display: none; }

.facade__play {
  width: 64px; height: 64px; border-radius: 50%;
  background: var(--magenta); color: var(--magenta-ink);
  display: grid; place-items: center; font-size: 22px; font-weight: 700;
  box-shadow: 0 10px 30px -8px rgba(0, 0, 0, .8);
}
.facade__label {
  font-family: var(--display); font-weight: 700; font-size: 15px; letter-spacing: -.01em;
}
.facade__hint { font-size: 12px; color: rgba(255, 242, 230, .78); }
.facade iframe { width: 100%; height: 100%; border: 0; }
.facade.is-playing { display: block; padding: 0; cursor: default; }

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