/* ============================================================
   COCUYO — Sistema de diseño (tokens)
   La ÚNICA fuente de verdad de estilos base. Ver CLAUDE.md.
   ============================================================ */

:root {
  /* --- Color: la oscuridad y la luz del Cocuyo ---
     SEGUNDA SUBIDA DE TONO (29-jul-2026, dueño: "colores más claros, gris
     claro mezclado con el verde del cocuyo, que la plataforma se vea más
     agradable"). La primera subida seguía siendo casi negra; esta lleva la
     casa a un GRIS GRAFITO VERDOSO: se sigue viendo cine (el video manda,
     los pósters brillan) pero la interfaz respira y deja de parecer un
     agujero. Los grises llevan verde dentro a propósito — no son grises
     neutros: es la misma luz del cocuyo, muy diluida.

     Contraste comprobado sobre el fondo (#1B2320): texto principal 13,4:1,
     secundario 7,6:1, terciario 5,3:1 — los tres por encima del 4,5:1 que
     pide WCAG AA. El verde de marca NO se toca: es la identidad.
     Valores anteriores entre paréntesis. */
  /* --- LIME FROST (22-ago-2026, decisión del dueño) ---
     Se adopta el tema "Lime Frost" de 21st.dev en su modo oscuro para TODO
     Cocuyo: NEGRO puro (sin tinte azul: decisión del dueño), acento LIMA eléctrico y
     superficies "escarcha" (vidrio translúcido con desenfoque). El verde
     bioluminiscente anterior queda anotado entre paréntesis: para volver
     basta con restaurar estos valores.
     Contraste sobre el fondo (#050505): texto principal 19:1, secundario
     13:1, terciario 7,5:1, lima 15:1 — todos muy por encima de AA. */
  --negro-abismo: #050505;      /* fondo principal · NEGRO (el LF background #020617 era azulado; el dueño lo quiso negro) (antes #1B2320) */
  --negro-elevado: #121212;     /* tarjetas y superficies · LF card (antes #263029) */
  --negro-borde: #262626;       /* bordes e inputs · LF border/input (antes #3A4741) */
  --verde-cocuyo: #AFF33E;      /* EL acento: LIMA · LF primary/ring (antes #00E77B) */
  --verde-profundo: #14532D;    /* fondos de acento, estados · LF accent (antes #126B47) */
  --verde-apagado: #22C55E;     /* hover/pressed de elementos verdes (antes #2C9468) */
  --lima-clara: #D9FF8A;        /* lima iluminada: la escarcha del hover en botones */
  --pizarra: #333333;           /* secundario neutro (LF secondary sin tinte azul): chips, separadores */
  --blanco-luz: #F8FAFC;        /* texto principal · LF foreground (antes #F4FFF9) */
  --gris-niebla: #CBD5E1;       /* texto secundario (antes #C6D3CB) */
  --gris-humo: #94A3B8;         /* terciario/placeholders (antes #A3B3AA) */
  --peligro: #F87171;           /* errores, legible sobre la noche (antes #FF7B86) */
  --peligro-fondo: #991B1B;     /* fondo de acciones destructivas · LF destructive */
  /* Escarcha: la superficie de vidrio de Lime Frost (ver .escarcha). */
  --escarcha: color-mix(in srgb, var(--negro-elevado) 72%, transparent);
  --escarcha-borde: color-mix(in srgb, var(--blanco-luz) 12%, transparent);

  /* --- El glow (la firma visual) --- */
  --glow-suave: 0 0 12px rgba(175, 243, 62, 0.30);
  --glow-medio: 0 0 24px rgba(175, 243, 62, 0.40), 0 0 6px rgba(175, 243, 62, 0.55);
  --glow-fuerte: 0 0 48px rgba(175, 243, 62, 0.50), 0 0 12px rgba(175, 243, 62, 0.75);

  /* Anillo de foco de teclado (accesibilidad AA): doble borde para contraste
     sobre cualquier fondo — un halo del color de fondo y encima el verde de
     marca, así se ve el foco tanto sobre negro como sobre superficies verdes. */
  --anillo-foco: 0 0 0 2px var(--negro-abismo), 0 0 0 4px var(--verde-cocuyo);

  /* Tinta oscura sobre el verde de marca (botones primarios, chips activos).
     Un ÚNICO valor para toda la app: antes convivían #04150D y #041a10. */
  --tinta-sobre-verde: #0A0A0A;  /* negro sobre lima (antes #041A10) */

  /* Fondo de acento con contraste AA: el verde de marca sobre --verde-profundo
     puro da 3,96:1 (suspenso). Oscurecido con el abismo, el texto verde y el
     blanco pasan de 4,5:1. Usar SIEMPRE este para cajas con texto de acento. */
  --acento-fondo: color-mix(in srgb, var(--verde-profundo) 45%, var(--negro-abismo));

  /* Escala de elevación (sombras neutras; el glow verde es aparte).
     Antes había 27 recetas distintas repartidas por los CSS. */
  --sombra-1: 0 8px 24px rgba(0, 0, 0, 0.35);
  --sombra-2: 0 12px 32px rgba(0, 0, 0, 0.45);
  --sombra-3: 0 18px 48px rgba(0, 0, 0, 0.5);

  /* --- Tipografía (sistema, sin CDNs) --- */
  /* Lime Frost pide Inter / JetBrains Mono. Sin CDNs (CLAUDE.md): se usan si
     están en el sistema y, si no, la pila del sistema de siempre. */
  --fuente: Inter, "Inter Variable", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --fuente-mono: "JetBrains Mono", "Cascadia Code", "SF Mono", Consolas, monospace; /* para "coordenadas del universo" */
  --espaciado-letra: -0.01em; /* Lime Frost: letra un pelo más apretada */
  --texto-xs: 0.75rem;
  --texto-sm: 0.875rem;
  --texto-base: 1rem;
  --texto-md: 1.05rem;
  --texto-lg: 1.25rem;
  --texto-xl: 1.75rem;
  --texto-hero: clamp(2rem, 8vw, 3.5rem);

  /* --- Espaciado y forma --- */
  --esp-1: 0.25rem; --esp-2: 0.5rem; --esp-3: 0.75rem;
  --esp-4: 1rem;    --esp-6: 1.5rem; --esp-8: 2rem;
  --radio-sm: 0.5rem; --radio-md: 1rem; --radio-lg: 1.5rem; --radio-pill: 999px; /* Lime Frost: radio base 1rem */

  /* --- Capas --- */
  --z-nav: 100; --z-overlay: 200; --z-modal: 300;

  /* --- Movimiento --- */
  --trans-rapida: 150ms ease;
  --trans-media: 300ms cubic-bezier(0.2, 0.8, 0.2, 1);
  --curva-suave: cubic-bezier(0.22, 1, 0.36, 1); /* salida elástica elegante, la curva de la casa */
}

