:root{
    /* ANIMACIÓN */
    --ease-premium: cubic-bezier(.4, 0, .2, 1);
    --dur-nav: 280ms;
    --dur-carousel: 550ms;
    --dur-fast: .2s;   /* micro-interacciones: hover de cards, botones, iconos */
    --dur-base: .22s;  /* la otra duración más repetida en hovers existentes */

    /* =====================================================
       SISTEMA DE DISEÑO (fase 1 — solo variables, sin tocar
       el diseño actual). Cada token toma el valor que ya usaba
       el patrón más repetido en el CSS existente; no son
       valores nuevos. Se migran primero los componentes más
       visibles (botones, cards, badges, hero) — el resto del
       archivo sigue con sus valores literales hasta que se
       vayan migrando en etapas siguientes.
    ===================================================== */

    /* Radios */
    --radius-pill: 999px;
    --radius-circle: 50%;
    --radius-card: 18px;

    /* Sombras — niveles tomados de las recetas ya más repetidas
       (no se intenta unificar toda la familia dorada todavía) */
    --shadow-elevate: 0 12px 28px rgba(0,0,0,.35), 0 0 20px rgba(255,179,0,.12);
    --shadow-glow-soft: 0 0 25px rgba(255,179,0,.08);
    --shadow-glow-strong: 0 10px 30px rgba(255,179,0,.35);

    /* Espaciado — escala base para gaps/paddings de componentes
       que se migren de a poco */
    --space-xs: 8px;
    --space-sm: 14px;
    --space-md: 20px;
    --space-lg: 32px;

    /* =====================================================
       IDENTIDAD OFICIAL INARI OKAMI
       Un único rojo cerezo de marca (#d16868), extraído de
       la palabra "Okami" del logotipo. Las variantes se
       derivan de ese mismo color (no son colores nuevos).
    ===================================================== */

    /* Rojo cerezo — MARCA (identidad, hover, activos, detalles) */
    --cherry: #d16868;
    --cherry-strong: #e15f66;   /* mismo color, +luminosidad para texto pequeño sobre negro */
    --cherry-soft: rgba(209,104,104,.4);
    --cherry-faint: rgba(209,104,104,.14);
    --cherry-glow: rgba(209,104,104,.25);

    /* Dorado — ACCIÓN (solo CTAs: Descargar, Iniciar sesión, Patreon, Premium) */
    --gold: #e8b23c;
    --gold-light: #f5cf6a;
    --gold-soft: rgba(232,178,60,.14);
    /* Dorado atenuado -- SOLO para el estado de reposo de los botones
       primarios (.dash-btn-primary/.auth-btn-primary): mismo matiz que
       --gold/--gold-light pero menos saturado, para que el botón no se
       vea "plástico" sobre el fondo oscuro en reposo. El hover de esos
       botones recupera --gold/--gold-light (el dorado vivo original).
       No reemplaza a --gold en ningún otro uso (avatares, badges,
       textos) -- esos siguen exactamente igual. */
    --gold-muted: #caa149;
    --gold-muted-light: #d8be79;
    /* Dorado/ámbar atenuado -- SOLO para la barrita vertical de acento
       junto a los títulos de card en ajustes-usuario.html
       (.account-settings-card-title span). Distinto de --gold-muted de
       arriba a propósito (ese es para el fondo de un botón; esto es un
       detalle de identidad, no una acción) -- ahora que los botones de
       esa misma pantalla son verdes, esta barra se suaviza para no
       competir visualmente, pero sigue siendo claramente dorada/ámbar
       para mantener la jerarquía verde=acción / dorado=identidad /
       rojo=importante. Sólido, sin degradado ni glow. */
    --gold-accent-soft: #b27f34;
    /* Verde de acción -- prueba visual A/B, EXCLUSIVA de los botones de
       ajustes-usuario.html (.account-settings-card .dash-btn-primary).
       Antes era dorado (--gold-deep/--gold-deep-light); renombrado a
       verde para no dejar un nombre "gold" engañoso sobre un color que
       ya no es dorado. No se usa en ningún otro lado del sitio --
       Dashboard general y auth-btn-primary siguen con --gold-muted/
       --gold/--gold-light tal cual, sin ningún cambio.
       Ronda 2 ("SeaGreen", S=50%/L=36%) quedó demasiado esmeralda/vivo.
       Ronda 3 (punto intermedio salvia/esmeralda) quedó bien pero sin
       la parte "bosque fantástico/mágico" pedida.
       Ronda 4 (pedido explícito, referencia visual: foto de bosque
       húmedo -- "verde de bosque natural, profundo, ligeramente
       fantasioso/mágico, no corporativo/pastel/salvia/esmeralda"):
       mismo matiz que el pedido (#2F7548/#388653/#3B9559/#45A965,
       ~140-141°, más puramente verde que las rondas 1-2 y coherente
       con la foto de referencia). --green-action y --green-action-light
       (hover) se usan tal cual, ya cumplían contraste (~5.6:1/~7.1:1).
       --green-action-deep tal cual (#2F7548) daba solo ~3.8:1 -- se
       sube lo mínimo dentro del mismo matiz/saturación hasta ~4.5:1;
       --green-action-deep-light sube un poco más para que el degradado
       sutil siga siendo perceptible (antes casi idéntico al deep
       ajustado) y queda en ~5.9:1. */
    --green-action-deep: #348350;
    --green-action-deep-light: #3d995d;
    --green-action: #3b9559;
    --green-action-light: #45a965;
    --green-action-rgb: 59, 149, 89;

    /* Azul cielo oscuro -- pedido explícito, EXCLUSIVO de los botones
       primarios de dashboard-pagina-principal.html (.dash-home-page
       .dash-btn-primary). No se usa en ningún otro lado -- Dashboard
       general y auth-btn-primary siguen con --gold-muted/--gold/
       --gold-light tal cual. Texto blanco en vez de #111 (a diferencia
       de gold/green): un azul realmente OSCURO (pedido explícito, no
       un celeste pastel) no da suficiente contraste con texto negro. */
    --sky-blue-deep: #1d5672;
    --sky-blue-deep-light: #23688b;
    --sky-blue: #2f7fa8;
    --sky-blue-light: #3a97c4;
    --sky-blue-rgb: 47, 127, 168;

    /* Negro / grises por capas (elegancia sin negro plano) */
    --bg-0: #0d0d0d;   /* fondo general */
    --bg-1: #141414;   /* cards, paneles */
    --bg-2: #1a1a1a;   /* elementos elevados sobre cards */

    /* Blanco cálido (nunca blanco puro) */
    --text-warm: #f5f0e8;
    --text-soft: #c9c4bc;
    --text-dim: #8a857d;

    /* Bordes */
    --border-soft: rgba(245,240,232,.08);

    /* Acento único de interfaz -- cerezo sangre (pedido explícito):
       sustituye al dorado como acento general de la UI (nav, indicadores
       de sección, "Ver juego", bordes de card). Reutiliza el mismo
       rgb(150,50,60) ya usado en el borde de las cards normales y en
       ".see-all-games-btn" -- no es un color nuevo. Tripleta sin rgb()
       para poder variar la opacidad con rgba(var(--accent-rgb), X), igual
       que ya se hacía con el literal repetido en el resto del sitio.
       Patreon conserva su propio cereza (--cherry, rgb(201,106,122)) sin
       tocar -- son colores distintos a propósito, nunca el mismo. */
    --accent-rgb: 150,50,60;
}
html {
  overflow-x: hidden;
}
body {
  margin: 0;
  font-family: 'Segoe UI', sans-serif;
  /* Negro carbón en vez de negro casi puro (pedido explícito): +~8
     unidades sobre el #0a0a0a anterior, con una pizca de calidez (R/G
     apenas por encima de B) -- perceptible solo como "menos plano" en
     las zonas vacías entre secciones, nunca como un color visible.
     Único punto que controla el fondo global -- no usa var(--bg-0) a
     propósito: esa variable también alimenta el degradado del Hero y
     la scrollbar (ver más abajo), y tocarla movería esos componentes
     con ella. */
  background: #121110;
  color: white;
}
body::before{
    content: "";

    position: fixed;

    inset: 0;

    background:
    radial-gradient(
        circle at top right,
        rgba(209,104,104,.05),
        transparent 30%
    ),
    radial-gradient(
        circle at bottom left,
        rgba(209,104,104,.04),
        transparent 28%
    );

    pointer-events: none;

    z-index: -1;
}
.container{
    width: min(1320px, calc(100% - 44px));
    margin: auto;
}
.footer-pro .container{

    width: 92%;

    max-width: 1400px;

    margin: auto;
}
/* NAVBAR */
.navbar {
  height: 78px;
  padding: 0 40px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: rgba(8,8,8,.72);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  position: fixed;
  left: 0;
  right: 0;
  z-index: 100;
  top: 0;
  transition: transform var(--dur-nav) var(--ease-premium),
              background var(--dur-nav) var(--ease-premium),
              backdrop-filter var(--dur-nav) var(--ease-premium);
}
.navbar.nav-hidden{
    transform: translateY(-100%);
}

/* El navbar está fuera del flujo (fixed) en todas las páginas que lo
   usan -- necesitan su altura como padding-top en el body para que el
   contenido no arranque tapado debajo suyo. La home entra acá también
   -- revertido el espacio extra que se probó (24px): el Hero debe
   empezar justo debajo del navbar, sin separación. Que la parte
   importante de la imagen no quede tapada se resuelve con
   object-position en la propia imagen, no con más espacio acá. */
body.has-navbar,
body.home-page{
    padding-top: 78px;
}

.navbar.scrolled{

    background:
    rgba(10,10,10,.88);

    backdrop-filter:
    blur(18px);

    -webkit-backdrop-filter:
    blur(18px);

    box-shadow:
    0 8px 30px rgba(0,0,0,.28);
}
.navbar::after{
    content: "";

    position: absolute;

    left: 0;
    bottom: 0;

    width: 100%;
    height: 1px;

    background:
    linear-gradient(
        90deg,
        transparent,
        rgba(var(--accent-rgb),.45),
        transparent
    );
}
.navbar nav{
    display: flex;
    align-items: center;
    gap: 28px;
}

.navbar-right{
    display: flex;
    align-items: center;
    gap: 36px;
}

.navbar nav a{
    position: relative;

    color: rgba(255,255,255,.72);

    text-decoration: none;

    text-transform: uppercase;
    letter-spacing: .6px;
    font-size: 13px;
    font-weight: 500;

    transition:
    color .25s ease,
    transform .25s ease,
    opacity .25s ease;
}

.navbar nav a:hover{
    color: rgb(var(--accent-rgb));

    transform: translateY(-2px);
}

.navbar nav a.active{
    color: rgb(var(--accent-rgb));
}

.navbar nav a.active::after{
    width: 100%;
}

/* BUSCADOR */
.navbar-search{
    display: flex;
    align-items: center;
    gap: 6px;
    height: 40px;
    padding: 0 6px 0 16px;
    border-radius: var(--radius-pill);
    border: 1px solid rgba(255,255,255,.12);
    background: rgba(255,255,255,.04);
    transition: border-color var(--dur-base) ease, background var(--dur-base) ease;
    /* Ancla del dropdown de resultados en vivo (navbar-search.js) --
       única línea nueva de esta regla, el resto no cambia. */
    position: relative;
}

.navbar-search:focus-within{
    border-color: rgba(var(--accent-rgb),.4);
    background: rgba(255,255,255,.06);
}

.navbar-search input{
    background: none;
    border: none;
    outline: none;
    color: var(--text-warm);
    font-size: 13px;
    width: 150px;
    font-family: inherit;
}

.navbar-search input::placeholder{
    color: var(--text-dim);
}

.navbar-search-btn{
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    flex-shrink: 0;
    border-radius: var(--radius-circle);
    border: none;
    background: none;
    color: var(--text-dim);
    cursor: pointer;
    transition: color var(--dur-fast) ease, background var(--dur-fast) ease;
}

.navbar-search-btn:hover{
    color: rgb(var(--accent-rgb));
    background: rgba(var(--accent-rgb),.1);
}

.navbar-search-btn svg{
    width: 15px;
    height: 15px;
    display: block;
}

@media (max-width: 980px){
    .navbar-search{ display: none; }
}

/* Dropdown de resultados en vivo (navbar-search.js, pedido explícito) --
   mismo lenguaje visual EXACTO que .nav-user-dropdown (el otro dropdown
   ya existente colgado del navbar): mismo fondo/blur/borde/radio/sombra/
   animación/z-index, así los dos se leen como el mismo componente del
   sitio, no como dos estilos distintos de "caja flotante". Solo cambia
   el ancho (más ancho, tiene que caber imagen+título+tags) y que cuelga
   a la izquierda del buscador en vez de a la derecha del avatar. */
.navbar-search-results{
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    width: 420px;
    max-width: 90vw;
    max-height: 420px;
    overflow-y: auto;
    background: rgba(15,15,15,.92);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid var(--border-soft);
    border-radius: 14px;
    padding: 6px;
    box-shadow: 0 16px 40px rgba(0,0,0,.5);
    animation: authAlertIn var(--dur-fast) ease;
    z-index: 200;
}

.navbar-search-results[hidden]{
    display: none;
}

/* Estado "buscando"/"sin resultados"/error -- un solo mensaje discreto,
   mismo tono que .card-category (--text-dim), nunca un error técnico. */
.navbar-search-status{
    padding: 14px 12px;
    font-size: 13px;
    color: var(--text-dim);
    text-align: center;
}

.navbar-search-result{
    display: flex;
    align-items: center;
    /* Un poco más grandes (pedido explícito: "se ven como chicos") --
       gap/padding suben junto con la miniatura y el título de abajo. */
    gap: 12px;
    padding: 10px;
    border-radius: 10px;
    text-decoration: none;
    color: inherit;
    transition: background .18s ease;
}

.navbar-search-result:hover,
.navbar-search-result:focus-visible{
    background: rgba(255,255,255,.06);
    outline: none;
}

.navbar-search-result-img{
    /* Venía de 44px (pedido explícito: resultados un poco más grandes). */
    width: 56px;
    height: 56px;
    flex-shrink: 0;
    border-radius: 8px;
    object-fit: cover;
    background: var(--bg-1);
}