/* ============ Reset y base ============ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  background: var(--negro-abismo);
  color: var(--blanco-luz);
  font-family: var(--fuente);
  font-size: var(--texto-base);
  line-height: 1.5;
  letter-spacing: var(--espaciado-letra);
  min-height: 100dvh;
  -webkit-font-smoothing: antialiased;
  /* SAFE AREA SUPERIOR: la app se dibuja bajo la barra de estado (notch)
     por viewport-fit=cover + status-bar translúcida en iOS. Este relleno
     baja TODO el contenido por debajo del notch/reloj, para que la cabecera
     no quede tapada. Vale 0 en móviles sin notch y en escritorio. */
  padding-top: env(safe-area-inset-top);
  /* Sin el destello gris al tocar: se siente app nativa, no web. */
  -webkit-tap-highlight-color: transparent;
}

/* Sensación de app SOLO cuando está instalada (standalone): sin el rebote
   elástico al llegar al final del scroll. En el navegador normal no se toca,
   para no quitar el "tirar para recargar" que el usuario espera ahí. */
@media (display-mode: standalone) {
  html, body { overscroll-behavior-y: none; }
}
img, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
input, select, textarea { font: inherit; accent-color: var(--verde-cocuyo); caret-color: var(--verde-cocuyo); }
::placeholder { color: var(--gris-humo); opacity: 1; }

/* ============ Foco visible global (WCAG 2.4.7 Focus Visible) ============ */
/* El teclado y los mandos de TV (relevante para una app de streaming de salón)
   deben ver SIEMPRE dónde está el foco. Damos el verde de marca como anillo
   (coherente con el lore "se enciende al tocar"). :focus-visible solo salta con
   teclado, no al hacer clic con el ratón/dedo, así que no ensucia el puntero. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible,
[role="tab"]:focus-visible,
[role="button"]:focus-visible {
  outline: none;
  box-shadow: var(--anillo-foco);
  border-radius: var(--radio-sm);
}

/* ============ El wordmark (COCUYO con la 2ª O encendida) ============ */
.wordmark { font-weight: 800; letter-spacing: 0.14em; color: var(--blanco-luz); }
.wordmark .o-viva { color: var(--verde-cocuyo); text-shadow: var(--glow-medio); }
.wordmark-cabecera { font-size: 1.3rem; }

/* ============ Los dos faros (logo mínimo, puro CSS) ============ */
.faros { display: inline-flex; gap: 0.45em; align-items: center; }
.faros i {
  width: 0.55em; height: 0.55em; border-radius: 50%;
  background: var(--verde-cocuyo);
  box-shadow: var(--glow-medio);
  /* LEY del lore: el Pyrophorus NO parpadea — se enciende una vez al llegar
     y queda BRILLANDO FIJO como un proyector. (Antes "respiraba" en bucle.) */
  animation: faro-enciende 650ms ease-out both;
}
.faros i:last-child { animation-delay: 130ms; }
@keyframes faro-enciende {
  from { opacity: 0; box-shadow: none; transform: scale(0.85); }
  to   { opacity: 1; box-shadow: var(--glow-medio); transform: scale(1); }
}

/* ============ Botones (Lime Frost, 22-ago-2026) ============
   Tres pesos: primario = lima lleno (la acción que vende); fantasma =
   escarcha (vidrio translúcido con borde de luz) para lo secundario;
   secundario = acento verde profundo con texto lima. Todos píldora,
   48px táctil, sin bordes duros. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--esp-2);
  padding: 0.8em 1.6em; border-radius: var(--radio-pill);
  font-weight: 700; letter-spacing: 0;
  transition: transform var(--trans-rapida), box-shadow var(--trans-media);
  min-height: 48px; /* táctil: pulgar */
}
.btn:active { transform: scale(0.97); }
.btn-primario {
  background: var(--verde-cocuyo); color: var(--tinta-sobre-verde);
  box-shadow: var(--glow-suave), inset 0 1px 0 color-mix(in srgb, var(--blanco-luz) 35%, transparent);
}
.btn-primario:hover { box-shadow: var(--glow-medio), inset 0 1px 0 color-mix(in srgb, var(--blanco-luz) 35%, transparent); }
.btn-fantasma {
  border: 1px solid var(--escarcha-borde); color: var(--blanco-luz);
  background: var(--escarcha);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
}
.btn-fantasma:hover { border-color: color-mix(in srgb, var(--verde-cocuyo) 55%, transparent); }

/* ---------- .btn-luz: el botón que se enciende ----------
   Port en CSS puro del "Interactive Hover Button" de 21st.dev (sin React,
   sin Tailwind, sin JS). Al pasar el ratón el texto se desliza y se apaga,
   un punto de luz que vive en la esquina crece hasta llenar el botón y
   entra el mismo texto con una flecha. Marcado:
     <button class="btn btn-primario btn-luz" data-texto="Comenzar">
       <span class="btn-luz-texto">Comenzar</span>
     </button>
   data-texto = texto de la capa que entra (la flecha la pone el CSS).
   En táctil no hay hover: se ve como un botón normal. */
.btn-luz { position: relative; overflow: hidden; isolation: isolate; }
.btn-luz .btn-luz-texto {
  display: inline-block; position: relative; z-index: 2;
  transition: transform 300ms var(--curva-suave), opacity 300ms var(--curva-suave);
}
.btn-luz::before {            /* el punto de luz que crece */
  content: ""; position: absolute; z-index: 1;
  left: 16%; top: 44%; width: 0.4rem; height: 0.4rem;
  border-radius: var(--radio-pill);
  background: var(--lima-clara);
  opacity: 0.55;
  transition: left 300ms var(--curva-suave), top 300ms var(--curva-suave),
              width 300ms var(--curva-suave), height 300ms var(--curva-suave),
              transform 300ms var(--curva-suave), opacity 300ms var(--curva-suave);
}
.btn-luz::after {             /* la capa que entra: texto + flecha */
  content: attr(data-texto) "\00a0\00a0" url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='%230A0A0A' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3Cpath d='m12 5 7 7-7 7'/%3E%3C/svg%3E");
  position: absolute; inset: 0; z-index: 3;
  display: flex; align-items: center; justify-content: center;
  color: var(--tinta-sobre-verde); font-weight: 700;
  transform: translateX(2.5rem); opacity: 0;
  transition: transform 300ms var(--curva-suave), opacity 300ms var(--curva-suave);
  pointer-events: none;
}
.btn-fantasma.btn-luz::before { background: var(--verde-cocuyo); }
/* En táctil/TV no hay hover: el punto de luz no tiene función y se esconde. */
@media (hover: none) {
  .btn-luz::before { display: none; }
}
@media (hover: hover) {
  .btn-luz:hover .btn-luz-texto,
  .btn-luz:focus-visible .btn-luz-texto { transform: translateX(2.5rem); opacity: 0; }
  .btn-luz:hover::before,
  .btn-luz:focus-visible::before { left: 0; top: 0; width: 100%; height: 100%; transform: scale(1.8); opacity: 1; }
  .btn-luz:hover::after,
  .btn-luz:focus-visible::after { transform: translateX(0); opacity: 1; }
}
/* Peso PRIMARIO sin llegar a la "joya" verde llena (btn-primario, reservada al
   pago): para la acción principal de una pantalla (p. ej. Entrar/Crear cuenta),
   que no debe quedar apagada como una fantasma. */
.btn-secundario { background: var(--verde-profundo); color: var(--verde-cocuyo); border: 1px solid var(--verde-apagado); }
.btn-secundario:hover { box-shadow: var(--glow-suave); border-color: var(--verde-cocuyo); }

/* ============ Tarjeta de mundo (carátula que se enciende) ============ */
.mundo-card {
  position: relative; border-radius: var(--radio-md); overflow: hidden;
  background: var(--negro-elevado); border: 1px solid var(--negro-borde);
  transition: transform var(--trans-media), box-shadow var(--trans-media), border-color var(--trans-media);
}
/* El :hover va DENTRO de @media (hover:hover): en táctil/TV no hay hover
   real y el estado se quedaba "pegado" tras el toque. El foco de teclado
   (:focus-visible) sigue funcionando en todos los aparatos. */
.mundo-card:focus-visible {
  transform: translateY(-4px) scale(1.02);
  border-color: var(--verde-apagado);
  /* El anillo de foco VA INCLUIDO: el glow solo no basta para saber dónde
     estás con el teclado sobre una carátula que ya es luminosa. */
  box-shadow: var(--anillo-foco), var(--glow-suave), var(--sombra-2);
}
@media (hover: hover) {
  .mundo-card:hover {
    transform: translateY(-4px) scale(1.02);
    border-color: var(--verde-apagado);
    box-shadow: var(--glow-suave), 0 12px 32px rgba(0,0,0,0.6);
  }
}