.navbar-search-result-body{
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.navbar-search-result-title{
    /* Venía de 13.5px (pedido explícito, mismo motivo que la miniatura
       de arriba). */
    font-size: 15px;
    font-weight: 600;
    color: var(--text-warm);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.navbar-search-result-tags{
    display: flex;
    gap: 6px;
}

/* Misma receta de color que .card-badge-genre (gris-lavanda neutro, ver
   arriba) pero sin position:absolute -- acá tiene que fluir inline
   dentro de la fila, no clavarse en la esquina de una imagen. Género
   se queda con este gris neutro; el motor (engine) gana color propio
   abajo (reapertura, pedido explícito). */
.navbar-search-tag{
    background: #34313F;
    border: 1px solid rgba(220,210,235,.25);
    color: #E3DDEC;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .01em;
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    white-space: nowrap;
}

/* Reapertura (pedido explícito): un color por motor en vez del gris
   neutro de arriba -- mismos 5 colores que ya usa .dash-chip.is-engine-*
   en dashboard.css (Traducciones Futuras), acá como valores literales
   porque style.css no carga las variables --dash-* del Dashboard.
   "Otros" (engineTagClass() devuelve "" -- ver navbar-search.js) se
   queda con el gris neutro de .navbar-search-tag, sin clase extra. */
.navbar-search-tag.is-engine-kirikiri{
    background: var(--cherry-faint);
    border-color: rgba(209,104,104,.35);
    color: var(--cherry-strong);
}

.navbar-search-tag.is-engine-rpgmaker{
    background: var(--gold-soft);
    border-color: rgba(232,178,60,.35);
    color: var(--gold-light);
}

.navbar-search-tag.is-engine-renpy{
    background: rgba(80,200,120,.12);
    border-color: rgba(80,200,120,.35);
    color: #6fd996;
}

.navbar-search-tag.is-engine-unity{
    background: rgba(92,156,255,.12);
    border-color: rgba(92,156,255,.35);
    color: #8fb4ff;
}

.navbar-search-tag.is-engine-wolf{
    background: rgba(178,122,255,.12);
    border-color: rgba(178,122,255,.35);
    color: #c9a8ff;
}

.navbar-search-viewall{
    display: block;
    text-align: center;
    padding: 10px 12px;
    margin-top: 2px;
    border-top: 1px solid var(--border-soft);
    font-size: 12.5px;
    font-weight: 600;
    color: rgb(var(--accent-rgb));
    text-decoration: none;
}

.navbar-search-viewall:hover{
    color: var(--text-warm);
}

/* Reapertura (pedido explícito, probado en celular real): botones de
   buscador plegable + menú hamburguesa -- ocultos en escritorio (ahí
   ya están <nav> y .navbar-search visibles tal cual), se muestran
   únicamente en mobile (ver @media abajo, que necesita esta regla
   base ANTES en el archivo para poder ganarle en el cascade). */
.navbar-search-toggle,
.navbar-hamburger{
    display: none;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    border-radius: var(--radius-circle);
    border: none;
    background: none;
    color: var(--text-warm);
    cursor: pointer;
    transition: color var(--dur-fast) ease, background var(--dur-fast) ease;
}

.navbar-search-toggle:hover,
.navbar-hamburger:hover{
    color: rgb(var(--accent-rgb));
    background: rgba(var(--accent-rgb),.1);
}

.navbar-search-toggle svg,
.navbar-hamburger svg{
    width: 20px;
    height: 20px;
}

.navbar nav a::after{
    content: "";

    position: absolute;

    left: 0;
    bottom: -7px;

    width: 0%;
    height: 2px;

    border-radius: var(--radius-pill);

    background:
    linear-gradient(
        90deg,
        rgba(var(--accent-rgb),.75),
        rgb(var(--accent-rgb))
    );

    transition: width var(--dur-nav) ease;
}

.navbar nav a:hover::after{
    width: 100%;
}

.logo-container {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: 14px;
  cursor: pointer;
}

.logo-emblem {
  height: 62px;
  width: 62px;
  object-fit: cover;
  border-radius: 50%;
  transition: 0.3s;
}

.logo-full {
  height: 64px;
  width: auto;
  object-fit: contain;
  transition: 0.3s;
}

.logo-full:hover {
  transform: scale(1.04);
}

.logo-wordmark {
  height: 40px;
  width: auto;
  object-fit: contain;
  transition: 0.3s;
  filter: drop-shadow(0 0 10px rgba(255,179,0,.16));
}

.logo-container:hover .logo-emblem {
  transform: scale(1.06);
}

.logo-container:hover .logo-wordmark {
  transform: scale(1.04);
}

/* Reapertura (pedido explícito): flash visual + corrimiento del navbar
   al cambiar de página con sesión ya iniciada -- el HTML crudo siempre
   arranca en "Iniciar sesión" (.login-btn, ~165px) y session.js lo
   reemplaza por el avatar+badge (.nav-user-menu, entre 44px sin badge y
   ~175px con el badge más largo, "Shogun Inari") recién en
   DOMContentLoaded. #navAuthArea pasa a ser un wrapper ESTABLE que
   nunca se reemplaza (session.js ahora le cambia el innerHTML, nunca el
   outerHTML) -- el min-width de acá cubre el estado más ancho posible
   de cualquiera de los dos contenidos, así ninguno de los dos empuja a
   los links del navbar al aparecer. justify-content:flex-end porque es
   el elemento más a la derecha: si el contenido real es más angosto
   (ej. member sin badge, solo 44px), queda pegado al borde derecho en
   vez de flotar centrado en el espacio de sobra. */
.nav-auth-slot{
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    min-height: 44px;
    min-width: 195px;
}

/* Ve con .nav-auth-slot de arriba: mientras se confirma si la sesión en
   localStorage sigue siendo válida (session.js todavía no corrió),
   esconde el "Iniciar sesión" que el HTML muestra por defecto -- evita
   mostrarlo por error cuando en realidad SÍ hay sesión. El espacio ya
   está reservado por .nav-auth-slot, así que ocultarlo (visibility, no
   display) no genera ningún salto adicional. Si termina sin haber
   sesión de verdad, session.js reemplaza el innerHTML igual y esta
   clase deja de aplicar. */
.nav-auth-slot-pending .login-btn{
    visibility: hidden;
}

/* Reapertura (pedido explícito): desplazamiento residual de INICIO/
   JUEGOS/etc. detectado DESPUÉS del fix de .nav-auth-slot de arriba --
   causa distinta, mismo síntoma. notifications-bell.js inserta la
   campana como un HERMANO NUEVO de #navAuthArea dentro de .navbar-right
   (gap:36px, sin justify-content -> flex-start), solo si hay sesión,
   de forma asíncrona. Como .navbar-right es el único hijo de la derecha
   en .navbar (justify-content:space-between con el logo), agregarle un
   hijo de 42px + 36px de gap corre su borde izquierdo -- y con él, a
   `nav` (el primer hijo) -- 78px hacia la izquierda, recién cuando la
   campana aparece.
   #navBellSlot es el mismo patrón que .nav-auth-slot: un slot ESTABLE
   en la posición donde iría la campana, que notifications-bell.js
   ahora rellena por dentro (nunca crea un hermano nuevo). Por defecto
   `display:none` -- no participa del flex ni consume gap, IGUAL que
   hoy para un visitante anónimo (nunca hubo campana ni hueco). Se
   activa por clase (mismo localStorage-hint que .nav-auth-slot-pending
   ya usa) para reservar el espacio real ANTES de que notifications-
   bell.js confirme la sesión, así cuando la campana de verdad aparece
   ya no cambia ningún ancho. */
.nav-bell-slot{
    display: none;
    width: 42px;
    height: 42px;
    flex-shrink: 0;
}

.nav-bell-slot-active{
    display: inline-flex;
}

/* BOTONES */
/* Iniciar sesión: acento rojo vívido (más saturado que el --cherry
   de marca) para que se distinga como la acción principal de la
   navbar, en vez del dorado sutil que usaba antes. */
.login-btn{
    height: 42px;

    padding: 0 20px;

    border-radius: var(--radius-pill);

    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    text-decoration: none;

    border:
    1.5px solid rgba(255,64,94,.55);

    background:
    rgba(255,64,94,.08);

    color: #ff8fa0;

    font-size: 14px;
    font-weight: 700;
    letter-spacing: .2px;

    cursor: pointer;

    transition:
    transform var(--dur-base) ease,
    background var(--dur-base) ease,
    border-color var(--dur-base) ease,
    box-shadow var(--dur-base) ease;
}

.login-btn svg{
    width: 15px;
    height: 15px;
    flex-shrink: 0;
}

.login-btn:hover{
    transform: translateY(-2px);

    background:
    rgba(255,64,94,.16);

    border-color:
    rgba(255,64,94,.85);

    box-shadow:
    0 0 22px rgba(255,64,94,.35);
}
.hero-stats{
    display: flex;

    gap: 18px;

    margin-top: 45px;
}

.hero-stat{
    background: rgba(255,255,255,0.06);

    border: 1px solid rgba(255,255,255,0.08);

    backdrop-filter: blur(10px);

    padding: 16px 20px;

    border-radius: 18px;

    min-width: 120px;
}

.hero-stat strong{
    display: block;

    color: white;

    font-size: 24px;

    margin-bottom: 6px;
}

.hero-stat span{
    color: rgba(255,255,255,0.7);

    font-size: 14px;
}
/* HERO (ver .discover-hero más abajo, sección nueva) */
.section-title{
    display: flex;
    align-items: center;

    gap: 10px;

    margin-bottom: 45px;
}

.title-line{
    width: 6px;
    height: 38px;

    border-radius: var(--radius-pill);

    background: rgb(var(--accent-rgb));

    box-shadow: 0 0 15px rgba(var(--accent-rgb),.45);
}

.section-title h2{

    font-size: 1.9rem;

    font-weight: 700;

    letter-spacing: -0.5px;
}
.section-title p{
    color: #828282;

    margin-top: 8px;

    font-size: .92rem;
}
/* SECTION */
.section {
  padding: 84px 0;
}

/* Anula el padding superior en TODAS las .section del sitio, no solo
   catálogo — reubicada acá en la auditoría de style.css: vivía junto
   a "CATALOG PAGE" sin ningún calificador que limitara su alcance,
   pese a afectar también a index.html/todos-los-juegos.html. Mismo
   selector que la regla de arriba, una sola ubicación. */
.section{
    padding-top: 42px;
}

/* GRID *//*cards mas grandes o pequeñas we*/
.grid {

  display: grid;

  grid-template-columns:
  repeat(3, 1fr);

  gap: 28px;

}

/* TREND SLIDER */

.trend-slider{

    display: flex;

    gap: 22px;

    overflow-x: auto;

    scroll-behavior: smooth;

    scrollbar-width: none;

    padding-bottom: 8px;

    padding-right: 120px;

    padding-bottom: 8px;
}

.trend-slider::-webkit-scrollbar{
    display: none;
}

.trend-slider .card{

    min-width: 480px;

    max-width: 480px;

    flex-shrink: 0;
}

.tag {
  position: absolute;
  top: 10px;
  left: 10px;
  background: #ff9900;
  color: black;
  padding: 5px 10px;
  font-size: 12px;
  border-radius: 10px;
  z-index: 3;
}

.card-info {
  position: absolute;
  bottom: 0;
  padding: 15px;
  z-index: 2;
}

.badge {
  display: inline-block;
  margin-top: 8px;
  background: #333;
  padding: 5px 10px;
  border-radius: 10px;
  font-size: 12px;
}

.play-btn {
  margin-top: 10px;
  background: #ff9900;
  border: none;
  padding: 6px 12px;
  border-radius: 10px;
  cursor: pointer;
}

/* FOOTER */
footer {
  background: #0d0d0d;
  padding: 40px;
  border-top: 1px solid #222;
}

.footer-content {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
}

.socials button {
  margin: 5px;
  padding: 8px 15px;
  border-radius: 20px;
  border: none;
  background: #222;
  color: white;
  cursor: pointer;
}

.copy {
  text-align: center;
  margin-top: 20px;
  color: #828282;
}

.arrow:hover {
  background: rgba(255, 153, 0, 0.7);
}

/* DOTS */
.dots {
  position: absolute;
  bottom: 15px;
  width: 100%;
  text-align: center;
  z-index: 3;
}

/* .dots/.dot legacy: reemplazado por .discover-hero-dot(s) */
.card{
    /* Pedido explícito (refinamiento visual): negro plano -> negro
       carbón con matiz púrpura muy sutil, para que combine mejor con
       los bordes/acentos rosados-morados de las cards (Patreon, hover)
       en vez de sentirse desconectado. Sigue leyéndose "prácticamente
       negro" -- la temperatura púrpura es deliberadamente mínima. */
    background:
    linear-gradient(
    180deg,
    #151219 0%,
    #100e13 100%
    );
    border-radius: var(--radius-card);
    overflow: hidden;
    position: relative;

    text-decoration: none;

    /* Pedido explícito: el título ya no reserva una altura fija de 2
       líneas (eso dejaba un hueco visible entre título y desarrollador
       cuando el título era de 1 sola línea) -- ahora el bloque de
       texto fluye a su alto natural. Sin align-self:start, el grid
       (que iguala la altura de fila a la card más alta) volvería a
       estirar esta card y dejaría un hueco suelto al fondo -- con
       align-self:start la card mide solo lo que su propio contenido
       necesita, nunca más. */
    align-self: start;

    /* Pedido explícito (refinamiento "premium"): easing más elegante
       en vez de "ease" liso -- reutiliza --ease-premium, ya definido
       y usado en otras partes del sitio (navbar, carrusel), en vez de
       inventar una curva nueva. */
    transition: transform var(--dur-fast) var(--ease-premium), box-shadow var(--dur-fast) var(--ease-premium), background var(--dur-fast) var(--ease-premium), border-color var(--dur-fast) var(--ease-premium);

    /* Corrección posterior (pedido explícito, bug real encontrado):
       esto era un border real de 1px (transparente en reposo, dorado
       en hover) para que el hover no moviera el layout al cambiar de
       color. Pero un border real ocupa espacio de caja -- empujaba
       .card-image/la imagen 1px hacia adentro por los cuatro lados,
       dejando ver por esa franja el fondo oscuro de la propia card en
       vez de la portada (justo el "espacio negro dentro del área de
       imagen" reportado). box-shadow inset da el mismo anillo visual
       sin ocupar espacio de caja -- la imagen ahora llega de verdad
       hasta el borde real de la card en los cuatro lados.

       Reapertura: el anillo neutro que vivía acá (inset 0 0 0 1px
       rgba(255,255,255,.06)) se reemplaza por el border real de abajo
       (.card:not(.card-patreon-active), pedido explícito) -- ya no
       hace falta un segundo anillo apenas visible compitiendo con el
       borde real. Se mantiene solo la sombra difusa de profundidad. */
    box-shadow: 0 4px 16px rgba(0,0,0,.28);

    /* Pedido explícito: box-sizing:border-box para que el border real
       de abajo (1px, solo en cards normales) no le sume tamaño extra
       a la card frente a una card Patreon vecina en la misma fila
       (esas usan box-shadow, no border) -- mismo tamaño exterior en
       los dos casos, el border se dibuja hacia adentro. */
    box-sizing: border-box;
}

/* Pedido explícito (reapertura: se revierte el intento anterior con
   ::after + mask -- "no lo compliques", quería específicamente un
   border real). Línea sólida, fina (1px) y pareja en los 4 lados,
   siguiendo el border-radius de la card de forma nativa (un border
   real ya respeta border-radius sin ningún recurso extra). Sin glow,
   sin sombra de color, sin degradado: solo el border.
   :not(.card-patreon-active) para que las cards Patreon (que usan su
   propio ::after + box-shadow cereza, sin tocar acá) nunca reciban
   este border.

   Reapertura (pedido explícito): dos cambios --
   1) Transparente en reposo, visible SOLO en :hover (antes quedaba
      dorado siempre) -- mismo ancho (1px) en los dos estados, así que
      el color cambia pero la caja nunca se mueve ni cambia de tamaño
      al pasar el mouse.
      2) Cerezo (mismo "cerezo de sangre" ya usado en otro lugar,
      rgb(150,50,60)) en vez de dorado -- pedido explícito, "todo
      tiene que tener el mismo color cerezo sangre". */
.card:not(.card-patreon-active){
    /* Pedido explícito: un poco más grueso (1px -> 2px -> 3px) para
       que se note mejor -- mismo ancho en los dos estados
       (reposo/hover), solo cambia el color, la caja sigue sin
       moverse. */
    border: 3px solid transparent;
}
.card:not(.card-patreon-active):hover{
    border-color: rgba(150,50,60,.95);
}

.card::before{
    content: "";

    position: absolute;

    inset: 0;

    background:
    linear-gradient(
        to top,
        rgba(var(--accent-rgb),.08),
        transparent 45%
    );

    opacity: 0;

    transition: .3s ease;

    pointer-events: none;

    z-index: 1;
}

.card:hover::before{
    opacity: 1;
}
.card:hover{
    /* Bug real encontrado (pedido explícito, reapertura): el
       translateY(-3px) de acá vivía en el MISMO elemento que dispara
       :hover -- si el cursor quedaba a menos de 3px del borde inferior
       real de la card, mover la card 3px hacia arriba sacaba ese borde
       de abajo del cursor, terminando el :hover; la card volvía a su
       posición, el cursor volvía a quedar adentro, se disparaba :hover
       de nuevo... un loop que se auto-sostiene solo con el cursor
       quieto ahí (confirmado midiendo el propio estado :hover: 5
       cambios reales en menos de 2 segundos, sin mover el mouse). Eso
       era la "barrita" que parpadeaba varias veces por segundo. Se
       saca el translateY -- la elevación ahora la da solo la sombra
       (--shadow-elevate, ya bastante perceptible), que no mueve la
       caja de la card ni puede volver a generar este loop. */

    /* Reapertura (pedido explícito, "en el borde hay 2 líneas,
       importante que quede solo 1"): el anillo inset cerezo que vivía
       acá (de varias reaperturas anteriores) se solapaba con el nuevo
       border real de .card:not(.card-patreon-active):hover (arriba) --
       dos trazos casi pegados, muy parecidos en color, se leían como
       una línea doble. Se saca el anillo de acá por completo -- el
       border real ya es la única línea. Queda solo la sombra difusa
       neutra (sin color) para la elevación. */
    box-shadow: 0 12px 28px rgba(0,0,0,.35);

    /* Mismo matiz púrpura sutil que el reposo (ver .card), apenas más
       claro -- pedido explícito: "puede aclararse ligeramente". */
    background: #18131c;
}

/* Pedido explícito: el título gana un poco de luminosidad en hover --
   mismo color, sin cambiar de tono, solo un poco más de brillo. */
.card:hover h3{
    filter: brightness(1.12);
}

.card:hover img{
    /* Reapertura (pedido explícito): micro-zoom sutil de vuelta --
       antes se había sacado el scale() del hover por completo (pedido
       explícito de esa vuelta: "no agregar recorte extra"), pero ahora
       se pide recuperarlo, con un tope bajo (nunca 1.06 como antes)
       para que sea una interacción chica, no un recorte importante.
       Object-fit:cover + overflow:hidden de .card/.card-image ya
       absorben el recorte extra mínimo sin desbordar el layout ni
       mover cards vecinas -- transform nunca afecta el flujo del
       documento.

       Reapertura posterior (pedido explícito): bajado de 1.03 a 1.02.
       No era un bug de renderizado (confirmado con una imagen de color
       sólido en el mismo hover: cero costura en cualquier frame de la
       transición) -- era el recorte real cambiando cuadro a cuadro
       mientras dura el zoom, más perceptible cuando hay algo claro
       (pelo/piel del personaje) muy pegado al borde inferior de esa
       imagen puntual. Un scale más chico reduce cuánto cambia ese
       recorte durante la animación, sin eliminarlo del todo (es
       inherente a cualquier zoom sobre arte no uniforme). */
    transform: scale(1.02);

    filter:
    brightness(1.08)
    saturate(1.08);
}
.card:hover .card-content{
    transform: translateY(-3px);
}

.card-image{
    position: relative;

    /* Bug real encontrado (pedido explícito, corrección posterior):
       sin este overflow:hidden PROPIO, el micro-zoom de la imagen en
       hover (.card:hover img, transform:scale) dependía únicamente
       del overflow:hidden del .card exterior para recortarse -- un
       nivel de DOM más lejos. Eso dejaba una costura/línea clara de
       render (artefacto de compositing del navegador al escalar un
       hijo y recortarlo desde un ancestro no inmediato) justo en el
       borde inferior de la imagen, entre la imagen y el contenido.
       .games-catalog-grid .card-image (todos-los-juegos.html) ya tenía
       este overflow:hidden propio y NUNCA mostró el problema -- mismo
       arreglo acá, para las cards de index.html. No cambia tamaño,
       recorte de encuadre (sigue siendo cover) ni nada más. */
    overflow: hidden;
}

/* Pedido explícito ("integra visualmente la imagen con el cuerpo de la
   card"): degradado oscuro sutil en la parte inferior de la imagen --
   mismo recurso que ya existe en .games-catalog-grid .card-image::after
   (todos-los-juegos.html), pero más tenue acá (esta regla base es la
   que usan las cards de index.html, que no tenían ninguno todavía). La
   más específica de abajo sigue ganando donde ya existía -- no se
   toca. Ancla arriba/abajo/izq/der de la propia .card-image, recortado
   por el overflow:hidden + border-radius de .card (ver arriba), así
   que respeta las mismas esquinas sin ningún ajuste extra acá. */
.card-image::after{
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(to top, rgba(0,0,0,.42), transparent 38%);
    pointer-events: none;
}

.card img{
    width: 100%;
    height: 200px;

    /* Pedido explícito, definitivo (varias reaperturas antes): la
       imagen debe llenar SIEMPRE el área de la card, sin fondos
       auxiliares ni huecos -- cover, sin JS de por medio. Recorta lo
       mínimo necesario para llenar ambas dimensiones (nunca deforma,
       nunca hace más zoom del que hace falta para llenar). */
    object-fit: cover;

    display: block;

    /* Pedido explícito, reapertura: micro-zoom sutil en hover (ver
       .card:hover img) -- transform con transición rápida (180ms)
       para que se sienta como una pequeña interacción, no un cambio
       de encuadre. filter se mantiene con su propia duración. Easing
       premium (ver .card) en vez de "ease" liso, para que el
       micro-zoom se sienta fluido y no mecánico. */
    transition:
    transform .18s var(--ease-premium),
    filter .5s ease;
}

.card-content{
     padding: 14px 16px 16px;
    transition: transform var(--dur-fast) var(--ease-premium);

    /* Pedido explícito ("indicador de interacción" en hover) -- ancla
       de posicionamiento para .card-content::after (abajo). No cambia
       nada visualmente por sí sola: .card-content ya no dependía de
       ningún ancestro posicionado para nada más. */
    position: relative;

    /* Reapertura (pedido explícito): el min-height que vivía acá (piso
       común para que ninguna card quedara dispar de sus vecinas, ver
       historial en git) ya no hace falta -- ahora .card-content h3
       reserva altura fija de 2 líneas por sí solo (ver más abajo), así
       que género + título (fijo) + desarrollador ya suman SIEMPRE el
       mismo alto total sin necesidad de forzar nada acá. Eliminarlo no
       cambia nada visualmente (la suma de los tres ya da el mismo
       número), pero saca una capa de indirección que dejó de ser la
       fuente de verdad de la altura. */
}

/* Pedido explícito ("indicador de interacción", opcional -- solo si no
   requiere tocar la estructura): "Ver juego →" aparece en hover, sin
   agregar ningún HTML nuevo (contenido generado por CSS). Absoluto
   dentro de .card-content (arriba, position:relative) -- no participa
   del flujo, así que no mueve ni el título ni el nombre del
   desarrollador ni afecta el min-height. Oculto por defecto
   (opacity:0 + pointer-events:none), aparece con un fade + deslizamiento
   corto en hover; nunca compite con el título (mismo dorado discreto
   que el resto de acentos del sitio, tamaño chico). */
.card-content::after{
    content: "Ver juego →";
    position: absolute;
    right: 16px;
    bottom: 14px;
    font-size: .72rem;
    font-weight: 600;
    color: rgb(var(--accent-rgb));
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity .25s var(--ease-premium), transform .25s var(--ease-premium);
    pointer-events: none;
}
.card:hover .card-content::after{
    opacity: 1;
    transform: translateX(0);
}

/* Pedido explícito, corrección posterior (reemplaza al .card-tag que
   vivía como pill sobre la imagen, referencia visual del usuario):
   el género principal pasa a ser la primera línea del bloque de
   texto, en vez de un badge sobre la imagen -- mismo criterio que
   .card-category/.card-creator (gris, discreto), pegado directo
   arriba del título. */
.card-genre-label{
    display: block;
    color: #8a8a8a;
    font-size: .78rem;
    margin-bottom: 4px;
}

.card-content h3{
    /* Prueba visual explícita (acotada solo al título de la card):
       lavanda suave en vez de blanco, sin tocar ningún otro color del
       sitio (dorado sigue siendo botones/badges/selección, cereza
       sigue siendo Patreon). */
    /* Reapertura (pedido explícito): lavanda más suave/desaturado --
       mismo espíritu (identidad lavanda de Inari Okami), menos
       intenso, para que se sienta elegante en vez de llamativo. Sigue
       siendo el elemento más prominente del bloque (categoría y
       desarrollador se mantienen en gris, sin tocar). */
    color: #D8C9E8;

    font-size: 15.5px;

    /* Bug real encontrado (pedido explícito, comparado contra una
       referencia real): <h3> trae un margin-top propio del navegador
       (~1em, nunca definido acá) que NUNCA se había anulado -- por
       margin-collapse con .card-genre-label{margin-bottom:4px} de
       arriba, ese default (más grande) le ganaba al de 4px y dejaba
       ~15.5px de hueco real entre categoría y título, mucho más de lo
       que cualquier regla de este archivo pedía a propósito. Anularlo
       acá es lo que de verdad cierra ese hueco a los 4px de
       .card-genre-label. */
    margin-top: 0;
    margin-bottom: 4px;

    /* Pedido explícito: un título largo no debe estirar la card entera
       -- tope de 2 líneas + puntos suspensivos (line-clamp). line-height
       explícito para que el recorte de 2 líneas sea predecible.

       Reapertura (pedido explícito): el min-height fijo de 2 líneas que
       vivía acá (ver historial en git) resolvía la consistencia de
       grid, pero reservaba 2 líneas SIEMPRE, incluso en filas donde
       ningún título las necesitaba -- pedido explícito ahora es más
       fino: la altura debe sincronizarse por FILA visual (si algún
       título de la fila necesita 2 líneas, toda la fila usa 2; si no,
       la fila usa 1), no una constante global. CSS Grid por sí solo no
       puede resolver esto -- el alto "correcto" de cada fila depende
       del CONTENIDO de sus títulos, y .card ya usa align-self:start
       (arriba) a propósito para que las cards no se estiren a ciegas
       al alto de fila más alto del grid completo. Sin min-height acá,
       el título mide su alto real (1 o 2 líneas); syncTitleRowHeights()
       (ver el <script> de esta página) agrupa las cards por su
       offsetTop real (nunca asume 3 por fila -- funciona igual en
       cualquier cantidad de columnas) y aplica el mismo min-height
       inline a todos los títulos de una misma fila, tomando el máximo
       real de esa fila. Se recalcula en cada render y en cada resize. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    line-height: 1.3;
}

/* Versión entre corchetes, siempre al lado del título (pedido
   explícito) -- más tenue y sin negrita que el título mismo, para que
   se lea como un dato secundario ("[v1.2]") y no compita con el
   nombre del juego. */
.card-version-tag{
    color: var(--text-dim);
    font-weight: 400;
    font-size: .85em;
}
.card-content p,
.card-content span{
    text-decoration: none;
}

.card-category{
    color: #8a8a8a;

    /* Reapertura (pedido explícito, comparado contra una referencia
       real): 12px era mucho más de lo que este elemento (última línea
       del bloque, el "desarrollador" de todos-los-juegos.html) necesita
       -- mismo criterio de margen chico (4-6px) ya aplicado a
       .card-creator (equivalente en index.html) y a .card-genre-label. */
    margin-bottom: 4px;

    font-size: .92rem;

    /* Pedido explícito: una sola línea, recortada con "..." si el
       nombre es largo -- mismo criterio que .card-creator. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.card-version{
    color: #ffb300;

    font-weight: 700;

    font-size: 1.05rem;
}

.card-tag{
    position: absolute;

    top: 14px;
    left: 14px;

    background: #ffb300;
    color: black;

    font-size: 13px;
    font-weight: bold;

    padding: 6px 12px;

    border-radius: var(--radius-pill);
}

/* Distintivo "Patreon" de la tarjeta (Sprint 26/27) -- opuesto a
   .card-tag (arriba a la derecha en vez de a la izquierda). Depende
   únicamente del estado real del juego (ver patreonBadgeHtml en
   todos-los-juegos.html/index.html), nunca de quién esté mirando --
   desaparece solo al llegar la fecha de liberación pública, sin
   ningún cambio de estilo adicional acá.

   Reapertura (pedido explícito): plateado claro/luminoso en vez de
   dorado -- antes se confundía con .card-tag (género) y otros
   elementos dorados del sitio (botones, selección). El dorado queda
   reservado para esos usos; el plateado es identidad propia de
   Patreon, mismo criterio que .comment-avatar.is-team (avatar de Staff
   en comentarios, también plateado). Sombra oscura de contacto (no glow de
   color) para mantener legibilidad incluso sobre portadas claras --
   nunca gris oscuro, el propio pedido lo descarta explícitamente. */
/* Corrección posterior (pedido explícito): antes era una pastilla
   blanca sólida -- se veía como una pegatina genérica pegada encima
   de la portada, sin relación con el resto de la estética (oscura,
   con vidrio/transparencia en varios componentes, ej. .showcase-arrow).
   Ahora es plateado sobre vidrio oscuro semitransparente (blur real,
   se percibe la imagen de atrás) -- misma jerarquía de colores del
   sitio: plateado queda reservado para este badge, lavanda para el
   título, cereza para el borde/glow Patreon de la card (sin tocar). */
/* Reapertura (pedido explícito): separar "acceso/estado" (Patreon +
   Actualizado) de "metadata descriptiva" (género) -- el primer grupo
   pasa de la esquina superior DERECHA a la IZQUIERDA de .card-image, el
   género nuevo ocupa la derecha en solitario (.card-badge-genre, más
   abajo). Con los dos badges de acceso presentes: Patreon arriba,
   Actualizado abajo (orden literal del pedido, sin cambios). Con uno
   solo, cae en la misma esquina superior izquierda -- nunca se mezcla
   con el género de la derecha. */
.card-badges-left{
    position: absolute;

    top: 14px;
    left: 14px;

    display: flex;
    flex-direction: column;
    align-items: flex-start;
    /* Pedido explícito (refinamiento visual): un poco más de aire entre
       ambos badges ahora que Patreon es notoriamente más chico -- así
       se leen como dos indicadores distintos, no como una pila. */
    gap: 7px;
}

/* Pedido explícito (refinamiento visual): antes era casi tan grande y
   pesado como un botón -- ahora es un indicador discreto (sólido
   morado/gris oscuro, texto chico) que se integra con la imagen en vez
   de taparla. Siempre el más chico/discreto de los dos badges cuando
   conviven con "¡Actualizado!" (ver .card-updated-badge, abajo). */
.card-patreon-badge{
    /* Reapertura (pedido explícito): prueba de color -- rojo sangre en
       vez de morado, alineado con el "cerezo sangre" que ya es la
       identidad Patreon en el resto del sitio (dashboard, --cherry de
       este mismo archivo). Sólido fijo, mismo criterio que las
       versiones anteriores (sin glow, consistente sobre cualquier
       portada). Reapertura (pedido explícito): el borgoña anterior
       quedaba demasiado cerca del cereza del borde/glow de la card
       (.card-patreon-active) -- este es más profundo y menos saturado,
       para que el badge se lea como un elemento funcional aparte, no
       como el mismo acento repetido dos veces. */
    /* Reapertura (pedido explícito, "último refinamiento"): rojo vino/
       carmesí profundo -- ni el rojo demasiado brillante ni el morado
       de versiones anteriores. Texto vuelve a ser claro (antes negro)
       para tener contraste real contra este fondo más oscuro -- la
       estrella (.card-patreon-badge-star, más abajo) ya no necesita
       ser una excepción de color, pero se deja igual para no tocar más
       de lo pedido. */
    background: #8F2638;
    border: 1px solid rgba(200,120,120,.35);
    color: #F8E8EC;

    /* Pedido explícito: tipografía "ligeramente más compacta" -- letter-
       spacing negativo en vez de bajar más el font-size (que ya está en
       un tamaño legible), para que el texto ocupe menos ancho sin
       sentirse comprimido. */
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: -0.01em;

    padding: 3.5px 10px;

    border-radius: var(--radius-pill);

    /* Pedido explícito: "mini glow" sutil, del mismo tono vino, bien
       por debajo del glow/estela de la card (.card-patreon-active,
       0 0 16-32px) -- una sola capa chica y difusa, nunca neón. */
    box-shadow: 0 1px 4px rgba(0,0,0,.3), 0 0 8px rgba(143,38,56,.35);
}

/* Pedido explícito: la estrella (✦) queda blanca aunque el resto del
   texto del badge sea negro -- único elemento que no sigue el color
   de .card-patreon-badge. */
.card-patreon-badge-star{
    color: #fff;
}

/* "¡Actualización!" (pedido explícito, "Nueva versión del juego") --
   mismo sólido oscuro que .card-patreon-badge (misma familia visual de
   badges de card). Reapertura (pedido explícito): Patreon pasó a rojo
   sangre (arriba) -- el morado que antes tenía Patreon se muda acá,
   pero más rico/profundo ("algo de la era shogun": púrpura imperial,
   no el lavanda gastado de antes). Nunca dorado (reservado para CTAs)
   -- necesita su propio color para no confundirse con Patreon cuando
   aparecen juntos. Pedido explícito (refinamiento visual): un poco más
   grande y con más contraste que .card-patreon-badge (arriba) -- cuando
   conviven, este debe leerse como el protagonista y Patreon como el
   secundario -- pero sin el glow multicapa que tenía antes (se sentía
   a botón): un único contacto suave alcanza para que siga leyéndose
   como indicador de estado, no como acción. */
.card-updated-badge{
    /* Reapertura (pedido explícito): vuelve al morado imperial de antes
       -- el morado ciruela ("mi favorita") era para .card-patreon-badge,
       no para este. */
    background: rgba(75,36,105,.9);
    border: 1px solid rgba(222,182,255,.40);
    color: #F1E4FF;

    font-size: 11px;
    font-weight: 700;

    padding: 4.5px 11px;

    border-radius: var(--radius-pill);

    box-shadow: 0 2px 6px rgba(0,0,0,.32);
}

/* Género principal (pedido explícito): esquina superior derecha,
   independiente de Patreon/Actualizado (que ahora viven a la izquierda,
   ver .card-badges-left) -- aparece siempre que el juego tenga un
   género resuelto, tenga o no acceso/estado a la izquierda. Mismo
   nombre que ya se muestra como texto plano bajo la imagen
   (principalGenreName) -- pedido explícito de conservar esa lógica tal
   cual, sin filtrar ni reinterpretar valores. El más chico/discreto de
   los tres badges (jerarquía Patreon > Actualizado > Género): tono
   neutro azul-grisáceo/lavanda a propósito, para que nunca compita con
   el borgoña de Patreon ni el morado de Actualizado. */
.card-badge-genre{
    position: absolute;

    top: 14px;
    right: 14px;

    background: #34313F;
    border: 1px solid rgba(220,210,235,.25);
    color: #E3DDEC;

    /* Reapertura (pedido explícito): un poco más grande que antes. */
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .01em;

    padding: 3.5px 10px;

    border-radius: var(--radius-pill);

    box-shadow: 0 1px 3px rgba(0,0,0,.25);
}

/* Borde + estela Patreon de la tarjeta (quinta reapertura, pedido
   explícito, comparando directamente contra una referencia real): el
   conic-gradient segmentado (tramos fuertes/tramos débiles alternados)
   terminaba leyéndose como un borde con partes "rotas" o desparejas
   en vez de una iluminación pareja -- la referencia que el usuario
   marcó como correcta muestra un borde de intensidad CONSTANTE en los
   cuatro lados. Se saca el conic-gradient por completo: el ::after
   ahora pinta un único color sólido parejo en todo el aro (misma
   técnica de mask para respetar border-radius, ya no hacen falta dos
   capas de background). La estela (box-shadow sobre .card, nunca
   clippeada por su propio overflow:hidden) pasa de 3 capas offset
   hacia esquinas distintas a capas centradas en 0 0 -- parejas en las
   cuatro direcciones, para que el glow "nazca" del aro parejo en vez
   de remarcar unas esquinas más que otras. Nunca dorado -- nunca
   lavanda tampoco (reservado para el título, pedido explícito):
   cereza, ahora en rgb(201,106,122) (#C96A7A) -- un poco más suave
   que el rgb(209,104,104) original, para armonizar con el lavanda
   nuevo de los títulos sin perder la identidad cereza de Patreon.
   Depende únicamente del estado real del juego (ver patreonBadgeHtml),
   nunca del visitante.

   :hover intensifica el borde y el glow por igual en las cuatro
   direcciones, sin agregar --shadow-elevate del dorado genérico --
   .card:hover/.card:hover::before quedan neutralizados acá (fuga de
   dorado ya reportada y corregida), nunca tocando .card:hover en sí
   (esa regla sigue intacta para las tarjetas normales). */
.card-patreon-active::after{
    content: "";

    position: absolute;
    inset: 0;

    border-radius: inherit;

    padding: 2px;

    background: rgba(201,106,122,.85);

    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;

    pointer-events: none;

    z-index: 2;
}

.card-patreon-active{
    box-shadow:
      0 0 16px 1px rgba(201,106,122,.4),
      0 0 32px 4px rgba(201,106,122,.18);
}

/* Neutraliza la fuga de dorado reportada: .card:hover pone
   border-color dorado real (border sólido de .card, aparte del ::after
   de arriba) y .card:hover::before muestra un degradado dorado por
   encima de la imagen -- ninguno de los dos está pensado para
   convivir con la identidad Patreon. Se anulan explícitamente acá,
   nunca en .card:hover (eso sí afectaría a las tarjetas normales). */
.card-patreon-active:hover{
    box-shadow:
      0 0 20px 2px rgba(201,106,122,.5),
      0 0 38px 6px rgba(201,106,122,.24);
}

.card-patreon-active:hover::before{
    opacity: 0;
}

.card-patreon-active:hover::after{
    background: rgba(201,106,122,1);
}
/* HERO JUEGO */
.game-hero {
  position: relative;
  height: 400px;
  overflow: hidden;
}

.game-hero img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* overlay oscuro */
.game-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to right, rgba(0,0,0,0.8), transparent);
}
.game-hero img {
  filter: brightness(0.6);
}

.game-hero-content {
  position: absolute;
  top: 50%;
  left: 60px;
  transform: translateY(-50%);
  z-index: 2;
}

.game-hero h1 {
  font-size: 48px;
  font-weight: 700;
}
.download-list{
    display: flex;
    flex-direction: column;

    gap: 14px;
}

.download-btn{
    position: relative;

    display: flex;
    align-items: center;
    justify-content: space-between;

    gap: 18px;

    padding: 16px 18px;

    border-radius: 16px;

    text-decoration: none;

    overflow: hidden;

    transition:
    transform .22s ease,
    border-color .22s ease,
    background .22s ease;

    backdrop-filter: blur(10px);
}

.download-btn.primary{
    background:
    rgba(255,179,0,.08);

    border:
    1px solid rgba(255,179,0,.18);
}

.download-btn.secondary{
    background:
    rgba(255,255,255,.03);

    border:
    1px solid rgba(255,255,255,.06);
}

.download-btn.primary:hover{
    background:
    rgba(255,179,0,.12);

    border-color:
    rgba(255,179,0,.28);
}

.download-btn.secondary:hover{
    border-color:
    rgba(255,255,255,.12);
}

.download-info{
    display: flex;
    flex-direction: column;

    gap: 4px;
}

.download-info strong{
    color: white;

    font-size: 15px;

    font-weight: 600;
}

.download-info span{
    color: rgba(255,255,255,.52);

    font-size: 13px;
}

.download-host{
    width: 42px;
    height: 42px;

    flex-shrink: 0;

    border-radius: 12px;

    display: flex;
    align-items: center;
    justify-content: center;

    background:
    rgba(255,255,255,.05);

    border:
    1px solid rgba(255,255,255,.08);

    color: #ffcc66;

    font-size: 12px;
    font-weight: 700;
}
.download-btn:hover::before{
    left: 130%;
}

.game-box {
  background: linear-gradient(145deg, #111, #0a0a0a);
  padding: 25px;
  border-radius: 15px;
  border: 1px solid #222;
}
/* LAYOUT GENERAL */
.game-page {
  display: flex;
  gap: 30px;
  padding: 40px;
}

/* IZQUIERDA */
.game-main {
  flex: 2;
}


.game-gallery img {
  width: 100px;
  border-radius: 10px;
  cursor: pointer;
}

/* CARD INFO */
.game-card {
  background: #111;
  padding: 20px;
  border-radius: 15px;
}

.game-card img {
  width: 100%;
  border-radius: 10px;
  margin-bottom: 15px;
}



/* ocultar barra */
.thumbs::-webkit-scrollbar {
  height: 6px;
}

.thumbs::-webkit-scrollbar-thumb {
  background: #333;
  border-radius: 10px;
}

.thumbs img {
    width: 140px;

    aspect-ratio: 16 / 9;

    object-fit: cover;

    flex-shrink: 0;

    border-radius: 16px;

    cursor: pointer;

    opacity: .45;

    border:
    2px solid transparent;

    transition:
    transform .28s ease,
    opacity .28s ease,
    border-color .28s ease,
    box-shadow .28s ease;

    box-sizing: border-box;
}

.thumbs img:hover {
    opacity: .9;

    transform: translateY(-3px);

    border-color:
    rgba(255,179,0,.35);

    box-shadow:
    0 0 24px rgba(255,179,0,.14);
}

/* IMAGEN LATERAL */
/* "A pelo": pedido explícito de que la portada quede al ras del borde
   superior/laterales de la tarjeta, sin el padding:18px que .game-sidebar-steam
   le da al resto de su contenido -- técnica de "bleed" con margen
   negativo igual al padding del contenedor. overflow:hidden del padre
   (arriba) clipa las esquinas cuadradas de abajo al mismo border-radius
   redondeado de la tarjeta. */
.side-cover {
    width: calc(100% + 36px);

    margin: -18px -18px 0;

    border-radius: 22px 22px 0 0;

    display: block;

    transition: transform .35s ease;
}

.side-cover:hover{
    transform: scale(1.02);
}

.game-info p{
    margin: 0;

    color: rgba(255,255,255,.82);

    font-size: 15px;

    display: flex;
    justify-content: space-between;

    gap: 20px;
}

.game-info strong{
    color: white;
}

/* TAGS -- borde dorado fino + fondo oscuro con toque muy sutil de
   dorado + texto crema/dorado (pedido explícito, "elegante y
   discreto", nunca un fondo amarillo sólido). Pedido explícito
   (reapertura): cada tag es un link real a todos-los-juegos.html con
   ese género ya marcado -- :link/:visited fijados a mano al mismo
   crema/dorado de siempre para que nunca aparezca el azul/violeta de
   link visitado por default del navegador (mismo criterio ya aplicado
   en dashboard-autores.html para .dash-table-link). */
.tags a,
.tags a:link,
.tags a:visited {
  display: inline-block;
  background: rgba(214,169,58,.08);
  color: #E3D2A0;
  border: 1px solid rgba(214,169,58,.35);
  padding: 5px 10px;
  border-radius: 10px;
  margin: 5px;
  font-size: 12px;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-fast) ease, color var(--dur-fast) ease, border-color var(--dur-fast) ease;
}

.tags a:hover{
  background: rgba(214,169,58,.16);
  border-color: rgba(214,169,58,.55);
  color: #D6A93A;
}

@keyframes zoomIn {
  from { transform: scale(0.8); opacity: 0; }
  to { transform: scale(1); opacity: 1; }
}

/* Flechas */
.arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  font-size: 28px;
  color: white;
  background: rgba(0,0,0,0.4);
  padding: 10px;
  cursor: pointer;
  border-radius: var(--radius-circle);
  opacity: 0;
  transition: var(--dur-fast);

  z-index: 10;
}
.main-view:hover .arrow {
  opacity: 1;
}


.arrow.left { left: 10px; }
.arrow.right { right: 10px; }

/* FULLSCREEN */
.fullscreen {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.95);
  display: none;
  justify-content: center;
  align-items: center;
  z-index: 9999;
  backdrop-filter: blur(8px);
}

/* IMAGEN */
.fullscreen img {
  max-width: 90%;
  max-height: 90%;
  border-radius: 10px;
  transition: opacity var(--dur-fast) ease;
  z-index: 1;
}

/* FLECHAS */
.fullscreen .arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  
  font-size: 45px;
  color: white;
  background: rgba(0,0,0,0.4);
  padding: 15px;
  border-radius: 10px;
  cursor: pointer;

  z-index: 2;

  opacity: 0.8; /* 🔥 SIEMPRE visibles */
  transition: var(--dur-fast);
}

/* POSICIÓN */
.fullscreen .arrow.left {
  left: 30px;
}

.fullscreen .arrow.right {
  right: 30px;
}

/* HOVER */
.fullscreen .arrow:hover {
  background: rgba(255,255,255,0.2);
  transform: translateY(-50%) scale(1.1);
}

/* BOTÓN CERRAR */
.close-btn {
  position: absolute;
  top: 20px;
  right: 30px;
  font-size: 30px;
  color: white;
  cursor: pointer;
}

.active-thumb {
    opacity: 1 !important;

    border-color: #ffb300;

    box-shadow:
    0 0 28px rgba(255,179,0,.25);

    transform: translateY(-4px);
}

.main-view {

    position: relative;

    width: 100%;

    height: 480px;
    border-radius: 20px;

    overflow: hidden;

    background:
    linear-gradient(
        to bottom,
        #151515,
        #080808
    );

    border:
    1px solid rgba(255,255,255,.05);

    box-shadow:
    0 20px 50px rgba(0,0,0,.45);

    isolation: isolate;
}
.main-view::before{
    content: "";

    position: absolute;

    inset: 0;

    background:
    radial-gradient(
        circle at top right,
        rgba(255,179,0,.12),
        transparent 32%
    );

    z-index: 2;

    pointer-events: none;
}

.main-view::after{
    content: "";

    position: absolute;

    inset: 0;

    background:
    linear-gradient(
        to top,
        rgba(0,0,0,.55),
        transparent 35%
    );

    z-index: 2;

    pointer-events: none;
}

.bg-img {
  z-index: 0;
  position: absolute;
  inset: 0;

  transform: scale(1.02);

  background-size: cover;
  background-position: center;

  opacity: 0;
  transition: opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1);

  will-change: opacity;

  backface-visibility: hidden;
  background-repeat: no-repeat;
}

.bg-img.active {
  opacity: 1;
  z-index: 2;
  animation: cinematicZoom 10s ease-in-out infinite;
}

/* BOTÓN FULLSCREEN */
.fullscreen-btn {
  position: absolute;
  bottom: 10px;
  right: 10px;
  background: rgba(0,0,0,0.6);
  color: white;
  padding: 6px 10px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 18px;

  opacity: 0;
  transition: 0.2s;

  z-index: 10; /* 👈 CLAVE */
}
.main-view:hover .fullscreen-btn {
  opacity: 1;
}

.thumbs{

    display: flex;

    gap: 12px;

    margin-top: 14px;

    margin-bottom: 0;

    padding-bottom: 0;

    cursor: grab;
}

.thumbs.dragging {
  cursor: grabbing;
}

.game-title h1 {
  font-size: 34px;
  font-weight: 800;
  letter-spacing: -0.5px;
  margin: 0;
  /* Pedido explícito: mantenerlo blanco pero un poco más suave que
     --text-warm (#f5f0e8, cálido) -- gris neutro claro, override local,
     no toca el token compartido. */
  color: #E8E8E8;
  text-shadow: 0 4px 20px rgba(0,0,0,.4);
  position: relative;
  /* Espacio para el acento dorado de abajo (::after). */
  padding-bottom: 14px;
}

/* Versión al lado del título de la ficha (pedido explícito, mismo
   criterio que .card-version-tag en las cards del catálogo) -- tenue
   y sin negrita, dato secundario, nunca compite con el título. */
.game-title-version-tag{
  color: var(--text-dim);
  font-weight: 400;
  font-size: .5em;
  text-shadow: none;
}

/* Línea dorada corta debajo del título -- conecta el título con la
   identidad de Inari Okami sin volverlo dorado por completo (pedido
   explícito). */
.game-title h1::after{
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 46px;
  height: 3px;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, rgba(var(--accent-rgb),.75), rgb(var(--accent-rgb)));
}
.game-header {

    width: 100%;
    max-width: 1180px;

    margin: 0 auto;

    /* Antes 34px 0 4px + .game-main-layout sumaba otros 38px de
       padding-top -- el título quedaba ~50-56px lejos de la imagen
       principal (pedido explícito: mucho más cerca, sin llegar a 0). */
    padding: 24px 0 4px;
}

/* Acceso anticipado -- primer bloque de .game-extra-left (debajo de la
   galería/miniaturas), ver renderAccessState() en juego.html. Tono
   ámbar/naranja (advertencia), distinto del dorado de marca a propósito
   -- comunica "restricción temporal", no una acción promocional. */
/* Corrección posterior (pedido explícito): antes se veía como una
   "tarjeta pegada encima de la página" -- borde completo naranja,
   fondo bien diferenciado, esquinas muy redondeadas. Ahora es un
   aviso integrado: sin borde completo (solo una barra cereza a la
   izquierda, misma identidad Patreon que el borde/glow de las cards),
   fondo apenas distinto al de la página, esquinas discretas, sin
   sombra. El texto base ya no es naranja -- mismo tono que el resto
   del contenido de la ficha (.extra-text); solo lo importante se
   resalta con .ea-lavender/.ea-gold (ver buildEarlyAccessText en
   juego.html), nunca todo el texto con el mismo color/peso. */
/* Reapertura visual (pedido explícito): el aviso pasaba desapercibido --
   fondo casi invisible (blanco al 3%) y borde lateral con el cereza
   PROPIO de Patreon (#C96A7A / rgb(201,106,122), que se deja intacto en
   todos lados donde referencia a Patreon como marca externa). Acá se
   reemplaza por el cerezo sangre de identidad general de Inari Okami
   (--accent-rgb, rgb(150,50,60), el mismo de los bordes de card/nav) para
   que el aviso se lea de inmediato como "acceso anticipado", con fondo
   traslúcido (no rojo sólido) y un borde general muy sutil sumado a la
   barra lateral ya existente -- sin glow ni sombra, pedido explícito. */
.early-access-banner{
    width: 100%;
    padding: 16px 22px;
    box-sizing: border-box;
    border-radius: 8px;
    border: 1px solid rgba(var(--accent-rgb),.28);
    border-left: 3px solid rgb(var(--accent-rgb));
    background: rgba(var(--accent-rgb),.12);
    color: rgba(255,255,255,.76);
    font-size: 14px;
    line-height: 1.6;
}
.early-access-banner[hidden]{
    display: none;
}

/* Nota(s) del traductor (reapertura, pedido explícito) -- reusa el
   mismo .early-access-banner de arriba (mismo lenguaje visual, no uno
   nuevo) para cada bloque tipo "nota", ver renderGameNotes() en
   juego.html. Este wrapper solo aporta el gap entre varias notas
   apiladas (si hay más de una) -- [hidden] lo saca del flujo entero
   cuando no hay ninguna, para no dejar un hueco vacío en .game-col-left
   (gap:22px entre TODOS sus hijos directos). */
#gameNotesContainer{
    display: flex;
    flex-direction: column;
    gap: 12px;
}
#gameNotesContainer[hidden]{
    display: none;
}

/* Compactado (pedido explícito, foto de referencia): la nota del
   traductor es casi siempre una línea corta -- el padding completo de
   .early-access-banner (pensado para el aviso de acceso anticipado,
   que suele tener texto más largo) le dejaba mucho aire sobrante
   arriba/abajo. Solo reduce el padding acá, nunca en el aviso real de
   #earlyAccessBanner (ese no cambia). */
#gameNotesContainer .early-access-banner{
    padding: 10px 16px;
}

/* "Nota:" en rojo fuerte (pedido explícito) -- deliberadamente NO usa
   --accent-rgb (el cerezo sangre de identidad general, ya usado en el
   borde/fondo de la banner) ni .ea-lavender/.ea-gold (reservados para
   nivel/fecha de Patreon): es una etiqueta propia, sin relación con
   esos sistemas. */
.game-note-label{
    color: #ff4747;
    font-weight: 700;
}

/* Utilidades de resalte del mensaje de acceso Patreon (pedido
   explícito de jerarquía de texto) -- no solo para .early-access-banner,
   también para #unlockPatreonText (mismo sistema visual, ver
   .patreon-inline-notice). Lavanda = nivel/audiencia (misma identidad
   que el título de las cards), dorado = fechas (misma identidad que
   el resto de la UI). Nunca cereza acá -- la cereza queda para el
   borde/acento del aviso, no para texto suelto. */
.ea-lavender{
    color: #D6C4F2;
    font-weight: 700;
}
.ea-gold{
    color: #ffb300;
    font-weight: 700;
}

/* Mismo lenguaje visual que .early-access-banner, aplicado al párrafo
   de #unlockPatreonBlock (pedido explícito: "aplicar el mismo lenguaje
   visual a las variantes del mensaje") -- el heading/botón/imagen del
   bloque no cambian (siguen el patrón de sección ya establecido en el
   resto de la ficha), solo el párrafo del mensaje en sí. Mismo cerezo
   sangre de identidad general que .early-access-banner (ver comentario
   ahí) -- el botón "Ir al Patreon oficial" (.main-direct-link) es un
   elemento aparte, sigue dorado, nunca se toca acá. */
.patreon-inline-notice{
    display: block;
    padding: 14px 18px;
    border-radius: 8px;
    border: 1px solid rgba(var(--accent-rgb),.28);
    border-left: 3px solid rgb(var(--accent-rgb));
    background: rgba(var(--accent-rgb),.12);
}

.game-title {
  display: flex;
  align-items: center;
  gap: 10px;
}

.version {
  font-size: 13px;
  background: #222;
  padding: 3px 8px;
  border-radius: 6px;
  color: #aaa;
}

.game-meta {
  margin-top: 8px;
}

.game-meta span {
  display: inline-block;
  background: #111;
  padding: 4px 10px;
  border-radius: 6px;
  margin-right: 6px;
  font-size: 12px;
  color: #aaa;
}

.game-right::before{
    content: "";

    position: absolute;

    inset: 0;

    background:
    radial-gradient(
        circle at top right,
        rgba(255,179,0,.08),
        transparent 35%
    );

    pointer-events: none;
}

.fullscreen img {
  max-width: 90%;
  max-height: 90%;

  z-index: 1;
}

.fullscreen .arrow:hover {
  opacity: 0.7;
  transform: translateY(-50%) scale(1.1);
}

/* =========================================================
   FOOTER EDITORIAL — firma de la marca (rediseño Fase 1.5)
   Composición centrada alrededor del logo vertical.
   Paleta oficial: cerezo = identidad, dorado = acción,
   blanco cálido = texto, grises por capas = estructura.
========================================================= */

.footer-pro {
  position: relative;
  padding: 40px 0 28px;
  margin-top: 100px;
  border-top: 1px solid var(--cherry-faint);
  opacity: 0;
  transform: translateY(20px);
  transition: opacity .8s var(--ease-premium), transform .8s var(--ease-premium);
  overflow: hidden;

  /* Capa 1: degradado oscuro con un matiz cerezo casi imperceptible,
     concentrado abajo, para dar calidez sin competir con el logo.
     Capa 2: viñeta radial centro→bordes, casi imperceptible, para
     dar profundidad sin oscurecer el contenido central. */
  background:
    radial-gradient(120% 90% at 50% 120%, rgba(209,104,104,.06), transparent 60%),
    radial-gradient(80% 70% at 50% 40%, rgba(255,255,255,.025), transparent 70%),
    linear-gradient(to bottom, var(--bg-0), #0a0a0a);
}

/* Capa 2: textura de papel japonés muy tenue (SVG inline, sin archivos).
   Un ruido fibroso apenas visible que da "grano" al fondo. */
.footer-pro::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .5;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.35'/%3E%3C/svg%3E");
}

/* Capa 3: rama de sakura muy tenue en la esquina superior derecha.
   SVG inline, en tono cerezo a baja opacidad — un detalle de identidad. */
.footer-pro::after {
  content: "";
  position: absolute;
  top: -20px;
  right: -30px;
  width: 340px;
  height: 340px;
  pointer-events: none;
  opacity: .07;
  background-repeat: no-repeat;
  background-position: top right;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cg fill='none' stroke='%23d16868' stroke-width='1.4' stroke-linecap='round'%3E%3Cpath d='M200 20 C150 35 120 60 95 95 M150 30 C140 55 135 75 138 100 M120 48 C100 60 85 80 78 105 M110 70 C95 78 82 95 80 118'/%3E%3C/g%3E%3Cg fill='%23d16868'%3E%3Ccircle cx='95' cy='95' r='6'/%3E%3Ccircle cx='138' cy='100' r='5'/%3E%3Ccircle cx='78' cy='105' r='5'/%3E%3Ccircle cx='80' cy='118' r='4'/%3E%3Ccircle cx='150' cy='30' r='4'/%3E%3Ccircle cx='120' cy='48' r='4'/%3E%3Ccircle cx='168' cy='52' r='5'/%3E%3Ccircle cx='112' cy='72' r='4'/%3E%3C/g%3E%3C/svg%3E");
}