/* ============ Coordenadas del universo (el prompt como estética) ============ */
.coordenadas {
  font-family: var(--fuente-mono); font-size: var(--texto-xs);
  color: var(--verde-cocuyo);
  /* Fondo oscurecido: el verde sobre --verde-profundo puro daba 3,96:1 (AA pide 4,5). */
  background: var(--acento-fondo); border: 1px solid var(--verde-apagado);
  border-radius: var(--radio-sm); padding: var(--esp-3) var(--esp-4);
  overflow-wrap: anywhere;
}

/* ============ Loader "Sintonizando señal…" ============ */
.sintonizando { display: flex; flex-direction: column; align-items: center; gap: var(--esp-4); }
.sintonizando .faros i { width: 14px; height: 14px; }

/* ============ Skeleton de carga (shimmer, acabado premium) ============ */
/* Reutilizable en cualquier página mientras carga (carátulas, tarjetas de
   perfil, email). Coherente con la marca: un brillo que "sintoniza". */
.skeleton {
  background: linear-gradient(100deg,
    var(--negro-elevado) 30%, var(--negro-borde) 50%, var(--negro-elevado) 70%);
  background-size: 200% 100%;
  animation: cargando-brillo 1.4s ease infinite;
  border-radius: var(--radio-md);
  color: transparent !important; /* oculta el texto de maqueta bajo el shimmer */
}
@keyframes cargando-brillo { to { background-position: -200% 0; } }

/* ============ Nav inferior móvil ============ */
.nav-inferior {
  position: fixed; bottom: 0; left: 0; right: 0; z-index: var(--z-nav);
  display: flex; justify-content: space-around; align-items: center;
  padding-top: var(--esp-2);
  padding-bottom: calc(var(--esp-2) + env(safe-area-inset-bottom));
  padding-left: calc(var(--esp-2) + env(safe-area-inset-left));
  padding-right: calc(var(--esp-2) + env(safe-area-inset-right));
  background: color-mix(in srgb, var(--negro-abismo) 92%, transparent); backdrop-filter: blur(14px);
  border-top: 1px solid var(--negro-borde);
}
.nav-inferior a {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  font-size: var(--texto-xs); color: var(--gris-niebla); padding: var(--esp-2) var(--esp-3);
  min-width: 64px; min-height: 48px; justify-content: center;
}
.nav-inferior a.activo { color: var(--verde-cocuyo); text-shadow: var(--glow-suave); }
/* Indicador de pestaña activa: una píldora de luz que se enciende
   sobre el icono (coherente con el lore: la señal sintonizada). */
.nav-inferior a { position: relative; transition: color var(--trans-media); }
.nav-inferior a::before {
  content: ""; position: absolute; top: 0; left: 50%;
  width: 18px; height: 3px; border-radius: var(--radio-pill);
  background: var(--verde-cocuyo); box-shadow: var(--glow-suave);
  transform: translateX(-50%) scaleX(0); opacity: 0;
  transition: transform var(--trans-media), opacity var(--trans-media);
}
.nav-inferior a.activo::before { transform: translateX(-50%) scaleX(1); opacity: 1; }
/* Micro-rebote del icono al tocar: se encoge al presionar y vuelve
   solo con la curva elástica al soltar. Solo transform. */
.nav-inferior a svg,
.nav-inferior a .faros { transition: transform 300ms var(--curva-suave); }
.nav-inferior a:active svg,
.nav-inferior a:active .faros { transform: scale(0.82); transition-duration: 80ms; }


/* Lanzamiento: Ver / Crear / Perfil en una cápsula compacta. */
.nav-inferior.nav-minima {
  left: 50%;
  right: auto;
  bottom: calc(var(--esp-3) + env(safe-area-inset-bottom));
  width: min(380px, calc(100vw - 2 * var(--esp-4)));
  transform: translateX(-50%);
  justify-content: center;
  gap: var(--esp-2);
  padding: 5px;
  border: 1px solid color-mix(in srgb, var(--blanco-luz) 12%, transparent);
  border-radius: var(--radio-pill);
  background: color-mix(in srgb, var(--negro-abismo) 88%, transparent);
  box-shadow: 0 14px 40px rgba(0, 0, 0, .38);
}
.nav-inferior.nav-minima a { flex: 1; border-radius: var(--radio-pill); }
.nav-inferior.nav-minima a.activo {
  background: color-mix(in srgb, var(--verde-profundo) 72%, transparent);
}

/* En escritorio la navegación deja de ocupar todo el borde inferior y se
   convierte en una cápsula superior. Conserva exactamente las mismas rutas,
   pero la interfaz se siente como una plataforma de cine de escritorio. */
@media (min-width: 900px) and (hover: hover) {
  .nav-inferior {
    top: calc(var(--esp-4) + env(safe-area-inset-top));
    bottom: auto;
    left: auto;
    right: max(var(--esp-4), calc((100vw - 1200px) / 2 + var(--esp-4)));
    width: auto;
    justify-content: flex-end;
    gap: var(--esp-1);
    padding: 5px;
    border: 1px solid color-mix(in srgb, var(--blanco-luz) 12%, transparent);
    border-radius: var(--radio-pill);
    background: color-mix(in srgb, var(--negro-abismo) 78%, transparent);
    box-shadow: 0 14px 40px rgba(0, 0, 0, .28);
  }
  .nav-inferior.nav-minima { transform: none; }
  .nav-inferior a {
    flex-direction: row;
    gap: var(--esp-2);
    min-width: auto;
    min-height: 40px;
    padding: .55rem .85rem;
    border-radius: var(--radio-pill);
  }
  .nav-inferior a::before { display: none; }
  .nav-inferior a.activo {
    color: var(--blanco-luz);
    background: color-mix(in srgb, var(--verde-profundo) 72%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--verde-cocuyo) 24%, transparent);
  }
}

/* ---------- Estados y variantes globales de .btn ----------
   Antes cada página redefinía disabled, bloque y peligro a su manera
   (perfil, soporte, admin, offline). Ahora viven aquí, una sola vez. */
.btn[disabled],
.btn[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; box-shadow: none; }
.btn[disabled]:active,
.btn[aria-disabled="true"]:active { transform: none; }
/* Un .btn-luz apagado no se enciende: ni punto, ni capa, ni deslizamiento. */
.btn-luz[disabled]::before, .btn-luz[aria-disabled="true"]::before,
.btn-luz[disabled]::after,  .btn-luz[aria-disabled="true"]::after { display: none; }
.btn-luz[disabled] .btn-luz-texto,
.btn-luz[aria-disabled="true"] .btn-luz-texto { transform: none !important; opacity: 1 !important; }
.btn-bloque { width: 100%; }
.btn-sm { min-height: 40px; padding: 0.55em 1.1em; font-size: var(--texto-sm); }
.btn-lg { min-height: 56px; padding: 0.95em 2em; font-size: var(--texto-md); }
/* Peligro (borrar cuenta, apagar pantallas…): rojo LF destructive. */
.btn-peligro {
  background: var(--peligro-fondo); color: var(--blanco-luz); font-weight: 800;
  border: 1px solid color-mix(in srgb, var(--peligro) 45%, transparent);
}
.btn-peligro:hover {
  filter: brightness(1.15);
  box-shadow: 0 0 18px color-mix(in srgb, var(--peligro) 40%, transparent);
}
/* Icono redondo (enviar en el chat, cerrar, controles). */
.btn-icono { width: 48px; height: 48px; min-height: 48px; padding: 0; border-radius: 50%; flex: 0 0 auto; }
.btn-icono svg { width: 22px; height: 22px; display: block; }

/* ============ Escarcha (Lime Frost): superficie de vidrio ============
   Para paneles, tarjetas y formularios que flotan sobre imagen o noche:
   fondo translúcido, desenfoque del fondo y un filo de luz arriba. */
.escarcha {
  background: var(--escarcha);
  border: 1px solid var(--escarcha-borde);
  -webkit-backdrop-filter: blur(18px) saturate(1.2); backdrop-filter: blur(18px) saturate(1.2);
  border-radius: var(--radio-md);
  box-shadow: var(--sombra-1), inset 0 1px 0 color-mix(in srgb, var(--blanco-luz) 8%, transparent);
}

/* ============ Utilidades ============ */
.oculto { display: none !important; }
/* El padding lateral suma el safe-area: en horizontal, el notch/las esquinas
   redondeadas no tapan el contenido. Vale --esp-4 a secas donde no hay notch. */