/* El contenido debe quedar por encima de las capas decorativas */
.footer-pro .container {
  position: relative;
  z-index: 1;
}

.footer-pro.visible {
  opacity: 1;
  transform: translateY(0);
}

/* ÁRBOL AMBIENTAL — EN EVALUACIÓN (2026-07-23). Elemento decorativo
   de fondo: muy grande y muy tenue, para que se sienta como una
   textura/profundidad y no como una ilustración pegada encima.
   Solo debe verse una porción — el resto se recorta con el
   overflow:hidden de .footer-pro, como si el árbol continuara
   fuera de pantalla. No mover a otras páginas hasta confirmar
   tamaño/posición/opacidad. */
.footer-tree{
    position: absolute;
    /* Cuarta iteración (pedido explícito): +45px hacia arriba
       (bottom: -20px -> 25px) para que la roca/raíces de abajo no se
       recorten tanto con el overflow:hidden de .footer-pro. */
    bottom: 25px;
    /* Reapertura (pedido explícito), segunda iteración de jerarquía
       visual: -18% de tamaño (792px -> 650px). Sexta iteración: -9%
       más (650px -> 592px) para que la copa deje más aire sobre
       "INARI OKAMI"/"EXPLORAR" -- solo la altura cambia, el ancho la
       sigue proporcionalmente (width:auto) y el resto (posición,
       opacidad, scaleX, filtros) queda igual. */
    height: 592px;
    width: auto;
    max-width: none;
    /* Quinta iteración (pedido explícito): sacado el drop-shadow (glow)
       -- ya no se quería. transform-origin: left center + scaleX(.88)
       para achicarlo un poco horizontalmente sin tocar la altura --
       el origen a la izquierda hace que la compresión salga del lado
       de las ramas/copa, no del tronco anclado. Séptima iteración:
       .45 resultó demasiado protagonista -- opacidad .45 -> .13.
       Octava iteración: esta es ahora la opacidad BASE (tronco/roca,
       objetivo ~.11-.13) -- .13 -> .12. La opacidad extra de las
       flores (~.16) se logra apilando una segunda copia de la misma
       imagen (.footer-tree-flower-boost, más abajo) enmascarada a la
       zona superior/copa, no separando la imagen en dos archivos. */
    opacity: .12;
    transform-origin: left center;
    transform: scaleX(.88);
    filter: blur(.5px) brightness(1.05) contrast(1.05) saturate(1.15);
    /* Reapertura (pedido explícito): sakura-v4.png (reemplazó a
       sakura-v3.png, mismo criterio) tiene canal alfa real, así que
       no hace falta el truco de mix-blend-mode:screen para disolver
       un fondo sólido -- blend normal, la transparencia del PNG hace
       el resto. */
    pointer-events: none;
    user-select: none;
    z-index: 0;
}

.footer-tree-right{
    right: -110px;
}

/* Octava iteración (pedido explícito): opacidad diferenciada
   flores(~.16) vs tronco/roca(~.11-.13) dentro de la MISMA imagen.
   CSS no puede aplicar opacidad por color/píxel sobre un único <img>,
   así que se apila una segunda copia idéntica (mismo src, mismas
   clases de tamaño/posición/transform vía .footer-tree) encima,
   con mask-image en gradiente para que solo se vea (y sume opacidad)
   en la franja superior donde está la copa de flores -- el tronco
   y la roca (abajo) quedan solo con la opacidad base de .footer-tree.
   Con base .12 + boost .045 sobre la misma imagen, la zona de flores
   queda en 1-(1-.12)(1-.045) ≈ .16. */
.footer-tree.footer-tree-flower-boost{
    opacity: .045;
    -webkit-mask-image: linear-gradient(to bottom, black 0%, black 55%, transparent 72%);
    mask-image: linear-gradient(to bottom, black 0%, black 55%, transparent 72%);
}

.footer-tree-left{
    /* Reapertura (pedido explícito): -50px extra para alejar la copa
       de la zona "EXPLORAR"/separador central. Quinta iteración:
       +40px de vuelta hacia la derecha (-60px -> -20px). */
    left: -20px;
}

/* PÉTALO OCASIONAL DEL FOOTER — uno solo, cada bastante tiempo,
   cruzando muy despacio. Nada de densidad: la idea es que la
   página nunca se sienta del todo estática, no llamar la atención.
   Lógica de spawn en initFooterPetal() (index.html/juego.html/
   todos-los-juegos.html), reutiliza .hero-petal y heroPetalWind. */
.footer-petal-layer{
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    z-index: 1;
}

/* FIRMA CENTRAL */
.footer-signature {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 16px;
}

.footer-logo-vertical {
  height: 260px;
  width: auto;
  object-fit: contain;
  filter: drop-shadow(0 8px 30px rgba(0,0,0,.5));
}

/* Divisor con florcita entre el logo y el tagline — mismo espíritu
   que .footer-divider de más abajo, pero con un acento central. */
.footer-divider-icon{
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 320px;
  color: var(--cherry-strong);
}

.footer-divider-icon span{
  flex: 1;
  height: 1px;
  background: linear-gradient(to right, transparent, var(--cherry-soft));
}

.footer-divider-icon span:last-child{
  background: linear-gradient(to left, transparent, var(--cherry-soft));
}

.footer-divider-icon svg{
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

.footer-tagline {
  margin: 0;
  color: var(--text-soft);
  font-size: 14px;
  line-height: 1.9;
  letter-spacing: .3px;
  max-width: 420px;
}

/* REDES — íconos circulares discretos, acento cerezo al hover */
.footer-social {
  display: flex;
  gap: 16px;
}

.footer-social-link {
  width: 44px;
  height: 44px;
  border-radius: var(--radius-circle);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-1);
  border: 1px solid var(--border-soft);
  transition: border-color var(--dur-nav) var(--ease-premium),
              background var(--dur-nav) var(--ease-premium),
              transform var(--dur-nav) var(--ease-premium);
}

.footer-social-link img {
  width: 18px;
  height: 18px;
  opacity: .7;
  filter: brightness(0) invert(1);
  transition: opacity var(--dur-nav) ease;
}

.footer-social-link:hover {
  border-color: var(--cherry-soft);
  background: var(--cherry-faint);
  transform: translateY(-3px);
}

.footer-social-link:hover img {
  opacity: 1;
}

/* COLUMNAS — mapa del sitio dentro del footer, reemplaza a la fila
   plana de links que había antes de esta versión. */
.footer-columns{
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 20px;
  max-width: 860px;
  margin: 38px auto 0;
}

.footer-col h4{
  position: relative;
  margin: 0 0 18px;
  padding-left: 14px;
  color: var(--text-warm);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 1.5px;
  text-transform: uppercase;
}

.footer-col h4::before{
  content: "";
  position: absolute;
  left: 0;
  top: 2px;
  width: 2px;
  height: 14px;
  background: var(--cherry-strong);
  border-radius: var(--radius-pill);
}

.footer-col-brand p{
  margin: 0;
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.8;
  max-width: 260px;
}

.footer-col a{
  display: block;
  color: var(--text-dim);
  text-decoration: none;
  font-size: 13.5px;
  line-height: 2.4;
  transition: color var(--dur-base) ease, transform var(--dur-base) ease;
}

.footer-col a:hover{
  color: var(--cherry-strong);
  transform: translateX(3px);
}

@media (max-width: 760px){
  .footer-columns{
    grid-template-columns: 1fr 1fr;
    row-gap: 40px;
    text-align: left;
  }
  .footer-col-brand{
    grid-column: 1 / -1;
    text-align: center;
  }
  .footer-col-brand p{
    max-width: none;
    margin: 0 auto;
  }
}

/* TORII — acento central del pie, entre copyright y crédito */
.footer-torii{
  display: flex;
  color: var(--cherry-strong);
  opacity: .8;
}

.footer-torii svg{
  width: 22px;
  height: 18px;
}

/* DIVISOR SUTIL con acento central cerezo */
.footer-divider {
  height: 1px;
  max-width: 640px;
  margin: 30px auto;
  background: linear-gradient(
    to right,
    transparent,
    var(--cherry-soft),
    transparent
  );
}

/* PIE — tres zonas equilibradas, texto tenue */
.footer-base {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 18px;
  max-width: 1000px;
  margin: 0 auto;
}

.footer-copy {
  color: var(--text-dim);
  font-size: 12.5px;
  letter-spacing: .3px;
}

.footer-nav {
  display: flex;
  gap: 26px;
}

.footer-nav a {
  color: var(--text-dim);
  text-decoration: none;
  font-size: 12.5px;
  transition: color .25s ease;
}

.footer-nav a:hover {
  color: var(--cherry-strong);
}

.footer-credit {
  color: var(--text-dim);
  font-size: 12.5px;
}

.footer-credit a {
  color: var(--cherry-strong);
  text-decoration: none;
  transition: opacity .25s ease;
}

.footer-credit a:hover {
  opacity: .8;
}

@media (max-width: 720px){

  .footer-logo-vertical {
    height: 205px;
  }

  .footer-base {
    flex-direction: column;
    text-align: center;
    gap: 14px;
  }

  .footer-nav {
    gap: 18px;
    flex-wrap: wrap;
    justify-content: center;
  }
}


.download-label{
    font-size: 12px;

    letter-spacing: 2px;

    font-weight: 700;

    color: rgba(255,255,255,.45);
}


.download-btn::before{
    content: "";

    position: absolute;

    top: 0;
    left: -120%;

    width: 70%;
    height: 100%;

    background:
    linear-gradient(
        90deg,
        transparent,
        rgba(255,255,255,.45),
        transparent
    );

    transform: skewX(-20deg);

    transition: .7s ease;
}

.download-btn:hover::before{
    left: 130%;
}

.download-btn:hover{
    transform: translateY(-4px);

    box-shadow:
    0 24px 50px rgba(255,179,0,.30);
}

.download-btn:active{
    transform: scale(.98);
}

.main-btn{
    position: relative;

    border: none;

    padding: 14px 26px;

    border-radius: 999px;

    cursor: pointer;

    overflow: hidden;

    background:
    linear-gradient(
        135deg,
        #ffb300,
        #ffd54a
    );

    color: #111;

    font-size: 15px;
    font-weight: 700;

    transition:
    transform .25s ease,
    box-shadow .25s ease,
    filter .25s ease;

    box-shadow:
    0 10px 30px rgba(255,179,0,.22);
}

.main-btn:hover{
    transform: translateY(-3px);

    box-shadow:
    0 18px 40px rgba(255,179,0,.30);

    filter: brightness(1.03);
}

.main-btn:active{
    transform: scale(.98);
}

@keyframes heroZoom {

  0%{
    transform: scale(1);
  }

  50%{
    transform: scale(1.06);
  }

  100%{
    transform: scale(1);
  }

}
@keyframes cinematicZoom{

    0%{
        transform: scale(1.02);
    }

    50%{
        transform: scale(1.07);
    }

    100%{
        transform: scale(1.02);
    }
}

* {
    cursor: none !important;
}
:root{

    /* Variables heredadas, ahora apuntando a la paleta oficial.
       Se irán reemplazando por las nuevas en la Fase 2. */
    --primary: var(--gold);
    --primary-light: var(--gold-light);

    --bg-main: var(--bg-0);
    --bg-card: var(--bg-1);

    --text-muted: var(--text-dim);
}
body {
  cursor: none;
}

/* Sin puntero fino (touch/celular) custom-cursor.js ni siquiera
   inicializa el cursor -- sin este @media, el usuario se queda sin
   ningún cursor visible en esos dispositivos (cursor:none global de
   arriba, sin nada dibujado por JS que lo reemplace). */
@media (hover: none), (pointer: coarse){
  body {
    cursor: auto;
  }
}

.custom-cursor{

  position: fixed;

  top: 0;
  left: 0;

  /* Pedido explícito: cursor un poco más chico (era 32px). */
  width: 26px;
  height: 26px;

  pointer-events: none;

  z-index: 999999999;

  will-change: transform;

  overflow: visible;

  contain: layout size style;

  /* Arranca invisible: custom-cursor.js recién lo muestra en el primer
     mousemove real, para no "volar" desde la esquina (0,0) hasta la
     posición real del mouse en cada carga de página. */
  opacity: 0;

}

.custom-cursor.is-visible{
  opacity: 1;
}

.custom-cursor img{

  width: 100%;
  height: 100%;

  object-fit: contain;

  user-select: none;

  filter:
    drop-shadow(0 0 10px rgba(255,170,40,.22));

}

/* Reapertura (pedido explícito, "se ve más smooth" -- referencia
   visual): el track antes usaba var(--bg-0), IDÉNTICO al fondo de la
   página -- sin ningún canal visible detrás, la barra quedaba como una
   línea roja flotando directo sobre el fondo, sin marco. Track más
   ancho + var(--bg-2) (gris elevado, distinto del fondo) le da ese
   "canal" visible; el thumb gana más borde (grosor igual al track, en
   el mismo color del track) para que se vea como una píldora angosta
   flotando adentro, no una barra que ocupa todo el ancho. */
::-webkit-scrollbar{
    width: 14px;
}

::-webkit-scrollbar-track{
    background: var(--bg-2);
}

::-webkit-scrollbar-thumb{
    background: var(--cherry);
    border-radius: var(--radius-pill);
    border: 4px solid var(--bg-2);
}

::-webkit-scrollbar-thumb:hover{
    background: var(--cherry-strong);
}
.reveal{

    opacity: 0;

    transform:
    translateY(40px);

    transition:
    opacity .7s var(--ease-premium),
    transform .7s var(--ease-premium);

    will-change:
    opacity,
    transform;
}

.reveal.active{

    opacity: 1;

    transform:
    translateY(0);
}
/* =========================
   VER TODOS
========================= */

.see-all-wrapper{

    display: flex;
    justify-content: center;
    margin-top: 30px;
}

.see-all-games-btn{

    /* Pedido explícito: más chico (era 16px 34px). */
    padding: 11px 26px;

    border-radius: var(--radius-pill);

    text-decoration: none;

    color: white;

    font-weight: 700;

    /* Pedido explícito: cerezo de sangre en vez de dorado (mismo
       rgb(150,50,60) ya usado en el borde de las cards). */
    border: 1px solid rgba(150,50,60,.5);

    background:
    rgba(150,50,60,.1);

    transition:
    .3s ease;
}

.see-all-games-btn:hover{

    transform:
    translateY(-2px);

    border-color:
    rgba(150,50,60,.85);

    background:
    rgba(150,50,60,.18);

    box-shadow: 0 0 25px rgba(150,50,60,.14);
}

/* =========================
   RECOMMENDATIONS
========================= */

.recommend-header{

    display: flex;

    justify-content: space-between;

    align-items: center;

    margin-bottom: 4px;
}

.view-all-btn{

    color: #ffb300;

    text-decoration: none;

    font-weight: 700;
}

.recommend-wrapper{

    /* Margen entre el borde de la sección y la primera/última tarjeta
       (pedido explícito) -- ya NO empuja las flechas (ver
       .recommend-viewport, que ahora es su propio ancla), así que
       este padding es puramente aire visual, no afecta dónde caen
       los botones. */
    padding: 0 24px;
}

.recommend-viewport{
    /* Ancla de las flechas (antes era .recommend-wrapper): así se
       superponen sobre el borde real de las tarjetas sin importar
       cuánto padding tenga el wrapper alrededor. */
    position: relative;
    overflow: hidden;
}

.recommend-slider{

    display: flex;

    gap: 24px;

    will-change: transform;

    transition: transform var(--dur-carousel) var(--ease-premium);
}

.recommend-slider.no-transition{
    transition: none;
}

/* Pedido explícito: sacar el "gris" de la tarjeta -- ya no tiene
   fondo/borde propio, el título queda directamente sobre el fondo de
   la página en vez de una caja gris aparte (como la referencia,
   imagen + texto, sin caja visible alrededor). El radio de esquinas
   pasa a la imagen sola (ver .recommend-card img). Corrección
   posterior: hubo un wrapper .recommend-image intermedio (para un
   fondo desenfocado que se probó y se descartó); se volvió a la
   imagen directa, sin contenedor propio. */
.recommend-card{

    flex: 0 0 calc((100% - 48px) / 3);

    text-decoration: none;

    color: white;

    transition:
    transform var(--dur-fast) ease;
}

.recommend-card:hover{

    transform:
    translateY(-4px);
}

/* Envuelve la imagen (corrección posterior, mismo criterio que
   .card-image): antes .recommend-card img no tenía contenedor propio,
   así que no había dónde poner el backdrop desenfocado sin afectar
   .recommend-info (el texto de abajo). El radio de esquinas y el alto
   fijo, que antes vivían en la imagen, pasan acá. */
.recommend-card img{

    width: 100%;

    /* Un poco más alta (pedido explícito, reapertura: "un poco más
       grandes verticalmente") -- venía de 190px, que a su vez venía de
       230px de antes de eso. */
    height: 215px;

    /* Pedido explícito, definitivo: la imagen llena siempre el área
       de la card -- cover, sin fondos ni contenedores auxiliares. */
    object-fit: cover;

    /* El radio de esquinas vivía en .recommend-card (junto con el
       fondo/borde que se sacó) -- ahora es solo de la imagen, ya que
       es lo único con una forma visible. Menos redondeado (pedido
       explícito, reapertura: "menos bordes, tirando más a un
       cuadrado") -- venía de 16px. */
    border-radius: 8px;

    transition:
    transform .5s ease;
}

/* Pedido explícito: el hover ya no agrega scale() extra a la imagen
   (mismo criterio que .card:hover img) -- .recommend-card:hover ya
   levanta la card entera con translateY, eso alcanza como feedback. */

.recommend-info{

    /* padding-top bien chico (10px -> 3px): el título queda pegado a
       la imagen, sin franja gris de sobra arriba. */
    padding: 3px 12px 12px;
}

.recommend-info h3{

    /* Mismo lavanda que .card-content h3 (pedido explícito): título
       del juego siempre en lavanda, en cualquier card. Antes heredaba
       el blanco de .recommend-card -- acá sí hace falta declararlo,
       la reseña (.recommend-info span) ya tiene su propio gris aparte
       y no se ve afectada. */
    color: #D6C4F2;

    font-size: 0.92rem;

    margin-bottom: 4px;

    line-height: 1.25;

    /* Mismo criterio que .card-content h3: tope de 2 líneas + puntos
       suspensivos, un título largo no debe estirar la card. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.recommend-info span{

    color: #7e7e7e;

    font-size: .78rem;

    /* Una sola línea siempre -- así la franja gris no crece según lo
       largo que sea el texto de cada uno. */
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Más chicas (venían de 52px) y ahora se superponen SOBRE la imagen
   de las tarjetas de los extremos en vez de flotar afuera -- top fijo
   en vez de porcentual, centrado sobre el alto real de la imagen
   (230px), no sobre toda la tarjeta (imagen + franja de info). */
.recommend-arrow{

    position: absolute;

    top: 115px;

    transform: translateY(-50%);

    width: 34px;
    height: 34px;

    border-radius: var(--radius-circle);

    border:
    1px solid rgba(255,255,255,.14);

    background:
    rgba(12,12,12,.72);

    backdrop-filter:
    blur(10px);

    -webkit-backdrop-filter:
    blur(10px);

    color: white;

    font-size: 15px;

    cursor: pointer;

    z-index: 20;

    transition:
    transform var(--dur-fast) ease,
    background var(--dur-fast) ease,
    border-color var(--dur-fast) ease,
    color var(--dur-fast) ease;
}

.recommend-arrow:hover{

    transform:
    translateY(-50%) scale(1.08);

    background:
    rgba(255,179,0,.24);

    border-color:
    rgba(255,179,0,.4);

    color:
    #ffb300;
}

/* Mini-cooldown entre clicks (0.8s, ver slideRecommend en index.html)
   -- se ve realmente apagado durante ese lapso, no solo ignora el
   click en silencio. */
.recommend-arrow:disabled{
    opacity: .35;
    cursor: not-allowed;
}

.recommend-arrow:disabled:hover{
    transform: translateY(-50%);
    background: rgba(12,12,12,.72);
    border-color: rgba(255,255,255,.14);
    color: white;
}

.recommend-arrow.left{
    left: 10px;
}

.recommend-arrow.right{
    right: 10px;
}
/* (antes había un padding-top reducido acá; se quitó para que
   todas las secciones respiren el mismo espacio entre sí) */
/* Ver .discover-hero* más abajo: reemplaza a la antigua "Featured Sanctuary" */
/* =========================
   CATALOG PAGE
========================= */

.catalog-hero{

    border-bottom:
    1px solid rgba(255,255,255,.05);
}

.catalog-top{

    display: flex;

    justify-content: space-between;

    align-items: flex-end;

    gap: 30px;

    flex-wrap: wrap;
}

.catalog-mini{

    display: inline-block;

    margin-bottom: 14px;

    padding: 6px 14px;

    border-radius: var(--radius-pill);

    background:
    rgba(var(--accent-rgb),.1);

    border:
    1px solid rgba(var(--accent-rgb),.3);

    color: rgb(var(--accent-rgb));

    font-size: 12px;

    letter-spacing: 1px;

    font-weight: 700;
}

.catalog-hero h1{

    margin: 0;

    font-size: 3rem;

    letter-spacing: -2px;
}

.catalog-hero p{

    color: #8b8b8b;

    margin-top: 14px;

    font-size: 1rem;

    max-width: 620px;
}

.catalog-stats{

    display: flex;

    gap: 14px;
}

.catalog-box{

    min-width: 130px;

    padding: 18px;

    border-radius: 18px;

    background:
    rgba(255,255,255,.03);

    border:
    1px solid rgba(255,255,255,.06);
}

.catalog-box strong{

    display: block;

    font-size: 1.4rem;

    color: white;

    margin-bottom: 6px;
}

.catalog-box span{

    color: #828282;

    font-size: .9rem;
}
/* =========================
   GAMES CATALOG FIX
========================= */

.games-catalog-grid{

    display: grid;

    grid-template-columns:
    repeat(3, minmax(280px, 1fr));

    gap: 18px;

    overflow-anchor: none;

    /* CAUSA REAL del bug de scroll (confirmada con un navegador real,
       Playwright+Chrome, no adivinada): no era "scroll anchoring" --
       era el propio navegador clampeando el scroll. Al pasar a una
       página/filtro con MENOS resultados, el documento se acorta; si
       el scroll ya no entra en el documento más corto, el navegador
       lo fuerza al nuevo máximo posible -- ningún scrollTo/scrollBy
       puede "restaurar" una posición que físicamente ya no existe.
       min-height fijo (reservar siempre 4 filas) evitaba el salto,
       pero dejaba un hueco enorme en páginas con menos resultados
       (la última, típicamente) -- pedido explícito: que se adapte a
       la cantidad real de tarjetas. Ahora setGridMinHeight() en
       todos-los-juegos.html calcula el alto exacto por página (según
       cuántas filas de 3 le tocan) y lo aplica inline -- entre
       páginas con la MISMA cantidad de filas (el caso común) el alto
       sigue siendo idéntico, cero salto; solo una página con MENOS
       filas que la anterior (ej. la última) puede necesitar un
       reajuste de scroll si se estaba muy desplazado, inevitable sin
       volver a dejar el hueco vacío. */
}

/* Reapertura (bug real, probado en celular): "repeat(3, minmax(280px,
   1fr))" fuerza un mínimo de 280px por columna SIEMPRE, sin importar
   el ancho real de pantalla -- en un celular angosto (ej. 390px) las
   3 columnas no entran (840px mínimo) y el navegador termina
   renderizando/zoomeando la página entera a escala de escritorio para
   que "quepa" todo, en vez de recortar. Eso era la causa real de "la
   biblioteca se ve como en la PC, todo grande". Una sola columna en
   mobile deja que cada tarjeta ocupe el ancho real disponible, sin
   forzar ningún mínimo -- alineada con el header/footer, sin espacio
   sobrante a la derecha. */
@media (max-width: 760px){
    .games-catalog-grid{
        grid-template-columns: 1fr;
    }
}

/* evita cards gigantes */
.games-catalog-grid .card{

    height: auto;

    min-height: unset;
}

/* imágenes normales */
.games-catalog-grid .card img{

    height: 220px;

    /* Mismo criterio que .card img -- cover, la imagen llena siempre
       el área de la card. */
    object-fit: cover;

    /* Pedido explícito: mismo tiempo de transición del micro-zoom que
       .card img (180ms) -- antes usaba --dur-carousel (550ms, pensado
       para el carrusel de imágenes, no para el hover), demasiado lento
       para sentirse como una "pequeña interacción" al pasar el mouse.
       Mismo easing premium que .card img (refinamiento posterior). */
    transition:
    transform .18s var(--ease-premium),
    filter .35s ease;
}

/* spacing mejor */
.games-catalog-grid .card-content{

    padding: 18px;
}

/* separa mejor del hero */
.catalog-hero{

    position: relative;

    padding:
    70px 0 42px;

    overflow: hidden;

    border-bottom:
    1px solid rgba(255,255,255,.05);
}

.catalog-hero::before{

    content: "";

    position: absolute;

    top: -180px;
    right: -120px;

    width: 520px;
    height: 520px;

    background:
    radial-gradient(
        circle,
        rgba(var(--accent-rgb),.08),
        transparent 68%
    );

    pointer-events: none;
}

/* Paginación real (.catalog-pagination/.catalog-page-number/
   .catalog-page-arrow) definida más abajo, junto al resto del panel
   de filtros del catálogo -- este bloque tenía los ".page-btn" de la
   paginación de mentira de Sprint 11 (4 botones fijos sin onClick,
   ver todos-los-juegos.html), ya sin ningún HTML que los use. */

.card-meta{

    display: flex;

    gap: 8px;

    margin-bottom: 14px;

    flex-wrap: wrap;
}

.card-meta span{

    padding: 5px 10px;

    border-radius: var(--radius-pill);

    background:
    rgba(255,255,255,.05);

    border:
    1px solid rgba(255,255,255,.05);

    color: #9f9f9f;

    font-size: .72rem;

    font-weight: 500;
}
.games-catalog-grid .card-image{

    position: relative;

    overflow: hidden;
}

.games-catalog-grid .card-image::after{

    content: "";

    position: absolute;

    inset: 0;

    background:
    linear-gradient(
        to top,
        rgba(0,0,0,.65),
        transparent 45%
    );

    opacity: .9;

    pointer-events: none;
}
/* =========================
   SEARCH BAR
========================= */

/* Buscador movido del Hero al panel de filtros (pedido explícito) --
   inline dentro de .catalog-filters-row-secondary, junto al toggle de
   Géneros y los botones Buscar/Limpiar, en vez de su propio bloque
   grande arriba. */
.catalog-search-inline{

    position: relative;

    flex: 1;

    min-width: 220px;
}

.catalog-search-inline input{

    width: 100%;

    height: 42px;

    border-radius: var(--radius-pill);

    border: 1px solid var(--border-soft);

    background: rgba(255,255,255,.03);

    padding: 0 44px 0 18px;

    color: var(--text-warm);

    font-size: .88rem;

    outline: none;

    transition: .25s ease;
}

.catalog-search-inline input:focus{

    border-color: rgba(var(--accent-rgb),.5);

    background: rgba(255,255,255,.05);

    box-shadow: 0 0 25px rgba(var(--accent-rgb),.14);
}

.catalog-search-inline input::placeholder{

    color: var(--text-dim);
}

.catalog-search-inline .search-icon{
    right: 16px;
    font-size: 16px;
}

.search-icon{

    position: absolute;

    right: 20px;
    top: 50%;

    transform: translateY(-50%);

    color: rgb(var(--accent-rgb));

    font-size: 20px;

    pointer-events: none;
}
/* =========================
   RECOMMENDATIONS HEADER
========================= */

.section-header{

    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
    gap: 20px;
}

/* .recommend-wrapper tiene 24px de padding lateral (aire alrededor de
   las tarjetas) -- sin este mismo padding acá, el título/botón
   quedaban pegados al borde de la sección mientras las tarjetas
   empezaban 24px más adentro (pedido explícito: alinear título y
   "Ver todos los juegos" con las tarjetas). */
.recommendations-section .section-header{
    padding: 0 24px;
}

/* .section (arriba en el archivo) pone padding:84px 0 en TODAS las
   secciones del sitio, y una regla posterior anula solo el top a
   42px -- el bottom de 84px queda -- normalmente eso queda disimulado
   porque la siguiente sección le sigue de cerca, pero Recomendados
   suele ser la ÚLTIMA antes del footer (que además tiene su propio
   margin-top:100px), así que acá los 84px SÍ se notaban como un hueco
   grande de sobra (pedido explícito). Acotado a esta sección
   específicamente -- no toca el espaciado del resto del sitio. */
.recommendations-section{
    padding-bottom: 24px;
}

/* Reapertura (pedido explícito): la reducción de arriba (84px -> 24px)
   achicó lo que le tocaba a esta sección, pero el hueco grande seguía
   ahí -- medido en la página real, el propio margin-top:100px de
   .footer-pro (compartido por TODAS las páginas, ver arriba) sigue
   sumando por su cuenta después. Acá se acota con el combinador de
   hermano general (~) en vez de adyacente (+) -- en index.html, entre
   .games-petal-zone y .footer-pro vive #trendFullscreen (el
   lightbox de "En tendencia", oculto por defecto/display:none), así
   que no son hermanos ADYACENTES, pero sí hermanos dentro del mismo
   padre, que es lo que hace falta acá. Fuera de la home, .footer-pro
   conserva su margin-top:100px de siempre, intacto.
   Reapertura (pedido explícito, pétalos por zona): el selector
   apuntaba a ".recommendations-section" -- esa sección ahora vive
   DENTRO de ".games-petal-zone" (wrapper nuevo, ver bloque de
   pétalos por zona más abajo), así que ya no es hermana directa de
   .footer-pro. Retargeteado al wrapper, que sí sigue siendo el
   hermano directo. */
/* Reapertura (pedido explícito): "un poquito más abajo, que no quede
   tan cerca de Recomendados" -- venía de 30px. */
.games-petal-zone ~ .footer-pro{
    margin-top: 60px;
}

.section-header .section-title{
    margin-bottom: 0;
}

/* Pedido explícito: suavizar el blanco del título "Recomendados" (foto
   de referencia) -- scoped a esta sección únicamente, .section-title h2
   es compartida por Hero/En tendencia/Todos los juegos/etc. y esas no
   se tocan. */
.recommendations-section .section-title h2{
    color: #E8E8E8;
}

/* Pill con borde (pedido explícito: que se vea como botón, no como
   texto suelto con flecha). */
.view-all-link{

    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 38px;
    padding: 0 18px;
    border-radius: var(--radius-pill);

    /* Pedido explícito (foto de referencia): "apenas se ve" -- borde y
       fondo un poco más presentes que antes (.5 -> .7, sin fondo -> con
       fondo tenue) más un glow sutil en reposo, sin llegar a la
       intensidad de :hover de abajo. Mismo cerezo de sangre de siempre,
       ningún color nuevo. */
    border: 1px solid rgba(var(--accent-rgb),.7);
    background: rgba(var(--accent-rgb),.1);
    box-shadow: 0 0 14px rgba(var(--accent-rgb),.12);

    color: rgb(var(--accent-rgb));
    text-decoration: none;
    font-weight: 600;
    font-size: 14px;
    transition: 0.3s ease;
}

.view-all-link:hover{

    color: rgb(var(--accent-rgb));
    border-color: rgba(var(--accent-rgb),1);
    background: rgba(var(--accent-rgb),.2);
    box-shadow: 0 0 25px rgba(var(--accent-rgb),.22);
}
/* Función de "admin rápido" retirada del sitio. */
/* =========================
   GAME EXTRA SECTION -- Sprint 21: eliminado como grid propio.
   .game-extra-section/.game-extra-layout/.game-extra-left/
   .game-extra-right vivían acá; su contenido ahora es parte de
   .game-col-left/.game-col-right dentro del único grid
   .game-main-layout (ver ese bloque más abajo) -- era la causa real
   del hueco enorme entre las miniaturas y "Links de Descarga" (dos
   grids de dos columnas apiladas, la fila de arriba terminaba donde
   terminaba el panel lateral, no donde terminaban las miniaturas).
========================= */

.extra-block{

    width: 100%;

    /* Antes max-width:760px + margin:0 auto lo centraba DENTRO de
       .game-extra-left -- eso lo dejaba con un hueco a la izquierda
       que la galería de arriba (sin ese centrado) no tiene, rompiendo
       el alineado vertical entre ambas secciones (pedido explícito:
       que quede a la izquierda, igual que la imagen principal). */

    background:
    linear-gradient(
      180deg,
      rgba(255,255,255,.035),
      rgba(255,255,255,.015)
    );

    border:
    1px solid rgba(255,255,255,.06);

    border-radius: 22px;

    /* Antes 14px 16px -- más aire interno, mismo pedido de que la
       sección respire más. */
    padding: 22px 24px;

    backdrop-filter: blur(10px);

    box-shadow:
    0 10px 30px rgba(0,0,0,.22);
}
.banner-block{

    padding: 22px 24px;

    width: 100%;

}

/* box-sizing explícito: sin esto, el padding se sumaría al 100%
   y los bloques se desbordarían del contenedor. */
.extra-block,
.banner-block,
.ad-download-box{
    box-sizing: border-box;
}

.banner-block .patreon-banner,
.banner-block .community-banner{

    width: 100%;

    max-width: unset;

    margin-top: 14px;
}

.extra-title{

    display: flex;
    align-items: center;

    gap: 14px;

    margin-bottom: 10px;
}

.extra-title span{

    width: 5px;
    height: 34px;

    border-radius: var(--radius-pill);

    background:
    rgb(var(--accent-rgb));
}

.extra-title h2{

    color: white;

    font-size: 15px;

    margin: 0;
}

/* Pedido explícito: solo este encabezado (no el resto de .extra-title
   h2, que comparten Comunidad/otros bloques) un poco más suave que el
   blanco puro. */
#unlockPatreonHeading{
    color: #E8E8E8;
}

.extra-text{

    color: rgba(255,255,255,.76);

    line-height: 1.8;

    font-size: 15px;
}

.direct-links{

    display: flex;
    flex-wrap: wrap;

    gap: 18px;
}

.direct-link-btn{

    height: 54px;

    padding:
    0 26px;

    border-radius: 16px;

    display: flex;
    align-items: center;
    justify-content: center;

    text-decoration: none;

    color: white;

    background:
    rgba(255,255,255,.04);

    border:
    1px solid rgba(255,255,255,.06);

    transition:
    .25s ease;
}

.direct-link-btn:hover{

    border-color:
    rgba(var(--accent-rgb),.5);

    background:
    rgba(var(--accent-rgb),.1);

    transform:
    translateY(-2px);
}
/* .game-extra-right eliminado (Sprint 21, ver comentario más arriba) --
   .promo-image/el iframe de Discord son hijos directos de
   .game-col-right, después de .game-sidebar-steam (ver comentario en
   el HTML: salieron de acá temporalmente mientras el panel era
   sticky, y volvieron al quitarse el sticky). El iframe ya no hereda
   el "overflow:hidden; border-radius" del contenedor viejo, así que
   gana el suyo propio acá. */
.game-col-right iframe{
    border-radius: var(--radius-card);
    overflow: hidden;
}

.promo-image{

    width: 100%;

    height: 620px;

    object-fit: cover;

    object-position: center top;

    border-radius: var(--radius-card);

    border:
    1px solid rgba(255,255,255,.03);

    box-shadow:
    0 12px 35px rgba(0,0,0,.28);

    display: block;

    transition:
    .3s ease;

}

.promo-image:hover{

    transform:
    translateY(-4px);

    border-color:
    rgba(255,179,0,.25);
}
/* MAIN DIRECT LINK */

/* Antes un relleno degradado dorado bastante fuerte ("bloque
   amarillo", palabras del pedido) -- ahora un botón fantasma: fondo
   casi transparente, borde y texto dorados. Mismo lenguaje ya usado en
   otros botones secundarios del sitio (ej. .view-all-link). */
.main-direct-link{

    height: 46px;
    margin-bottom: 12px;

    border-radius: 14px;

    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;

    text-decoration: none;

    color: #ffd54f;

    font-size: 15px;
    font-weight: 600;

    background: rgba(255,255,255,.03);

    border:
    1px solid rgba(255,179,0,.35);

    transition:
    .25s ease;
}