.contenedor {
  width: 100%; max-width: 1200px; margin-inline: auto;
  padding-left: calc(var(--esp-4) + env(safe-area-inset-left));
  padding-right: calc(var(--esp-4) + env(safe-area-inset-right));
}
.texto-secundario { color: var(--gris-niebla); }
.solo-lectores { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* ============ Menos movimiento (accesibilidad, WCAG 2.3.3) ============ */
/* Si el usuario pide reducir el movimiento en su sistema, apagamos animaciones
   y transiciones en TODA la app (los faros aparecen en cada página y latir en
   bucle marea a quien tiene sensibilidad vestibular). Los faros quedan
   ENCENDIDOS fijos — coherente con el lore: el cocuyo real (Pyrophorus) no
   parpadea, brilla constante. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .faros i {
    animation: none !important;
    opacity: 1 !important;
    box-shadow: var(--glow-medio) !important;
  }
  .skeleton { animation: none !important; }
}

/* ============================================================
   App Android (Google Play / TWA): DECISIÓN DEL DUEÑO 26-jul-2026 —
   el pago SÍ se muestra y se compra desde la app. Tras Epic vs
   Google (2026), en EE.UU. Google no puede prohibir el pago externo.
   checkout.stripe.com queda fuera del ámbito del TWA, así que el
   pago se abre como pestaña de navegador (Custom Tab). Las reglas
   que ocultaban la UI de pago con `html.en-twa` se retiraron aquí;
   la clase `en-twa` sigue existiendo (pwa.js) por si algún estilo
   futuro necesita distinguir la app.
   ============================================================ */

/* ============================================================
   Modo TV (mando a distancia): tv-nav.js pone la clase `modo-tv`
   en <html>. El foco debe verse fuerte desde lejos (sofá) y el
   elemento enfocado debe destacar. Reutiliza el verde de marca.
   ============================================================ */
html.modo-tv :focus {
  outline: 4px solid var(--verde-cocuyo, #00E77B) !important;
  outline-offset: 3px;
  border-radius: var(--radio-md, 12px);
}
html.modo-tv :focus-visible {
  outline: 4px solid var(--verde-cocuyo, #00E77B) !important;
}
/* Tarjetas/mundos enfocados: además un glow y un ligero zoom para
   que sea obvio dónde estás en la parrilla. */
html.modo-tv .plan-card:focus,
html.modo-tv .mundo:focus,
html.modo-tv .card:focus,
html.modo-tv [data-tv-focus]:focus {
  transform: scale(1.06);
  box-shadow: 0 0 0 4px var(--verde-cocuyo, #00E77B), 0 12px 40px rgba(0,0,0,.6);
  z-index: 5;
  transition: transform .12s ease, box-shadow .12s ease;
}
/* Micro-textos de las carátulas: a 3 metros de una tele son invisibles;
   en modo TV se suben al token mínimo legible. Cero impacto en móvil/PC. */
html.modo-tv .caratula-genero,
html.modo-tv .caratula-meta,
html.modo-tv .badge-nueva {
  font-size: var(--texto-xs);
}
/* Creator es una herramienta de trabajo con teclado/táctil, no una
   experiencia de sofá. En TV desaparece de la navegación por completo. */
html.modo-tv .nav-crear {
  display: none !important;
}
html.modo-tv .nav-inferior.nav-minima {
  width: min(280px, calc(100vw - 2 * var(--esp-4)));
}

/* ============================================================
   App iOS (Capacitor): ios-app.js pone `en-ios` en <html>.
   Reader-app: no se cobra dentro de la app (se paga en la web), así que
   ocultamos SOLO los elementos de pago. La navegación web (.nav-inferior)
   se MANTIENE visible; si no, el usuario se queda sin forma de volver a la
   home (aún no hay tab bar nativa). Cuando se añada la tab bar nativa, se
   podrá volver a ocultar .nav-inferior aquí.
   ============================================================ */
html.en-ios .planes,
html.en-ios #fundadores,
html.en-ios .franja-fundador,
html.en-ios .plan-card,
html.en-ios [data-plan],
html.en-ios #btn-comenzar,
html.en-ios #btn-fundador-checkout,
html.en-ios #btn-senal,
html.en-ios #unete-cocuyo,
html.en-ios #abrir-recarga,
html.en-ios #cuenta-recargar,
html.en-ios #recarga-fondo,
html.en-ios #btn-recargar-perfil {
  display: none !important;
}

/* Aviso reader-app: oculto en web/Android; visible solo en la cáscara iOS. */
.aviso-reader-ios { display: none; }
html.en-ios .aviso-reader-ios {
  display: block;
  margin: 0 0 var(--esp-4);
  padding: var(--esp-3) var(--esp-4);
  border: 1px solid var(--negro-borde);
  border-radius: var(--radio-md);
  background: var(--acento-fondo);
  color: var(--blanco-luz);
  font-size: var(--texto-sm);
}


/* ============================================================
   HOME — RETENCIÓN (home-extras.js): filas "Seguir viendo" y
   "Mi lista", estrella de guardar en cada carátula y caja del
   buscador con lupa. Los usan index.html + home-extras.js.
   ============================================================ */

/* Las filas extra entran con un fundido suave (nada de saltos). */
.fila-extra { animation: fila-extra-aparece 0.4s ease; }
@keyframes fila-extra-aparece { from { opacity: 0; } to { opacity: 1; } }

/* Barra de progreso pegada al borde inferior de la carátula
   ("Seguir viendo"): el trozo ya visto se enciende en verde. */
.continuar-progreso {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  height: 4px;
  background: color-mix(in srgb, var(--blanco-luz) 16%, transparent);
  overflow: hidden;
  pointer-events: none;
}
.continuar-progreso i {
  display: block; height: 100%;
  background: var(--verde-cocuyo);
  box-shadow: var(--glow-suave);
}

/* Estrella "Mi lista" (abajo-derecha de cada carátula). Es un botón
   DENTRO del enlace de la tarjeta: home-extras.js frena la navegación
   al tocarla. Apagada = tenue; guardada = verde encendido con glow. */
.btn-estrella {
  position: absolute; right: 0.4em; bottom: 0.45em; z-index: 3;
  /* 44px = mínimo táctil real; a 36px, errar por 4px navegaba a otra página. */
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: color-mix(in srgb, var(--blanco-luz) 80%, transparent);
  background: var(--escarcha);
  border: 1px solid var(--escarcha-borde);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  transition: color var(--trans-rapida), border-color var(--trans-rapida),
              box-shadow var(--trans-media), transform var(--trans-rapida);
}
.btn-estrella:focus-visible {
  color: var(--verde-cocuyo);
  border-color: color-mix(in srgb, var(--verde-cocuyo) 55%, transparent);
}
@media (hover: hover) {
  .btn-estrella:hover {
    color: var(--verde-cocuyo);
    border-color: color-mix(in srgb, var(--verde-cocuyo) 55%, transparent);
  }
}
.btn-estrella:active { transform: scale(0.9); }
.btn-estrella.guardada {
  color: var(--verde-cocuyo);
  border-color: var(--verde-cocuyo);
  box-shadow: var(--glow-suave);
}
.btn-estrella.guardada svg { fill: currentColor; }
/* Con estrella, el pie de la carátula deja hueco para no chocar. */
.caratula.con-estrella .caratula-pie { padding-right: 3.4rem; } /* 44px de estrella + margen: antes "10 EPISODIOS" se metía debajo */

/* Caja del buscador con la lupa dentro ("rastrear señales"). */
.buscar-caja { position: relative; }
.buscar-caja .buscar-lupa {
  position: absolute; left: var(--esp-4); top: 50%;
  translate: 0 -50%;
  color: var(--gris-humo);
  pointer-events: none;
  transition: color var(--trans-rapida);
}
.buscar-caja:focus-within .buscar-lupa {
  color: var(--verde-cocuyo);
  filter: drop-shadow(var(--glow-suave));
}
.buscar-caja .campo-busqueda {
  padding-left: calc(var(--esp-4) + 20px + var(--esp-2));
}

/* Menos movimiento: el fundido de las filas extra se apaga (la regla
   global de tokens ya frena todo; esto lo deja explícito). */
@media (prefers-reduced-motion: reduce) {
  .fila-extra { animation: none; }
}

/* ============================================================
   === TEATRO VISUAL (fx.js): encendido, señal-cargando, splash
   === y transiciones de página. Añadido al final de tokens.css.
   ============================================================ */

/* ---------- 1) Encendido bioluminiscente de las carátulas ----------
   En reposo la carátula está levemente apagada; al pasar el dedo, el
   ratón o el foco de teclado, el Cocuyo la ilumina: brillo pleno +
   glow verde (la elevación del hover ya vive en .mundo-card:hover,
   más arriba). Aquí se añade la LUZ (filter), la transición 240 ms y
   el estado :active para el toque en móvil. */
.mundo-card .caratula,
.mundo-card img {
  filter: brightness(0.88) saturate(0.96);
  transition: filter 240ms ease, transform 240ms ease,
              box-shadow 240ms ease, border-color 240ms ease,
              opacity 240ms ease;
}
.mundo-card:focus-visible .caratula,
.mundo-card:active .caratula,
.mundo-card:focus-visible img,
.mundo-card:active img {
  filter: brightness(1.06) saturate(1.05);
}
/* El :hover solo donde existe hover real (ratón): en táctil se quedaba pegado. */
@media (hover: hover) {
  .mundo-card:hover .caratula,
  .mundo-card:hover img {
    filter: brightness(1.06) saturate(1.05);
  }
}
/* :active = el toque en móvil enciende igual que el hover de
   escritorio (misma elevación y glow que .mundo-card:hover). */
.mundo-card:active {
  transform: translateY(-4px) scale(1.02);
  border-color: var(--verde-apagado);
  box-shadow: var(--glow-suave),
              0 12px 32px color-mix(in srgb, var(--negro-abismo) 85%, transparent);
}

/* ---------- 2) "Sintonizando señal…": esqueleto de carga ----------
   fx.js pone .señal-cargando en el CONTENEDOR de cada imagen del grid
   hasta que su señal llega (load/error): esqueleto oscuro con barrido
   de luz verde. La clase va DOBLADA en el selector para ganar a los
   ::before/::after decorativos de cada página sin usar !important. */
.señal-cargando.señal-cargando {
  position: relative;
  overflow: hidden;
  background-color: var(--negro-elevado);
}
.señal-cargando.señal-cargando::after {
  content: "";
  position: absolute; inset: 0; z-index: 3;
  pointer-events: none;
  background: linear-gradient(100deg,
    transparent 25%,
    color-mix(in srgb, var(--verde-cocuyo) 18%, transparent) 50%,
    transparent 75%);
  background-size: 220% 100%;
  animation: señal-barrido 1.3s ease-in-out infinite;
}
@keyframes señal-barrido {
  from { background-position: 180% 0; }
  to   { background-position: -80% 0; }
}
/* La imagen no se enseña a medias: invisible hasta llegar entera y,
   al llegar, entra con un fundido suave (clase que pone fx.js). */
.señal-cargando.señal-cargando img { opacity: 0; }
img.señal-recibida { animation: señal-aparece 400ms ease; }
@keyframes señal-aparece { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .señal-cargando.señal-cargando::after { animation: none; opacity: 0.5; }
  img.señal-recibida { animation: none; }
}

/* ---------- 3) Splash de los dos faros (fx.js, 1ª carga de la sesión) --
   Overlay negro con las dos elipses verdes encendiéndose (glow
   creciente) y fundido a la página. fx.js lo autodestruye a los
   1200 ms pase lo que pase, y con menos-movimiento ni lo crea. */
.fx-splash {
  position: fixed; inset: 0;
  z-index: calc(var(--z-modal) + 20);
  display: flex; align-items: center; justify-content: center;
  background: var(--negro-abismo);
  pointer-events: none;              /* JAMÁS bloquea un toque */
  animation: fx-splash-fuera 350ms ease 750ms forwards;
}
.fx-splash .fx-faros { display: inline-flex; gap: 0.55em; font-size: 3rem; }
.fx-splash .fx-faros i {
  width: 0.72em; height: 0.88em;     /* elipse vertical: el faro del insecto */
  border-radius: 50%;
  background: var(--verde-cocuyo);
  animation: fx-faro-enciende 650ms ease-out both;
}
.fx-splash .fx-faros i + i { animation-delay: 130ms; }
@keyframes fx-faro-enciende {
  0%   { opacity: 0; box-shadow: none; transform: scale(0.85); }
  60%  { opacity: 1; box-shadow: var(--glow-medio); }
  100% { opacity: 1; box-shadow: var(--glow-fuerte); transform: scale(1); }
}
@keyframes fx-splash-fuera { to { opacity: 0; visibility: hidden; } }
@media (prefers-reduced-motion: reduce) {
  .fx-splash { display: none; }      /* doble cinturón: fx.js tampoco lo crea */
}

/* ---------- 4) Transiciones de página (view transitions, mismo origen) --
   Solo los navegadores que las soportan (Chrome/Edge 126+) las
   activan; el resto ignora este bloque ENTERO y navega como siempre
   (degradación total, sin JS). Fundido + deslizamiento sutil 200 ms. */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: fx-pagina-sale 200ms ease both; }
::view-transition-new(root) { animation: fx-pagina-entra 200ms ease both; }
@keyframes fx-pagina-sale  { to { opacity: 0; } }
@keyframes fx-pagina-entra {
  from { opacity: 0; transform: translateY(10px); }
}
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none; }
}

/* ============ Toque premium de los botones ============
   El glow crece con suavidad (curva elegante), el :active se hunde
   con una respuesta rápida y el primario "flota" un pelo al pasar
   el ratón. Solo transform/box-shadow/filter (rendimiento). */
.btn {
  transition: transform 280ms var(--curva-suave),
              box-shadow 280ms var(--curva-suave),
              border-color 280ms var(--curva-suave),
              filter 280ms var(--curva-suave);
}
.btn:active {
  transform: translateY(1px) scale(0.97); /* hundimiento físico */
  transition-duration: 80ms;              /* respuesta inmediata al dedo */
}
@media (hover: hover) {
  .btn-primario:hover { transform: translateY(-1px); filter: brightness(1.06); }
  .btn-fantasma:hover {
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--verde-cocuyo) 25%, transparent);
  }
}

/* ============ Detalles de lujo globales ============ */
/* Seleccionar texto enciende el verde del Cocuyo */
::selection { background: var(--verde-cocuyo); color: var(--negro-abismo); text-shadow: none; }

/* Scrollbar del documento: fina y abisal, solo donde hay puntero fino
   (en móvil y TV no existe y todo queda limpio como está). */
@media (hover: hover) and (pointer: fine) {
  html { scrollbar-width: thin; scrollbar-color: var(--negro-borde) transparent; }
  html::-webkit-scrollbar { width: 8px; }
  html::-webkit-scrollbar-thumb { background: var(--negro-borde); border-radius: var(--radio-pill); }
  html::-webkit-scrollbar-thumb:hover { background: var(--verde-apagado); }
  html::-webkit-scrollbar-track { background: transparent; }
}