.main-direct-link:hover{

    transform:
    translateY(-2px);

    border-color:
    rgba(255,179,0,.6);

    background:
    rgba(255,179,0,.08);
}
/* DISCORD BUTTON */

/* Antes con acento dorado igual al resto de los botones -- pedido
   explícito de que se identifique (apenas) como Discord, sin volver
   toda la tarjeta azul: fondo sigue oscuro, solo el borde/hover llevan
   un toque del "blurple" oficial de Discord (#5865F2), nunca como
   color dominante. */
.discord-btn{

    /* Antes 56px -- quedaba notablemente más alto que .main-direct-link
       (el botón "Ir al Patreon oficial", 46px) sin que hubiera un motivo
       de diseño para esa diferencia (pedido explícito: misma altura). */
    width: 100%;
    height: 46px;

    border-radius: var(--radius-card);

    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;

    text-decoration: none;

    color: var(--text-warm);

    font-size: 17px;
    font-weight: 600;

    background:
    rgba(88,101,242,.05);

    border:
    1px solid rgba(88,101,242,.22);

    transition:
    .25s ease;
}

.discord-btn:hover{

    transform:
    translateY(-2px);

    border-color:
    rgba(88,101,242,.55);

    background:
    rgba(88,101,242,.12);
}

/* Ícono de la plataforma al final del texto (pedido explícito) --
   mismo criterio de color que el resto del botón: nunca el logo de
   marca a todo color (blurple/naranja), solo un ícono neutro en tono
   claro, igual que .footer-social-link img ya hace con estos mismos
   SVGs de simple-icons. */
.direct-link-icon{
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    filter: brightness(0) invert(1);
    opacity: .85;
}
.arrow,
.fullscreen-btn{
    z-index: 5;
}
*{
    box-sizing: border-box;
}
.discord-widget{

    background:
    linear-gradient(
        180deg,
        #5865F2,
        #2d327a
    );

    border-radius: 16px;

    overflow: hidden;

    border:
    1px solid rgba(255,255,255,.08);
}

.discord-top{

    padding: 14px 16px;

    display: flex;
    align-items: center;
    justify-content: space-between;
}

.discord-left{

    display: flex;
    align-items: center;

    gap: 12px;
}

.discord-left strong{

    display: block;

    font-size: 18px;
}

.discord-left span{

    font-size: 13px;

    opacity: .8;
}

.discord-members{

    background: #1e1f28;

    padding: 14px 16px;

    display: flex;
    flex-direction: column;

    gap: 10px;

    font-size: 14px;
}

.member{

    color: rgba(255,255,255,.82);
}

.join-discord-btn{

    display: flex;
    align-items: center;
    justify-content: center;

    height: 52px;

    background: rgba(255,255,255,.06);

    color: white;

    text-decoration: none;

    font-weight: 700;
}
iframe{

    width: 100%;

    border: none;

    border-radius: var(--radius-card);

    overflow: hidden;

    display: block;

    background: #2b2d31;
}

.fox-image{

    object-position: center top;

}
.patreon-banner{

    width: 100%;

    height: 240px;

    object-fit: cover;

    object-position: center 35%;

    image-rendering: auto;

    transform: translateZ(0);

    backface-visibility: hidden;

    border-radius: var(--radius-card);

    margin-top: 14px;

    display: block;

    border:
    1px solid rgba(255,255,255,.06);

    background: #111;

    transition:
    transform .3s ease,
    border-color .3s ease;

}

/* Antes sin hover propio (pese a tener la transición ya declarada
   arriba) -- un acento dorado sutil al pasar el mouse la conecta con
   el botón de Patreon de arriba, en vez de sentirse un elemento suelto. */
.patreon-banner:hover{

    transform: translateY(-3px);

    border-color: rgba(255,179,0,.3);

}
.community-banner{

    width: 100%;

    max-width: unset;

    height: 240px;

    object-fit: cover;

    object-position: center 30%;

    border-radius: var(--radius-card);

    margin: 14px auto 0;

    display: block;

    border: 1px solid rgba(255,255,255,.06);

    background: #111;
}
/* Antes moradas -- fondo, borde y sombra unificados con .extra-block
   (misma tarjeta oscura que el resto de la ficha, sin introducir un
   color principal aparte). El acento de esta sección es dorado, igual
   que "Acerca del juego" -- ver .ad-download-top span. */
.ad-download-box{

    padding: 22px 24px;

    width: 100%;

    border-radius: 22px;

    /* Un pelín más de presencia que .extra-block (wash dorado muy
       tenue arriba, en vez del mismo blanco parejo) -- es la acción
       principal de la ficha, tiene que notarse antes de leer nada,
       sin dejar de ser el mismo negro/gris del resto. */
    background:
    linear-gradient(
      180deg,
      rgba(255,179,0,.05),
      rgba(255,255,255,.015)
    );

    border:
    1px solid rgba(255,179,0,.1);

    box-shadow:
    0 10px 30px rgba(0,0,0,.25);

    backdrop-filter: blur(10px);
}

.ad-download-top{

    display: flex;

    align-items: center;

    gap: 14px;

    margin-bottom: 18px;
}

.ad-download-top span{

    width: 5px;

    height: 34px;

    border-radius: var(--radius-pill);

    background: rgb(var(--accent-rgb));
}

.ad-download-top h2{

    margin: 0;

    color: white;

    font-size: 16px;

    font-weight: 700;
}

.ad-download-text{

    color: rgba(255,255,255,.72);

    font-size: 13px;

    line-height: 1.5;

    margin-bottom: 18px;
}


/* Reapertura: reemplaza al único .ad-download-btn fijo (siempre "PC",
   nunca Android) -- ahora 0 a 4 "cascaras" dentro de .ad-download-shells,
   una por combinación Público/Patreon x PC/Android que tenga un link
   activo cargado (ver buildDownloadShell() en juego.html).
   Reapertura (pedido explícito, refinamiento visual final) --
   --ad-gold-rgb (242,185,63 = #F2B93F) ya no tiñe toda la cascara: el
   estado "Con publicidad"/Patreon se mudó a la fila del enlace (ver
   .ad-download-shell-btn-status más abajo), así que acá solo hace falta
   un tinte de fondo sutil para seguir diferenciando la tarjeta.
   --ad-patreon-rgb (225,95,102) es una versión más viva/rosada de
   --cherry (209,104,104, ya reservado en todo el sitio para Patreon)
   usada SOLO acá -- el tono base se sentía marrón/apagado sobre el
   fondo casi negro, sin tocar la variable compartida. */
.ad-download-shells{

    --ad-gold-rgb: 242, 185, 63;

    --ad-patreon-rgb: 225, 95, 102;

    display: flex;

    flex-direction: column;

    gap: 10px;
}

/* Cada cascara es un <div> con un encabezado chico (solo plataforma +
   ícono) y una fila con el/los enlace(s) debajo -- reapertura, pedido
   explícito: menos padding/gap que la vuelta anterior, "no debe haber
   espacio vertical innecesario entre título, estado y enlaces". */
.ad-download-shell{

    width: 100%;

    padding: 12px 14px;

    border-radius: var(--radius-card);

    display: flex;

    flex-direction: column;

    gap: 8px;

    background: rgba(var(--ad-gold-rgb),.045);

    border: 1px solid rgba(var(--ad-gold-rgb),.28);

    transition:
    transform var(--dur-nav) ease,
    box-shadow var(--dur-nav) ease,
    border-color var(--dur-nav) ease,
    background var(--dur-nav) ease;
}

.ad-download-shell:hover{

    transform: translateY(-2px);

    border-color: rgba(var(--ad-gold-rgb),.5);

    background: rgba(var(--ad-gold-rgb),.08);

    box-shadow: 0 8px 24px rgba(var(--ad-gold-rgb),.14);
}

/* Patreon -- mismo fondo/borde sutil que Público (arriba), pero en rojo/
   rosado vivo (--ad-patreon-rgb) en vez de dorado, con un glow sutil en
   reposo (pedido explícito: "que se perciba mejor sobre el fondo
   oscuro... sin que parezca una alerta") -- se intensifica un poco más
   al pasar el mouse, nunca neón. */
.ad-download-shell.is-patreon{

    background: rgba(var(--ad-patreon-rgb),.06);

    border-color: rgba(var(--ad-patreon-rgb),.35);

    box-shadow: 0 0 16px rgba(var(--ad-patreon-rgb),.1);
}

.ad-download-shell.is-patreon:hover{

    transform: translateY(-2px);

    border-color: rgba(var(--ad-patreon-rgb),.6);

    background: rgba(var(--ad-patreon-rgb),.1);

    box-shadow: 0 0 22px rgba(var(--ad-patreon-rgb),.22);
}

/* Encabezado compacto -- solo plataforma + ícono real (Windows/Android)
   al extremo derecho (reapertura, pedido explícito: el estado Público/
   Patreon ya no vive acá, ver .ad-download-shell-btn-status). */
.ad-download-shell-header{

    display: flex;

    align-items: center;

    justify-content: space-between;

    gap: 12px;
}

.ad-download-shell-header strong{

    color: white;

    font-size: 15.5px;

    font-weight: 700;
}

.ad-download-shell-platform-icon{

    flex-shrink: 0;

    width: 20px;

    height: 20px;

    object-fit: contain;
}

/* Columna que agrupa el/los botón(es) principal(es) + el badge de Full
   Save (reapertura, pedido explícito -- corrige un intento anterior de
   ponerlos en fila: "no me gusta que estén 1 a 1 uno al lado de otro,
   se corta el nombre del repo". Con varios links del mismo destino
   (ej. 3 repositorios "Con publicidad · PC"), cada uno necesita el
   ancho completo de la tarjeta para no truncar el nombre -- por eso
   ahora se apilan verticalmente. Full Save es el único que NO ocupa
   ancho completo (align-self:flex-start más abajo), para seguir
   leyéndose como elemento compacto/secundario, nunca como otro botón
   de descarga más. */
.ad-download-shell-links{

    display: flex;

    flex-direction: column;

    gap: 8px;
}

/* Botón principal de descarga (reapertura, pedido explícito, refinamiento
   visual final) -- protagonista de la cascara: nombre del repositorio +
   estado (Con publicidad/Patreon, ver -status más abajo) a la izquierda,
   ícono real del repositorio al extremo derecho. Azul ÚNICO y GLOBAL
   para todos los repositorios (--ad-link-rgb, más vivo que la vuelta
   anterior -- pedido explícito: "se ve demasiado gris/desaturado") --
   ya no varía por repositorio, el ícono real sigue siendo el único
   elemento que distingue de dónde viene cada enlace. Ancho completo
   (columna, ver -links arriba) para que el nombre del repositorio
   nunca tenga que truncar por falta de espacio, aunque haya varios
   links del mismo destino apilados. */
.ad-download-shell-btn{

    --ad-link-rgb: 23, 131, 232;

    display: flex;

    align-items: center;

    justify-content: space-between;

    gap: 12px;

    width: 100%;

    min-width: 0;

    padding: 9px 14px;

    border-radius: var(--radius-pill);

    background: rgba(var(--ad-link-rgb),.28);

    border: 1px solid rgba(var(--ad-link-rgb),.5);

    text-decoration: none;

    transition: background var(--dur-nav) ease, border-color var(--dur-nav) ease, transform var(--dur-nav) ease;
}

.ad-download-shell-btn:hover,
.ad-download-shell-btn:focus-visible{

    background: rgba(var(--ad-link-rgb),.38);

    border-color: rgba(var(--ad-link-rgb),.75);

    transform: translateX(2px);
}

/* Agrupa nombre + estado -- separados del ícono (extremo derecho) por
   el justify-content:space-between del botón. min-width:0 + overflow
   hidden para que el nombre del repositorio pueda truncar con "…" en
   vez de empujar el estado/ícono fuera del botón (repositorios con
   nombre largo, ver pedido explícito). */
.ad-download-shell-btn-info{

    display: flex;

    align-items: baseline;

    gap: 9px;

    min-width: 0;

    overflow: hidden;
}

.ad-download-shell-btn-label{

    color: white;

    font-weight: 700;

    font-size: 13.5px;

    flex-shrink: 1;

    min-width: 0;

    overflow: hidden;

    text-overflow: ellipsis;

    white-space: nowrap;
}

/* Estado (Con publicidad/Patreon · Sin publicidad) -- reapertura,
   pedido explícito: se mudó del subtítulo bajo el título a la propia
   fila del enlace, conservando su color semántico (nunca el azul del
   botón). flex-shrink:0 -- nunca se trunca, un nombre de repositorio
   largo cede espacio primero (ver -label arriba). */
.ad-download-shell-btn-status{

    flex-shrink: 0;

    font-size: 11.5px;

    font-weight: 600;

    color: rgb(var(--ad-gold-rgb));

    white-space: nowrap;
}

.ad-download-shell-btn-status.is-patreon{

    color: #ff9aa4;
}

.ad-download-shell-btn-icon{

    flex-shrink: 0;

    width: 20px;

    height: 20px;

    object-fit: contain;

    border-radius: 5px;
}

/* Full Save (reapertura, pedido explícito) -- badge COMPACTO, no otra
   barra del tamaño del botón principal ("recurso adicional/secundario",
   "no debe competir con el enlace principal"): ancho por contenido
   (flex:0 0 auto, nunca flex:1), ícono chico primero + "Full Save" (al
   revés del botón principal, a propósito, para que se lea como
   etiqueta chica). Identidad SIEMPRE morada, fija -- nunca el color ni
   el nombre de su repositorio real, que sigue existiendo solo a nivel
   de URL. */
.ad-download-shell-save{

    /* -links de arriba ahora es una columna (align-items:stretch por
       default) -- align-self:flex-start es lo que evita que este badge
       se estire a lo ancho como los botones principales, para que siga
       leyéndose chico/secundario en vez de otro botón de descarga. */
    align-self: flex-start;

    flex: 0 0 auto;

    display: flex;

    align-items: center;

    gap: 6px;

    padding: 7px 12px;

    border-radius: var(--radius-pill);

    background: rgba(199,146,234,.14);

    border: 1px solid rgba(199,146,234,.4);

    color: #e4c9f7;

    font-weight: 700;

    font-size: 12px;

    text-decoration: none;

    white-space: nowrap;

    transition: background var(--dur-nav) ease, border-color var(--dur-nav) ease;
}

.ad-download-shell-save:hover,
.ad-download-shell-save:focus-visible{

    background: rgba(199,146,234,.22);

    border-color: rgba(199,146,234,.6);
}

.ad-download-shell-save-icon{

    flex-shrink: 0;

    width: 15px;

    height: 15px;

    object-fit: contain;
}
.game-main-layout{

    display: grid;

    /* Antes 320px -- la galería principal quedaba demasiado grande en
       proporción al sidebar (pedido explícito: pareja más equilibrada,
       portada del sidebar más grande). */
    grid-template-columns:
    minmax(0,1fr) 420px;

    /* Antes 24px -- las dos columnas quedaban casi pegadas, sin una
       brecha central clara (pedido explícito, referencia visual con
       una separación mucho más visible). */
    gap: 48px;

    /* Antes 38px (+ 4px del padding-bottom de .game-header) -- el
       título quedaba demasiado lejos de la imagen principal (pedido
       explícito: mucho más cerca, sin llegar a 0). */
    padding: 14px 0 0;
}

/* Sprint 21 -- columnas únicas del grid de arriba. Antes .game-media
   y .game-sidebar-steam eran los únicos hijos de este grid, y
   "Links de Descarga"/el resto de la ficha vivían en un SEGUNDO grid
   separado más abajo (.game-extra-layout, eliminado) -- esa fila
   extra apilada era la causa real del hueco enorme entre las
   miniaturas y "Links de Descarga". Ahora cada columna es un simple
   flex vertical con todo su contenido adentro. */
.game-col-left,
.game-col-right{
    display: flex;
    flex-direction: column;
    gap: 22px;
    min-width: 0;
}

/* LEFT */

.game-media{

    display: flex;

    flex-direction: column;

    gap: 14px;

    min-width: 0;
}

/* RIGHT */

.game-sidebar-steam{

    /* Pedido explícito: sin sticky -- ambas columnas hacen scroll
       normal juntas, sin que ninguna quede fija en el viewport. */

    background:
    linear-gradient(
        180deg,
        #151515,
        #0c0c0c
    );

    border:
    1px solid rgba(255,255,255,.06);

    border-radius: 22px;

    /* overflow:hidden clipa la portada "a pelo" (ver .side-cover) al
       mismo border-radius de la tarjeta -- sin esto, sus esquinas
       cuadradas de abajo se saldrían del contorno redondeado. */
    overflow: hidden;

    padding: 18px;

    display: flex;

    flex-direction: column;

    gap: 18px;

    box-shadow:
    0 14px 40px rgba(0,0,0,.35);
}
.sidebar-meta{

    display: flex;

    flex-direction: column;

    gap: 14px;
}

.meta-row{

    display: flex;

    justify-content: space-between;

    gap: 14px;
}

.meta-row span{

    /* Etiquetas (PUBLICADO EL, DESARROLLADOR(ES), etc.) -- dorado/beige
       apagado, nunca gris plano ni blanco (paleta pedida explícitamente). */
    color: #9C8B70;

    font-size: 12px;

    letter-spacing: .5px;
}

.meta-row strong{

    /* Valores normales -- crema cálido, nunca blanco puro. */
    color: #D8C9A8;

    font-size: 14px;

    text-align: right;
}

/* Traductor tiene su propio acento dorado, distinto del resto de los
   valores (paleta pedida explícitamente) -- el dorado fuerte queda
   reservado para esto. */
#metaTranslator{
    color: rgb(var(--accent-rgb));
}

/* TESTER(ES) usa el mismo color que cualquier otro valor (#D8C9A8, ver
   .meta-row strong) cuando hay un tester real -- .meta-value-empty
   (agregado por JS en renderGame() cuando no hay ninguno) lo apaga a
   un gris tenue para "—", sin ocultar la fila entera. */
.meta-value-empty{
    color: #77736E !important;
}
.game-main-layout{

    width: 100%;

    max-width: 1180px;

    margin: 0 auto;
}

/* Sin esto, la columna lateral de 420px (minmax(0,1fr) 420px) nunca
   colapsaba y la página desbordaba horizontalmente en cualquier
   celular. Sprint 21: una sola regla, antes eran dos grids separados
   (.game-main-layout/.game-extra-layout) que había que colapsar cada
   uno por su cuenta. */
@media (max-width: 900px){
    .game-main-layout{
        grid-template-columns: 1fr;
    }
}

/* =========================================================
   AUTH PAGE (login.html)
========================================================= */

.auth-page{
    background: var(--bg-main);
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    overflow: hidden;
    padding: 60px 20px;
}

.auth-glow{
    position: absolute;
    border-radius: var(--radius-circle);
    filter: blur(120px);
    pointer-events: none;
    z-index: 0;
}

.auth-glow.one{
    width: 480px;
    height: 480px;
    top: -160px;
    left: -140px;
    background: rgba(255,179,0,.16);
}

.auth-glow.two{
    width: 420px;
    height: 420px;
    bottom: -160px;
    right: -120px;
    background: rgba(255,179,0,.10);
}

.auth-wrapper{
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 440px;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.auth-brand{
    display: flex;
    flex-direction: column;
    align-items: center;
    text-decoration: none;
    margin-bottom: 22px;
}

.auth-brand img{
    width: 68px;
    height: 68px;
    border-radius: var(--radius-circle);
    object-fit: cover;
    border: 1px solid rgba(255,179,0,.35);
    box-shadow: 0 0 30px rgba(255,179,0,.25);
    transition: transform .3s ease, box-shadow .3s ease;
}

.auth-brand:hover img{
    transform: scale(1.06);
    box-shadow: 0 0 40px rgba(255,179,0,.4);
}

.auth-heading{
    text-align: center;
    margin-bottom: 26px;
}

.auth-heading h1{
    font-size: 24px;
    color: #f5f5f5;
    margin: 0 0 8px;
    letter-spacing: .3px;
}

.auth-heading p{
    font-size: 13.5px;
    color: var(--text-muted);
    max-width: 340px;
    line-height: 1.5;
    margin: 0 auto;
}

/* TABS */
.auth-tabs{
    position: relative;
    display: flex;
    width: 100%;
    background: rgba(255,255,255,.04);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-pill);
    padding: 4px;
    margin-bottom: 22px;
}

.auth-tab-highlight{
    position: absolute;
    top: 4px;
    left: 4px;
    width: calc(50% - 4px);
    height: calc(100% - 8px);
    /* Pedido explícito: un poquito menos brillante que el dorado vivo
       (--primary/--gold) -- exclusivo de este componente (.auth-tab-
       highlight no se usa en ninguna otra página), así que se ajusta
       directo acá en vez de tocar la variable compartida. */
    background: linear-gradient(135deg, #d5a437, #e1be62);
    border-radius: var(--radius-pill);
    transition: transform .32s cubic-bezier(.65,0,.35,1);
    z-index: 0;
}

.auth-tabs[data-active="register"] .auth-tab-highlight{
    transform: translateX(100%);
}

.auth-tab{
    position: relative;
    z-index: 1;
    flex: 1;
    border: none;
    background: transparent;
    padding: 11px 0;
    font-size: 13.5px;
    font-weight: 600;
    color: var(--text-muted);
    cursor: pointer;
    border-radius: var(--radius-pill);
    transition: color .25s ease;
}

.auth-tabs[data-active="login"] .auth-tab[data-tab="login"],
.auth-tabs[data-active="register"] .auth-tab[data-tab="register"]{
    color: #111;
}

/* CARD */
.auth-card{
    width: 100%;
    background: rgba(17,17,17,.55);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border: 1px solid var(--border-soft);
    border-radius: 22px;
    padding: 30px 28px 26px;
    box-shadow: 0 20px 60px rgba(0,0,0,.45);
}

.auth-form{
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.auth-form[hidden]{
    display: none;
}

.auth-field{
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.auth-field label{
    font-size: 12.5px;
    color: #ccc;
    font-weight: 600;
}

.auth-optional-hint{
    font-weight: 400;
    color: var(--text-dim);
}

.auth-field input{
    height: 46px;
    border-radius: 12px;
    border: 1px solid var(--border-soft);
    background: rgba(255,255,255,.03);
    color: #f0f0f0;
    padding: 0 14px;
    font-size: 14px;
    outline: none;
    transition: border-color var(--dur-base) ease, box-shadow var(--dur-base) ease, background var(--dur-base) ease;
}

.auth-field input::placeholder{
    color: #666;
}

.auth-field input:focus{
    border-color: rgba(255,179,0,.6);
    background: rgba(255,179,0,.05);
    box-shadow: 0 0 0 4px rgba(255,179,0,.14);
}

.auth-field:focus-within label{
    color: var(--primary-light);
    transition: color var(--dur-base) ease;
}

/* MOSTRAR / OCULTAR CONTRASEÑA */
.auth-password-wrap{
    position: relative;
}

.auth-password-wrap input{
    padding-right: 44px;
}

.auth-toggle-pass{
    position: absolute;
    top: 50%;
    right: 5px;
    transform: translateY(-50%);
    width: 34px;
    height: 34px;
    border: none;
    background: transparent;
    border-radius: 8px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background var(--dur-fast) ease;
}

.auth-toggle-pass:hover{
    background: rgba(255,179,0,.1);
}

.auth-toggle-pass svg{
    position: absolute;
    width: 18px;
    height: 18px;
    color: var(--text-muted);
    transition: opacity var(--dur-nav) ease, transform var(--dur-nav) ease, color var(--dur-base) ease;
}

.auth-toggle-pass:hover svg{
    color: var(--primary-light);
}

.auth-toggle-pass .icon-eye{
    opacity: 1;
    transform: scale(1) rotate(0deg);
}

.auth-toggle-pass .icon-eye-off{
    opacity: 0;
    transform: scale(.6) rotate(12deg);
}

.auth-toggle-pass.is-active .icon-eye{
    opacity: 0;
    transform: scale(.6) rotate(-12deg);
}

.auth-toggle-pass.is-active .icon-eye-off{
    opacity: 1;
    transform: scale(1) rotate(0deg);
}

.auth-row-between{
    display: flex;
    justify-content: flex-end;
    margin-top: -4px;
}

.auth-link{
    font-size: 12.5px;
    color: var(--primary);
    text-decoration: none;
    transition: color var(--dur-fast) ease;
}

.auth-link:hover{
    color: var(--primary-light);
}

/* Reapertura (Sprint 33, MFA/TOTP para el Propietario) -- staff-login.html
   necesita dos acciones con este mismo estilo que no son navegación real
   (alternan el estado del formulario, no cambian de página), así que van
   como <button>, no <a>. Reset mínimo del chrome nativo del botón --
   .auth-link ya resuelve color/tamaño/hover, esto solo lo deja "parecer
   un link" sin duplicar esas reglas. */
button.auth-link{
    background: none;
    border: none;
    padding: 0;
    font-family: inherit;
    cursor: pointer;
}

.auth-btn-primary{
    height: 48px;
    border: none;
    border-radius: var(--radius-pill);
    background: linear-gradient(135deg, var(--gold-muted), var(--gold-muted-light));
    color: #111;
    font-size: 14.5px;
    font-weight: 700;
    cursor: pointer;
    transition: transform var(--dur-base) ease, box-shadow var(--dur-base) ease, background var(--dur-base) ease;
}

.auth-btn-primary:hover{
    background: linear-gradient(135deg, var(--gold), var(--gold-light));
    transform: translateY(-2px) scale(1.02);
    box-shadow: var(--shadow-glow-strong);
}

.auth-divider{
    display: flex;
    align-items: center;
    gap: 12px;
    color: var(--text-muted);
    font-size: 12px;
    margin: 4px 0;
}

.auth-divider::before,
.auth-divider::after{
    content: "";
    flex: 1;
    height: 1px;
    background: var(--border-soft);
}

.auth-btn-patreon{
    height: 48px;
    border: none;
    border-radius: var(--radius-pill);
    background: #ff424d;
    color: #fff;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    transition: transform var(--dur-base) ease, box-shadow var(--dur-base) ease, background var(--dur-base) ease;
}

.auth-btn-patreon img{
    width: 16px;
    height: 16px;
    filter: brightness(0) invert(1);
}

.auth-btn-patreon:hover{
    transform: translateY(-2px) scale(1.02);
    background: #ff5b64;
    box-shadow: 0 10px 28px rgba(255,66,77,.32), 0 0 18px rgba(255,179,0,.18);
}

/* Reapertura IDENTITY_FREEZE.md §21 -- "Desvincular Patreon" es una
   acción destructiva de Ajustes, no el CTA de marca de Patreon: fondo
   transparente + borde/texto en rojo de peligro, nunca el rojo sólido de
   marca de .auth-btn-patreon (evita que parezca "vincular" de nuevo). */
.auth-btn-patreon.is-danger{
    background: transparent;
    border: 1px solid rgba(229,83,83,.45);
    color: #e55353;
}

.auth-btn-patreon.is-danger:hover{
    background: rgba(229,83,83,.12);
    box-shadow: none;
    color: #ff6b6b;
}

.auth-btn-patreon.is-danger:disabled{
    opacity: .6;
    cursor: default;
    transform: none;
}

.auth-note{
    font-size: 12px;
    color: var(--text-muted);
    line-height: 1.5;
}

.auth-note a{
    color: var(--primary);
    text-decoration: none;
}

.auth-note a:hover{
    color: var(--primary-light);
}

/* Reapertura (pedido explícito, exclusivo de login.html): "Iniciar
   sesión"/"Continuar con Patreon" se sentían como "pegatinas" -- bloques
   sólidos y planos encima de la card. .auth-btn-primary/.auth-btn-patreon
   son clases COMPARTIDAS por 6 páginas (recuperar-contrasena, staff-
   login, patreon-callback, mi-cuenta, verificar-correo, login) -- para no
   tocar esas otras 5, la regla se ata por ID a los 4 botones reales de
   ESTA página (login + register, ambas pestañas comparten el mismo
   tratamiento visual). Nunca se toca .auth-btn-primary/.auth-btn-patreon
   en sí.
   OJO: #loginSubmit/#loginForm se reutilizan tal cual en staff-login.html
   (confirmado por grep) -- un selector por ID solo no alcanza para
   distinguir las páginas. #authTabs SÍ es exclusivo de login.html (las
   pestañas Iniciar sesión/Crear cuenta; staff-login.html no tiene
   pestañas), así que todo va prefijado con "#authTabs ~ .auth-card" para
   que esta regla nunca se aplique fuera de esta página. */
/* Ronda 3 (pedido explícito, "un poco más pequeños" sobre la ronda 2):
   48px -> 44px -> 40px de alto; ~100% -> 93% -> 87% de ancho. .auth-form
   es flex column con align-items:stretch por defecto, así que hace
   falta un align-self propio para poder angostarlo. Aplica a los 4
   botones -- gold Y Patreon comparten el mismo ajuste de tamaño, pedido
   explícito de la Parte 3 ("solo aplica la reducción indicada"). */
#authTabs ~ .auth-card #loginSubmit,
#authTabs ~ .auth-card #registerSubmit,
#authTabs ~ .auth-card #loginPatreonBtn,
#authTabs ~ .auth-card #registerPatreonBtn{
    height: 40px;
    width: 87%;
    align-self: center;
}

/* Ronda 2 (pedido explícito): la ronda anterior (#95752f/#a88940) quedó
   "demasiado oscura/marrón, como deshabilitado". Mismo matiz dorado,
   bastante más luminoso (contraste contra texto negro ~7.7:1 y ~10:1,
   contra ~4.9:1 y ~6.3:1 de la ronda anterior) -- cálido y claramente
   activo en reposo, sin llegar al amarillo plano de antes de la ronda 1. */
#authTabs ~ .auth-card #loginSubmit,
#authTabs ~ .auth-card #registerSubmit{
    /* Ronda 3 (pedido explícito): un poquito más brillante que la ronda
       anterior (#b89a3f/#d0b052), sin llegar al dorado vivo del hover. */
    background: linear-gradient(135deg, #c7a644, #e0be5c);
    box-shadow: 0 2px 8px rgba(199,166,68,.2);
}

/* Hover queda tal cual lo definía .auth-btn-primary:hover (dorado vivo +
   shadow-glow-strong) -- ya cumplía "más brillante y luminoso", no hacía
   falta tocarlo. */

#authTabs ~ .auth-card #loginPatreonBtn,
#authTabs ~ .auth-card #registerPatreonBtn{
    background: linear-gradient(135deg, #e03a44, #e8474f);
    border: 1px solid rgba(255,255,255,.1);
    box-shadow: 0 3px 10px rgba(224,58,68,.22);
    transition: transform var(--dur-base) ease, box-shadow var(--dur-base) ease, background var(--dur-base) ease, border-color var(--dur-base) ease;
}

#authTabs ~ .auth-card #loginPatreonBtn:hover,
#authTabs ~ .auth-card #registerPatreonBtn:hover{
    background: linear-gradient(135deg, #ff424d, #ff5b64);
    border-color: transparent;
}

.auth-highlight{
    color: var(--primary);
    font-weight: 700;
}

a.auth-highlight:hover{
    color: var(--primary-light);
}

.auth-back{
    margin-top: 22px;
    font-size: 12.5px;
    color: var(--text-muted);
    text-decoration: none;
    transition: color var(--dur-fast) ease;
}

.auth-back:hover{
    color: #ffe082;
}

/* Sprint 19 -- el link de Staff en login.html reusa .auth-back (mismo
   tono/tamaño que "Volver al Santuario") pero eso lo dejaba indistinguible
   del párrafo de aviso de Patreon justo arriba (bug reportado: "no veo el
   botón de Staff"). Este modificador solo se separa visualmente -- borde
   superior + más aire + subrayado -- nunca lo convierte en un botón grande,
   sigue siendo texto secundario, solo dejó de camuflarse. */
.auth-staff-link{
    margin-top: 16px;
    padding-top: 12px;
    width: 100%;
    text-align: center;
    border-top: 1px solid var(--border-soft);
    text-decoration: underline;
    text-underline-offset: 3px;
}

@media (max-width: 480px){
    .auth-card{
        padding: 24px 20px 22px;
    }
}

/* =========================================================
   AUTH — VALIDACIONES, ALERTAS, LOADING (login.html)
========================================================= */

@keyframes authShake{
    10%, 90% { transform: translateX(-1px); }
    20%, 80% { transform: translateX(2px); }
    30%, 50%, 70% { transform: translateX(-4px); }
    40%, 60% { transform: translateX(4px); }
}

.auth-field .auth-error-msg{
    display: none;
    font-size: 11.5px;
    color: #ff6b6b;
    margin-top: -2px;
}

.auth-field.invalid input{
    border-color: rgba(255,93,93,.6);
    background: rgba(255,93,93,.06);
    animation: authShake .4s ease;
}

.auth-field.invalid .auth-error-msg{
    display: block;
}

.auth-field.invalid label{
    color: #ff8a8a;
}

/* ALERTAS */
.auth-alert{
    display: none;
    font-size: 12.5px;
    line-height: 1.5;
    padding: 11px 14px;
    border-radius: 12px;
    border: 1px solid transparent;
}

.auth-alert.is-visible{
    display: block;
    animation: authAlertIn .25s ease;
}

@keyframes authAlertIn{
    from { opacity: 0; transform: translateY(-6px); }
    to { opacity: 1; transform: translateY(0); }
}

.auth-alert.error{
    background: rgba(255,93,93,.08);
    border-color: rgba(255,93,93,.3);
    color: #ff9c9c;
}

.auth-alert.success{
    background: rgba(255,179,0,.08);
    border-color: rgba(255,179,0,.3);
    color: #ffd54a;
}

/* SPINNER / LOADING */
.auth-spinner{
    width: 15px;
    height: 15px;
    border: 2px solid rgba(17,17,17,.3);
    border-top-color: #111;
    border-radius: var(--radius-circle);
    display: inline-block;
    margin-right: 8px;
    vertical-align: -3px;
    animation: authSpin .6s linear infinite;
}

@keyframes authSpin{
    to { transform: rotate(360deg); }
}

.auth-btn-primary.is-loading,
.auth-btn-patreon.is-loading{
    opacity: .85;
    cursor: not-allowed;
    pointer-events: none;
}

.auth-btn-primary:disabled,
.auth-btn-patreon:disabled{
    transform: none !important;
}

/* MEDIDOR DE FUERZA DE CONTRASEÑA */
.auth-strength{
    display: flex;
    gap: 5px;
    margin-top: 2px;
}

.auth-strength span{
    height: 4px;
    flex: 1;
    border-radius: var(--radius-pill);
    background: rgba(255,255,255,.08);
    transition: background .25s ease;
}

.auth-strength span.filled{
    background: var(--text-muted);
}

.auth-strength[data-level="1"] span.filled{
    background: #ff6b6b;
}

.auth-strength[data-level="2"] span.filled{
    background: #ffb300;
}

.auth-strength[data-level="3"] span.filled{
    background: #6be675;
}

/* RESPONSIVE EXTRA */
@media (max-width: 380px){

    .auth-heading h1{
        font-size: 21px;
    }

    .auth-heading p{
        font-size: 12.5px;
    }

    .auth-card{
        padding: 20px 16px 18px;
    }

    .auth-tab{
        font-size: 12.5px;
    }
}

/* =========================================================
   VERIFICAR CORREO (verificar-correo.html)
========================================================= */

.auth-verify-status{
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    color: var(--text-muted);
    font-size: 13.5px;
    padding: 10px 0 18px;
}

.auth-spinner-lg{
    width: 22px;
    height: 22px;
    border-width: 3px;
    border-color: rgba(255,179,0,.25);
    border-top-color: var(--primary);
    margin-right: 0;
}

.auth-btn-link{
    display: flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    margin-top: 6px;
}

.auth-verify-secondary{
    display: block;
    text-align: center;
    margin-top: 14px;
    font-size: 12.5px;
}

/* =========================================================
   PANEL DE ÉXITO (recuperar-contrasena.html, paso 2)
========================================================= */

.auth-success-panel{
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 6px;
    padding: 6px 4px 4px;
    animation: authAlertIn .3s ease;
}

/* Bug real encontrado (mismo patrón ya documentado en .comment-composer/
   .report-modal-overlay más abajo en este archivo): el display:flex de
   arriba pisaba el [hidden] nativo del navegador -- a diferencia de
   .auth-form, que ya tenía su propio .auth-form[hidden]{display:none}
   (línea ~4128), a este panel hermano nunca se le agregó el mismo
   override, así que quedaba SIEMPRE visible desde la carga de la
   página, sin importar el estado real (encontrado verificando en vivo
   con Playwright que un código de recuperación incorrecto igual
   mostraba el panel de éxito). */
.auth-success-panel[hidden]{
    display: none;
}

.auth-success-icon{
    width: 52px;
    height: 52px;
    border-radius: var(--radius-circle);
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255,179,0,.12);
    border: 1px solid rgba(255,179,0,.35);
    color: var(--primary);
    margin-bottom: 6px;
}

.auth-success-icon svg{
    width: 26px;
    height: 26px;
}

.auth-success-title{
    font-size: 17px;
    font-weight: 700;
    color: #f5f5f5;
    margin: 0;
}

.auth-success-text{
    font-size: 13px;
    color: var(--text-muted);
    margin: 0 0 10px;
}

.auth-success-panel .auth-btn-primary{
    width: 100%;
}

.auth-success-countdown{
    font-size: 11.5px;
    color: var(--text-muted);
    margin: 10px 0 0;
}

/* =========================================================
   MENÚ DE USUARIO EN NAVBAR (sesión iniciada)
========================================================= */

/* Reapertura (pedido explícito -- "solo la foto de perfil debe ser el
   elemento clicable que abre/cierra el menú"): el badge (#navUserTag)
   pasó a ser hermano del botón, no su hijo -- .nav-user-menu es quien
   ahora los alinea lado a lado (antes ese gap/alineación vivía en
   .nav-user-trigger, cuando el botón todavía envolvía a los dos). El
   posicionamiento absoluto de .nav-user-dropdown sigue igual: sigue
   siendo hijo directo de este mismo contenedor `position: relative`. */
.nav-user-menu{
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 10px;
}

/* Reapertura (pedido explícito -- "eliminar únicamente ese contenedor
   exterior que engloba a foto+rango"): ya no es una cápsula con fondo/
   borde propios, solo el propio avatar actuando de botón -- el clic y el
   toggle del desplegable siguen siendo este mismo elemento, nada de eso
   cambió. */
.nav-user-trigger{
    display: inline-flex;
    align-items: center;
    /* 44px, no 42 -- efecto colateral necesario del avatar a 44px: sin
       esto el botón (su única función es ser el hit-target/contenedor
       del avatar) queda 2px más chico que su propio contenido y el
       círculo se sale de su caja. El navbar sigue fijo en 78px
       (.navbar) y todo sigue centrado vía align-items:center -- este
       cambio no mueve ni agranda nada más. */
    height: 44px;
    padding: 0;
    border: none;
    border-radius: var(--radius-circle);
    background: none;
    cursor: pointer;
    transition: transform var(--dur-fast) ease;
}

.nav-user-trigger:hover{
    transform: translateY(-1px);
}

/* Foco de teclado real (Tab) -- el trigger ya no tiene texto visible
   (antes el nombre lo daba gratis como affordance), así que necesita su
   propio indicador de foco explícito, no heredado de otra parte. */
.nav-user-trigger:focus-visible{
    outline: 2px solid rgba(255,179,0,.6);
    outline-offset: 2px;
}

.nav-user-avatar{
    /* Reapertura -- "la foto de perfil debe verse un poco más grande"
       (30px -> 38px -> 44px, pedido explícito en esta última ronda),
       circular sin cambios (var(--radius-circle) ya lo era, width=height
       la mantiene circular sin importar el tamaño). */
    width: 44px;
    height: 44px;
    border-radius: var(--radius-circle);
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--primary), var(--primary-light));
    color: #111;
    font-size: 14px;
    font-weight: 800;
    flex-shrink: 0;
    overflow: hidden;
}

.nav-user-avatar img{
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Reapertura (pedido explícito -- "el badge se ve demasiado discreto
   comparado con el resto del header"): tamaño/padding/glow SOLO para el
   badge del header (selector por id, nunca gana especificidad sobre
   .comment-badge en ningún otro lado -- comentarios y demás usos de la
   clase compartida quedan sin cambios). Mismo diseño/texto/ícono de
   siempre (.comment-badge / .comment-badge-* de más abajo no se tocan),
   esto solo agranda un poco y agrega un glow muy sutil EN EL BADGE, no
   en la foto. */
#navUserTag{
    font-size: 12px;
    padding: 3px 11px;
}

/* Un glow por variante, tomando el mismo color que ya usa cada una (ver
   .comment-badge-staff/-owner/-patreon-* más abajo) -- nunca un valor
   inventado ni un mismo color para todas. Magnitud a propósito modesta
   (blur bajo, alpha ~.4), "elegante y discreto", nunca un neón fuerte.
   Owner/Patreon-3 ya tenían un glow propio en .comment-badge-owner/-3
   (mismo lenguaje, distinto contexto) -- acá se pisa con el mismo
   criterio pero unificado para los 5 rangos, exclusivo del header. */
#navUserTag.comment-badge-staff{
    box-shadow: 0 0 8px rgba(var(--accent-rgb), .4);
}

#navUserTag.comment-badge-owner{
    box-shadow: 0 0 8px rgba(var(--accent-rgb), .4);
}

/* Antes las 3 variantes compartían el mismo cereza (un solo selector
   combinado); ahora cada rango tiene su propio color de identidad (ver
   .comment-badge-patreon-1/-2/-3 más abajo), así que cada glow del
   header también pasa a ser el suyo propio. Mismo blur/alpha que ya
   regía acá (8px, ~.4), solo cambia el color de cada uno. */
#navUserTag.comment-badge-patreon-1{
    box-shadow: 0 0 8px rgba(217,164,65,.4);
}

#navUserTag.comment-badge-patreon-2{
    box-shadow: 0 0 8px rgba(199,91,42,.4);
}

#navUserTag.comment-badge-patreon-3{
    box-shadow: 0 0 8px rgba(139,30,63,.4);
}

.nav-user-dropdown{
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    min-width: 180px;
    background: rgba(15,15,15,.92);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid var(--border-soft);
    border-radius: 14px;
    padding: 6px;
    box-shadow: 0 16px 40px rgba(0,0,0,.5);
    animation: authAlertIn var(--dur-fast) ease;
    z-index: 200;
}

/* Reapertura (pedido explícito -- "evitar repetir el nombre del usuario
   entre el header y el menú"): cabecera chica de identificación dentro
   del propio desplegable (@usuario o el email, ver session.js), a
   propósito discreta -- nunca debe competir visualmente con los ítems
   reales del menú. */
.nav-user-dropdown-header{
    padding: 8px 12px 10px;
    /* Reapertura -- "aumentarlo ligeramente" (12px -> 14px, pedido
       explícito en esta última ronda); peso/color sin tocar. Sigue sin
       superar el tamaño de los ítems del menú (13px)... levemente por
       encima ahora, a propósito (pedido explícito), pero sin acercarse
       al tamaño de un título. */
    font-size: 14px;
    font-weight: 600;
    /* Reapertura -- "mucho más legible, blanco o casi blanco" (pasó por
       #888 y por #cfcfcf antes de este valor final, pedido explícito). */
    color: #f0f0f0;
    border-bottom: 1px solid var(--border-soft);
    margin-bottom: 4px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nav-user-dropdown-item{
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    color: #ddd;
    font-size: 13px;
    font-family: inherit;
    padding: 10px 12px;
    border-radius: 9px;
    cursor: pointer;
    text-decoration: none;
    transition: background .18s ease, color .18s ease;
}

/* Corrección posterior: pedido explícito -- tuerca junto a "Ajustes de
   usuario" y puerta con flecha junto a "Cerrar sesión" (los únicos dos
   ítems de este menú que la ganan). Mismo lenguaje de ícono (stroke,
   24x24) que el resto del sitio. */
.nav-user-dropdown-icon{
    width: 15px;
    height: 15px;
    flex-shrink: 0;
}

.nav-user-dropdown-item:hover{
    background: rgba(255,179,0,.1);
    color: var(--primary-light);
}

.nav-user-logout{
    color: #ff9c9c;
    margin-top: 4px;
    border-top: 1px solid var(--border-soft);
    border-radius: 0 0 9px 9px;
}

.nav-user-logout:hover{
    background: rgba(255,93,93,.1);
    color: #ffb3b3;
}

/* =========================================================
   CAMPANA DE NOTIFICACIONES (navbar pública) -- pedido explícito.
   notifications-bell.js inyecta este bloque como hermano de
   #navAuthArea (mismo criterio que navbar-search.js con su dropdown de
   resultados: nada de esto vive en el HTML de cada página). Dropdown
   con el mismo lenguaje visual EXACTO que .nav-user-dropdown (fondo,
   blur, borde, radio, sombra, animación) -- misma pieza, otro contenido.
========================================================= */

.notif-bell-wrap{
    position: relative;
}

.notif-bell-trigger{
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: var(--radius-circle);
    border: 1px solid var(--border-soft);
    background: rgba(255,255,255,.03);
    color: #ddd;
    cursor: pointer;
    transition: border-color var(--dur-fast) ease, background var(--dur-fast) ease, transform var(--dur-fast) ease;
}

.notif-bell-trigger:hover{
    border-color: rgba(255,179,0,.4);
    background: rgba(255,179,0,.06);
    transform: translateY(-1px);
}

.notif-bell-trigger svg{
    width: 19px;
    height: 19px;
}

.notif-bell-badge{
    position: absolute;
    top: 2px;
    right: 2px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: var(--radius-pill);
    background: linear-gradient(135deg, #ff5d5d, #ff8080);
    color: #2a0000;
    font-size: 10px;
    font-weight: 800;
    line-height: 16px;
    text-align: center;
}

.notif-bell-badge[hidden]{
    display: none;
}

.notif-bell-dropdown{
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    width: 360px;
    max-width: 90vw;
    background: rgba(15,15,15,.92);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid var(--border-soft);
    border-radius: 14px;
    box-shadow: 0 16px 40px rgba(0,0,0,.5);
    animation: authAlertIn var(--dur-fast) ease;
    z-index: 200;
    overflow: hidden;
}

.notif-bell-dropdown[hidden]{
    display: none;
}

.notif-bell-header{
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 16px 8px;
    font-size: 14px;
    font-weight: 800;
    color: var(--text-warm);
}

.notif-bell-tabs{
    display: flex;
    gap: 8px;
    padding: 0 16px 10px;
}

.notif-bell-tab{
    height: 28px;
    padding: 0 12px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--border-soft);
    background: transparent;
    color: var(--text-dim);
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: border-color var(--dur-fast) ease, color var(--dur-fast) ease, background var(--dur-fast) ease;
}

.notif-bell-tab:hover{
    color: #eee;
}

.notif-bell-tab.is-active{
    border-color: rgba(255,179,0,.4);
    background: rgba(255,179,0,.1);
    color: var(--primary-light);
}

.notif-bell-list{
    max-height: 360px;
    overflow-y: auto;
    padding: 0 6px 6px;
    display: flex;
    flex-direction: column;
    /* Pedido explícito: quedaban demasiado pegadas entre sí -- antes 2px. */
    gap: 8px;
}

.notif-bell-item{
    display: block;
    padding: 10px 10px;
    border-radius: 10px;
    text-decoration: none;
    transition: background .18s ease;
    border-left: 2px solid transparent;
}

.notif-bell-item:hover{
    background: rgba(255,255,255,.05);
}

.notif-bell-item.is-unread{
    border-left-color: var(--gold, #e8b23c);
    background: rgba(255,179,0,.05);
}

.notif-bell-item-title{
    display: block;
    color: var(--text-warm);
    font-size: 13px;
    font-weight: 700;
    margin: 0 0 3px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.notif-bell-item-message{
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    color: var(--text-soft);
    font-size: 12.5px;
    line-height: 1.4;
    margin: 0 0 4px;
    /* Pedido explícito: un mensaje sin espacios (ej. "aaaa...") no tenía
       dónde partir línea y quedaba cortado a mitad de camino en vez de
       recortarse limpio en la 3ª línea -- mismo fix ya aplicado en
       Reportes (.dash-report-detail-description). */
    word-break: break-word;
}

.notif-bell-item-time{
    display: block;
    color: var(--text-dim);
    font-size: 11px;
}

.notif-bell-empty{
    padding: 28px 16px 30px;
    text-align: center;
    color: var(--text-dim);
    font-size: 13px;
}

.notif-bell-viewall{
    display: block;
    text-align: center;
    padding: 12px;
    border-top: 1px solid var(--border-soft);
    color: var(--primary-light);
    font-size: 12.5px;
    font-weight: 700;
    text-decoration: none;
}

.notif-bell-viewall:hover{
    background: rgba(255,255,255,.04);
}

.notif-bell-viewall[hidden]{
    display: none;
}

/* =========================================================
   MI CUENTA (mi-cuenta.html)
========================================================= */

#accountCard{
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

.account-avatar-lg{
    width: 64px;
    height: 64px;
    border-radius: var(--radius-circle);
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--primary), var(--primary-light));
    color: #111;
    font-size: 26px;
    font-weight: 800;
    margin-bottom: 14px;
}

.account-name{
    font-size: 18px;
    font-weight: 700;
    color: #f5f5f5;
    margin: 0;
}

.account-email{
    font-size: 13px;
    color: var(--text-muted);
    margin: 4px 0 14px;
}

.account-badges{
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: center;
    margin-bottom: 14px;
}

.account-badge{
    font-size: 11.5px;
    font-weight: 600;
    padding: 5px 11px;
    border-radius: var(--radius-pill);
    background: rgba(255,255,255,.06);
    color: var(--text-muted);
    border: 1px solid var(--border-soft);
}

.account-badge-ok{
    background: rgba(107,230,117,.1);
    color: #8be99a;
    border-color: rgba(107,230,117,.3);
}

.account-badge-warn{
    background: rgba(255,179,0,.1);
    color: var(--primary-light);
    border-color: rgba(255,179,0,.3);
}

.account-badge-premium{
    background: linear-gradient(135deg, rgba(255,179,0,.2), rgba(255,213,74,.2));
    color: var(--primary-light);
    border-color: rgba(255,179,0,.4);
    font-weight: 700;
}

.account-since{
    font-size: 12px;
    color: var(--text-muted);
    margin: 0 0 18px;
}

#accountCard .auth-btn-primary{
    width: 100%;
}

/* =========================================================
   AJUSTES DE USUARIO (ajustes-usuario.html) -- pantalla real de
   configuración para cuentas públicas/member (antes el menú del
   navbar prometía "Ajustes de usuario" pero apuntaba a
   dashboard-ajustes.html, la pantalla de Staff -- inaccesible/sin
   sentido para una cuenta member). Reutiliza tal cual la lógica de
   dashboard-form.js (InariForm.build/buildAvatarDrop -- mismo upload
   real a /api/uploads/avatar, misma validación de tipo/tamaño) y los
   mismos endpoints /api/identity/accounts/me* que ya usa
   dashboard-ajustes.html -- lo único nuevo acá es el CSS: los mismos
   nombres de clase que ya arma InariForm (.dash-form-field, etc.)
   tenían su estilo SOLO en dashboard.css (cargado nada más en el
   Dashboard) -- estas reglas les dan una piel propia, en la paleta
   pública (dorado/negro de Inari, no la del panel de Staff), sin
   tocar dashboard.css ni nada de lo que ya usa el Dashboard.
   Todo escapado bajo .account-settings-page para que nunca puje
   contra ninguna otra clase del sitio. */

.account-settings-page .game-header{
    padding: 34px 0 4px;
}

.account-settings-grid{
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    padding: 14px 0 70px;
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: start;
    gap: 24px;
}

.account-settings-card{
    background:
    linear-gradient(
      180deg,
      rgba(255,255,255,.035),
      rgba(255,255,255,.015)
    );
    border: 1px solid var(--border-soft);
    border-radius: 22px;
    padding: 26px 24px;
    backdrop-filter: blur(10px);
    box-shadow: 0 10px 30px rgba(0,0,0,.22);
}

.account-settings-card-title{
    display: flex;
    align-items: center;
    gap: 14px;
    margin: 0 0 18px;
    color: white;
    font-size: 16px;
}

.account-settings-card-title span{
    width: 5px;
    height: 22px;
    border-radius: var(--radius-pill);
    background: var(--gold-accent-soft);
    flex-shrink: 0;
}

/* Perfil en la columna izquierda; contraseña + info de cuenta apiladas
   a la derecha -- mismo criterio de agrupación que la referencia. */
.account-settings-grid > .account-settings-card:first-child{
    grid-row: 1 / span 2;
}

@media (max-width: 780px){
    .account-settings-grid{
        grid-template-columns: 1fr;
    }
    .account-settings-grid > .account-settings-card:first-child{
        grid-row: auto;
    }
}

@media (max-width: 480px){
    /* Reapertura (pulido visual, Ajustes de Usuario) -- las filas de
       Cancelar/Enviar/Reenviar/Verificar son un <div style="display:flex">
       armado en JS (sin clase propia, es siempre el último hijo agregado
       al <form>, ver ajustes-usuario.html) -- en una pantalla angosta dos
       botones pill de padding generoso lado a lado se salían del ancho de
       la tarjeta. Nunca toca la lógica/el markup, solo deja que esa fila
       envuelva en vez de desbordar. */
    .account-settings-card .dash-form > div:last-child{
        flex-wrap: wrap;
    }
    .account-settings-card .dash-form > div:last-child .dash-btn-primary,
    .account-settings-card .dash-form > div:last-child .dash-btn-ghost{
        flex: 1 1 auto;
    }
}

/* ---- Formularios (InariForm.build/buildAvatarDrop) ---- */

.account-settings-card .dash-form{
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.account-settings-card .dash-form-field{
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.account-settings-card .dash-form-label{
    font-size: 12.5px;
    color: #ccc;
    font-weight: 600;
}

.account-settings-card .dash-form-field input[type="text"],
.account-settings-card .dash-form-field input[type="password"],
.account-settings-card .dash-form-field input[type="email"]{
    height: 46px;
    width: 100%;
    box-sizing: border-box;
    border-radius: 12px;
    border: 1px solid var(--border-soft);
    background: rgba(255,255,255,.03);
    color: #f0f0f0;
    padding: 0 14px;
    font-size: 14px;
    font-family: inherit;
    outline: none;
    transition: border-color var(--dur-base) ease, box-shadow var(--dur-base) ease, background var(--dur-base) ease;
}

.account-settings-card .dash-form-field input:focus{
    border-color: rgba(255,179,0,.6);
    background: rgba(255,179,0,.05);
    box-shadow: 0 0 0 4px rgba(255,179,0,.14);
}

.account-settings-card .dash-form-field.has-error input{
    border-color: rgba(255,93,93,.6);
    background: rgba(255,93,93,.06);
}

.account-settings-card .dash-form-hint{
    margin: 0;
    font-size: 12px;
    color: var(--text-muted);
}

.account-settings-card .dash-form-error{
    margin: 0;
    font-size: 11.5px;
    color: #ff8a8a;
}

/* Corrección posterior -- unificación de "Email de recuperación" +
   "Correo electrónico y seguridad" en una sola tarjeta (pedido explícito):
   la recuperación pasa a vivir como subsección dentro de la misma card,
   separada solo por un borde superior sutil y un título más chico -- sin
   inventar un componente visual nuevo, mismos tokens de color/borde que
   ya usa el resto de esta tarjeta (var(--border-soft)/var(--text-muted)). */
.account-settings-card .account-settings-subsection{
    margin-top: 22px;
    padding-top: 18px;
    border-top: 1px solid var(--border-soft);
}

.account-settings-card .account-settings-subsection-title{
    margin: 0 0 10px;
    font-size: 12.5px;
    font-weight: 700;
    color: #ccc;
    text-transform: uppercase;
    letter-spacing: .04em;
}

.account-settings-card .dash-password-wrap{
    position: relative;
}

.account-settings-card .dash-password-wrap input{
    padding-right: 44px;
}

.account-settings-card .dash-password-toggle{
    position: absolute;
    top: 50%;
    right: 5px;
    transform: translateY(-50%);
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: transparent;
    border-radius: 8px;
    color: var(--text-muted);
    cursor: pointer;
    transition: background var(--dur-fast) ease, color var(--dur-fast) ease;
}

.account-settings-card .dash-password-toggle:hover{
    background: rgba(255,179,0,.1);
    color: var(--primary-light);
}

.account-settings-card .dash-password-toggle svg{
    width: 18px;
    height: 18px;
}

.account-settings-card .dash-btn-primary{
    align-self: flex-start;
    height: 37px;
    padding: 0 20px;
    border: 1px solid rgba(var(--green-action-rgb),.18);
    border-radius: var(--radius-pill);
    background: linear-gradient(135deg, var(--green-action-deep), var(--green-action-deep-light));
    color: #111;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(var(--green-action-rgb),.15);
    transition: transform var(--dur-fast) ease, background var(--dur-fast) ease, border-color var(--dur-fast) ease, box-shadow var(--dur-fast) ease;
}

.account-settings-card .dash-btn-primary:hover{
    background: linear-gradient(135deg, var(--green-action), var(--green-action-light));
    border-color: transparent;
    transform: translateY(-1px);
    box-shadow: 0 4px 14px rgba(var(--green-action-rgb),.28);
}

.account-settings-card .dash-btn-primary:focus-visible{
    outline: 2px solid rgba(var(--green-action-rgb),.6);
    outline-offset: 2px;
}

.account-settings-card .dash-btn-primary:active{
    transform: translateY(0);
    box-shadow: none;
}

.account-settings-card .dash-btn-primary:disabled{
    opacity: .6;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

/* Reapertura (pulido visual, Ajustes de Usuario) -- .dash-btn-ghost no
   tenía NINGUNA regla en este scope (solo existía en dashboard.css, que
   esta página nunca carga), así que "Cancelar"/"Reenviar correo" caían al
   botón nativo del navegador (blanco/gris). Mismas dimensiones que
   .dash-btn-primary de arriba (altura/padding/radio), para que ambos
   queden alineados lado a lado -- solo cambia fondo/borde/color, mismo
   criterio "secundario" que ya usa dashboard.css. */
.account-settings-card .dash-btn-ghost{
    align-self: flex-start;
    height: 46px;
    padding: 0 26px;
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--text-soft);
    font-size: 14px;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
    transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease, color var(--dur-fast) ease;
}

.account-settings-card .dash-btn-ghost:hover{
    background: rgba(255,255,255,.05);
    border-color: rgba(255,255,255,.18);
    color: var(--text-warm);
}

.account-settings-card .dash-btn-ghost:disabled{
    opacity: .5;
    cursor: not-allowed;
}

.account-settings-card .dash-btn-ghost:disabled:hover{
    background: transparent;
    border-color: var(--border-soft);
    color: var(--text-soft);
}

/* Mismo hueco -- "✓ Verificado"/"🟡 Pendiente de verificación" usaban
   dash-status-badge, también exclusivo de dashboard.css hasta ahora, así
   que se mostraban como texto plano sin pastilla ni color. Mismos valores
   exactos que dashboard.css (fuente única de verdad de este componente en
   todo el sitio), para que si algún día esta página empieza a cargar
   dashboard.css no haya que reconciliar dos definiciones distintas. */
.account-settings-card .dash-status-badge{
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: var(--radius-pill);
    font-size: 11.5px;
    font-weight: 700;
}

.account-settings-card .dash-status-badge.is-active{
    background: rgba(80,200,120,.12);
    color: #6fd996;
}

.account-settings-card .dash-status-badge.is-pending{
    background: var(--cherry-faint);
    color: var(--cherry-strong);
}

/* Pedido explícito (sistema de notificaciones -- tarjeta "Mi reporte"
   self-service): mismos 3 estados que dashboard.css agrega para el
   workflow de reportes, ausentes acá hasta ahora porque esta página
   nunca había necesitado mostrar el estado de un Report. Mismos valores
   exactos, mismo criterio que is-active/is-pending de arriba. */
.account-settings-card .dash-status-badge.is-resolved{
    background: rgba(80,200,120,.12);
    color: #6fd996;
}

.account-settings-card .dash-status-badge.is-dismissed{
    background: rgba(255,255,255,.06);
    color: var(--text-dim);
}

.account-settings-card .dash-status-badge.is-reviewed{
    background: var(--gold-soft);
    color: var(--gold-light);
}

.account-settings-card .dash-editor-save-status{
    margin: 10px 0 0;
    font-size: 12.5px;
    color: var(--text-muted);
}

.account-settings-card .dash-editor-save-status.is-success{
    color: #8be99a;
}

.account-settings-card .dash-editor-save-status.is-error{
    color: #ff8a8a;
}

/* ---- Avatar (InariForm.buildAvatarDrop) ---- */

.account-settings-card .dash-cover-drop{
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 130px;
    padding: 16px;
    border: 1px dashed var(--border-soft);
    border-radius: 12px;
    background: rgba(255,255,255,.02);
    color: var(--text-muted);
    font-size: 12.5px;
    text-align: center;
    cursor: pointer;
    transition: border-color var(--dur-fast) ease, background var(--dur-fast) ease;
}

.account-settings-card .dash-cover-drop:hover,
.account-settings-card .dash-cover-drop:focus-visible{
    border-color: rgba(255,179,0,.5);
    outline: none;
}

.account-settings-card .dash-cover-drop.is-dragover{
    border-color: rgba(255,179,0,.7);
    background: rgba(255,179,0,.06);
    color: #f0f0f0;
}

.account-settings-card .dash-cover-drop-link{
    color: var(--primary-light);
    font-weight: 600;
    text-decoration: underline;
}

.account-settings-card .dash-cover-drop.is-uploading{
    opacity: .6;
    pointer-events: none;
}

.account-settings-card .dash-avatar-drop{
    /* Reapertura (pulido visual, Ajustes de Usuario) -- a 110px, el texto
       heredado de .dash-cover-drop (12.5px, sin ajuste propio) envolvía en
       3-4 líneas muy angostas y apretadas dentro del círculo -- a simple
       vista se leían como rayas horizontales decorativas, no como una
       frase. Un poco más de diámetro + tipografía propia más chica (ver
       el párrafo de abajo) resuelve las dos causas a la vez, sin tocar
       nada del comportamiento de arrastrar/soltar/subir. */
    width: 136px;
    height: 136px;
    min-height: 0;
    border-radius: var(--radius-circle);
    padding: 14px;
    margin: 0 auto 6px;
}

.account-settings-card .dash-avatar-drop p{
    margin: 0;
    font-size: 11px;
    line-height: 1.4;
}

.account-settings-card .dash-avatar-drop.has-preview{
    border-radius: var(--radius-circle);
    overflow: visible;
    padding: 0;
    border-style: solid;
}

.account-settings-card .dash-cover-drop-preview{
    width: 100%;
    max-height: 220px;
    object-fit: cover;
    display: block;
    border-radius: 11px;
}

.account-settings-card .dash-avatar-drop .dash-cover-drop-preview{
    width: 100%;
    height: 100%;
    max-height: none;
    border-radius: var(--radius-circle);
}

.account-settings-card .dash-cover-drop-change{
    position: absolute;
    bottom: 2px;
    right: 2px;
    width: 30px;
    height: 30px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-circle);
    border: 2px solid #0c0c0c;
    background: #151515;
    color: #f0f0f0;
    cursor: pointer;
    transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease;
}

.account-settings-card .dash-cover-drop-change:hover{
    background: #1c1c1c;
    border-color: rgba(255,179,0,.4);
}

.account-settings-card .dash-cover-drop-change svg{
    width: 14px;
    height: 14px;
}

/* ---- Información de cuenta (solo lectura) ---- */

.account-settings-card .dash-status-list{
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.account-settings-card .dash-status-list > div{
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--border-soft);
}

.account-settings-card .dash-status-list > div:last-child{
    border-bottom: none;
    padding-bottom: 0;
}

.account-settings-card .dash-status-list dt{
    margin: 0;
    color: var(--text-muted);
    font-size: 13px;
}

.account-settings-card .dash-status-list dd{
    margin: 0;
    color: #f0f0f0;
    font-weight: 600;
    font-size: 13.5px;
    text-align: right;
}

/* =========================================================
   MIS REPORTES (rediseño de Reportes, pedido explícito) — sección
   propia, ya no una tarjeta enterrada dentro de Ajustes de Usuario.
   Reutiliza .account-settings-card/.dash-status-badge/.dash-status-list/
   .dash-form-hint tal cual (arriba) para cada ticket -- solo agrega el
   contenedor de la página y el apilado vertical de varias cards, nunca
   el grid de 2 columnas de .account-settings-grid (pensado para
   perfil/contraseña/info emparejados, no para una lista).
========================================================= */

.my-reports-page-content{
    width: 100%;
    max-width: 900px;
    margin: 0 auto;
    padding: 14px 0 70px;
}

.my-reports-list{
    display: flex;
    flex-direction: column;
    gap: 24px;
}

.my-report-card .dash-status-badge{
    margin-top: -6px;
}

/* Deep-link desde la notificación "tu reporte fue atendido" -- resalta
   brevemente el ticket correspondiente al entrar, mismo criterio de
   color que el foco dorado ya usado en el resto del sitio. */
.my-report-card.is-highlighted{
    border-color: rgba(255,179,0,.6);
    box-shadow: 0 0 0 3px rgba(255,179,0,.18);
}

/* Paginación (revisión pedida explícitamente: "Mis reportes" no tenía --
   se agrega en cliente, mismo patrón Anterior/Página X de Y/Siguiente que
   .dash-pagination ya usa en dashboard-notificaciones.html). Botones con
   los mismos valores que .account-settings-card .dash-btn-ghost de más
   arriba -- acá sin ese escope porque la paginación vive fuera de
   cualquier .account-settings-card, como hermana de .my-reports-list. */
.my-reports-pagination{
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    margin-top: 8px;
}

.my-reports-pagination-info{
    color: var(--text-muted);
    font-size: 13px;
}

.my-reports-pagination .dash-btn-ghost{
    height: 46px;
    padding: 0 26px;
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--text-soft);
    font-size: 14px;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
    transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease, color var(--dur-fast) ease;
}

.my-reports-pagination .dash-btn-ghost:hover{
    background: rgba(255,255,255,.05);
    border-color: rgba(255,255,255,.18);
    color: var(--text-warm);
}

.my-reports-pagination .dash-btn-ghost:disabled{
    opacity: .5;
    cursor: not-allowed;
}

.my-reports-pagination .dash-btn-ghost:disabled:hover{
    background: transparent;
    border-color: var(--border-soft);
    color: var(--text-soft);
}

/* =========================================================
   DISCOVER HERO (portada) — banner grande y cinematográfico.
   Escala inspirada en un banner tipo Palworld, identidad propia:
   negro/dorado, sin precios/reseñas. Se navega con flechas y
   puntos (no con una fila de miniaturas aparte).
========================================================= */

.discover-hero{
    padding: 0;
}

/* Margen lateral -- la imagen ya no toca los bordes del navegador (el
   "corte" real lo disimula el degradado de borde de la propia imagen,
   ver .discover-hero-media img más abajo, así el margen nunca se ve
   como espacio vacío/recortado a lo bruto). Acotado a "body.home-page"
   -- el Dashboard (dashboard-pagina-principal.html) reutiliza el mismo
   <section class="discover-hero"> para su vista previa compactada
   (.dash-home-hero-preview), y ahí no hace falta ni conviene este
   margen (el panel ya es angosto de por sí). */
body.home-page .discover-hero{
    padding: 0 clamp(20px, 3vw, 48px);
}

.discover-hero-card{
    position: relative;
    /* Vuelto a ocupar toda la pantalla verticalmente (pedido
       explícito: "que ocupe toda la pantalla de manera vertical") --
       la ronda pasada lo había bajado a 92vh para recortar menos
       arriba/abajo de las imágenes, pero eso importa menos que llenar
       la altura completa. Sigue restando 78px del navbar, que no se
       superpone. Ancho sin tocar (el padding lateral de
       .discover-hero es un eje aparte). */
    height: calc(100vh - 78px);
    max-height: 1000px;
    min-height: 560px;
    overflow: hidden;
}

.discover-hero-media img{
    /* Fundido puro entre diapositivas -- sin transform acá: el
       cambio de diapositiva y la "respiración" continua de abajo
       (heroImageBreathe) son dos animaciones separadas, no se pisan. */
    transition: opacity var(--dur-carousel) var(--ease-premium);
}

.discover-hero-card.is-fading .discover-hero-media img{
    opacity: 0;
}

/* Respiración muy sutil sobre la imagen activa (no sobre el cambio de
   diapositiva, que es puro fade arriba) -- un zoom casi imperceptible
   a lo largo de toda la duración de la diapositiva, solo para dar
   sensación de vida. Duración atada a HERO_ROTATION_MS vía la
   variable --hero-dur (seteada una vez desde JS) para no repetir el
   número en dos lugares. El JS reinicia la animación a mano en cada
   cambio de diapositiva (el <img> es el mismo nodo, solo cambia el
   src, así que la animación no se reinicia sola). */
@media (prefers-reduced-motion: no-preference){
    .discover-hero-media img{
        animation: heroImageBreathe var(--hero-dur, 8s) linear forwards;
    }
}

@keyframes heroImageBreathe{
    from{ transform: scale(1); }
    to{ transform: scale(1.03); }
}

/* Entrada en cascada: cada elemento del hero (título, descripción,
   CTA) se funde por separado con un pequeño delay creciente, en vez
   de moverse todos como un solo bloque -- pero SOLO opacity, sin
   transform: nada se desplaza durante el cambio de diapositiva
   (pedido explícito). Se nota tanto al cargar la página como al
   cambiar de destacado. */
.discover-hero-info h1,
.discover-hero-desc{
    transition: opacity var(--dur-carousel) var(--ease-premium);
}

.discover-hero-card.is-fading .discover-hero-info h1{
    opacity: 0;
}

.discover-hero-card.is-fading .discover-hero-desc{
    opacity: 0;
    transition-delay: .05s;
}

.discover-hero-card.is-fading .discover-hero-cta{
    opacity: 0;
    transition-delay: .1s;
}