/* Cada página se ENCIENDE al llegar: fundido de 160ms (<200ms, sin FOUC:
   tokens.css carga en el <head>, así que la regla existe antes del primer
   pintado). Complementa a las view transitions de Chrome y da el mismo
   acabado en Safari/Firefox, que no las soportan. */
@media (prefers-reduced-motion: no-preference) {
  body { animation: pagina-enciende 160ms ease-out; }
  @keyframes pagina-enciende { from { opacity: 0; } }
}

/* ---------- Revelado al hacer scroll (fx.js pone .revela/.revelado) ------
   Solo opacity/transform (compositor). Si el JS falla, .revela nunca se
   añade y todo se ve normal. Con menos-movimiento, visible siempre. */
.revela {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 700ms var(--curva-suave), transform 700ms var(--curva-suave);
}
.revela.revelado { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .revela { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* ---------- "Saltar al contenido" (accesibilidad; guía maestra p. 33) ----
   Primer enlace del <body> en cada página: invisible hasta que recibe el
   foco con el tabulador. Quien navega con teclado o lector de pantalla
   salta la cabecera y el menú de un golpe; el resto no lo ve jamás. */
.saltar-contenido {
  position: absolute;
  left: -9999px;
  top: var(--esp-3);
  z-index: 9999;
  padding: var(--esp-2) var(--esp-4);
  border-radius: var(--radio-pill);
  background: var(--negro-elevado);
  border: 1px solid var(--verde-cocuyo);
  color: var(--verde-cocuyo);
  text-decoration: none;
  box-shadow: var(--glow-suave);
}
.saltar-contenido:focus-visible,
.saltar-contenido:focus {
  left: var(--esp-3, 12px);
}

/* Barra inferior Ver/Crear/Perfil: SOLO para quien ya tiene pista de
   sesion (pwa.js pone data-viajero en <html>). Un invitado que llega a
   mundo/perfil/legales desde la intro no ve pestanas de app (dueno,
   23-ago-2026). visibility conserva el hueco: nada salta. */
.nav-inferior { visibility: hidden; }
html[data-viajero] .nav-inferior { visibility: visible; }