.discover-hero-media{
    position: absolute;
    inset: 0;
    /* Reapertura (bug real reportado): la máscara de borde vivía en el
       propio <img>, que ADEMÁS tiene `filter` y una `animation` de
       transform (heroImageBreathe, ver más abajo). Esa combinación
       (mask-image + filter + animation en el mismo elemento) es un
       disparador conocido de un glitch de compositing en Chromium/
       WebKit: el primer frame (o el reinicio de la animación en cada
       cambio de diapositiva) puede pintarse un instante SIN la máscara
       aplicada -- ahí la imagen se ve "de bordes a bordes"/más grande
       de lo normal hasta que el navegador recompone la capa (~1s,
       coincide con lo reportado). Se corrige moviendo la máscara acá,
       al wrapper (que nunca anima ni tiene filter) -- mismo resultado
       visual exacto (el wrapper mide lo mismo que el <img>, inset:0 +
       100%/100%), pero desacoplado del elemento que sí se anima. */
    -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 3%, #000 97%, transparent 100%);
    mask-image: linear-gradient(to right, transparent 0%, #000 3%, #000 97%, transparent 100%);
}

.discover-hero-media img{
    /* "cover" a propósito, otra vez -- "contain" con letterboxing (dos
       rondas atrás) dejaba cada diapositiva con una escala distinta
       según la proporción real de la imagen (algunas quedaban chicas,
       flotando en un mar de negro): rompía la sensación de "un mismo
       Hero". Con "cover" todas llenan el marco completo, siempre al
       mismo tamaño -- se prioriza consistencia sobre mostrar el 100%
       de cada imagen. object-position explícito (no el default
       implícito) para poder ofrecer un punto focal configurable por
       Hero más adelante sin tener que tocar esta línea otra vez --
       vuelto a "center" (se probó "center 25%" para no comerse la
       parte de arriba de la ilustración, pero ayudaba a unas imágenes
       y perjudicaba a otras: sin un punto focal real por imagen, un
       sesgo fijo hacia arriba es tan arbitrario como el centro. Base
       neutra por ahora -- el punto focal configurable queda pendiente
       para el Dashboard). */
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    filter: brightness(.7) saturate(1.1);
}

.discover-hero-scrim{
    position: absolute;
    inset: 0;
    /* Séptima vuelta (pedido explícito): el degradado full-bleed de la
       vuelta anterior oscurecía prácticamente todo el Hero -- vuelto a
       ser nada más que el desvanecido general del borde inferior, sin
       apuntar a ningún bloque en particular. El contraste local detrás
       del texto ahora vive en .discover-hero-info::before (ver más
       abajo), acotado a esa zona, no acá. */
    background: linear-gradient(to top, rgba(6,6,6,.55) 0%, transparent 26%);
}

.discover-hero-info{
    position: absolute;
    left: 6%;
    /* Subido un poco (venía de 70px). Los indicadores
       (.discover-hero-dots) quedan aparte, pegados abajo del todo a
       propósito. */
    bottom: 98px;
    z-index: 2;
    max-width: 680px;
}

/* Séptima vuelta (pedido explícito): sacada la tarjeta de cristal
   (fondo propio + blur + esquinas redondeadas + sombra, "no quiero una
   tarjeta/panel") Y sacado también el degradado full-bleed que la
   reemplazó en la vuelta anterior (oscurecía todo el Hero, no solo la
   zona del texto). Este ::before es el reemplazo correcto: un
   radial-gradient suave, sin bordes duros, acotado a un margen
   razonable alrededor de .discover-hero-info (inset negativo, mismo
   mecanismo que la vieja tarjeta de cristal, pero sin fondo sólido/
   blur/radio/sombra) -- se desvanece del todo antes de llegar a su
   propio borde, así que nunca llega a rozar el borde real de la
   imagen. El resto del Hero (fuera de esta zona) queda sin ningún
   oscurecimiento adicional. Octava vuelta (pedido explícito): opacidad
   bajada (.48/.28 -> .32/.18) y el desvanecido final adelantado (75%
   -> 72%) -- todavía se leía como una mancha oscura aparte detrás del
   texto; el text-shadow del h1/desc ya hace la mayor parte del trabajo
   de legibilidad, esto ahora es solo un empujón extra de profundidad,
   no una zona oscura marcada. */
.discover-hero-info::before{
    content: "";
    position: absolute;
    inset: -40px -70px -40px -40px;
    z-index: -1;
    background: radial-gradient(ellipse at left center, rgba(0,0,0,.32) 0%, rgba(0,0,0,.18) 45%, rgba(0,0,0,0) 72%);
    pointer-events: none;
}

.discover-hero-info h1{
    /* "Playfair Display" (serif dramática) reemplazada por "Nunito" --
       sans-serif redondeada, se lee mucho más amigable/cercana en vez
       de formal/editorial. Ver el <link> de Google Fonts en index.html. */
    font-family: 'Nunito', 'Segoe UI', sans-serif;
    /* Más chico otra vez (venía de 2.05rem, después 1.8rem, después 1.55rem). */
    font-size: 1.35rem;
    font-weight: 800;
    line-height: 1.05;
    letter-spacing: -.5px;
    /* Todavía más pegado a la descripción. */
    margin: 0 0 4px;
    /* Pedido explícito (legibilidad, sin tocar la imagen): color/sombra
       puntuales en vez de var(--text-warm) -- una sombra más corta y
       oscura (antes 6px/30px de blur, muy difusa) pega el texto al
       contorno de las letras en vez de un glow amplio alrededor. */
    color: #F5F2F5;
    text-shadow: 0 2px 4px rgba(0,0,0,.65);
    /* Hasta 2 líneas, sin romper el layout con un título largo. Ya NO
       reserva el alto de 2 líneas siempre -- casi todos los títulos
       reales son de una sola línea, y reservar el espacio de una
       segunda que nunca aparece dejaba un salto grande y vacío hasta
       la descripción. Se prioriza compacidad; en el caso raro de un
       título que sí ocupe 2 líneas, el botón de abajo se corre un
       poco (aceptable frente al hueco que dejaba antes en el caso
       común). */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.discover-hero-desc{
    font-family: 'Nunito', 'Segoe UI', sans-serif;
    /* Pedido explícito (legibilidad, sin tocar la imagen): color sólido
       + text-shadow en vez de blanco cálido atenuado por opacidad --
       secundario frente al título por tamaño/peso, nunca por ilegible. */
    color: #F0EDF0;
    text-shadow: 0 2px 4px rgba(0,0,0,.55);
    font-size: .96rem;
    line-height: 1.55;
    /* Bloque de lectura más angosto (antes 520px) -- columna más
       limpia, la imagen sigue siendo la protagonista. */
    max-width: 440px;
    /* Menos separación con el botón de abajo -- mismo criterio que el
       margen del h1, título/descripción/botón como un solo bloque. */
    margin: 0 0 14px;
    /* Hasta 4 líneas (antes 2 -- se perdía demasiada info) con puntos
       suspensivos si no entra. Mismo criterio que el h1: SIEMPRE
       reserva el alto de esas 4 líneas (6.2em = 4 × line-height 1.55),
       haya o no subtítulo (ver "visibility:hidden" en vez de "hidden"
       en el JS que arma cada diapositiva) -- así el botón queda en el
       mismo lugar sin importar cuánto texto tenga cada diapositiva. */
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: 6.2em;
}

.discover-hero-cta{
    display: inline-flex;
    align-items: center;
    /* Más chico otra vez (venía de 46px/0 38px/.92rem). */
    height: 40px;
    padding: 0 26px;
    /* Esquinas más redondeadas (10px->14px) y una sombra propia en
       reposo (antes solo aparecía al hover) -- pedido explícito de que
       se sienta menos "plano", más amigable, sin volver al pill
       original (999px). */
    border-radius: 14px;
    /* Reapertura (pedido explícito, "también en el Hero este botón de
       ese color") -- venía de dorado (#ffb300/#ffd54f); ahora azul
       cielo en las dos secciones (Hero y En tendencia, ver .trend-cta
       más abajo, que ya no necesita su propio color). Un poco más
       oscuro/menos brillante que el celeste de .legal-contact-box a
       (pedido explícito) -- sigue siendo lo bastante claro para texto
       negro (contraste ~6.4:1 en el extremo más oscuro del degradé). */
    background: linear-gradient(135deg, #569cd2, #76afdb);
    color: #111;
    font-weight: 600;
    font-size: .85rem;
    text-decoration: none;
    box-shadow: 0 6px 16px rgba(86,156,210,.2);
    transition: opacity var(--dur-carousel) var(--ease-premium),
                transform var(--dur-fast) ease,
                box-shadow var(--dur-fast) ease;
}

.discover-hero-cta:hover{
    transform: translateY(-2px);
    box-shadow: 0 10px 24px rgba(86,156,210,.3);
}

/* Etiqueta+título+subtítulo+CTA ocultos por default en la home real,
   aparecen solo al pasar el mouse por el Hero (o al enfocar algo
   adentro con teclado, vía :focus-within) -- pedido explícito: "que
   solo quede la imagen grande". Acotado a "@media (hover: hover)":
   sin mouse (celular/tablet táctil) no hay forma de "pasar el mouse
   por encima", así que ahí se queda con el comportamiento de siempre
   (siempre visible) -- ocultarlo sin una forma de revelarlo dejaría
   el título/botón "Ver juego" inalcanzables en táctil. Acotado además
   a "body.home-page" para no tocar la vista previa del Hero en el
   Dashboard (dashboard-pagina-principal.html), que reutiliza las
   mismas clases .discover-hero-* pero necesita mostrar el texto
   siempre, sin hover, para poder editarlo. */
@media (hover: hover) and (pointer: fine){

    body.home-page .discover-hero-info{
        opacity: 0;
        pointer-events: none;
        /* Mini animación pedida: el cuadro "aparece desde abajo" al
           entrar el mouse, no solo un fundido plano. translateZ(0)
           sumado al desplazamiento real (no solo como hack de capa)
           para que ambos animen sobre la misma transform. */
        transform: translateY(18px) translateZ(0);
        transition: opacity var(--dur-carousel) var(--ease-premium),
                    transform var(--dur-carousel) var(--ease-premium);
        /* El fix anterior solo le puso will-change al ::before (la
           alfombra) -- pero el elemento cuyo opacity en verdad anima es
           ESTE (el padre). Al llegar a opacity:0 el navegador descarta
           toda la capa compuesta del subárbol, blur del hijo incluido,
           sin importar el will-change del hijo -- por eso seguía
           "tardando" al reaparecer. Puesto acá, en el elemento que
           realmente transiciona. */
        will-change: opacity, transform;
    }

    body.home-page .discover-hero-card:hover .discover-hero-info,
    body.home-page .discover-hero-card:focus-within .discover-hero-info{
        opacity: 1;
        pointer-events: auto;
        transform: translateY(0) translateZ(0);
    }

}

/* Indicadores tipo "/" para saltar entre destacados -- única
   navegación visual del carrusel (las flechas laterales se sacaron:
   "rompían la estética del Hero"; queda teclado (flechas del teclado)
   + swipe táctil + estos indicadores, ver goToHeroSlide()/listeners
   en index.html). Centrados abajo en vez de a la derecha. */
.discover-hero-dots{
    position: absolute;
    left: 50%;
    bottom: 34px;
    transform: translateX(-50%);
    z-index: 3;
    display: flex;
    gap: 18px;
}

/* Pedido explícito: glow sutil para que se noten sobre la imagen --
   antes solo el ".active" tenía box-shadow, los inactivos (rgba blanco
   muy tenue) se perdían fácil contra fondos con detalle. Blur chico
   (6px) y alpha bajo a propósito, "no muy potente". */
.discover-hero-dot{
    width: 34px;
    height: 4px;
    border-radius: var(--radius-pill);
    border: none;
    background: rgba(255,255,255,.25);
    box-shadow: 0 0 6px rgba(255,255,255,.35);
    transform: rotate(-25deg);
    cursor: pointer;
    padding: 0;
    transition: .3s ease;
}

.discover-hero-dot:hover{
    background: rgba(255,255,255,.45);
    box-shadow: 0 0 8px rgba(255,255,255,.5);
}

/* Pedido explícito: rojo vino tinto más fuerte que el accent global
   del sitio (--accent-rgb: 150,50,60, bastante apagado) -- valor
   propio, más saturado/profundo, solo para el indicador activo del
   Hero, sin tocar el token compartido por el resto del sitio. */
.discover-hero-dot.active{
    width: 52px;
    background: #8C1030;
    box-shadow: 0 0 18px rgba(140,16,48,.5);
}

/* PÉTALOS DEL HERO — dos capas de profundidad respecto al logo
   del navbar (fixed, z-index:100): "back" queda por detrás,
   "front" pasa por delante. La lógica de ráfagas vive en JS
   (initHeroPetals), esto solo define capas + animación. */
.hero-petals{
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    opacity: 1;
    transition: opacity 1.1s var(--ease-premium);
}

.hero-petals.is-hidden{
    opacity: 0;
}

.hero-petals-back{ z-index: 1; }
.hero-petals-front{ z-index: 120; }

/* Reapertura (pedido explícito): silueta de pétalo real -- antes era
   una hoja/almendra simétrica (mismo punto arriba y abajo, sin notch).
   Ahora: notch sutil arriba (punta redondeada con leve hendidura,
   rasgo distintivo de un pétalo de sakura) + base afilada abajo,
   reutilizando la curva lateral que ya funcionaba bien a tamaños
   chicos. El color pasó de estar quemado dentro del SVG a
   background-color, así JS puede variarlo por instancia (ver
   initMiddlePetals/initFooterPetal en index.html) sin duplicar el
   data-URI. .petal-shape-b y .petal-shape-c (más abajo) son variantes
   de silueta muy similares -- misma lógica de notch+base, curvas
   levemente distintas -- para que no todos los pétalos sean clones
   exactos. Esta regla (sin variante de forma ni color inline) es el
   fallback: forma A + #B84F5F, lo que ven las páginas que todavía no
   eligen variante por JS. Ver .page-petal más abajo (mismo shape). */
.hero-petal, .page-petal{
    position: absolute;
    opacity: 0;
    background-color: #B84F5F;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12,3.2C10.6,1.3 9.4,0.9 9.6,1.9C6.6,4 5,10 6,15C6.8,18.4 9.4,21 12,22C14.6,21 17.2,18.4 18,15C19,10 17.5,4.3 14.7,2.2C15.6,1 13.2,1 12,3.2Z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12,3.2C10.6,1.3 9.4,0.9 9.6,1.9C6.6,4 5,10 6,15C6.8,18.4 9.4,21 12,22C14.6,21 17.2,18.4 18,15C19,10 17.5,4.3 14.7,2.2C15.6,1 13.2,1 12,3.2Z'/%3E%3C/svg%3E");
    will-change: transform, opacity;
}

/* Variantes de silueta (reapertura, pedido explícito: 2-3 formas muy
   similares para que no todos los pétalos sean clones). Se aplican
   sumando la clase a .hero-petal/.page-petal, elegida al azar en JS. */
.petal-shape-b{
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12.4,3.6C10.8,1 8.7,0.7 8.6,2.1C5.9,4.4 4.8,10 6,15.3C6.9,18.6 9.6,21.2 12.2,22.2C14.7,21 17.4,18.2 18.2,15C19.3,9.8 18,4.6 15.4,2.4C16.5,0.9 13.7,0.8 12.4,3.6Z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12.4,3.6C10.8,1 8.7,0.7 8.6,2.1C5.9,4.4 4.8,10 6,15.3C6.9,18.6 9.6,21.2 12.2,22.2C14.7,21 17.4,18.2 18.2,15C19.3,9.8 18,4.6 15.4,2.4C16.5,0.9 13.7,0.8 12.4,3.6Z'/%3E%3C/svg%3E");
}

.petal-shape-c{
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M11.8,2.9C10.7,1.2 9.5,1 9.7,1.7C7,3.7 5.4,9.5 6.4,14.8C7.2,18.2 9.7,20.8 11.6,21.8C14.2,20.6 16.8,17.9 17.7,14.7C18.6,9.7 17.2,4.2 14.6,2C15.4,1 13,0.9 11.8,2.9Z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M11.8,2.9C10.7,1.2 9.5,1 9.7,1.7C7,3.7 5.4,9.5 6.4,14.8C7.2,18.2 9.7,20.8 11.6,21.8C14.2,20.6 16.8,17.9 17.7,14.7C18.6,9.7 17.2,4.2 14.6,2C15.4,1 13,0.9 11.8,2.9Z'/%3E%3C/svg%3E");
}

@keyframes heroPetalFall{
    0%   { transform: translate(0, 0) rotate(var(--rot-start)); opacity: 0; }
    10%  { opacity: var(--petal-opacity); }
    50%  { transform: translate(var(--dx-mid), var(--dy-mid)) rotate(calc((var(--rot-start) + var(--rot-end)) / 2)); }
    88%  { opacity: var(--petal-opacity); }
    100% { transform: translate(var(--dx-end), var(--dy-end)) rotate(var(--rot-end)); opacity: 0; }
}

/* Capa del "viento ocasional" en la ficha de juego / todos los
   juegos: fixed a toda la ventana (no acotada a un hero), reutiliza
   heroPetalWind. NOTA: en index.html (página de inicio) esta capa
   global fue reemplazada por zonas (.hero-petal-zone/.games-petal-zone,
   más abajo) -- .page-petal-layer sigue existiendo tal cual para
   juego.html y todos-los-juegos.html, que no fueron tocadas por este
   cambio. */
.page-petal-layer{
    position: fixed;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    z-index: 40;
}

/* Reapertura (pedido explícito): pétalos por ZONA en vez de globales
   (solo en index.html/página de inicio). Cada wrapper es el elemento
   estático que envuelve una sección dinámica (nunca tocado por el JS
   de esa sección, ver comentarios en index.html) y da el contexto de
   posicionamiento para su propia capa de pétalos -- mismo patrón que
   ya usaba .footer-pro/.footer-petal-layer. overflow:hidden asegura
   que los pétalos de una zona nunca se vean flotando sobre otra
   sección al hacer scroll. */
.hero-petal-zone,
.games-petal-zone{
    position: relative;
    overflow: hidden;
}

.hero-zone-petal-layer,
.games-zone-petal-layer{
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    z-index: 1;
}

@keyframes heroPetalWind{
    0%   { transform: translate(0, 0) rotate(var(--rot-start)); opacity: 0; }
    12%  { opacity: var(--petal-opacity); }
    55%  { transform: translate(var(--dx-mid), var(--dy-mid)) rotate(calc((var(--rot-start) + var(--rot-end)) / 2)); }
    85%  { opacity: var(--petal-opacity); }
    100% { transform: translate(var(--dx-end), var(--dy-end)) rotate(var(--rot-end)); opacity: 0; }
}

/* Reapertura (pedido explícito): microinteracción de golpear pétalos
   con el cursor -- triggerPetalHit() (index.html), al detectar el
   golpe, cancela heroPetalWind y arranca esta animación en su lugar,
   reutilizando las MISMAS 4 custom properties (--rot-start/--rot-end/
   --dx-end/--dy-end) que ya traía el pétalo, solo con valores nuevos
   (punto de partida = donde lo agarró el hit-test, destino = impulso
   calculado a partir de la velocidad/dirección del mouse). La curva
   fuerte de salida (ver "cubic-bezier(.16,1,.3,1)" en el JS, no acá)
   da el arranque rápido + desaceleración; acá solo se define que la
   opacidad se mantiene hasta 35% y después cae a 0 -- así se ve
   sólido durante el impulso y se desvanece hacia el final, sin volver
   a sortear opacidad (usa la que ya tenía el pétalo). */
@keyframes petalImpact{
    0%   { transform: translate(0, 0) rotate(var(--rot-start)); opacity: var(--petal-opacity); }
    35%  { opacity: var(--petal-opacity); }
    100% { transform: translate(var(--dx-end), var(--dy-end)) rotate(var(--rot-end)); opacity: 0; }
}

/* Reapertura (pedido explícito): capa position:fixed al viewport (no a
   una sección) donde initScrollPetals() (index.html) hace cruzar
   pétalos sin importar en qué parte del scroll esté el usuario --
   misma mecánica de spawn/animación (heroPetalWind) que las zonas de
   hero/juegos/footer, reutiliza .hero-petal como clase de los pétalos.
   z-index por debajo del navbar (100) pero por encima del contenido
   normal. */
.scroll-petal-layer{
    position: fixed;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    z-index: 90;
}

@media (max-width: 900px){

    /* Reapertura (bug real, probado en celular): con el alto atado a
       calc(100vh - 78px) (o 78vh acá), el recuadro queda MUY alto y
       angosto en una pantalla de teléfono (ej. ~350x660) -- object-fit:
       cover recorta casi todo el ancho de la imagen para llenar ese
       alto, dejando solo una tira vertical central, muy recortada. Se
       pasa a aspect-ratio (ancho manda, como .trend-main) para que el
       recuadro escale con el ancho real de la pantalla, no con su alto.
       SIN min-height acá a propósito -- combinado con aspect-ratio y
       width:auto es justo lo que causaba el bug real encontrado
       después ("se come la derecha"): cuando el alto que pide el
       aspect-ratio (ancho_real × 9/16) queda por debajo del mínimo, el
       navegador prioriza cumplir el aspect-ratio usando el ALTO ya
       forzado por min-height y en cambio agranda el ANCHO más allá del
       contenedor para sostener la proporción -- la caja terminaba 38px
       más ancha que la pantalla y ese sobrante se recortaba en el
       borde derecho. 3:2 (más alta que 16:9) evita necesitar un mínimo:
       ya da lugar de sobra para título+descripción+botón sin ese
       conflicto. */
    .discover-hero-card{
        height: auto;
        aspect-ratio: 3 / 2;
        /* min-height:0 -- sin esto, el min-height:560px de escritorio
           (regla base, nunca pensada para acá) seguía aplicando y
           volvía a disparar el mismo bug de "ancho se agranda para
           sostener el aspect-ratio", esta vez con el 560px de
           escritorio en vez del 220px que yo mismo había puesto antes. */
        min-height: 0;
    }

    .discover-hero-info{
        left: 24px;
        right: 24px;
        bottom: 20px;
        max-width: none;
    }

    /* Reapertura (pedido explícito: "el titulo el subtitulo y mas aun
       el boton de ver juego mas pequeños para que no agobie tanto en
       android") -- la tarjeta 3:2 es baja (~235px en un teléfono
       angosto), así que título+descripción+botón al mismo tamaño que
       antes ocupaban demasiada proporción del recuadro. Reducidos otra
       vez, solo acá (max-width:900px), sin tocar la versión de
       escritorio (1.35rem/.96rem/.85rem respectivamente). */
    .discover-hero-info h1{ font-size: .85rem; }

    /* Reapertura (pedido explícito -- "no muestra la descripción"): con
       3:2 (más alta que el 16:9 original) ya entra un resumen corto
       sin pisar el botón "Ver juego" -- recortada a 2 líneas (mismo
       recurso que .trend-side h3) para no comerse el alto disponible
       si el texto es largo. */
    .discover-hero-desc{
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
        font-size: .74rem;
        max-width: none;
        /* Sin esto seguía mostrando 4 líneas pese al clamp:2 -- el
           min-height:6.2em de escritorio (reservado ahí para 4 líneas)
           no se resetea solo, y el modelo legacy de -webkit-line-clamp
           termina mostrando tantas líneas como el alto reservado
           permita, no exactamente el número del clamp. 2.2em ≈ 2
           líneas a este line-height (1.55, heredado) con el font-size
           más chico de acá. */
        min-height: 2.2em;
    }

    .discover-hero-cta{
        height: 32px;
        padding: 0 18px;
        font-size: .72rem;
        border-radius: 10px;
    }

    /* Reapertura (bug real, pedido explícito: "aun se corta lo de
       abajo" + "las barras de desplazamiento... un poquito mas
       pequeñas"): los indicadores (.discover-hero-dot) están rotados
       -25deg, así que su caja real ocupa más alto que su height:4px
       nominal (una barra de 34px rotada sobresale ~7px por encima Y
       por debajo de su propio centro). Con bottom:8px en una tarjeta
       de solo ~235px de alto, ese sobrante rozaba/pisaba el borde
       inferior real de la tarjeta -- .discover-hero-card tiene
       overflow:hidden, así que la punta del indicador activo (el más
       ancho, 52px) quedaba recortada ahí: eso es lo que se veía como
       "se corta de abajo". Se corrige en dos frentes: los indicadores
       más chicos en Android (menos sobresaliente al rotar) Y más
       margen desde el borde (8px -> 12px). */
    .discover-hero-dots{ left: 50%; right: auto; bottom: 12px; transform: translateX(-50%); gap: 12px; }

    .discover-hero-dot{ width: 22px; height: 3px; }

    .discover-hero-dot.active{ width: 34px; }
}

/* Reapertura (pedido explícito, probado en celular real): antes acá
   solo se ocultaba <nav> por completo, sin ningún reemplazo -- ahora
   se reposiciona como panel plegable (mismo <nav>, mismos links,
   ninguno nuevo) que .navbar-hamburger abre/cierra (ver
   navbar-mobile.js). Mismo criterio para el buscador: en vez de
   ocultarlo sin más (regla ya existente en .navbar-search, arriba,
   @media max-width:980px), .navbar-search-toggle lo abre como fila
   propia debajo del navbar. Bloque puesto acá (al final del archivo,
   no junto al resto de reglas de .navbar) a propósito -- necesita
   ganarle en el cascade a .logo-full/.login-btn/etc, definidas mucho
   más arriba; puesto antes, esas reglas base (sin @media) le ganaban
   por orden de aparición pese a que la media query sí matcheaba
   (bug real, encontrado probando en celular). */
@media (max-width: 760px){

    .navbar{ padding: 0 16px; }

    .logo-container{ margin-left: 0; }
    .logo-full{ height: 40px; }

    .navbar-right{ gap: 10px; }

    .navbar-search-toggle,
    .navbar-hamburger{ display: flex; }

    /* Login compacto -- "Iniciar sesión" con su padding/tamaño de
       escritorio no entra junto al resto (logo+buscador+campana+
       hamburguesa) en un ancho de celular. */
    .login-btn{
        padding: 0 12px;
        font-size: 11px;
        gap: 4px;
    }

    .navbar nav{
        display: none;
        position: fixed;
        top: 78px;
        left: 0;
        right: 0;
        flex-direction: column;
        align-items: stretch;
        gap: 2px;
        padding: 10px 16px 18px;
        background: rgba(10,10,10,.97);
        backdrop-filter: blur(20px);
        -webkit-backdrop-filter: blur(20px);
        border-bottom: 1px solid rgba(255,255,255,.12);
        z-index: 98;
    }

    .navbar nav.is-open{ display: flex; }

    .navbar nav a{
        padding: 12px 4px;
        font-size: 15px;
    }

    .navbar-search{
        display: none;
        position: fixed;
        top: 78px;
        left: 0;
        right: 0;
        width: auto;
        height: auto;
        margin: 0;
        padding: 12px 16px;
        border-radius: 0;
        border: none;
        border-bottom: 1px solid rgba(255,255,255,.12);
        background: rgba(10,10,10,.97);
        backdrop-filter: blur(20px);
        -webkit-backdrop-filter: blur(20px);
        z-index: 98;
    }

    .navbar-search.is-open{ display: flex; }

    /* :focus-within de escritorio (más arriba) aclara el fondo al
       enfocar -- acá el input se enfoca solo al abrir (ver
       navbar-mobile.js), así que sin esto el panel quedaba casi
       transparente apenas se abría. */
    .navbar-search.is-open:focus-within{
        background: rgba(10,10,10,.97);
        border-color: transparent;
    }

    .navbar-search input{
        flex: 1;
        width: auto;
        font-size: 15px;
    }

    /* Reapertura (pedido explícito, bug real probado en celular
       logueado como Owner): .nav-auth-slot reserva 195px fijos para
       que el ancho no salte entre "Iniciar sesión" (más ancho) y el
       avatar (más angosto) -- pensado para escritorio, donde sobra
       espacio de sobra. En un navbar mobile ya ajustado al límite,
       esos 195px reservados de más eran justo lo que empujaba la
       hamburguesa fuera de pantalla. Acá el salto entre estados no
       importa (recién se ve una vez, al cargar la página). */
    .nav-auth-slot{ min-width: 0; }

    .nav-bell-slot{ width: 34px; height: 34px; }

    /* Reapertura (bug real, probado en celular): .nav-bell-slot de
       arriba solo achica el CONTENEDOR -- el botón real de la campana
       (notifications-bell.js) tiene su propio tamaño fijo de 42px,
       que no depende del contenedor y por eso se seguía viendo más
       grande que el resto (avatar/hamburguesa/lupa, todos en 34-36px),
       "desfasado" con el resto de la fila. */
    .notif-bell-trigger{ width: 34px; height: 34px; }
    .notif-bell-trigger svg{ width: 16px; height: 16px; }

    .nav-user-menu{ gap: 6px; }

    .nav-user-trigger,
    .nav-user-avatar{ width: 34px; height: 34px; }

    #navUserTag{
        font-size: 10px;
        padding: 2px 8px;
    }
}

/* Reapertura (corrección posterior, pedido explícito -- "hubo una
   confusión, quiero algo como en la biblioteca, o sea todo en
   vertical no horizontal"): en mobile, "Todos los juegos" (vista
   previa de Inicio) pasa de grilla de 3 columnas a UNA sola columna
   vertical (una tarjeta por fila, ancho completo) -- mismo criterio
   que .games-catalog-grid en la Biblioteca, no un carrusel horizontal
   (esa idea se descartó). Mismo criterio para "Recomendados": sin su
   subtítulo (ver .section-title p más abajo), el título dispone de
   todo el ancho para no partirse en 3 líneas. */
@media (max-width: 760px){

    #catalogPreview{
        grid-template-columns: 1fr;
    }

    /* Sin el subtítulo ("Explora nuestro catálogo..."/"Traducciones
       que queremos destacar"), el título usa todo el ancho disponible
       y ya no se parte en 2-3 líneas cortas. */
    .catalog-preview-section .section-title p,
    .recommendations-section .section-title p{
        display: none;
    }

    /* "Ver todos los juegos" (link corto al lado del título) quedaba
       partido en 4 líneas angostas sin el subtítulo que antes lo
       empujaba -- redundante en mobile de todas formas (ya está en la
       hamburguesa y como botón debajo de "Todos los juegos"). */
    .recommendations-section .view-all-link{
        display: none;
    }
}

/* =========================================================
   EN TENDENCIA — panel estilo "Steam Featured", sin precio ni
   reseñas: imagen grande + info + miniaturas (hover cambia la
   imagen) + flechas para pasar a otro destacado.
========================================================= */

/* Título y panel comparten el MISMO .container (y por lo tanto el
   mismo ancho/borde) -- antes .trend-wrapper tenía su propio
   max-width+margin:auto anidado DENTRO de un .container ya centrado,
   un doble centrado que dejaba el panel más metido hacia adentro que
   el título (pedido explícito: alinear "En tendencia" con el borde de
   la imagen grande).
   Reapertura (pedido explícito, referencia visual: "el carrusel llega
   casi de borde a borde, quiero un margen lateral EXTERIOR de ~5-6%
   del ancho de la pantalla, como en Steam"): el .container base
   (min(1320px, calc(100% - 44px)), arriba en el archivo) deja un
   margen fijo de 44px total -- a un ancho de ventana típico (~1366px,
   donde el tope de 1320px ya está en juego) eso son ~23px por lado,
   ~1.7%, ahí es donde se veía "pegado". Este override cambia SOLO esta
   sección a un margen porcentual (10% de hueco total = 5% por lado),
   sin tocar el .container base (que sigue afectando a todo el resto
   del sitio) ni agregar padding interno a .trend-panel -- el hueco
   queda afuera del carrusel, entre el bloque y el borde de la página,
   igual en el título (mismo .container) y en el panel. */
/* Reapertura (pedido explícito, "un poquito menos horizontal, compite
   con el Hero, pero no demasiado") -- venía de 90% (5% de margen por
   lado). Achicado a 86% (7% por lado) -- un ajuste chico, no un
   volantazo. */
.trend-section .container{
    width: min(1320px, 86%);
    margin: 0 auto;
}

.trend-section .section-title{
    margin-bottom: 20px;
}

/* Pedido explícito: hueco muy grande entre "En tendencia" y "Todos
   los juegos" -- .section (base, sitewide) pone padding:84px 0 y solo
   se anula el top (42px) globalmente, así que el bottom de 84px queda
   sumado al padding-top:42px de la sección siguiente (126px en total).
   Se acota acá, solo para esta sección (no se toca el .section base,
   que afecta a todo el sitio) -- mismo criterio para
   .catalog-preview-section más abajo. */
.trend-section{
    padding-bottom: 32px;
}

.trend-wrapper{
    position: relative;
    display: flex;
    align-items: stretch;
    gap: 18px;
}

.trend-panel{
    flex: 1;
    display: grid;
    /* Reapertura (pedido explícito, comparado contra la referencia de
       Steam): la columna de info era un ancho FIJO (340px, después
       300px) -- a 1320px de contenedor eso es solo ~22-23% (imagen
       ~77-78%), muy lejos del ~70/30 de la referencia, y ese ancho fijo
       significa además que el % real cambiaba solo con el viewport, sin
       control. Pasa a fracciones (7fr/3fr): ~70/30 SIEMPRE, sea cual
       sea el ancho real del contenedor. Sin minmax(0,...) en cada
       columna, el contenido (imagen/texto) podría forzar un track más
       ancho de lo debido -- salvaguarda ya usada acá antes, se
       mantiene igual con fr en vez de un valor fijo. */
    grid-template-columns: minmax(0,7fr) minmax(0,3fr);
    /* Reapertura (pedido explícito, "eliminar el marco -- la imagen
       debe quedar directamente sobre el fondo de la sección, como en
       Steam"): esto tuvo padding/background/border/box-shadow propios
       (una ronda anterior, "aire alrededor del contenido") -- se
       revierte todo eso acá. Sin padding, .trend-main/.trend-side
       vuelven a llenar el 100% de esta caja; sin background/border/
       box-shadow, no queda ningún rectángulo visible detrás, solo el
       fondo real de la sección (index.html no le pone nada a
       #homeTrendingPanels). border-radius + overflow:hidden SÍ se
       mantienen -- son las esquinas EXTERIORES del carrusel completo
       (imagen+panel como un solo bloque), no un marco.
       Reapertura (pedido explícito, "todo cuadrado, nada de bordes
       redondeados") -- venía de 20px. overflow:hidden se mantiene
       (sigue conteniendo la imagen dentro de los límites del bloque),
       solo cambia el radio. */
    border-radius: 0;
    overflow: hidden;
    /* Reapertura (pedido explícito, "reducir casi a cero el espacio
       entre imagen y panel, el punto más importante"): venía de 18px. */
    column-gap: 0;
    /* Reapertura (bug real reportado, "probando varias imágenes ya no
       se mantiene el mismo tamaño"): esto era min-height, no height --
       la fila (una sola, implícita, de este grid) crecía según el
       contenido más alto de .trend-side, que varía con el largo del
       título de cada juego (1 línea vs 2). Como .trend-main img es
       height:100% de su celda, la imagen grande cambiaba de tamaño
       según qué juego estuviera activo. Fija de verdad -- el título
       gana line-clamp:2 más abajo para no poder forzarla a crecer.
       Reapertura (pedido explícito, "el cuadro en general mucho más
       grande") -- venía de 460px, después 560px.
       Reapertura (pedido explícito, "quítale un poco de altura a la
       imagen grande para darle protagonismo a las miniaturas") -- baja
       un poco desde 560px. */
    height: 500px;
    /* Más profundidad/animación (pedido explícito): leve elevación al
       pasar el mouse, no solo un panel estático. Sin box-shadow propio
       (revertido arriba), el hover ya no tiene sombra que agrandar --
       solo queda la elevación. */
    transition: transform var(--dur-base) ease;
}

.trend-panel:hover{
    transform: translateY(-6px);
}

.trend-main{
    position: relative;
    overflow: hidden;
}

/* Reapertura (pedido explícito): mientras no se elija una imagen a
   mano (miniatura o subida propia), no hay respaldo automático a la
   portada del juego -- se muestra este aviso en su lugar, tanto acá
   como en el editor del Dashboard (mismo componente .trend-panel),
   para evitar que quede una imagen vieja o no elegida publicada sin
   querer. */
.trend-main-empty{
    display: none;
    position: absolute;
    inset: 0;
    align-items: center;
    justify-content: center;
    color: var(--text-dim, rgba(255,255,255,.4));
    font-size: .95rem;
    background: var(--bg-2);
}

.trend-main.is-image-empty img{
    visibility: hidden;
}

.trend-main.is-image-empty .trend-main-empty{
    display: flex;
}

.trend-main img{
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    /* Reapertura (pedido explícito, "baja la calidad y en fullscreen
       se ve bien"): la imagen fuente ya es 1920x1079 -- de sobra para
       el tamaño mostrado acá, no hay upscaling real. Lo que se percibía
       como "menor calidad" era este filter oscureciendo/aumentando
       contraste (brightness .86 = 14% más oscura) -- trendFullscreen
       (index.html) pinta el mismo <img> SIN filtro, de ahí la
       diferencia. Se saca para que ambas vistas se vean igual. */
    transition: opacity var(--dur-carousel) var(--ease-premium);
    /* Pedido explícito: se puede cliquear para agrandar (ver
       trendFullscreen en index.html) -- mismo cursor que
       .showcase-main img en juego.html para el mismo gesto. */
    cursor: zoom-in;
}

/* Fundido puro al cambiar de juego -- sin transform acá, a propósito:
   pisaría el "respirar" de abajo (mismo criterio que .discover-hero-
   media img). */
.trend-main.is-fading img{
    opacity: .35;
}

/* Respiración muy sutil (mismo recurso que el Hero) -- pedido
   explícito de "más animación". Sin duración atada a ningún carrusel
   automático (Tendencia no rota sola): un ciclo largo y constante. */
@media (prefers-reduced-motion: no-preference){
    .trend-main img{
        animation: trendImageBreathe 9s ease-in-out infinite alternate;
    }
}

@keyframes trendImageBreathe{
    from{ transform: scale(1); }
    to{ transform: scale(1.045); }
}

.trend-side{
    display: flex;
    flex-direction: column;
    /* Reapertura (pedido explícito, "el título junto con los géneros
       cerca del borde de arriba") -- venía centrado, con el panel ahora
       de altura fija (460px, ver .trend-panel) dejaba un hueco arriba
       visible cuando el contenido no llenaba todo el alto. */
    justify-content: flex-start;
    /* Reapertura (pedido explícito, "corregir el espacio alrededor de
       las miniaturas/panel", rango pedido "gap y separación interna")
       -- venía de 16px. Se achica lo justo para que título+tags+
       miniaturas+botón sigan entrando en el alto disponible (ver
       cuenta abajo), ya que .trend-panel ahora resta su propio padding
       antes de llegar acá. */
    gap: 10px;
    /* Reapertura (pedido explícito, "20-24px vertical, 24-28px
       horizontal") -- venía de 26px 30px. Con .trend-panel restando
       16px arriba/abajo (padding nuevo), el alto disponible acá pasa
       de 500px a 468px; con este padding entran cómodos título (2
       líneas, line-clamp) + tags + las 2 filas de miniaturas (130px,
       sin tocar) + botón, con margen de sobra. */
    padding: 20px 24px;
    /* Este fondo NO es "el marco" (eso era .trend-panel, revertido
       arriba) -- es el fondo propio del panel de info, necesario para
       que el texto se lea (mismo criterio que el panel derecho de la
       referencia de Steam, que también tiene su propio fondo sólido).
       Se mantiene igual. */
    background: linear-gradient(to bottom, rgba(12,12,12,.97), rgba(8,8,8,.99));
    /* Reapertura (pedido explícito, "reducir el gap a 0"): con
       column-gap:0 en .trend-panel, este panel vuelve a tocar la
       imagen directamente en el medio -- un border-radius propio acá
       redondearía también esa esquina interior (contra la imagen),
       viéndose como una muesca justo donde el gap debería ser 0. Las
       esquinas EXTERIORES (arriba/abajo a la derecha) ya las resuelve
       overflow:hidden + border-radius de .trend-panel. */
    transition: opacity var(--dur-carousel) var(--ease-premium),
                transform var(--dur-carousel) var(--ease-premium);
}

.trend-side.is-fading{
    opacity: 0;
    transform: translateY(12px);
}

/* Reapertura (pedido explícito): la etiqueta "En tendencia" acá adentro
   era redundante con el título de la SECCIÓN entera (arriba del todo)
   -- se sacó del template (index.html y su espejo en dashboard-pagina-
   principal.html), así que .trend-status queda sin ningún uso; se
   borra en vez de dejarla muerta. */

.trend-side h3{
    /* Más chico (pedido explícito, dos rondas: venía de 1.5rem, después
       1.35rem). Ahora es lo primero del panel (ya no debajo de la
       etiqueta). */
    font-size: 1.2rem;
    font-weight: 700;
    margin: 0;
    line-height: 1.15;
    color: #f5f5f5;
    /* Tope de 2 líneas (mismo criterio que .card-content h3) -- ahora
       que .trend-panel tiene height fijo (arriba), un título de 3+
       líneas ya no puede desbordar la caja: se recorta con "...". */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* 2x2 (venía siendo una fila horizontal de 4) -- referencia de Steam:
   menos ancho ocupado, mismo criterio que el resto de .trend-side.
   Alto de cada miniatura subido (54px->78px) para no quedar demasiado
   achatada ahora que cada una es más ancha (2 columnas en vez de 4). */
.trend-shots{
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
}

.trend-shots img{
    width: 100%;
    /* Reapertura (pedido explícito, "les falta protagonismo, quiero
       las proporciones de la referencia [Steam]") -- venía de 78px,
       después 92px, después 116px, después 130px.
       Reapertura (pedido explícito, "un poquito menos verticales, un
       poquito más horizontales") -- con el ancho de columna real
       (~148px), 130px de alto se sentía casi cuadrado/vertical; baja
       un poco para leerse más horizontal sin tocar el ancho. */
    height: 112px;
    object-fit: cover;
    border-radius: 8px;
    cursor: pointer;
    opacity: .55;
    border: 1px solid transparent;
    transition: opacity var(--dur-fast) ease, border-color var(--dur-fast) ease;
}

.trend-shots img:hover{
    opacity: .85;
}

.trend-shots img.active{
    opacity: 1;
    /* Pedido explícito: mismo cerezo de sangre que el borde de las
       cards del catálogo (rgb(150,50,60)), no dorado. */
    border-color: rgba(150,50,60,.95);
}

.trend-desc{
    font-size: .88rem;
    line-height: 1.5;
    color: rgba(255,255,255,.75);
    margin: 0;
}

.trend-tags{
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.trend-tags span{
    /* Reapertura (pedido explícito, "los géneros de ese lugar que estén
       en azul") -- mismo azul que .trend-cta/.discover-hero-cta
       (#569cd2/#76afdb), como badge translúcido en vez de sólido. */
    background: rgba(86,156,210,.14);
    border: 1px solid rgba(86,156,210,.4);
    padding: 5px 11px;
    border-radius: var(--radius-pill);
    font-size: .72rem;
    color: #9cc7e8;
}

.trend-cta{
    height: 46px;
    padding: 0 24px;
    font-size: .88rem;
    align-self: flex-start;
    /* Reapertura (pedido explícito, "el botón más abajo") -- .trend-side
       es flex-column con justify-content:flex-start (título/tags/
       miniaturas quedan arriba, pedido explícito de una ronda
       anterior), así que sobraba aire abajo sin usar. margin-top:auto
       empuja SOLO el botón a pegarse contra el borde inferior del
       panel, ocupando ese espacio suelto -- el resto del contenido no
       se mueve de arriba. */
    margin-top: auto;
    /* Reapertura (pedido explícito, "menos puntiagudo, más cuadrado")
       -- venía de 14px (heredado de .discover-hero-cta, Hero, sin
       tocar). El color de fondo ya no se pisa acá: pasó a la regla
       base de .discover-hero-cta (pedido explícito, "también en el
       Hero este botón de ese color"), así que Hero y En tendencia
       comparten el mismo azul sin duplicar la declaración. */
    border-radius: 8px;
}

/* Reapertura (bug real reportado, "el título debe ir alineado con la
   imagen grande, no full izquierda"): antes eran flex siblings de
   .trend-panel dentro de .trend-wrapper -- la flecha izquierda (38px +
   18px de gap) le comía ancho al panel desde la izquierda, así que la
   imagen empezaba ~56px más adentro que el título de arriba (que usa
   el mismo .container, pero no pasa por .trend-wrapper). Position
   absolute -- salen del flujo, .trend-panel pasa a ocupar el 100% de
   .trend-wrapper (mismo ancho que el título) y las flechas quedan
   flotando SOBRE los bordes de la imagen (no la recortan: son
   hermanas de .trend-panel, no hijas -- su overflow:hidden no las
   afecta). Fondo semitransparente nuevo: sin eso, sobre una imagen
   clara se veían casi invisibles (antes flotaban sobre el fondo
   sólido de la página). */
/* Reapertura (pedido explícito, "sacar las flechas fuera de la
   imagen, a cada lado del carrusel, como en Steam"): seguían siendo
   position:absolute (eso se conserva, no vuelven al flex) pero
   overlaid ENCIMA de la imagen (left/right:16px, hacia adentro). Ahora
   van hacia AFUERA del bloque (valores negativos, hacia el margen
   exterior de la sección -- .trend-section .container ya deja ~5% de
   aire a cada lado, ver arriba en el archivo, así que hay lugar real
   ahí para que floten sin pisar contenido de al lado ni recortarse:
   siguen siendo hermanas de .trend-panel, no hijas, así que su
   overflow:hidden no las afecta). El fondo semitransparente que tenían
   (para leerse sobre CUALQUIER imagen de fondo) ya no hace falta --
   ahora están sobre el fondo liso de la página, se revierte a
   transparente como el diseño original. */
.trend-nav{
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 5;
    width: 38px;
    height: 38px;
    border-radius: var(--radius-circle);
    border: 1px solid rgba(255,255,255,.14);
    background: transparent;
    color: rgba(255,255,255,.7);
    font-size: 16px;
    cursor: pointer;
    transition: border-color var(--dur-base) ease, color var(--dur-base) ease, transform var(--dur-base) ease, background var(--dur-base) ease;
}

/* Reapertura (pedido explícito, "quedaron un poquito pegadas") --
   venía de -40px. */
.trend-nav[data-trend-dir="-1"]{ left: -56px; }
.trend-nav[data-trend-dir="1"]{ right: -56px; }

.trend-nav:hover{
    background: rgba(255,179,0,.08);
    border-color: rgba(255,179,0,.5);
    color: #ffb300;
    /* translateY(-50%) se repite acá a propósito -- si solo pusiera
       scale(), pisaría el centrado vertical de la regla base y el
       botón saltaría hacia abajo al pasar el mouse. */
    transform: translateY(-50%) scale(1.08);
}

/* Indicadores debajo del panel -- para saber cuál está activo cuando
   hay más de un juego en Tendencia, además de las flechas. Dorado a
   propósito (pedido explícito: "no en blanco"), mismo tono que el
   resto de acentos del sitio (#ffb300). */
.trend-dots{
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-top: 18px;
}

.trend-dot{
    width: 26px;
    height: 4px;
    border-radius: var(--radius-pill);
    border: none;
    background: rgba(255,179,0,.25);
    cursor: pointer;
    padding: 0;
    transition: .3s ease;
}

.trend-dot:hover{
    background: rgba(255,179,0,.5);
}

.trend-dot.active{
    width: 40px;
    background: #ffb300;
    box-shadow: 0 0 14px rgba(255,179,0,.4);
}

@media (max-width: 900px){

    .trend-panel{
        grid-template-columns: 1fr;
        /* Reapertura: la regla de escritorio pasó de min-height a height
           fija (arriba) -- acá había que anular "min-height", ahora hay
           que anular "height" para que el panel siga apilando imagen +
           info sin forzar los 460px del desktop en una sola columna. */
        height: auto;
    }

    .trend-main{ height: 220px; }
    .trend-nav{ display: none; }
}

/* =========================================================
   TODOS LOS JUEGOS — misma tarjeta, pero con más imagen y
   menos texto: se quitó la versión y se muestra el creador.
========================================================= */

.card-creator{
    color: #8a8a8a;
    font-size: .82rem;
    margin: 2px 0 0;

    /* Pedido explícito: una sola línea, recortada con "..." si el
       nombre es largo -- ayuda a mantener el bloque inferior compacto,
       mismo criterio que el line-clamp del título (arriba). */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.catalog-preview-section .container{
    width: min(1260px, calc(100% - 90px));
}

/* Reapertura (pedido explícito): "el título un poco más abajo, para
   que se pegue más con las fotos" -- el título compartía el
   margin-bottom:45px de base (.section-title, arriba) con Hero/En
   tendencia/Recomendados; se achica SOLO acá, sin tocar esa regla
   general (mismo criterio ya usado para .trend-section .section-title
   y .section-header .section-title). */
.catalog-preview-section .section-title{
    margin-bottom: 26px;
}

/* Pedido explícito: mismo motivo que .trend-section (arriba) -- hueco
   grande entre el final de "Todos los juegos" y "Recomendados". */
.catalog-preview-section{
    padding-bottom: 32px;
}

/* =========================================================
   RECOMENDADOS — tarjeta con ranking visual, sin comparar
   estadísticas: el número es solo jerarquía de curaduría.
========================================================= */

.recommend-card{
    position: relative;
}

/* Sin ranking ni badges: la tarjeta solo muestra imagen, título,
   creador y etiquetas (pedido explícito, "nada más"). */

@media (max-width: 1000px){
    .recommend-card{
        flex-basis: calc((100% - 24px) / 2);
    }
}

@media (max-width: 640px){
    .recommend-card{
        flex-basis: 100%;
    }

    .recommend-wrapper{
        padding: 0 8px;
    }
}

/* =========================================================
   GALERÍA ESTILO STEAM (juego.html)
   Imagen grande + tira de miniaturas + flechas finas,
   con los colores e identidad de Inari Okami.
========================================================= */

.showcase-main{
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    /* Antes 480px -- junto con el sidebar más ancho (.game-main-layout),
       la imagen principal quedaba demasiado grande en proporción al
       resto de la ficha (pedido explícito). */
    max-height: 400px;
    border-radius: var(--radius-card);
    overflow: hidden;
    background: #0c0c0c;
    border: 1px solid rgba(255,255,255,.06);
}

.showcase-main img{
    /* Sin cambios de TAMAÑO/POSICIÓN de la caja (pedido explícito):
       sigue siendo position:absolute + inset:0 sobre .showcase-main
       (ya position:relative). Corrección posterior: ya no hay una
       segunda capa -- antes acá vivía además la transición de opacity
       del cross-fade (#showcaseImage + overlay #showcaseImageNext). Se
       sacó por completo junto con esa segunda capa: un único <img>,
       cambio de src directo, sin ninguna animación de opacidad que
       pueda dejar dos imágenes visibles a la vez, ni una fracción de
       segundo (ver paintShowcase() en juego.html).

       Reapertura definitiva (pedido explícito, varias vueltas antes):
       la imagen debe llenar SIEMPRE la caja, sin fondos ni contenedores
       auxiliares -- cover, sin JS de por medio. Recorta lo mínimo
       necesario para llenar ambas dimensiones, nunca deforma. La caja
       (.showcase-main: aspect-ratio 16/9, max-height 400px) no cambia
       -- solo cómo se encuadra la imagen adentro.

       Reapertura (pedido explícito): se probó "object-fit: contain"
       para reducir el recorte en imágenes no-16:9 (cuadradas,
       verticales), pero el resultado (barras negras a los costados)
       se vio peor que el recorte original -- revertido a "cover" a
       propósito, no un descuido. */
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    cursor: zoom-in;
}

.showcase-arrow{
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 3;
    /* Antes 46px -- reducidas en proporción a la imagen principal, ya
       más chica (.showcase-main). */
    width: 42px;
    height: 42px;
    border-radius: var(--radius-circle);
    border: 1px solid rgba(255,255,255,.14);
    background: rgba(10,10,10,.55);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    color: white;
    font-size: 16px;
    cursor: pointer;
    opacity: 0;
    transition: opacity .25s ease, background var(--dur-base) ease, border-color var(--dur-base) ease, transform var(--dur-base) ease;
}

.showcase-main:hover .showcase-arrow{
    opacity: 1;
}

.showcase-arrow:hover{
    background: rgba(255,179,0,.2);
    border-color: rgba(255,179,0,.4);
    transform: translateY(-50%) scale(1.06);
}

.showcase-arrow.left{ left: 16px; }
.showcase-arrow.right{ right: 16px; }

.showcase-fullscreen{
    position: absolute;
    top: 14px;
    right: 14px;
    z-index: 3;
    width: 38px;
    height: 38px;
    border-radius: 10px;
    border: 1px solid rgba(255,255,255,.14);
    background: rgba(10,10,10,.55);
    backdrop-filter: blur(8px);
    color: white;
    font-size: 16px;
    cursor: pointer;
    opacity: 0;
    transition: opacity .25s ease, background var(--dur-base) ease;
}

.showcase-main:hover .showcase-fullscreen{
    opacity: 1;
}

.showcase-fullscreen:hover{
    background: rgba(255,179,0,.2);
}

/* Sprint 21 -- envuelve .showcase-thumbs para poder overlayear las
   flechas de navegación de la tira (.showcase-thumb-arrow) encima,
   mismo criterio que .showcase-main con sus propias flechas. Antes la
   tira ya soportaba scroll horizontal (overflow-x:auto) pero con la
   scrollbar oculta y sin ninguna pista visual de que hubiera más
   miniaturas -- con 5+ imágenes, nada indicaba que se podía llegar a
   ellas. */
.showcase-thumbs-row{
    position: relative;
}

.showcase-thumbs{
    display: flex;
    gap: 10px;
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: 2px;
    scroll-behavior: smooth;
}

/* Mismo lenguaje visual que .showcase-arrow (círculo semitransparente
   con blur), pero más chico y siempre visible cuando hace falta --
   a diferencia de .showcase-arrow, que solo aparece al hacer hover
   sobre la imagen principal, estas flechas viven sobre una tira
   angosta donde ese hover es menos descubrible. */
.showcase-thumb-arrow{
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 3;
    width: 32px;
    height: 32px;
    border-radius: var(--radius-circle);
    border: 1px solid rgba(255,255,255,.14);
    background: rgba(10,10,10,.75);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    color: white;
    font-size: 13px;
    cursor: pointer;
    transition: background var(--dur-base) ease, border-color var(--dur-base) ease, transform var(--dur-base) ease;
}

.showcase-thumb-arrow:hover{
    background: rgba(255,179,0,.25);
    border-color: rgba(255,179,0,.4);
    transform: translateY(-50%) scale(1.06);
}

.showcase-thumb-arrow.left{ left: 4px; }
.showcase-thumb-arrow.right{ right: 4px; }

.showcase-thumbs::-webkit-scrollbar{
    display: none;
}

.showcase-thumb{
    flex-shrink: 0;
    /* Antes 150x85 -- +~17% de alto (pedido explícito), ancho escalado
       en la misma proporción para no deformar las miniaturas.
       Corrección posterior: 176px de ancho quedaba un poco grande --
       se achica solo el ancho (pedido explícito "de manera
       horizontal"), el alto no cambia. object-fit:cover en la imagen
       de adentro absorbe el nuevo recorte sin deformarla. */
    width: 152px;
    height: 100px;
    padding: 0;
    border-radius: 10px;
    overflow: hidden;
    border: 2px solid transparent;
    cursor: pointer;
    /* Corrección posterior (pedido explícito): las miniaturas NO
       seleccionadas se veían "apagadas"/deshabilitadas -- opacity:.55
       de base, .85 en hover, recién 1 al estar activa. Ahora todas
       quedan siempre a opacity:1 (luminosidad normal); la única que se
       distingue es la activa, por su border-color (abajo). El hover
       usa un scale sutil en vez de tocar brillo/opacidad, para que
       ninguna miniatura se perciba nunca oscurecida.
       Sin logic de "apagado" es un realce puramente sutil (transform),
       nunca un efecto de deshabilitado. */
    transition: transform var(--dur-fast) ease, border-color var(--dur-fast) ease;
}

.showcase-thumb img{
    width: 100%;
    height: 100%;
    /* Reapertura definitiva (pedido explícito): la miniatura llena
       siempre su caja fija (152x100px, sin cambios de tamaño/diseño)
       -- cover, sin fondos ni contenedores auxiliares. */
    object-fit: cover;
    display: block;
}

.showcase-thumb:hover{
    transform: scale(1.04);
}

.showcase-thumb.active{
    border-color: rgba(var(--accent-rgb),.95);
}

@media (max-width: 760px){
    .showcase-thumb{
        width: 84px;
        height: 48px;
    }
}

/* =========================================================
   COMENTARIOS (juego.html)
========================================================= */

/* =========================================================
   COMENTARIOS (juego.html)
   Paleta intacta (negro + dorado, sin azules/verdes de Discord).
========================================================= */

.game-comments-section{
    /* Corrección posterior: el border-top (el separador visual) vivía
       pegado directo al contenido de arriba, sin ningún aire antes --
       el padding-top solo daba espacio DESPUÉS de esa línea, no antes.
       margin-top acá agrega el hueco pedido (~44px) antes de toda la
       sección (línea incluida), sin tocar .game-main-layout ni su gap
       de 48px entre columnas -- es una propiedad de esta sección
       únicamente. */
    margin-top: 44px;

    /* Antes 30px 0 70px, sin ningún divisor -- quedaba pegado al
       contenido de arriba (pedido explícito de separación más clara). */
    padding: 44px 0 70px;
    border-top: 1px solid var(--border-soft);
}

.game-comments-layout{
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
}

/* ESTADÍSTICAS */
.comments-stats{
    display: flex;
    align-items: center;
    gap: 10px;
    color: #8a8a8a;
    font-size: 13px;
    margin: -6px 0 20px;
}

.comments-count{
    color: #ddd;
    font-weight: 600;
}

.comments-stats-dot{
    color: #555;
}

/* COMPOSER */
.comment-composer{
    display: flex;
    gap: 14px;
    margin-bottom: 30px;
}

/* Mismo bug real que .meta-row/.report-modal-overlay: display:flex
   pisaba [hidden] -- composer y login-prompt (los dos con el mismo
   problema, ver más abajo) podían quedar visibles los dos a la vez
   sin importar si había sesión o no. */
.comment-composer[hidden]{
    display: none;
}

.comment-composer-body{
    flex: 1;
}

.comment-input-wrap{
    position: relative;
}

.comment-input-wrap textarea{
    width: 100%;
    resize: vertical;
    min-height: 60px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 14px;
    padding: 12px 100px 40px 14px;
    color: #f0f0f0;
    font-family: inherit;
    font-size: 14px;
    outline: none;
    transition: border-color var(--dur-nav) ease, background var(--dur-nav) ease, box-shadow var(--dur-nav) ease, min-height .2s ease;
}

.comment-input-wrap textarea::placeholder{
    color: #6a6a6a;
}

/* Reapertura visual (pedido explícito, §6): "puede expandirse
   ligeramente" al enfocar -- crece un poco (min-height) además del
   anillo de foco que ya existía, nunca una caja gigante. */
.comment-input-wrap textarea:focus{
    border-color: rgba(255,179,0,.4);
    background: rgba(255,179,0,.03);
    box-shadow: 0 0 0 3px rgba(255,179,0,.08);
    min-height: 76px;
}

.comment-submit-btn{
    position: absolute;
    right: 8px;
    bottom: 8px;
    height: 34px;
    padding: 0 18px;
    border: none;
    border-radius: var(--radius-pill);
    background: linear-gradient(135deg, #ffb300, #ffd54f);
    color: #111;
    font-weight: 700;
    font-size: 13px;
    cursor: pointer;
    transition: transform var(--dur-base) ease, box-shadow var(--dur-base) ease, opacity var(--dur-base) ease;
}

.comment-submit-btn:hover{
    transform: scale(1.04);
    box-shadow: 0 8px 20px rgba(255,179,0,.28);
}

/* Sin texto todavía -- deshabilitado (pedido explícito, §6), mismo
   criterio ya usado en .reply-submit-btn:disabled. */
.comment-submit-btn:disabled{
    opacity: .5;
    cursor: default;
    pointer-events: none;
    transform: none;
    box-shadow: none;
}

/* PROMPT DE LOGIN */
.comment-login-prompt{
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 14px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.06);
    border-radius: 16px;
    padding: 16px 20px;
    margin-bottom: 30px;
}

.comment-login-prompt[hidden]{
    display: none;
}

.comment-login-prompt p{
    margin: 0;
    color: rgba(255,255,255,.75);
    font-size: 14px;
}

.comment-login-btn{
    flex-shrink: 0;
    height: 38px;
    padding: 0 20px;
    display: inline-flex;
    align-items: center;
    border-radius: var(--radius-pill);
    background: linear-gradient(135deg, #ffb300, #ffd54f);
    color: #111;
    font-weight: 700;
    font-size: 13px;
    text-decoration: none;
    transition: transform var(--dur-base) ease;
}

.comment-login-btn:hover{
    transform: translateY(-2px) scale(1.02);
}

/* LISTA -- gap entre comentarios reducido de 26px a 18px (pedido
   explícito, §4: "aproximadamente 16-18px" entre comentarios; las
   respuestas usan su propio gap más chico, ver .comment-replies-list). */
.comment-list{
    display: flex;
    flex-direction: column;
    gap: 18px;
}

/* Sprint 21 -- antes no hacía falta (el mock siempre tenía 3
   comentarios fijos); ahora un juego nuevo real empieza en 0. */
.comments-empty{
    color: var(--text-dim);
    font-size: 14px;
    padding: 8px 0 4px;
}

.comment-delete-btn{
    margin-left: auto;
}

.comment-item{
    display: flex;
    gap: 14px;
}

/* AVATAR — degradado sutil + borde dorado fino. Corrección posterior
   (pedido explícito): la foto de perfil real del autor (avatarUrl,
   siempre la ACTUAL -- ver comentario de cabecera de esta sección en
   juego.html) reemplaza a las iniciales cuando existe; overflow:hidden
   para que la imagen respete el recorte circular. Mismo patrón que
   .nav-user-avatar (navbar). */
.comment-avatar{
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border-radius: var(--radius-circle);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    background: linear-gradient(145deg, #262626, #171717);
    border: 1px solid rgba(255,179,0,.4);
    color: #ffcc66;
    font-size: 12.5px;
    font-weight: 800;
    letter-spacing: .3px;
}

.comment-avatar img{
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Corrección posterior (pedido explícito): borde plateado en vez de
   dorado para distinguir a Staff -- el dorado quedaba reservado para
   otros usos (CTAs, hover) en el resto de la página. */
.comment-avatar.is-team{
    background: linear-gradient(145deg, #2e3238, #1c1c1c);
    border-color: rgba(201,210,220,.75);
    color: #c9d2dc;
    box-shadow: 0 0 0 2px rgba(201,210,220,.12);
}

/* CUERPO DEL COMENTARIO — menos "caja", borde dorado sutil al hover */
.comment-body{
    flex: 1;
    background: #171717;
    border: 1px solid rgba(255,255,255,.05);
    border-left: 2px solid transparent;
    border-radius: 14px;
    padding: 13px 16px;
    box-shadow: 0 6px 18px rgba(0,0,0,.14);
    transition: border-left-color .25s ease, background .25s ease, transform var(--dur-fast) ease;
}

.comment-body:hover{
    border-left-color: rgba(255,179,0,.55);
    background: #1a1a1a;
}

.comment-meta{
    display: flex;
    align-items: baseline;
    gap: 9px;
    margin-bottom: 5px;
    flex-wrap: wrap;
}

.comment-meta strong{
    color: #f0f0f0;
    font-size: 13.5px;
}

/* Reapertura (Sprint 26, pedido explícito): rediseño de los badges de
   identidad dentro de un comentario. Base compartida (.comment-badge)
   + una variante por tipo.
   - Staff: cerezo sangre de identidad general (--accent-rgb, el mismo
     de nav/bordes de card), discreto -- es un estado interno, no algo
     que "vender" visualmente. Mismo estilo para los 4 casos (Owner/
     Admin/Traductor/Moderador), solo cambia el texto -- ver
     resolveCommentTag() en juego.html.
   - Patreon (3 niveles): el cereza PROPIO de Patreon (--cherry, ya
     reservado en todo el sitio para la marca de Patreon, nunca el
     --accent-rgb general -- mismo criterio ya establecido para el
     aviso de acceso anticipado). Progresión de intensidad por nivel.
     Nunca amarillo (reservado para CTA, §10).
   Reapertura (pedido explícito, segunda vuelta): Staff y Patreon ya NO
   conviven -- si es Staff (cualquier rol) ese tag gana siempre, nunca
   los dos a la vez (resolveCommentTag() en juego.html decide cuál se
   manda). El ícono de cada nivel de Patreon ahora vive DENTRO del
   nombre del tier (PATREON_TIER_LABELS), no como ::before separado --
   por eso se sacó el "★"/"✦" que había acá. */
.comment-badge{
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 10.5px;
    font-weight: 700;
    padding: 2px 9px;
    border-radius: var(--radius-pill);
    letter-spacing: .2px;
    line-height: 1.5;
    /* No son botones -- pedido explícito, §10 ("no deben parecer
       clicables, no deben competir con el nombre"). */
    user-select: none;
}

/* Bug real (mismo de siempre en este sitio, ver .comment-composer[hidden]
   más abajo): display:inline-flex de arriba pisaba el [hidden] nativo
   del navegador -- necesario acá porque #navUserTag (session.js, tag
   del navbar) se oculta/muestra vía el atributo hidden reutilizando
   esta misma clase. */
.comment-badge[hidden]{
    display: none;
}

.comment-badge-staff{
    background: rgba(var(--accent-rgb), .14);
    border: 1px solid rgba(var(--accent-rgb), .45);
    color: #e9d3d6;
}

/* Pedido explícito: glow para el tag de Owner (referencia visual
   enviada por el usuario) -- modificador ENCIMA de .comment-badge-staff,
   nunca lo reemplaza, así que Admin/Traductor/Moderador no se ven
   afectados. Mismo --accent-rgb que ya usa el badge de Staff (nunca
   --cherry, reservado para Patreon, ver nota de arriba) -- Owner es la
   única cuenta de todo el sitio con este rol. Misma magnitud que el
   glow ya existente de Patreon nivel 3 (sutil, no un glow fuerte). */
.comment-badge-owner{
    box-shadow: 0 0 9px rgba(var(--accent-rgb), .38);
}

/* Reapertura (pedido explícito): cada rango de Patreon pasa a tener su
   propio color de identidad en vez de compartir el mismo cereza --
   Barón (ámbar), Conde (cobre), Shogun (vino profundo) -- cada uno con
   su propio glow a juego, en vez de que solo Nivel 3 tuviera uno. Same
   magnitud/filosofía que ya regía acá ("elegante y discreto", nunca un
   neón fuerte), solo cambia de qué color sale cada glow. */
.comment-badge-patreon-1{
    background: rgba(217,164,65,.14);
    border: 1px solid rgba(217,164,65,.45);
    color: #f0dab0;
    box-shadow: 0 0 6px rgba(217,164,65,.25);
}

.comment-badge-patreon-2{
    background: rgba(199,91,42,.20);
    border: 1px solid rgba(199,91,42,.55);
    color: #f2c9ab;
    box-shadow: 0 0 7px rgba(199,91,42,.3);
}

/* Nivel 3 -- el más exclusivo: degradado sutil + sombra tenue (nunca un
   glow fuerte, pedido explícito ya desde antes), ahora en su propio
   vino profundo en vez del cereza compartido. */
.comment-badge-patreon-3{
    background: linear-gradient(135deg, rgba(139,30,63,.34), rgba(178,45,84,.24));
    border: 1px solid rgba(178,45,84,.75);
    color: #ffd0dc;
    box-shadow: 0 0 9px rgba(139,30,63,.35);
}

/* "↳ en respuesta a Nombre" -- reapertura (Sprint 26, pedido
   explícito): cita textual pequeña para conservar el contexto de una
   respuesta a otra respuesta SIN crear anidamiento visual real (nunca
   un bloque de cita grande). */
.comment-reply-context{
    margin: 0 0 4px;
    color: rgba(255,255,255,.4);
    font-size: 11.5px;
}

.comment-reply-context [data-reply-context-name]{
    color: rgba(255,255,255,.62);
    font-weight: 600;
}

.comment-time{
    color: #828282;
    font-size: 12px;
}

.comment-text{
    margin: 0 0 10px;
    color: rgba(255,255,255,.8);
    font-size: 13.5px;
    line-height: 1.55;
}

/* ACCIONES -- barra más discreta (pedido explícito, §9): gap reducido,
   separador "·" real entre los botones conversacionales (like/
   responder/desplegable, ver comment-actions-sep), no solo espacio en
   blanco. Eliminar queda afuera de esa cadena, sigue empujado al
   extremo derecho (margin-left:auto). */
.comment-actions{
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    row-gap: 6px;
}

.comment-action-btn{
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: none;
    border: none;
    color: #888;
    font-size: 12.5px;
    font-family: inherit;
    cursor: pointer;
    padding: 2px 0;
    transition: color var(--dur-fast) ease;
}

.comment-action-btn:hover{
    color: #ffd54f;
}

.comment-action-btn:focus-visible{
    outline: 1px solid rgba(255,213,79,.6);
    outline-offset: 3px;
    border-radius: 3px;
}

.comment-actions-sep{
    color: #444;
    font-size: 12px;
    user-select: none;
}

.comment-action-btn.like-btn.is-liked{
    color: #ff8a8a;
}

.comment-action-btn.more-btn{
    margin-left: auto;
    font-size: 15px;
}

/* =========================================================
   HILOS DE RESPUESTA (Sprint 25) -- ver juego.html, sección
   COMENTARIOS. .comment-thread agrupa un comentario principal + su
   composer de respuesta (si está abierto) + sus respuestas (si hay y
   no están contraídas). .comment-list ya separaba a sus hijos
   directos con gap:26px -- antes eran .comment-item, ahora son
   .comment-thread, mismo resultado visual para la lista de arriba.
========================================================= */
.comment-thread{
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Reapertura visual (pedido explícito, prioridad principal): las
   respuestas quedan plegadas por defecto -- este wrapper es el que se
   anima al abrir/cerrar. SIEMPRE está en el DOM cuando hay respuestas
   (nunca se quita/agrega, ver buildThreadHtml en juego.html); lo que
   cambia es la clase .is-open, para que sea una transición CSS real
   sobre el mismo nodo, no una reconstrucción de HTML.
   Técnica grid-template-rows 0fr->1fr: anima una altura "auto" sin
   tener que medir el contenido en JS (el número real de respuestas es
   variable) -- mejor soportada y más prolija que animar max-height a
   un valor adivinado. ~200ms, sin rebote (ease simple), como pide el
   punto 13. */
.comment-replies-wrap{
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows .2s ease;
}

.comment-replies-wrap.is-open{
    grid-template-rows: 1fr;
}

.comment-replies-wrap > .comment-replies-list{
    overflow: hidden;
    min-height: 0;
}

/* Lista de respuestas -- misma estructura .comment-item de siempre
   (avatar + cuerpo), a menor escala, con una línea vertical sutil que
   conecta visualmente el hilo con su comentario principal (mismo
   lenguaje que el resto del sitio: bordes finos translúcidos, sin
   cajas nuevas). Gap reducido de 14px a 10px (pedido explícito, §4:
   "las respuestas deben estar más compactas"). */
.comment-replies-list{
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-left: 20px;
    margin-left: 20px;
    border-left: 2px solid rgba(255,255,255,.06);
}

.comment-item-reply .comment-avatar{
    width: 32px;
    height: 32px;
    font-size: 11px;
}

/* Fondo levemente más oscuro que el comentario principal (#141414
   contra #171717, ver .comment-body) -- pedido explícito, §2/§3: la
   respuesta debe sentirse subordinada, nunca un comentario
   independiente con el mismo peso visual. */
.comment-item-reply .comment-body{
    padding: 11px 14px;
    background: #141414;
}

.comment-replies-toggle-arrow{
    display: inline-block;
    font-size: 10px;
}

/* COMPOSER DE RESPUESTA -- mismo lenguaje visual que #commentComposer
   (arriba de toda la lista), a escala de hilo. Nunca comparte flujo
   con él -- crea únicamente respuestas, nunca comentarios principales
   (ver juego.html). Indentado 54px = ancho del avatar (40px) + su gap
   (14px) del comentario al que pertenece, para alinear con el texto
   en vez de con el avatar. */
/* Entrada suave (pedido explícito, §8: "aparece... desaparece al
   cancelar") -- se reproduce una sola vez al montarse el nodo, ~180ms,
   sin rebote; el cierre sigue siendo instantáneo (se saca del DOM al
   cancelar), no hace falta animar la salida. */
@keyframes replyComposerReveal{
    from{ opacity: 0; transform: translateY(-4px); }
    to{ opacity: 1; transform: translateY(0); }
}

.reply-composer,
.reply-composer-guest{
    margin: 2px 0 2px 54px;
    animation: replyComposerReveal .18s ease;
}

.reply-composer{
    display: flex;
    gap: 12px;
}

.reply-composer .comment-avatar{
    width: 30px;
    height: 30px;
    font-size: 10.5px;
}

.reply-composer-body{
    flex: 1;
}

/* "Respondiendo a Nombre" -- pedido explícito, §8: antes esa
   información solo vivía en el placeholder del textarea (desaparecía
   apenas se empezaba a escribir); ahora es una línea fija arriba. */
.reply-composer-target{
    margin: 0 0 6px;
    color: rgba(255,255,255,.55);
    font-size: 12px;
}

.reply-composer-target:empty{
    display: none;
}

/* Cita breve del comentario al que se responde (reapertura Sprint 26,
   pedido explícito, §4: "solo una referencia pequeña", nunca un bloque
   de cita enorme) -- truncada en JS a ~80 caracteres. */
.reply-composer-quote{
    margin: 0 0 8px;
    padding: 4px 0 4px 10px;
    border-left: 2px solid rgba(255,255,255,.12);
    color: rgba(255,255,255,.42);
    font-size: 11.5px;
    font-style: italic;
    line-height: 1.4;
}

.reply-composer-quote:empty{
    display: none;
}

.reply-input{
    width: 100%;
    resize: vertical;
    min-height: 48px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,179,0,.25);
    border-radius: 12px;
    padding: 10px 12px;
    color: #f0f0f0;
    font-family: inherit;
    font-size: 13.5px;
    outline: none;
    transition: border-color var(--dur-nav) ease, background var(--dur-nav) ease, box-shadow var(--dur-nav) ease;
}

.reply-input::placeholder{
    color: #6a6a6a;
}

.reply-input:focus{
    border-color: rgba(255,179,0,.5);
    background: rgba(255,179,0,.03);
    box-shadow: 0 0 0 3px rgba(255,179,0,.08);
}

.reply-composer-actions{
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 8px;
}

.reply-cancel-btn,
.reply-submit-btn{
    height: 30px;
    padding: 0 16px;
    border: none;
    border-radius: var(--radius-pill);
    font-weight: 700;
    font-size: 12.5px;
    cursor: pointer;
    font-family: inherit;
    transition: transform var(--dur-base) ease, box-shadow var(--dur-base) ease;
}

.reply-cancel-btn{
    background: rgba(255,255,255,.06);
    color: rgba(255,255,255,.75);
}

.reply-cancel-btn:hover{
    background: rgba(255,255,255,.1);
}

.reply-submit-btn{
    background: linear-gradient(135deg, #ffb300, #ffd54f);
    color: #111;
}

.reply-submit-btn:hover{
    transform: scale(1.04);
    box-shadow: 0 6px 16px rgba(255,179,0,.28);
}

.reply-submit-btn:disabled{
    opacity: .6;
    cursor: default;
    transform: none;
    box-shadow: none;
}

.reply-login-hint{
    margin: 0;
    color: rgba(255,255,255,.6);
    font-size: 12.5px;
}

.reply-login-hint a{
    color: #ffd54f;
    text-decoration: none;
}

.reply-login-hint a:hover{
    text-decoration: underline;
}

@media (max-width: 560px){

    .comment-input-wrap textarea{
        padding: 12px 14px 46px;
    }

    .reply-composer,
    .reply-composer-guest{
        margin-left: 0;
    }

    /* Pedido explícito, §17: reducir indentación de respuestas en
       móvil -- 20px se siente excesivo en una pantalla angosta. */
    .comment-replies-list{
        padding-left: 12px;
        margin-left: 8px;
    }

    /* Evita que la barra de acciones se salga del ancho -- ya envuelve
       (flex-wrap, ver .comment-actions) pero en pantallas muy angostas
       el separador "·" no aporta nada pegado al borde de línea. */
    .comment-actions-sep{
        display: none;
    }

    /* Pedido explícito, §19: varios badges + nombre largo no deben
       desbordar -- .comment-meta ya envuelve (flex-wrap), acá solo se
       achican un poco los badges para que quepan más por línea. */
    .comment-badge{
        font-size: 10px;
        padding: 2px 7px;
    }

}

/* =========================================================
   CATÁLOGO — panel de filtros (todos-los-juegos.html): motor +
   género. "Según tus gustos"/"Plataformas"/"Ordenar" quedaron fuera
   a propósito, ver comentario en el HTML.
========================================================= */

.catalog-filters-panel{
    background: var(--bg-1);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-card);
    padding: 20px 22px;
    margin-bottom: 24px;
}

.catalog-filters-row{
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}

.catalog-filters-row-secondary{
    margin-top: 14px;
}

.catalog-filters-label{
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--text-soft);
    font-size: .85rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .4px;
}

.catalog-filters-label svg{
    width: 18px;
    height: 18px;
}

.catalog-filter-select{
    height: 42px;
    padding: 0 16px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--border-soft);
    background: rgba(255,255,255,.03);
    color: var(--text-warm);
    font-size: .88rem;
    cursor: pointer;
}

.catalog-filter-select option{
    background: var(--bg-1);
    color: var(--text-warm);
}

.catalog-filters-actions{
    display: flex;
    gap: 10px;
    margin-left: auto;
}

.catalog-filter-btn{
    height: 42px;
    padding: 0 22px;
    border-radius: var(--radius-pill);
    font-size: .85rem;
    font-weight: 600;
    cursor: pointer;
    transition: opacity var(--dur-fast) ease, background var(--dur-fast) ease, border-color var(--dur-fast) ease;
}

.catalog-filter-btn.is-primary{
    border: none;
    background: linear-gradient(135deg, #ffb300, #ffd54f);
    color: #111;
}

.catalog-filter-btn.is-primary:hover{
    opacity: .9;
}

.catalog-filter-btn.is-ghost{
    border: 1px solid var(--border-soft);
    background: transparent;
    color: var(--text-soft);
}

.catalog-filter-btn.is-ghost:hover{
    border-color: rgba(255,179,0,.5);
    color: #ffb300;
}

/* Pill con borde (mismo lenguaje visual que .catalog-filter-select/
   .catalog-filter-btn) -- antes era texto plano, no se notaba que
   fuera clickeable (pedido explícito de que se vea como un botón). */
.catalog-genre-toggle{
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
    height: 42px;
    padding: 0 18px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--border-soft);
    background: rgba(255,255,255,.03);
    color: var(--text-warm);
    font-size: .85rem;
    font-weight: 700;
    cursor: pointer;
    transition: border-color var(--dur-fast) ease, background var(--dur-fast) ease;
}

.catalog-genre-toggle:hover,
.catalog-genre-toggle[aria-expanded="true"]{
    border-color: rgba(255,179,0,.5);
    background: rgba(255,179,0,.06);
}

.catalog-genre-toggle-arrow{
    display: inline-block;
    color: #ffb300;
    transition: transform var(--dur-fast) ease;
}

.catalog-genre-toggle[aria-expanded="true"] .catalog-genre-toggle-arrow{
    transform: rotate(90deg);
}

.catalog-genre-toggle span:last-child{
    color: var(--text-dim);
    font-weight: 400;
}

.catalog-genre-panel{
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid var(--border-soft);
    /* Mismo motivo que .games-catalog-grid: el contenido se
       reconstruye entero (ver renderGenreGrid()), sin esto el
       navegador podía intentar compensar el cambio de alto al
       abrir/cerrar el acordeón moviendo el scroll solo. */
    overflow-anchor: none;
}

.catalog-genre-panel-label{
    margin: 0 0 12px;
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .4px;
    text-transform: uppercase;
    color: var(--text-dim);
}

.catalog-genre-grid{
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.catalog-genre-pill{
    height: 34px;
    padding: 0 16px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--border-soft);
    background: rgba(255,255,255,.03);
    color: var(--text-soft);
    font-size: .82rem;
    cursor: pointer;
    transition: border-color var(--dur-fast) ease, background var(--dur-fast) ease, color var(--dur-fast) ease;
}

.catalog-genre-pill:hover{
    border-color: rgba(255,179,0,.4);
    color: var(--text-warm);
}

.catalog-genre-pill.active{
    background: rgba(255,179,0,.12);
    border-color: #ffb300;
    color: #ffcc66;
}

.catalog-results-count{
    margin: 0 0 16px;
    color: var(--text-dim);
    font-size: .85rem;
    overflow-anchor: none;
}

/* Estado vacío del catálogo (pedido explícito) -- zorrito + mensaje
   propio de Inari Okami, reemplaza el texto plano que antes vivía solo
   en .catalog-results-count cuando la búsqueda/filtros no encuentran
   nada. Tamaño de la imagen acotado a propósito ("visible pero que no
   domine toda la página") -- se respeta la imagen tal cual viene
   (transparente, ya recortada), sin fondo/sombra/efecto agregado. */
.catalog-empty-state{
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 48px 24px;
}

/* Bug real encontrado en vivo (mismo patrón ya visto varias veces en
   este proyecto -- ver .dash-btn-ghost[hidden] en dashboard.css):
   display:flex de arriba y el display:none del user-agent para
   [hidden] tienen la misma especificidad -- gana esta regla por venir
   después en la hoja, dejando el panel visible aunque JS le ponga
   `.hidden = true` (reproducido: después de "Limpiar", con resultados
   de vuelta, el zorrito seguía mostrándose superpuesto a las cards). */
.catalog-empty-state[hidden]{
    display: none;
}

.catalog-empty-state-img{
    width: 180px;
    max-width: 60%;
    height: auto;
    margin-bottom: 20px;
}

/* Pedido explícito (refinamiento visual) -- degradado muy sutil entre
   --gold-light y un amarillo apenas más cálido, en vez del dorado
   plano de antes. `color` de respaldo primero (navegadores sin soporte
   de degradado en texto siguen viendo dorado sólido, nunca invisible);
   -webkit-text-fill-color es lo que de verdad revela el degradado en
   Safari. text-shadow extremadamente suave del mismo tono -- glow, no
   neón (radio chico, alpha bajo). */
.catalog-empty-state-title{
    margin: 0 0 10px;
    color: var(--gold-light);
    background: linear-gradient(135deg, var(--gold-light) 25%, #ffdd93 80%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    text-shadow: 0 0 16px rgba(232,178,60,.16);
    font-size: 1.2rem;
    font-weight: 700;
    max-width: 460px;
}

/* Separador decorativo (pedido explícito) -- línea fina a cada lado +
   marca central, armado con ::before/::after (primer/último hijo
   automático de un flex container) en vez de tres elementos HTML
   sueltos. Dorado tenue, opacidad moderada -- discreto a propósito. */
.catalog-empty-state-divider{
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    width: 100%;
    max-width: 130px;
    margin: 2px 0 14px;
    color: var(--gold-light);
    font-size: .7rem;
    opacity: .55;
}

.catalog-empty-state-divider::before,
.catalog-empty-state-divider::after{
    content: "";
    flex: 1;
    height: 1px;
    background: var(--gold-light);
}

/* Pedido explícito -- "blanco cálido/gris claro, no gris oscuro":
   var(--text-soft) (#c9c4bc) ya es ese tono exacto en la paleta
   existente, se reutiliza tal cual en vez de sumar un color nuevo. */
.catalog-empty-state-text{
    margin: 0;
    color: var(--text-soft);
    font-size: .9rem;
    font-weight: 400;
    max-width: 420px;
}

.catalog-pagination{
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 36px;
    flex-wrap: wrap;
    overflow-anchor: none;
}

/* Botones redondos numerados (pedido explícito: "por números, no que
   pases 1 por 1") -- min-width en vez de width fijo, así "69"/"120"
   no quedan apretados contra el borde circular. */
.catalog-page-number,
.catalog-page-arrow{
    min-width: 36px;
    height: 36px;
    padding: 0 4px;
    border-radius: 50%;
    border: 1px solid var(--border-soft);
    background: rgba(255,255,255,.03);
    color: var(--text-warm);
    font-size: .85rem;
    font-weight: 600;
    cursor: pointer;
    transition: border-color var(--dur-fast) ease, color var(--dur-fast) ease, background var(--dur-fast) ease, opacity var(--dur-fast) ease;
}

.catalog-page-number:hover:not(.active),
.catalog-page-arrow:hover:not(:disabled){
    border-color: rgba(255,179,0,.5);
    color: #ffb300;
}

.catalog-page-number.active{
    background: #ffb300;
    border-color: #ffb300;
    color: #111;
}

.catalog-page-arrow:disabled{
    opacity: .35;
    cursor: not-allowed;
}

.catalog-page-ellipsis{
    color: var(--text-dim);
    padding: 0 4px;
    font-size: .85rem;
}

@media (max-width: 700px){
    .catalog-filters-actions{
        margin-left: 0;
        width: 100%;
    }
    .catalog-filter-btn{
        flex: 1;
    }
    .catalog-pagination{
        gap: 12px;
    }
}

/* =========================================================
   ACCESIBILIDAD — prefers-reduced-motion
   Regla global (mismo patrón que usan Bootstrap y la mayoría de
   guías WCAG para este caso): reduce animaciones y transiciones a
   una duración casi nula para quienes activaron esta preferencia
   en su sistema operativo, sin eliminar ninguna regla ni alterar
   el estado final de ningún componente — cada animación termina
   en el mismo lugar en que terminaría normalmente (verificado
   contra los @keyframes reales del archivo: cinematicZoom,
   authShake y authAlertIn ya vuelven a su estado base/final sin
   desplazamiento visible), solo que casi instantáneamente.

   El seguimiento continuo del cursor personalizado (.custom-cursor) se
   calcula frame a frame desde custom-cursor.js (requestAnimationFrame),
   no desde CSS -- esta regla no puede alcanzarlo. Resuelto del lado de
   JS en cambio: custom-cursor.js ahora respeta este mismo media query
   (además de "hover: none"/"pointer: coarse") y directamente no
   inicializa el cursor personalizado en ninguno de los dos casos, cae
   al cursor del sistema.

   Excepción deliberada: .auth-spinner. Su giro infinito es
   información funcional (indica "procesando"), no decorativo —
   detenerlo daría la falsa impresión de que el proceso terminó o
   se colgó, así que se excluye explícitamente de la regla general.
========================================================= */
@media (prefers-reduced-motion: reduce){

    *,
    *::before,
    *::after{
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }

    .auth-spinner{
        animation-duration: .6s !important;
        animation-iteration-count: infinite !important;
    }

}

/* =========================================================
   AGE GATE (+18) — overlay a pantalla completa, primera visita
   únicamente (localStorage). z-index por encima de todo lo demás del
   sitio (navbar incluida, z-index:100).

   Reapertura (bug real reportado -- "recargando muy rápido todavía se
   alcanza a ver el +18" en visitas ya confirmadas): el diseño anterior
   dejaba .age-gate visible por defecto (display:flex) y dependía de
   que el <script> inline de cada página lo sacara del DOM (.remove())
   ANTES de que el navegador pintara el primer frame. Esa carrera
   normalmente se gana, pero en una recarga muy rápida (todo en un
   único paquete de red, típico en local) el compositor puede pintar
   un frame antes de que ese script termine de correr -- ahí se alcanza
   a ver.

   Ahora el default es invisible (display:none) y SOLO se muestra
   cuando el propio <html> tiene la clase "age-gate-locked" -- clase
   que el script inline únicamente agrega si el usuario TODAVÍA NO
   confirmó. Para una visita ya confirmada, esa clase nunca se agrega,
   así que no hay ninguna ventana de tiempo en la que el overlay pueda
   pintarse, sin importar cuándo corra el script. */
html.age-gate-locked{
    overflow: hidden;
}

html.age-gate-locked .age-gate{
    display: flex;
}

.age-gate{
    position: fixed;
    inset: 0;
    z-index: 10000;
    /* display:none por defecto -- ver comentario arriba de
       html.age-gate-locked. Solo html.age-gate-locked .age-gate (mayor
       especificidad, gana sin importar el orden en el archivo) lo pone
       en flex. */
    display: none;
    justify-content: center;
    align-items: center;
    padding: 24px;
    background:
        radial-gradient(circle at 50% 20%, rgba(232,178,60,.08), transparent 60%),
        rgba(6,6,6,.97);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}

.age-gate-card{
    position: relative;
    width: 100%;
    max-width: 480px;
    background: var(--bg-1);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: var(--radius-card);
    box-shadow: 0 20px 60px rgba(0,0,0,.5);
    padding: 38px 36px 32px;
}

.age-gate-heading{
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 18px;
}

.age-gate-accent{
    flex: 0 0 auto;
    width: 6px;
    height: 34px;
    border-radius: var(--radius-pill);
    background: rgb(var(--accent-rgb));
    box-shadow: 0 0 15px rgba(var(--accent-rgb),.45);
}

.age-gate-heading h1{
    margin: 0;
    font-size: 1.5rem;
    font-weight: 800;
    letter-spacing: -.3px;
    color: var(--text-warm);
}

.age-gate-text{
    margin: 0 0 18px;
    color: var(--text-soft);
    font-size: .96rem;
    line-height: 1.55;
}

.age-gate-list{
    margin: 0 0 28px;
    padding-left: 20px;
    color: var(--text-dim);
    font-size: .88rem;
    line-height: 1.6;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.age-gate-actions{
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
}

.age-gate-continue-btn{
    width: 100%;
    height: 48px;
    border: none;
    border-radius: 10px;
    background: linear-gradient(135deg, #ffb300, #ffd54f);
    color: #241a00;
    font-family: inherit;
    font-size: .96rem;
    font-weight: 700;
    cursor: pointer;
    transition: transform var(--dur-fast) ease, box-shadow var(--dur-fast) ease;
}

.age-gate-continue-btn:hover{
    transform: translateY(-1px);
    box-shadow: 0 8px 22px rgba(255,179,0,.28);
}

.age-gate-links{
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    justify-content: center;
}

.age-gate-links a{
    color: var(--text-dim);
    font-size: .82rem;
    text-decoration: none;
    transition: color var(--dur-fast) ease;
}

.age-gate-links a:hover{
    color: #ffb300;
}

.age-gate-links-sep{
    color: rgba(255,255,255,.15);
    font-size: .8rem;
}

@media (max-width: 520px){
    .age-gate-card{
        padding: 30px 24px 26px;
    }
}

/* =========================================================
   PÁGINAS LEGALES ESTÁTICAS (terminos.html, privacidad.html,
   contacto-reportes.html, aviso-18.html) — mismo criterio tipográfico
   en las cuatro, reutilizando .title-line/.container ya existentes
   para no inventar un lenguaje visual nuevo.
========================================================= */
.legal-page{
    padding: 56px 0 100px;
}

.legal-page .container{
    max-width: 820px;
}

.legal-page .section-title{
    margin-bottom: 12px;
}

.legal-page .legal-updated{
    color: var(--text-dim);
    font-size: .85rem;
    margin: 0 0 40px;
}

.legal-page .legal-intro{
    color: var(--text-soft);
    font-size: 1rem;
    line-height: 1.7;
    margin: 0 0 36px;
}

/* EN CONSTRUCCIÓN (pedido explícito, reapertura de la sección) --
   layout propio de 2 columnas en desktop (texto + ilustración de la
   encargada del santuario), apilado en mobile. Reutiliza .legal-page
   (padding de sección) y .section-title/.legal-intro (misma tipografía
   que Privacidad/Términos/Aviso +18) -- esas reglas de arriba NO se
   tocan, son compartidas con esas 3 páginas. Todo lo nuevo vive acá,
   scoped bajo .construction-page/.construction-*, exclusivo de
   en-construccion.html. */

/* Reapertura (pedido explícito, tercera vuelta): "sigue sintiéndose
   plano" -- pedido explícito de NO subir la intensidad del halo
   anterior sino construir profundidad real con varias capas, todas
   MUY sutiles, en un único `background` (sigue siendo solo eso: no
   agrega elementos, no puede generar overflow, no toca layout). Orden
   de las capas (la primera de la lista pinta ENCIMA de las
   siguientes):

   1) Viñeta -- oscurece bordes/esquinas (transparent en el centro,
      farthest-corner por defecto para que el oscurecido llegue de
      verdad a las esquinas), unifica todo lo de abajo.
   2) Iluminación ambiental cálida detrás de ella -- TRES elipses de
      distinta forma y centro superpuestas (no una sola). Pedido
      explícito: "no debe parecer un círculo ni un radial-gradient
      visible" -- una sola forma perfecta se lee como mancha; tres
      siluetas distintas solapadas se leen como una zona de luz difusa
      e irregular, no como una figura. Núcleo cálido (marrón rojizo,
      120,60,45) hacia el cereza de identidad (--accent-rgb, 150,50,60).
   3) Variación de luminosidad casi imperceptible detrás del texto (sin
      cambios respecto a la versión anterior).
   4) Insinuación arquitectónica (pedido explícito: "paneles japoneses...
      extremadamente difuminado... casi subliminal") -- líneas
      verticales tipo shoji a .015 de opacidad, separadas 140px: solo
      se notan mirando de cerca, no compiten con la ilustración. */
.construction-page{
    background:
        radial-gradient(ellipse at 50% 50%, transparent 45%, rgba(10,8,7,.34) 100%),
        radial-gradient(ellipse 780px 640px at 76% 38%, rgba(120,60,45,.10), transparent 62%),
        radial-gradient(ellipse 560px 820px at 70% 58%, rgba(150,50,60,.08), transparent 66%),
        radial-gradient(ellipse 980px 460px at 80% 50%, rgba(150,50,60,.05), transparent 72%),
        radial-gradient(ellipse 900px 600px at 32% 55%, rgba(255,255,255,.02), transparent 70%),
        repeating-linear-gradient(90deg, rgba(255,255,255,.015) 0px, rgba(255,255,255,.015) 1px, transparent 1px, transparent 140px);
}

/* Pedido explícito: espacio muerto antes del footer -- .footer-pro
   trae margin-top:100px de fábrica (compartido por todo el sitio) que
   se suma a los 100px de padding inferior que ya pone .legal-page.
   Mismo criterio que ya existe para ".games-petal-zone ~ .footer-pro"
   (30px): reducirlo con un selector de hermano, sin tocar la regla
   base de .footer-pro (afectaría a todas las páginas). */
.construction-page ~ .footer-pro{
    margin-top: 0;
}

.construction-page .construction-layout{
    /* Pedido explícito: subido de 980px -- el título necesitaba más
       ancho para volver a entrar en una sola línea (la zorrita se
       quedó en 400px, sin cambios, así que este extra va todo para
       .construction-copy, que es flex-grow:1). */
    max-width: 1160px;
    display: flex;
    align-items: center;
    gap: 48px;
    text-align: left;
}

.construction-copy{
    flex: 1 1 380px;
    min-width: 0;
    /* Pedido explícito: subir el bloque ~20-30px respecto a la
       ilustración -- margin-top negativo en un flex item centrado
       (align-items:center del padre) lo despega hacia arriba de su
       posición centrada sin tocar a .construction-art ni el alto de
       la fila. Se anula en mobile (ver media query) porque ahí no
       aplica el mismo criterio de centrado con la imagen al costado. */
    margin-top: -24px;
}

.construction-copy .section-title{
    justify-content: flex-start;
}

.construction-cta{
    margin: 32px 0 0;
}

/* Firma chica debajo del botón (pedido explícito: "para que se sienta
   más realista") -- discreta, a la derecha en desktop. */
.construction-signature{
    margin: 14px 0 0;
    text-align: right;
    font-size: .8rem;
    font-style: italic;
    color: var(--text-dim);
}

.construction-art{
    /* Prueba (pedido explícito): más grande, solo para ver cómo se ve (era 290px). */
    flex: 0 0 400px;
    display: flex;
    justify-content: center;
}

.construction-art img{
    width: 100%;
    max-width: 400px;
    height: auto;
    display: block;
    /* Pensada para el vignette/alpha ya incluido en el propio PNG --
       el drop-shadow solo le da un poco de profundidad contra el fondo
       oscuro del sitio, no reemplaza ningún fondo. */
    filter: drop-shadow(0 18px 34px rgba(0,0,0,.55));
}

@media (max-width: 760px){

    /* El halo de fondo estaba pensado para la zorrita a la derecha
       (desktop) -- acá el layout se apila y centra, así que se
       recentra con ella para no quedar corrido hacia un costado que ya
       no tiene contenido. Solo posición, mismos colores/opacidades. */
    .construction-page{
        background:
            radial-gradient(ellipse at 50% 50%, transparent 40%, rgba(10,8,7,.34) 100%),
            radial-gradient(ellipse 88% 34% at 50% 60%, rgba(120,60,45,.10), transparent 62%),
            radial-gradient(ellipse 70% 46% at 47% 66%, rgba(150,50,60,.08), transparent 66%),
            radial-gradient(ellipse 95% 26% at 53% 58%, rgba(150,50,60,.05), transparent 72%),
            radial-gradient(ellipse 90% 45% at 50% 20%, rgba(255,255,255,.02), transparent 70%),
            repeating-linear-gradient(90deg, rgba(255,255,255,.015) 0px, rgba(255,255,255,.015) 1px, transparent 1px, transparent 140px);
    }

    .construction-page .construction-layout{
        flex-direction: column;
        text-align: center;
        gap: 24px;
    }

    /* El translateY hacia arriba es un ajuste pensado para el centrado
       lateral con la imagen en desktop -- en mobile el layout se apila
       (imagen abajo, no al costado), así que no aplica: se anula acá
       para no correr el bloque de texto hacia arriba sin motivo. */
    .construction-copy{
        margin-top: 0;
    }

    .construction-copy .section-title{
        justify-content: center;
    }

    /* En mobile todo el bloque ya queda centrado (columna apilada) --
       la firma sigue esa misma regla en vez de quedar sola pegada a la
       derecha de una columna centrada. */
    .construction-signature{
        text-align: center;
    }

    .construction-art{
        flex: 0 0 auto;
    }

    .construction-art img{
        /* Mismo +12% que en desktop (era 200px). */
        max-width: 225px;
    }

}

.legal-section{
    margin-bottom: 34px;
}

.legal-section h2{
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--text-warm);
    margin: 0 0 12px;
}

.legal-section h3{
    font-size: .98rem;
    font-weight: 700;
    color: var(--text-warm);
    margin: 20px 0 10px;
}

.legal-section p{
    color: var(--text-soft);
    font-size: .94rem;
    line-height: 1.7;
    margin: 0 0 14px;
}

.legal-section ul{
    margin: 0 0 14px;
    padding-left: 20px;
    color: var(--text-soft);
    font-size: .94rem;
    line-height: 1.7;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.legal-section a{
    color: #ffb300;
    text-decoration: none;
}

.legal-section a:hover{
    text-decoration: underline;
}

.legal-contact-box{
    background: var(--bg-1);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: var(--radius-card);
    padding: 22px 24px;
    margin: 0 0 34px;
}

/* Reapertura (pedido explícito): "un azul mucho más suave, tirando a
   cielo" para el link de mailto -- antes sin regla propia, caía al azul
   default del navegador. Pastel a propósito (mucho más claro que
   --sky-blue-deep del Dashboard, que es para botones oscuros con texto
   blanco) -- acá es texto sobre --bg-1, necesita ser el elemento claro. */
.legal-contact-box a{
    color: #8ecae6;
}

.legal-contact-box a:hover{
    color: #a9dced;
}

.legal-contact-box p{
    margin: 0 0 8px;
}

.legal-contact-box p:last-child{
    margin-bottom: 0;
}

.legal-report-list{
    margin: 0 0 34px;
    padding-left: 20px;
    color: var(--text-soft);
    font-size: .94rem;
    line-height: 1.7;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.legal-toc{
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 0 0 40px;
    padding: 20px 22px;
    background: var(--bg-1);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: var(--radius-card);
}

.legal-toc a{
    color: var(--text-soft);
    font-size: .88rem;
    text-decoration: none;
}

.legal-toc a:hover{
    color: #ffb300;
}

/* =========================================================
   FICHA DE JUEGO — Tags (reusa Géneros, ver juego.html) y botón
   "Reportar problema" en el sidebar, más el modal real que abre.
========================================================= */
.sidebar-tags-heading{
    margin: 18px 0 0;
    color: #828282;
    font-size: 12px;
    letter-spacing: .5px;
}

.report-game-btn{
    display: block;
    width: 100%;
    margin-top: 18px;
    height: 40px;
    border-radius: var(--radius-pill);
    border: 1px solid rgba(255,77,77,.35);
    background: rgba(255,77,77,.08);
    color: #ff8080;
    font-family: inherit;
    font-size: .86rem;
    font-weight: 600;
    cursor: pointer;
    transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease;
}

.report-game-btn:hover{
    background: rgba(255,77,77,.16);
    border-color: rgba(255,77,77,.55);
}

.report-modal-overlay{
    position: fixed;
    inset: 0;
    z-index: 9998;
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 24px;
    background: rgba(6,6,6,.85);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}

/* Bug real: display:flex de arriba pisaba el [hidden] nativo del
   navegador (misma especificidad que la regla UA, pero la hoja de
   estilos del autor siempre gana) -- el modal quedaba visible desde
   que cargaba la página, y "Cancelar"/cerrar tampoco se notaban porque
   solo tocan el atributo hidden, nunca display directamente. */
.report-modal-overlay[hidden]{
    display: none;
}

.report-modal{
    width: 100%;
    max-width: 460px;
    max-height: 90vh;
    overflow-y: auto;
    background: var(--bg-1);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: var(--radius-card);
    box-shadow: 0 20px 60px rgba(0,0,0,.5);
    padding: 26px 26px 24px;
}

.report-modal-header{
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 10px;
}

.report-modal-header h2{
    margin: 0;
    font-size: 1.15rem;
    font-weight: 800;
    color: var(--text-warm);
}

.report-modal-close{
    background: none;
    border: none;
    color: var(--text-dim);
    font-size: 1rem;
    cursor: pointer;
    line-height: 1;
    padding: 4px;
}

.report-modal-close:hover{
    color: white;
}

.report-modal-subtitle{
    color: var(--text-soft);
    font-size: .88rem;
    line-height: 1.5;
    margin: 0 0 20px;
}

.report-modal-label{
    display: block;
    color: var(--text-warm);
    font-size: .84rem;
    font-weight: 600;
    margin: 0 0 8px;
}

.report-modal-select,
.report-modal-textarea{
    width: 100%;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 10px;
    padding: 10px 12px;
    color: #f0f0f0;
    font-family: inherit;
    font-size: .88rem;
    outline: none;
    transition: border-color var(--dur-nav) ease;
    box-sizing: border-box;
}

.report-modal-select:focus,
.report-modal-textarea:focus{
    border-color: rgba(255,179,0,.4);
}

.report-modal-textarea{
    resize: vertical;
    min-height: 90px;
    margin-bottom: 4px;
}

.report-modal-select{
    margin-bottom: 18px;
}

/* El popup nativo del <select> no hereda el fondo oscuro del propio
   elemento (limitación real del navegador, no algo que CSS del sitio
   pueda tapar) -- fondo blanco de facto, así que sin esto el texto
   quedaba blanco sobre blanco, invisible salvo al pasar el mouse (el
   resaltado azul del hover sí lo hacía legible). Se mantiene solo por
   si algún navegador llegase a pintar el <select> oculto igual. */
.report-modal-select option{
    color: #111;
    background: #fff;
}

/* Reemplazo visual del <select> nativo (menú blanco del navegador,
   imposible de restylear de forma consistente) -- el <select> real
   sigue existiendo como modelo de datos, ver comentario en el HTML. */
.report-modal-select-native{
    display: none;
}

.report-modal-select-wrap{
    position: relative;
    margin-bottom: 18px;
}

.report-modal-select-trigger{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    width: 100%;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 10px;
    padding: 10px 12px;
    color: #f0f0f0;
    font-family: inherit;
    font-size: .88rem;
    text-align: left;
    cursor: pointer;
    box-sizing: border-box;
    transition: border-color var(--dur-nav) ease;
}

.report-modal-select-trigger:hover{
    border-color: rgba(255,255,255,.16);
}

.report-modal-select-wrap.is-open .report-modal-select-trigger,
.report-modal-select-trigger:focus-visible{
    border-color: rgba(255,179,0,.4);
    outline: none;
}

.report-modal-select-caret{
    flex: 0 0 auto;
    color: var(--text-dim);
    font-size: .7rem;
    transition: transform var(--dur-fast) ease;
}

.report-modal-select-wrap.is-open .report-modal-select-caret{
    transform: rotate(180deg);
}

.report-modal-select-listbox{
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    z-index: 20;
    margin: 0;
    padding: 6px;
    list-style: none;
    max-height: 220px;
    overflow-y: auto;
    background: rgba(15,15,15,.95);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid rgba(255,255,255,.1);
    border-radius: 12px;
    box-shadow: 0 16px 34px rgba(0,0,0,.45);
    animation: authAlertIn var(--dur-fast) ease;
}

/* Mismo bug real de siempre: [hidden] nativo pierde contra cualquier
   regla de autor que fije display (acá display:absolute vía position
   no alcanza a pisarlo, pero el default "block" del <ul> sí lo hace). */
.report-modal-select-listbox[hidden]{
    display: none;
}

.report-modal-select-option{
    padding: 9px 10px;
    border-radius: 8px;
    color: var(--text-soft);
    font-size: .85rem;
    cursor: pointer;
}

.report-modal-select-option.is-active{
    background: rgba(255,255,255,.07);
    color: #fff;
}

.report-modal-select-option.is-selected{
    color: var(--text-warm);
    font-weight: 600;
}

.report-modal-hint{
    margin: 0 0 18px;
    color: var(--text-dim);
    font-size: .76rem;
}

.report-modal-file-meta{
    margin: -10px 0 16px;
    color: var(--text-soft);
    font-size: .78rem;
}

.report-modal-preview{
    margin: 0 0 16px;
}

.report-modal-preview-label{
    margin: 0 0 8px;
    color: var(--text-dim);
    font-size: .76rem;
}

/* Envoltorio de la vista previa (pedido explícito: "no puedo quitar la
   imagen una vez elegida") -- fit-content + position:relative para que
   el botón "×" quede anclado a la esquina de la imagen real, nunca del
   ancho completo del modal. */
.report-modal-preview-frame{
    position: relative;
    width: fit-content;
    margin: 0 auto;
}

.report-modal-preview-img{
    display: block;
    max-width: 100%;
    max-height: 220px;
    width: auto;
    height: auto;
    border-radius: 10px;
    border: 1px solid rgba(255,255,255,.08);
    background: rgba(255,255,255,.02);
    object-fit: contain;
}

.report-modal-preview-remove{
    position: absolute;
    top: 8px;
    right: 8px;
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: 1px solid rgba(255,255,255,.15);
    background: rgba(10,10,10,.75);
    color: #fff;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease;
}

.report-modal-preview-remove:hover{
    background: rgba(255,93,93,.85);
    border-color: rgba(255,93,93,.9);
}

.report-modal-file-row{
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 6px;
}

.report-modal-file-btn{
    flex: 0 0 auto;
    height: 34px;
    display: flex;
    align-items: center;
    padding: 0 16px;
    border-radius: var(--radius-pill);
    border: 1px solid rgba(255,255,255,.14);
    background: rgba(255,255,255,.04);
    color: var(--text-soft);
    font-size: .8rem;
    cursor: pointer;
    transition: border-color var(--dur-fast) ease, background var(--dur-fast) ease;
}

.report-modal-file-btn:hover{
    border-color: rgba(255,255,255,.3);
    background: rgba(255,255,255,.07);
}

#reportScreenshotFileName{
    color: var(--text-dim);
    font-size: .8rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.report-modal-error{
    margin: 0 0 14px;
    color: #ff8080;
    font-size: .82rem;
}

.report-modal-actions{
    display: flex;
    justify-content: flex-end;
    gap: 12px;
    margin-top: 8px;
}

.report-modal-cancel{
    height: 40px;
    padding: 0 18px;
    border-radius: var(--radius-pill);
    border: 1px solid rgba(255,255,255,.14);
    background: transparent;
    color: var(--text-soft);
    font-family: inherit;
    font-size: .86rem;
    cursor: pointer;
    transition: border-color var(--dur-fast) ease, color var(--dur-fast) ease;
}

.report-modal-cancel:hover{
    border-color: rgba(255,255,255,.3);
    color: white;
}

.report-modal-submit{
    height: 40px;
    padding: 0 22px;
    border-radius: var(--radius-pill);
    border: none;
    background: linear-gradient(135deg, #ffb300, #ffd54f);
    color: #241a00;
    font-family: inherit;
    font-size: .86rem;
    font-weight: 700;
    cursor: pointer;
    transition: transform var(--dur-fast) ease, box-shadow var(--dur-fast) ease, opacity var(--dur-fast) ease;
}

.report-modal-submit:hover{
    transform: translateY(-1px);
    box-shadow: 0 8px 22px rgba(255,179,0,.28);
}

.report-modal-submit:disabled{
    opacity: .55;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}
