/* =========================================================
   RiosTec Comunidad — "Comunidad KiweGame"
   Tema oscuro azul/blanco/negro (variante gamer de la marca RiosTec).
   Estructura inspirada en el tema "gamer" de rt-bio, RECOLOREADA a azul.
   Mobile-first. BEM. Sin dependencias externas. Color/tipografía por variables.
   ========================================================= */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

[hidden] { display: none !important; }

/* ---------------------------------------------------------
   SISTEMA DE 2 TEMAS CONMUTABLES (SPEC 0006).
   El MISMO set de tokens con 2 valores → el resto del CSS (y el panel) solo
   consume var(--…): así público + panel + login obedecen el tema activo.

   - oled  → "OLED" (oscuro azul eléctrico sobre negro; default del modo oscuro
     del SO). Es el tema base: superficies casi negras con leve tinte azul.
   - claro → "Día" (fondo claro on-brand, texto oscuro; default modo claro).

   El tema se fija client-side (data-tema en <html>) por el script anti-FOUC +
   el conmutador (theme.js), sin variar el HTML por request → compatible con el
   caché LiteSpeed. Contrato: NINGÚN color hardcodeado fuera de estos bloques.

   Tokens SOBRE azul: --sobre-acento (texto/íconos sobre gradiente o fill azul).
   En claro --blanco invierte a navy oscuro, así que NO sirve sobre botón azul.
   --------------------------------------------------------- */
[data-tema="oled"] {
  --azul: #35a8ff;
  --azul-claro: #7ccbff;
  --azul-dim: rgba(53, 168, 255, 0.15);
  --azul-borde: rgba(53, 168, 255, 0.42);
  /* SPEC 0020: azul FUERTE para fill sólido con texto blanco (--sobre-acento). El --azul
     de marca sobre blanco cae bajo AA (~2.6:1); este llega ≥4.5:1 (medido ~6.3:1). Solo
     lo usa el chip "Dueño" del hub de comunidad (jerarquía máxima del control de nivel). */
  --azul-fuerte: #0d5cc0;

  --negro: #000000;
  --azul-oscuro: #05070c;
  --superficie: #0b0e16;
  --superficie-2: #141a26;
  --borde: rgba(120, 170, 240, 0.18);
  --top-bg: rgba(0, 0, 0, 0.86);
  --scrim: rgba(7, 12, 24, 0.7);
  color-scheme: dark;

  --blanco: #f5f8ff;
  --gris: #93a6c6;
  --gris-suave: #bccce6;

  --vivo: #ff5566;
  --vivo-rgb: 255, 85, 102;
  /* "Jugando ahora" (SPEC 0011): violeta, distinto del rojo "En vivo". */
  --jugando: #b98cff;
  --jugando-rgb: 185, 140, 255;
  --ok: #35e29a;
  --ok-rgb: 53, 226, 154;
  --verde-tinta: #05210f;

  --grad-azul: linear-gradient(135deg, #35a8ff, #7ccbff);
  --sobre-acento: #ffffff;

  --texto: var(--blanco);
  --texto-suave: var(--gris-suave);
  --error: #ff6b76;
  --error-rgb: 255, 107, 118;
  --grad: var(--grad-azul);

  /* Negro puro: glow casi nulo + jerarquía por borde/elevación, no por glow. */
  --fondo-glows: radial-gradient(ellipse 70% 45% at 15% 0%, rgba(53,168,255,0.07) 0%, transparent 55%);
  --rejilla-color: rgba(53,168,255,0.02);
  --sombra-card: 0 0 0 1px rgba(120,170,240,0.06);
  --sombra-hover: 0 6px 26px rgba(53,168,255,0.16);
  --sombra-modal: 0 20px 60px rgba(0,0,0,0.7);

  /* SPEC 0026: tinte de superficie del evento de admin (se layerea SOBRE --superficie,
     nunca a secas). Sutil para no competir con el rojo "EN VIVO". */
  --admin-ev-wash: rgba(53, 168, 255, 0.09);

  --font-head: 'Rajdhani', sans-serif;
  --font-body: 'Inter', sans-serif;

  --radio: 14px;
  --radio-sm: 10px;
  --tap: 44px;

  --p-twitch: #a970ff;
  --p-youtube: #ff6161;
  --p-tiktok: var(--azul-claro);
  --p-facebook: #3b8bff;
  --p-kick: #53fc18;
  --p-instagram: #e56ab3;
  --p-x: #e7ecf5;

  /* Espíritus (SPEC 0016 presentación v2): el RECUADRO del cromo se colorea por
     VARIANTE (no por rareza) vía .rtc-esp--v-*; la rareza va como etiqueta NO cromática
     (.rtc-esp__rareza). Los 4 tokens de variante (incl. --var-estandar, neutro/acero
     sobrio) quedan AA en los 2 temas. Los --rareza-* se conservan solo por si un texto
     informativo los necesita, pero ya NO tiñen el marco. */
  --rareza-rare: #7aa2ff;      --rareza-rare-rgb: 122, 162, 255;
  --rareza-epic: #c264ff;      --rareza-epic-rgb: 194, 100, 255;
  --rareza-legendary: #ff9b3d; --rareza-legendary-rgb: 255, 155, 61;
  --rareza-mythic: #ffd24a;    --rareza-mythic-rgb: 255, 210, 74;
  --var-estandar: #a6b4cc;     --var-estandar-rgb: 166, 180, 204;
  --var-gold: #f5c542;         --var-gold-rgb: 245, 197, 66;
  /* Oro PARA TEXTO (≥AA sobre tintes): en oled el gold brillante ya contrasta. */
  --oro-texto: #f5c542;
  --var-gummy: #ff8ac2;        --var-gummy-rgb: 255, 138, 194;
  --var-galaxy: #a78bfa;       --var-galaxy-rgb: 167, 139, 250;
  --var-holofoil: #34e7e4;     --var-holofoil-rgb: 52, 231, 228;
  --grad-galaxy: linear-gradient(135deg, #7c5cff 0%, #22d3ee 55%, #ff6ec7 100%);
  --grad-holofoil: linear-gradient(135deg, #a7f3d0 0%, #67e8f9 35%, #c4b5fd 70%, #fbcfe8 100%);
  --esp-falta-opacidad: 0.42;
  /* SPEC 0023 — anillo de progreso (pista del donut, tras el fill --azul) y trama diagonal
     del estado "falta" (lee "ranura por conseguir" en ambas superficies). Tenues a propósito
     (canal secundario), NO texto → no requieren AA de texto. */
  /* §D m1 — pista un pelo más presente para que a 0% el anillo no se vea "muerto"/roto. */
  --esp-anillo-track: rgba(120, 170, 240, 0.24);
  --esp-falta-patron: rgba(147, 166, 198, 0.10);
  /* Fondo de la figura en estado "te falta". En oled `--superficie-2` ya despega del lienzo
     negro, así que aquí NO cambia. Ver el valor propio de `claro`. */
  --esp-falta-fondo: var(--superficie-2);
  /* Relleno de la barra de progreso. En oled es el azul de marca: medido contra la pista
     (rgba(120,170,240,.24) sobre #000 → rgb(28.8,40.8,57.6)) da 5.75:1. */
  --esp-medidor-fill: var(--azul);
}

[data-tema="claro"] {
  --azul: #2f9bff;
  --azul-claro: #0b62c9;
  --azul-dim: rgba(47, 155, 255, 0.12);
  --azul-borde: rgba(47, 155, 255, 0.45);
  /* SPEC 0020: azul FUERTE (fill del chip "Dueño") con texto blanco ≥AA (medido ~8:1). */
  --azul-fuerte: #0d4f9e;

  --negro: #eef2f8;         /* lienzo claro (rol invertido) */
  --azul-oscuro: #dce6f5;
  --superficie: #ffffff;
  --superficie-2: #f1f5fb;
  --borde: rgba(15, 40, 80, 0.14);
  --top-bg: rgba(238, 242, 248, 0.86);
  --scrim: rgba(7, 12, 24, 0.7);   /* velo navy: aísla el modal también en Día */
  color-scheme: light;

  --blanco: #0f1b2e;         /* "texto principal": ahora navy oscuro sobre claro */
  --gris: #5b6b85;
  --gris-suave: #3f4f6b;

  --vivo: #d0142a;
  --vivo-rgb: 208, 20, 42;
  /* "Jugando ahora" (SPEC 0011): violeta AA sobre claro. */
  --jugando: #6d28d9;
  --jugando-rgb: 109, 40, 217;
  /* Verde de éxito en claro: oscurecido a #0b7a45 para AA transversal — texto --verde-tinta
     (blanco) sobre relleno --ok da 5.42:1 (badge .rtc-estado--abierto Y CTA WhatsApp). */
  --ok: #0b7a45;
  --ok-rgb: 11, 122, 69;
  --verde-tinta: #ffffff;

  --grad-azul: linear-gradient(135deg, #1668d6, #2f9bff);
  --sobre-acento: #ffffff;

  --texto: var(--blanco);
  --texto-suave: var(--gris-suave);
  --error: #c81e2c;
  --error-rgb: 200, 30, 44;
  --grad: var(--grad-azul);

  --fondo-glows: none;
  --rejilla-color: transparent;
  --sombra-card: 0 1px 3px rgba(15,30,60,0.08), 0 8px 24px rgba(15,30,60,0.06);
  --sombra-hover: 0 10px 28px rgba(15,30,60,0.12);
  --sombra-modal: 0 24px 60px rgba(15,30,60,0.20);

  /* SPEC 0026: tinte del evento de admin (layer sobre --superficie), sutil en claro. */
  --admin-ev-wash: rgba(47, 155, 255, 0.12);

  --font-head: 'Rajdhani', sans-serif;
  --font-body: 'Inter', sans-serif;

  --radio: 14px;
  --radio-sm: 10px;
  --tap: 44px;

  --p-twitch: #772ce8;
  --p-youtube: #e60000;
  --p-tiktok: #111111;
  --p-facebook: #1877f2;
  --p-kick: #17a34a;
  --p-instagram: #c13584;
  --p-x: #0f1419;

  /* Espíritus (SPEC 0016 presentación v2): mismas familias, valores MÁS PROFUNDOS para
     contraste AA sobre fondo claro. --var-gold baja a #946a00 (el histórico #a97b00 no
     alcanzaba AA). --var-estandar es un acero sobrio legible sobre blanco. */
  --rareza-rare: #3b5bdb;      --rareza-rare-rgb: 59, 91, 219;
  --rareza-epic: #8b2fd6;      --rareza-epic-rgb: 139, 47, 214;
  --rareza-legendary: #c2560a; --rareza-legendary-rgb: 194, 86, 10;
  --rareza-mythic: #9a7000;    --rareza-mythic-rgb: 154, 112, 0;
  --var-estandar: #5f6f88;     --var-estandar-rgb: 95, 111, 136;
  --var-gold: #946a00;         --var-gold-rgb: 148, 106, 0;
  /* Oro PARA TEXTO en claro: más oscuro que el --var-gold (marco 3:1) para pasar AA
     como texto (≥4.5) sobre tintes claros; NO afecta al oro de los espíritus. */
  --oro-texto: #6e4f00;
  --var-gummy: #c02a7a;        --var-gummy-rgb: 192, 42, 122;
  --var-galaxy: #6d28d9;       --var-galaxy-rgb: 109, 40, 217;
  --var-holofoil: #0e7f8c;     --var-holofoil-rgb: 14, 127, 140;
  --grad-galaxy: linear-gradient(135deg, #5b3fd6 0%, #0e8fb0 55%, #c2569e 100%);
  --grad-holofoil: linear-gradient(135deg, #34d399 0%, #22d3ee 35%, #a78bfa 70%, #f472b6 100%);
  /* v0.51.2 — 0.5 → 0.66. Con el lienzo claro, seis filas seguidas de sprites al 50 % se leían
     como skeleton de carga. Sube el peso del sprite sin llegar al 1.0 de "lo tengo". */
  --esp-falta-opacidad: 0.66;
  /* SPEC 0023 — anillo de progreso + trama "falta". Valores propios del tema claro
     (algo más marcados que en oled para que la trama se lea sobre superficies blancas). */
  /* §D m1 — pista más presente (tema claro) para que a 0% el anillo no se vea vacío. */
  --esp-anillo-track: rgba(15, 40, 80, 0.18);
  --esp-falta-patron: rgba(91, 107, 133, 0.14);
  /* Fondo de la figura en estado "te falta" (v0.51.2). `--superficie-2` (#f1f5fb) sobre el
     lienzo `--negro` (#eef2f8) son casi el mismo valor: con seis filas seguidas sin marcar, el
     bloque se leía como SKELETON DE CARGA (página rota), no como colección vacía.
     ⚠️ v0.51.3 — NÚMERO CORREGIDO. Este token mide 1.087:1 contra el lienzo (#e2e9f4 vs
     #eef2f8): NO "se separa lo justo para leerse como ranura", como afirmaba v0.51.2 — a
     1.087:1 el ojo casi no lo distingue. Lo que de hecho quitó el aspecto de skeleton fue la
     subida de `--esp-falta-opacidad` de 0.5 a 0.66 (el peso del sprite), ratificada por el
     guardián de tema. El token se CONSERVA porque suma como refuerzo, pero no es el mérito. */
  --esp-falta-fondo: #e2e9f4;
  /* Relleno de la barra de progreso. `--azul` (#2f9bff) contra la pista compuesta sobre el
     lienzo (rgb(197.9, 205.6, 217.8)) mide 1.82:1 — muy por debajo del 3:1 de objeto gráfico,
     y sustituye a un aro que medía 5.75:1, así que era regresión del mismo canal. El paliativo
     `inset 0 0 0 1px var(--borde)` que llevaba v0.51.1 medía 2.23:1 compuesto CONTRA EL PROPIO
     RELLENO: no dibujaba contorno, se eliminó. `--azul-claro` (#0b62c9) mide **3.66:1** ✓
     (v0.51.3: el 3.75 publicado por v0.51.2 no se reproduce; recalculado sRGB/WCAG2 contra la
     pista compuesta rgb(197.86, 205.64, 217.76) da 3.662, y el guardián de tema midió 3.66 en
     vivo. Pasa el 3:1 de objeto gráfico igual, pero el número correcto es 3.66). */
  --esp-medidor-fill: var(--azul-claro);
}

html, body {
  min-height: 100vh;
  background-color: var(--negro);
  font-family: var(--font-body);
  color: var(--blanco);
}

/* Anti scroll-horizontal SIN romper el `position:sticky` del top bar.
   Antes: `overflow-x: hidden` en html/body convertía al DOCUMENTO en contenedor
   de scroll → anulaba el sticky del header (quedaba estático). `overflow-x: clip`
   NO crea contenedor de scroll (no afecta al sticky) pero igual ACOTA cualquier
   desbordamiento horizontal de un hijo. Va en `body` (no en html) para que el
   viewport siga siendo el ancestro de scroll del header sticky. */
body { overflow-x: clip; }

body.rtc {
  background-image: var(--fondo-glows);
  background-attachment: fixed;
}

body.rtc::before {
  content: '';
  position: fixed;
  inset: 0;
  background-image:
    linear-gradient(var(--rejilla-color) 1px, transparent 1px),
    linear-gradient(90deg, var(--rejilla-color) 1px, transparent 1px);
  background-size: 48px 48px;
  pointer-events: none;
  z-index: 0;
}

/* Accesibilidad: enlace para saltar al contenido. */
.rtc-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--azul);
  color: var(--sobre-acento);
  padding: 10px 16px;
  border-radius: 0 0 var(--radio-sm) 0;
  z-index: 1000;
}
.rtc-skip:focus { left: 0; }

/* ---------------------------------------------------------
   TOP BAR delgado (rework del menú móvil) + NAV
   Mobile-first: barra de ~56px en 1 fila → hamburguesa (☰) + marca compacta +
   acciones (tema ◐ · Acceso). Las 7 secciones viven en el DRAWER (más abajo).
   Desktop (≥900px, media query al final del bloque): vuelve la nav inline de 7
   enlaces sin hamburguesa (el header de 1 fila de siempre). El top bar es STICKY
   de verdad porque el overflow-x del documento pasó a `clip` (ver html,body).
   --------------------------------------------------------- */
.rtc-top {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--top-bg);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--borde);
}

.rtc-top__in {
  max-width: 1080px;
  margin: 0 auto;
  padding: 0.4rem 0.9rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 56px;
}

/* Hamburguesa: SOLO móvil (el desktop la oculta). Abre el drawer (nav.js). */
.rtc-top__ham {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  min-width: var(--tap);
  padding: 0;
  border: 0;
  border-radius: var(--radio-sm);
  background: transparent;
  color: var(--blanco);
  cursor: pointer;
  flex-shrink: 0;
  transition: background-color 0.18s, color 0.18s;
}
.rtc-top__ham:hover,
.rtc-top__ham:focus-visible { background: var(--azul-dim); color: var(--azul-claro); }
.rtc-top__ham:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-top__hamico { display: inline-flex; }
.rtc-top__hamico svg { width: 24px; height: 24px; }

.rtc-brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  color: var(--blanco);
  min-width: 0;
}

.rtc-brand__logo {
  /* SPEC 0027 — emblema KG de marca (PNG transparente, sirve en ambos temas).
     Reemplaza la antigua caja azul con "▶". El wordmark va como texto al lado. */
  display: block;
  width: auto;
  height: 32px;
  object-fit: contain;
  flex-shrink: 0;
}

.rtc-brand__txt {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.2rem;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
/* Marca compacta: móvil muestra "KiweGame"; desktop, el nombre completo (media
   query). Las dos variantes viven en el DOM; el CSS alterna cuál se ve. */
.rtc-brand__txt--full { display: none; }
.rtc-brand__txt--corta { display: inline; }

/* Acciones del top bar (tema + Acceso), separadas de la navegación y empujadas a
   la derecha en ambos layouts. La primera `margin-left:auto` (aquí o en la nav en
   desktop) reparte el espacio libre → deja la marca a la izquierda. */
.rtc-top__acc {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
  flex-shrink: 0;
}

/* Nav INLINE: oculta en móvil (sus enlaces van al drawer); reaparece en desktop. */
.rtc-nav {
  display: none;
  gap: 4px;
}

.rtc-nav__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 14px;
  border-radius: 999px;
  color: var(--gris-suave);
  text-decoration: none;
  font-size: 0.95rem;
  font-weight: 600;
  transition: background 0.2s, color 0.2s;
}

.rtc-nav__link:hover,
.rtc-nav__link:focus-visible {
  background: var(--azul-dim);
  color: var(--blanco);
}

.rtc-nav__link.is-active {
  background: var(--grad-azul);
  color: var(--sobre-acento);
}

/* "Acceso / Mi panel": acción (no una sección) → contorno azul. Móvil = icon-only
   (el texto se oculta; el aria-label del enlace da el nombre accesible). */
.rtc-top__acceso {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  min-height: var(--tap);
  padding: 0;
  border-radius: 999px;
  color: var(--blanco);
  text-decoration: none;
  font-size: 0.95rem;
  font-weight: 600;
  border: 1px solid var(--azul);
  transition: background 0.2s, color 0.2s;
}
.rtc-top__acceso:hover,
.rtc-top__acceso:focus-visible { background: var(--azul-dim); color: var(--blanco); }
.rtc-top__acceso:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-nav__accico { display: inline-flex; }
.rtc-nav__accico svg { width: 18px; height: 18px; }
.rtc-nav__acctxt { display: none; } /* móvil: solo ícono (desktop lo restaura). */

/* ---------------------------------------------------------
   CONMUTADOR DE TEMA (SPEC 0006). Botón redondo en la nav que alterna
   oled ↔ claro. Muestra el ícono del tema ACTIVO: los íconos
   viven en el DOM y el CSS muestra el que corresponde a [data-tema] del <html>
   (fijado por el anti-FOUC antes del primer paint → sin parpadeo). theme.js
   solo actualiza aria-label/title/meta al ciclar.
   --------------------------------------------------------- */
.rtc-temabtn {
  width: var(--tap);
  height: var(--tap);
  min-width: var(--tap);
  min-height: var(--tap);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--gris-suave);
  cursor: pointer;
  flex-shrink: 0;
  transition: background-color 0.18s, color 0.18s, transform 0.12s;
}
.rtc-temabtn:hover,
.rtc-temabtn:focus-visible {
  background: var(--azul-dim);
  color: var(--azul-claro);
}
.rtc-temabtn:active { transform: scale(0.94); }
.rtc-temabtn:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

.rtc-temabtn__ico {
  display: none;
  align-items: center;
  justify-content: center;
  transition: transform 0.18s;
}
.rtc-temabtn__ico svg { width: 22px; height: 22px; }
/* Solo el ícono del tema activo se muestra (según data-tema del <html>). */
[data-tema="oled"] .rtc-temabtn__ico--oled,
[data-tema="claro"] .rtc-temabtn__ico--dia { display: inline-flex; }
/* Micro-rotación al enfocar/pasar el cursor (guiño de "cambiar"). */
.rtc-temabtn:hover .rtc-temabtn__ico,
.rtc-temabtn:focus-visible .rtc-temabtn__ico { transform: rotate(180deg); }

@media (prefers-reduced-motion: reduce) {
  .rtc-temabtn,
  .rtc-temabtn__ico { transition: none; }
  .rtc-temabtn:hover .rtc-temabtn__ico,
  .rtc-temabtn:focus-visible .rtc-temabtn__ico { transform: none; }
}

/* Transición suave SOLO durante el cambio manual de tema (clase temporal que
   pone theme.js ~380ms). No afecta el primer paint ni los hovers permanentes.
   Se omite `background-image` a propósito: los gradientes/glows no interpolan
   suave y darían un salto; el cambio dominante (superficies, texto, bordes,
   sombras) sí transiciona. */
html.rtc-tema-anim,
html.rtc-tema-anim *,
html.rtc-tema-anim *::before,
html.rtc-tema-anim *::after {
  transition: background-color 0.38s ease, color 0.38s ease,
              border-color 0.38s ease, box-shadow 0.38s ease, fill 0.38s ease !important;
}
@media (prefers-reduced-motion: reduce) {
  html.rtc-tema-anim,
  html.rtc-tema-anim *,
  html.rtc-tema-anim *::before,
  html.rtc-tema-anim *::after { transition: none !important; }
}

/* ---------------------------------------------------------
   DRAWER de navegación (móvil): overlay + panel lateral con las 7 secciones +
   Acceso/Mi panel + Aviso de privacidad. Oculto por defecto ([hidden]) y en
   desktop (display:none). Lo abre/cierra nav.js (data-rtc-drawer): añade
   .is-abierto para animar la entrada y bloquea el scroll del body
   (html.rtc-no-scroll). Foco atrapado dentro del panel; Esc/overlay/enlace/✕ cierran.
   Superficies del tema (nada de card blanca sobre el shell oled): scrim = --scrim.
   --------------------------------------------------------- */
.rtc-drawer {
  position: fixed;
  inset: 0;
  z-index: 200;
}

.rtc-drawer__overlay {
  position: absolute;
  inset: 0;
  background: var(--scrim);
  opacity: 0;
  transition: opacity 0.28s ease;
}

.rtc-drawer__panel {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: min(84vw, 320px);
  display: flex;
  flex-direction: column;
  background: var(--superficie);
  border-right: 1px solid var(--borde);
  box-shadow: var(--sombra-modal);
  transform: translateX(-100%);
  transition: transform 0.28s ease;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.rtc-drawer.is-abierto .rtc-drawer__overlay { opacity: 1; }
.rtc-drawer.is-abierto .rtc-drawer__panel { transform: translateX(0); }

.rtc-drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--borde);
}
.rtc-drawer__marca {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: 0.02em;
  color: var(--blanco);
}
.rtc-drawer__cerrar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  min-width: var(--tap);
  padding: 0;
  border: 0;
  border-radius: var(--radio-sm);
  background: transparent;
  color: var(--gris-suave);
  cursor: pointer;
}
.rtc-drawer__cerrar:hover,
.rtc-drawer__cerrar:focus-visible { background: var(--azul-dim); color: var(--azul-claro); }
.rtc-drawer__cerrar:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-drawer__cerrar svg { width: 22px; height: 22px; }

.rtc-drawer__links {
  display: flex;
  flex-direction: column;
  padding: 0.6rem;
  gap: 2px;
}
.rtc-drawer__link {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: var(--tap);
  padding: 0 14px;
  border-radius: var(--radio-sm);
  color: var(--gris-suave);
  text-decoration: none;
  font-size: 1rem;
  font-weight: 600;
  transition: background 0.18s, color 0.18s;
}
.rtc-drawer__link:hover,
.rtc-drawer__link:focus-visible { background: var(--azul-dim); color: var(--blanco); }
.rtc-drawer__link:focus-visible { outline: 2px solid var(--azul); outline-offset: -2px; }
.rtc-drawer__link.is-active {
  background: var(--grad-azul);
  color: var(--sobre-acento);
}
.rtc-drawer__linkico { display: inline-flex; }
.rtc-drawer__linkico svg { width: 18px; height: 18px; }
.rtc-drawer__link--acceso { border: 1px solid var(--azul); color: var(--blanco); }
.rtc-drawer__sep {
  height: 1px;
  margin: 0.5rem 0.4rem;
  background: var(--borde);
}

/* Bloqueo del scroll del body con el drawer abierto (lo añade/quita nav.js). */
html.rtc-no-scroll,
html.rtc-no-scroll body { overflow: hidden; }

/* Guard de movimiento: sin transiciones de entrada/salida para quien lo pide
   (el drawer sigue funcionando, solo aparece/desaparece sin animar). */
@media (prefers-reduced-motion: reduce) {
  .rtc-drawer__overlay,
  .rtc-drawer__panel { transition: none; }
}

/* ---------------------------------------------------------
   DESKTOP (≥900px): se conserva el header de 1 fila de siempre. Vuelve la nav
   inline de 7 enlaces, se ocultan hamburguesa y drawer, la marca muestra su
   nombre completo y Acceso recupera su etiqueta de texto. Umbral 900px: por
   debajo, 7 enlaces + marca + acciones no caben en una fila (era justo el wrap
   que consumía el fold móvil) → hamburguesa.
   --------------------------------------------------------- */
@media (min-width: 900px) {
  .rtc-top__ham { display: none; }
  .rtc-drawer { display: none; }

  /* Header de siempre: si marca + 7 enlaces + Acceso no caben en una fila, la nav
     y las acciones ENVUELVEN a una 2ª fila en vez de solaparse (v0.32.0 quitó el
     wrap y la marca —flex-shrink:1 + min-width:0— se aplastaba a 0, desbordando su
     texto sobre la nav). Se restaura el wrap y se blinda la marca. */
  .rtc-top__in { flex-wrap: wrap; }

  /* La marca NO se aplasta en desktop: neutraliza el `min-width:0` (necesario en
     móvil) para conservar su ancho intrínseco y mostrar "Comunidad KiweGame" entero. */
  .rtc-brand { flex-shrink: 0; }

  .rtc-brand__txt--full { display: inline; }
  .rtc-brand__txt--corta { display: none; }

  /* La nav inline vuelve. `margin-left:auto` en la nav (aquí) y en `.rtc-top__acc`
     (base) mantiene marca a la izquierda y nav+acciones a la derecha. Cuando no
     caben en una fila (marca + 7 enlaces + Acceso ~superan el ancho útil de 1080),
     la nav sube a la 1ª fila (derecha) y las ACCIONES envuelven a una 2ª fila
     alineadas a la derecha bajo la nav (su propio `margin-left:auto`) — sin solape
     ni recorte de la marca. Los dos `auto` nunca conviven en la misma línea (el
     contenido excede el ancho útil), así que no abren huecos raros entre marca y nav. */
  .rtc-nav { display: flex; margin-left: auto; }

  /* Acceso recupera ícono + texto (deja de ser icon-only). */
  .rtc-top__acceso {
    width: auto;
    padding: 0 14px;
    gap: 7px;
  }
  .rtc-nav__acctxt { display: inline; }
}

/* ---------------------------------------------------------
   MAIN + secciones
   --------------------------------------------------------- */
.rtc-main {
  position: relative;
  z-index: 1;
  max-width: 1080px;
  margin: 0 auto;
  /* Aire superior contenido: la franja no debe dejar medio viewport vacío. */
  padding: 1rem 1rem 3rem;
}

/* ---------------------------------------------------------
   HERO (franja informativa del calendario): SIN marketing.
   Solo dato vivo — "Próximo stream" + stats (streamers / en
   vivo). Si el JS no llena nada (sin próximos ni en vivo y sin
   streamers), colapsa sin dejar hueco gracias al gap del flex.
   --------------------------------------------------------- */
.rtc-hero {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}
/* El margen va en los HIJOS visibles (prox/stats), no en el contenedor: si
   ambos están ocultos (sin próximos, sin en-vivo y sin streamers) el hero no
   ocupa alto ni deja hueco antes del calendario. */
.rtc-hero__prox:not([hidden]),
.rtc-hero__stats { margin-bottom: 0.3rem; }

.rtc-sec__head { margin-bottom: 1.4rem; }

.rtc-sec__titulo {
  font-family: var(--font-head);
  font-size: 1.9rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1.1;
  background: var(--grad-azul);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.rtc-sec__sub {
  color: var(--gris);
  font-size: 0.98rem;
  margin-top: 0.35rem;
}

.rtc-cargando,
.rtc-vacio,
.rtc-foot p {
  color: var(--gris);
}

/* Estado vacío "rico" del calendario: redirige al directorio + suscripción. */
.rtc-vacio--rico {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 1.6rem 1.2rem;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}
.rtc-vacio__tit {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.3rem;
  color: var(--blanco);
}
.rtc-vacio__sub { color: var(--gris-suave); font-size: 0.98rem; }
.rtc-vacio__cta { margin-top: 0.4rem; }
.rtc-vacio__susc { color: var(--gris); font-size: 0.88rem; margin-top: 0.2rem; }

/* ---------------------------------------------------------
   COMPONENTE ÚNICO DE ESTADO VACÍO (SPEC 0027 §B)
   Mascota kiwi (decorativa, alt="") + heading + subtítulo (+ CTA opcional). Fuente
   única de la marca en los vacíos: antes fragmentados en .rtc-vacio / .rtc-espgrid__vacio
   / .rtc-espmatch-cta / vacío del calendario. Color SOLO por tokens (sirve en 2 temas).
   Sin CLS: la img reserva su alto por --kiwi-empty. Flotación sutil con guard RM.
   --------------------------------------------------------- */
.rtc-empty {
  --kiwi-empty: 120px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.5rem;
  padding: 1.8rem 1.2rem;
}
.rtc-empty__kiwi {
  width: auto;
  height: var(--kiwi-empty);
  margin-bottom: 0.2rem;
  animation: rtc-kiwi-flota 4s ease-in-out infinite;
}
.rtc-empty__heading {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.25rem;
  color: var(--texto);
}
.rtc-empty__sub {
  color: var(--gris-suave);
  font-size: 0.98rem;
  max-width: 42ch;
}
.rtc-empty__cta { margin-top: 0.5rem; min-height: var(--tap); }

/* Variante "rica": tarjeta on-brand (empty-state del calendario y del matcher). */
.rtc-empty--rico,
.rtc-empty--matcher {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

@media (min-width: 720px) {
  .rtc-empty { --kiwi-empty: 160px; }
}

@keyframes rtc-kiwi-flota {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}
@media (prefers-reduced-motion: reduce) {
  .rtc-empty__kiwi { animation: none; }
}

/* ---------------------------------------------------------
   "EN VIVO AHORA"
   --------------------------------------------------------- */
.rtc-live {
  background: var(--superficie);
  border: 1px solid var(--azul-borde);
  border-radius: var(--radio);
  padding: 1rem;
  margin-bottom: 1.5rem;
}

.rtc-live__head { margin-bottom: 0.8rem; }

.rtc-badge-live {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(var(--vivo-rgb), 0.14);
  color: var(--vivo);
  border: 1px solid rgba(var(--vivo-rgb), 0.4);
  border-radius: 999px;
  padding: 3px 12px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.rtc-badge-live--lg { font-size: 14px; padding: 5px 16px; }

/* =========================================================
   "Jugando ahora" (SPEC 0011) — badge VIOLETA (--jugando), distinto del rojo
   "En vivo": disponibilidad para jugar juntos, no transmisión. El punto late;
   respeta prefers-reduced-motion (guard global al final del archivo).
   ========================================================= */
.rtc-badge-jugando {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(var(--jugando-rgb), 0.16);
  color: var(--jugando);
  border: 1px solid rgba(var(--jugando-rgb), 0.45);
  border-radius: 999px;
  padding: 3px 12px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.rtc-badge-jugando--lg { font-size: 14px; padding: 5px 16px; }
.rtc-badge-jugando__ico {
  display: inline-flex;
  width: 16px;
  height: 16px;
  animation: rtc-jugando-latido 2.4s ease-in-out infinite;
}
.rtc-badge-jugando__ico svg { width: 100%; height: 100%; }

/* Latido sutil del gamepad (guard global de prefers-reduced-motion al final). */
@keyframes rtc-jugando-latido {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.12); opacity: 0.82; }
}

/* =========================================================
   Badge "Premium" (SPEC 0012) — insignia ORO, acento distinto del rojo "En vivo"
   y del violeta "Jugando". Marco/relleno con --var-gold-rgb; el TEXTO usa
   --oro-texto (AA en ambos temas por diseño). Informativo (no interactivo).
   ========================================================= */
.rtc-badge-premium {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(var(--var-gold-rgb), 0.14);
  color: var(--oro-texto);
  border: 1px solid rgba(var(--var-gold-rgb), 0.45);
  border-radius: 999px;
  padding: 3px 12px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.rtc-badge-premium--lg { font-size: 14px; padding: 5px 16px; }
.rtc-badge-premium__ico {
  display: inline-flex;
  color: var(--var-gold);
  font-size: 0.95em;
  line-height: 1;
}

/* =========================================================
   Badge "Admin" (SPEC 0026) — insignia de quien administra la comunidad.
   Azul de marca SÓLIDO (--azul-fuerte) con texto --sobre-acento (par ya AA en
   ambos temas), distinto del oro "Premium", el rojo "En vivo" y el violeta
   "Jugando". Informativo (no interactivo). Cero color hardcodeado.
   ========================================================= */
.rtc-badge-admin {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--azul-fuerte);
  color: var(--sobre-acento);
  border: 1px solid var(--azul-fuerte);
  border-radius: 999px;
  padding: 3px 12px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.rtc-badge-admin__ico {
  display: inline-flex;
  width: 14px;
  height: 14px;
  line-height: 1;
}
.rtc-badge-admin__ico svg { width: 100%; height: 100%; }

/* Contenedor de badges de la tarjeta (Admin + Premium): envuelven sin romper. */
.rtc-card__badges {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* =========================================================
   Modos que juega — chips (perfil + tarjeta del directorio)
   ========================================================= */
.rtc-modos {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.rtc-modos__chip {
  display: inline-flex;
  align-items: center;
  background: var(--azul-dim);
  color: var(--azul-claro);
  border: 1px solid var(--azul-borde);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 0.82rem;
  font-weight: 600;
}
.rtc-modos__chip--sm { padding: 3px 10px; font-size: 0.75rem; }
.rtc-card__modos {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0.6rem 0 0;
}

/* =========================================================
   Epic / Fortnite ID (perfil público) — valor + botón copiar
   ========================================================= */
.rtc-epic {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.rtc-epic__id {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--blanco);
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  padding: 6px 12px;
  word-break: break-all;
}
.rtc-epic__copiar {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--tap);
  padding: 6px 12px;
  background: transparent;
  color: var(--azul-claro);
  border: 1px solid var(--azul-borde);
  border-radius: var(--radio-sm);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.rtc-epic__copiarico { display: inline-flex; width: 18px; height: 18px; }
.rtc-epic__copiarico svg { width: 100%; height: 100%; }
/* SPEC 0022 — etiqueta y microcopy del Epic ID en el tracker (bloque junto al contacto). */
.rtc-epic__lbl {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--azul-claro);
}
.rtc-epic__hint {
  flex-basis: 100%;
  color: var(--gris-suave);
  font-size: 0.9rem;
}
/* Epic ID en el Sprite Tracker por streamer: pegado al bloque de contacto (SPEC 0022). */
.rtc-espst__epic {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--borde);
}

/* =========================================================
   Código QR del tracker (SPEC 0022) — el QR YA NO se pinta en la página (cambio v0.31.1):
   vive SOLO en la imagen descargable (espDibujar en comunidad.js), así que las clases de
   página `.rtc-espqr*` se retiraron por quedar huérfanas. Los píxeles de dato del QR de la
   imagen los pinta el canvas en memoria, no dependen de CSS.
   ========================================================= */

.rtc-live__lista {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.rtc-live__item {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--superficie-2);
  border: 1px solid var(--azul-borde);
  border-radius: 999px;
  padding: 6px 8px 6px 6px;
}

/* Avatar con anillo gradiente azul (mismo lenguaje que las cards del directorio). */
.rtc-live__avatar {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--grad-azul);
  padding: 2px;
  flex-shrink: 0;
}
.rtc-live__avatar img,
.rtc-live__avatar .rtc-card__ini {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  background: var(--azul-oscuro);
}
.rtc-live__avatar .rtc-card__ini { font-size: 1rem; }

.rtc-live__info { display: flex; flex-direction: column; line-height: 1.15; }
.rtc-live__nombre {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--blanco);
}
.rtc-live__estado {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--vivo);
}
.rtc-live__punto {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--vivo);
  box-shadow: 0 0 0 0 rgba(var(--vivo-rgb), 0.5);
  animation: rtc-latido 1.6s ease-out infinite;
  flex-shrink: 0;
}

.rtc-live__ver {
  min-height: var(--tap);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 16px;
  border-radius: 999px;
  background: var(--grad-azul);
  color: var(--sobre-acento);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 600;
  flex-shrink: 0;
  transition: transform 0.15s;
}
.rtc-live__ver:hover,
.rtc-live__ver:focus-visible { transform: translateY(-1px); }
.rtc-live__ver:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-live__verico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1em;
  height: 1em;
  flex-shrink: 0;
}
.rtc-live__verico svg { width: 100%; height: 100%; }

/* ---------------------------------------------------------
   CALENDARIO
   --------------------------------------------------------- */
/* Mobile-first: el toggle y la etiqueta de zona se apilan (evita overflow en ≤390px). */
.rtc-cal__barra {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.6rem;
  margin-bottom: 1rem;
}

/* Indicador de zona horaria (UX): "Horarios en tu zona · GMT-6". Bloque
   reutilizable (barra del calendario `.rtc-cal__tz`, perfil `.rtc-perfil__tz` y
   cabeceras de eventos `.rtc-eventos__tz` — torneos/sorteos/intercambios).
   Lo llena el motor (initZonaHoraria) 100% en cliente; PHP lo deja vacío y con
   [hidden] para no fragmentar el caché. Discreto y por tokens (ambos temas). */
.rtc-tzinfo {
  margin: 0;
  color: var(--gris);
  font-size: 0.85rem;
}

/* Colocación del indicador en las cabeceras de /torneos, /sorteos e /intercambios:
   respira bajo el subtítulo `.rtc-sec__sub` (mismo ritmo que ese bloque). */
.rtc-eventos__tz { margin-top: 0.35rem; }

/* Agenda (móvil por defecto): lista de días con sus streams. */
.rtc-cal__dia { margin-bottom: 1.4rem; }

.rtc-cal__diahead {
  font-family: var(--font-head);
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--azul-claro);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding-bottom: 6px;
  margin-bottom: 10px;
  border-bottom: 1px solid var(--borde);
}

.rtc-cal__lista { list-style: none; display: flex; flex-direction: column; gap: 10px; }

.rtc-ev {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 12px;
  align-items: center;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-left: 3px solid var(--azul);
  border-radius: var(--radio-sm);
  padding: 12px 14px;
  text-decoration: none;
  color: inherit;
  transition: transform 0.15s, border-color 0.2s, box-shadow 0.2s;
}
.rtc-ev:hover,
.rtc-ev:focus-visible {
  transform: translateY(-1px);
  border-color: var(--azul-borde);
  box-shadow: var(--sombra-hover);
}
.rtc-ev--en_vivo { border-left-color: var(--vivo); }
.rtc-ev--finalizado { opacity: 0.6; }
/* SPEC 0026: acento del evento cuyo organizador es admin. Layerea el wash SOBRE
   --superficie (no a secas) + borde azul interior. NO fija border-left-color: deja
   que el status (azul/rojo) mande el borde izq cuando coincida admin+en_vivo. */
.rtc-ev--admin {
  background: linear-gradient(var(--admin-ev-wash), var(--admin-ev-wash)), var(--superficie);
  box-shadow: inset 0 0 0 1px var(--azul-borde);
}
.rtc-ev--admin:hover,
.rtc-ev--admin:focus-visible {
  box-shadow: inset 0 0 0 1px var(--azul-borde), var(--sombra-hover);
}

.rtc-ev__hora {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.1rem;
  color: var(--blanco);
  white-space: nowrap;
}

.rtc-ev__cuerpo { min-width: 0; }

.rtc-ev__titulo {
  font-weight: 600;
  font-size: 1rem;
  display: block;
  overflow-wrap: anywhere; /* el título envuelve (evita corte/overflow en móvil). */
}

.rtc-ev__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 10px;
  margin-top: 4px;
  font-size: 0.82rem;
  color: var(--gris);
}

.rtc-ev__streamer { color: var(--azul-claro); font-weight: 600; }

.rtc-chip {
  display: inline-flex;
  align-items: center;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--azul-dim);
  color: var(--azul-claro);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Chip de TIPO de evento (SPEC 0004): colaboración / torneo / comunitario.
   Mismo lenguaje de chip azul (NO el rojo de "EN VIVO", que es semántico),
   con borde acentuado para distinguirlo de la plataforma. */
.rtc-chip--tipo {
  border: 1px solid var(--azul-borde);
}

/* ---------------------------------------------------------
   ACCIONES POR EVENTO (recordatorios / compartir, SPEC 0005)
   El <li> del calendario apila el evento + su fila de acciones.
   --------------------------------------------------------- */
.rtc-cal__lista > li {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.rtc-ev__acciones {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding-left: 2px;
}

/* Botón de acción compacto (secundario oscuro on-brand). */
.rtc-acc {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--tap);
  padding: 0 14px;
  border-radius: 999px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  color: var(--blanco);
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s;
}
.rtc-acc:hover,
.rtc-acc:focus-visible { border-color: var(--azul); background: var(--azul-dim); }
.rtc-acc__ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.05em;
  height: 1.05em;
  flex-shrink: 0;
}
.rtc-acc__ico svg { width: 100%; height: 100%; }

/* Menú "Avísame" (Google Calendar / descargar .ics): superficie oscura elevada. */
.rtc-aviso { position: relative; display: inline-block; }
.rtc-aviso__menu {
  position: absolute;
  z-index: 5;
  top: calc(100% + 6px);
  left: 0;
  min-width: 200px;
  display: flex;
  flex-direction: column;
  padding: 6px;
  background: var(--superficie-2);
  border: 1px solid var(--azul-borde);
  border-radius: var(--radio-sm);
  box-shadow: var(--sombra-modal);
}
.rtc-aviso__op {
  display: block;
  min-height: var(--tap);
  padding: 10px 12px;
  border-radius: var(--radio-sm);
  color: var(--blanco);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 600;
}
.rtc-aviso__op:hover,
.rtc-aviso__op:focus-visible { background: var(--azul-dim); color: var(--azul-claro); }

/* ---------------------------------------------------------
   BLOQUE "SUSCRIBIR CALENDARIO" + CTA grupo (pie del calendario)
   --------------------------------------------------------- */
.rtc-suscribir {
  margin-top: 1.6rem;
  padding: 1.2rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* Cabecera de la tarjeta: badge "campana" (azul) + título + subtítulo de beneficio. */
.rtc-suscribir__cab {
  display: flex;
  align-items: center;
  gap: 0.85rem;
}
.rtc-suscribir__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: 999px;
  background: var(--azul-dim);
  color: var(--azul-claro);
}
.rtc-suscribir__badge svg { width: 22px; height: 22px; }
.rtc-suscribir__txt { min-width: 0; }
.rtc-suscribir__titulo {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.3rem;
  color: var(--blanco);
}
.rtc-suscribir__sub { color: var(--gris-suave); font-size: 0.95rem; margin-top: 0.2rem; }

/* Fila de acciones: primario (gradiente) dominante; WhatsApp secundario verde
   tras un separador "o"; "Copiar enlace" baja como fallback ghost (abajo). */
.rtc-suscribir__acciones {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.rtc-suscribir__primario,
.rtc-suscribir__wa { width: 100%; justify-content: center; }
.rtc-suscribir__o {
  display: block;
  text-align: center;
  color: var(--gris);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* Fallback sutil: enlace de bajo peso que conserva el contrato de copiar
   (data-rtc-copiar + .rtc-btn__txt). Tap-target real ≥44px aunque sea ligero. */
.rtc-suscribir__copiar {
  display: inline-flex;
  align-self: center;
  align-items: center;
  gap: 6px;
  min-height: var(--tap);
  padding: 0 10px;
  background: none;
  border: 0;
  color: var(--gris-suave);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.82rem;
  cursor: pointer;
}
.rtc-suscribir__copiarico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1em;
  height: 1em;
  flex-shrink: 0;
}
.rtc-suscribir__copiarico svg { width: 100%; height: 100%; }
.rtc-suscribir__copiar:hover,
.rtc-suscribir__copiar:focus-visible { color: var(--azul-claro); }
.rtc-suscribir__copiar.is-ok { color: var(--ok); }
.rtc-suscribir__copiar:focus-visible {
  outline: 2px solid var(--azul);
  outline-offset: 2px;
  border-radius: var(--radio-sm);
}

/* Botón estándar reutilizable (primario / secundario / WhatsApp). */
.rtc-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: var(--tap);
  padding: 0 20px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
  cursor: pointer;
}
.rtc-btn__ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.15em;
  height: 1.15em;
  flex-shrink: 0;
}
.rtc-btn__ico svg { width: 100%; height: 100%; }
.rtc-btn--primario { background: var(--grad-azul); color: var(--sobre-acento); }
.rtc-btn--sec {
  background: var(--superficie-2);
  border-color: var(--borde);
  color: var(--blanco);
}
.rtc-btn--sec:hover,
.rtc-btn--sec:focus-visible { border-color: var(--azul); }
.rtc-btn--sec.is-ok { border-color: var(--ok); color: var(--ok); }
/* Botón compacto (atajos del tracker de espíritus). Mantiene tap-target por padding. */
.rtc-btn--mini {
  min-height: 40px;
  padding: 0 14px;
  font-size: 0.85rem;
  background: var(--superficie-2);
  border-color: var(--borde);
  color: var(--texto);
}
.rtc-btn--mini:hover,
.rtc-btn--mini:focus-visible { border-color: var(--azul); }
.rtc-btn--wa { background: var(--ok); color: var(--verde-tinta); }

/* Foco visible azul en todos los controles de acción. */
.rtc-acc:focus-visible,
.rtc-aviso__op:focus-visible,
.rtc-btn:focus-visible {
  outline: 2px solid var(--azul);
  outline-offset: 2px;
}

@media (min-width: 860px) {
  /* Desktop: cabecera y acciones en una fila; el primario manda, WhatsApp a su
     lado con el "o"; el "Copiar enlace" sigue debajo a la derecha, discreto. */
  .rtc-suscribir {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "cab acc"
      "cab copiar";
    align-items: center;
    column-gap: 1.4rem;
    row-gap: 0.4rem;
  }
  .rtc-suscribir__cab { grid-area: cab; }
  .rtc-suscribir__acciones {
    grid-area: acc;
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
    justify-content: flex-end;
  }
  .rtc-suscribir__primario,
  .rtc-suscribir__wa { width: auto; }
  .rtc-suscribir__copiar { grid-area: copiar; justify-self: end; align-self: start; }
}

/* ---------------------------------------------------------
   DIRECTORIO
   --------------------------------------------------------- */
/* SPEC 0026: sección "Administradores de la comunidad" encabezando el directorio. */
.rtc-dir__admins {
  margin-bottom: 1.5rem;
}
.rtc-dir__adminshead {
  margin-bottom: 1rem;
}
.rtc-dir__adminstit {
  font-family: var(--font-head);
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--texto);
  margin: 0;
}
.rtc-dir__adminssub {
  color: var(--texto-suave);
  font-size: 0.92rem;
  margin: 0.25rem 0 0;
}
/* Grid de admins: 1 columna en móvil; auto-fit desde 600px. */
.rtc-dir__adminsgrid {
  list-style: none;
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  justify-content: center;
}
@media (min-width: 600px) {
  .rtc-dir__adminsgrid { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
}
/* Rótulo del grid general (solo cuando existe la sección de admins arriba). */
.rtc-dir__generaltit {
  font-family: var(--font-head);
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--texto);
  margin: 0 0 1rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--borde);
}

/* Mobile-first: una sola columna a 390px (sin minmax que fuerce overflow).
   En desktop pasamos a auto-fit (ver @media) para que el nº de columnas siga al
   nº de streamers: con 2, dos columnas centradas; nunca una 3ª columna huérfana. */
.rtc-dir__grid {
  list-style: none;
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  justify-content: center;
}

/* Cada card no crece sin límite: con pocos streamers el grid no estira las cards
   a lo ancho. width:100% para llenar su columna en móvil (≤390px sano).
   min-width:0 — un grid item nace con min-width:auto, así que su contenido
   intrínseco (el título "Próximo stream" con nowrap) forzaba la card a ~516px y
   desbordaba a 360-414px (avatar cortado). Con min-width:0 la card puede encogerse
   por debajo de su contenido y el ellipsis de .rtc-card__proxtit trunca bien.
   Mismo patrón que .rtc-nav / .rtc-ev__cuerpo en este archivo. */
.rtc-card { max-width: 520px; width: 100%; min-width: 0; }

.rtc-card {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra-card);
  padding: 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

.rtc-card__head { display: flex; gap: 12px; align-items: center; }

.rtc-card__avatar {
  position: relative;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--grad-azul);
  padding: 2px;
  flex-shrink: 0;
}
.rtc-card__avatar img,
.rtc-card__ini {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  display: flex;
  align-items: center;
  justify-content: center;
}
.rtc-card__ini {
  background: var(--azul-oscuro);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.4rem;
  color: var(--azul-claro);
}
.rtc-card__avatar .rtc-badge-live {
  position: absolute;
  bottom: -6px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 9px;
  padding: 2px 8px;
  /* Sobre el avatar el chip translúcido no se distinguía (se veía la foto por debajo).
     Fondo ROJO sólido + texto blanco + anillo del color de la card para que el badge
     se separe del avatar y siempre sea legible. */
  background: var(--vivo);
  color: var(--sobre-acento);
  border-color: var(--vivo);
  box-shadow: 0 0 0 2px var(--azul-oscuro);
  white-space: nowrap;
}

.rtc-card__nombre {
  font-family: var(--font-head);
  font-size: 1.25rem;
  font-weight: 700;
}
.rtc-card__bio { color: var(--gris); font-size: 0.88rem; margin-top: 2px; }

.rtc-card__plats { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; }

.rtc-plat {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px; /* a11y: área táctil ≥44px (§4) */
  padding: 0 12px;
  border-radius: 999px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  text-decoration: none;
  color: var(--blanco);
  font-size: 0.82rem;
  font-weight: 600;
  transition: border-color 0.2s, transform 0.15s;
}
.rtc-plat:hover,
.rtc-plat:focus-visible { transform: translateY(-1px); border-color: var(--azul-borde); }

.rtc-plat__ico { display: inline-flex; width: 18px; height: 18px; }
.rtc-plat__ico svg { width: 18px; height: 18px; }
.rtc-plat--twitch .rtc-plat__ico { color: var(--p-twitch); }
.rtc-plat--youtube .rtc-plat__ico { color: var(--p-youtube); }
.rtc-plat--tiktok .rtc-plat__ico { color: var(--p-tiktok); }
.rtc-plat--facebook .rtc-plat__ico { color: var(--p-facebook); }
.rtc-plat--kick .rtc-plat__ico { color: var(--p-kick); }
.rtc-plat--instagram .rtc-plat__ico { color: var(--p-instagram); }
.rtc-plat--x .rtc-plat__ico { color: var(--p-x); }

.rtc-card__proxhead {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--gris);
  text-decoration: none;
  margin-bottom: 6px;
  transition: color 0.2s;
}
a.rtc-card__proxhead:hover,
a.rtc-card__proxhead:focus-visible { color: var(--azul-claro); }
.rtc-card__proxlist { list-style: none; display: flex; flex-direction: column; gap: 4px; }
.rtc-card__proxlist li { display: flex; gap: 8px; font-size: 0.85rem; }
.rtc-card__proxfecha { color: var(--azul-claro); font-weight: 600; white-space: nowrap; }
.rtc-card__proxtit { color: var(--gris-suave); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.rtc-card__cta {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 18px;
  border-radius: 999px;
  background: var(--grad-azul);
  color: var(--sobre-acento);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.92rem;
}

/* CTA sin destino: estado "Próximamente" (no un hueco mudo, no parece activo). */
.rtc-card__cta--pronto {
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  color: var(--gris);
  cursor: default;
}

/* Tarjeta compacta: sin bio NI plataformas → menos altura, ritmo del grid sano.
   La cabecera (avatar + nombre) y el CTA bastan para no dejar la card "muerta". */
.rtc-card--compacta {
  gap: 0.7rem;
}
.rtc-card--compacta .rtc-card__head { align-items: center; }

/* Cross-link al final del directorio: lleva al calendario (flujo entre superficies). */
.rtc-dir__cross {
  margin-top: 1.4rem;
  text-align: center;
}
.rtc-dir__crosslink {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 18px;
  color: var(--azul-claro);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.95rem;
}
.rtc-dir__crosslink:hover,
.rtc-dir__crosslink:focus-visible { text-decoration: underline; }

/* ---------------------------------------------------------
   INFO DE COMUNIDAD
   --------------------------------------------------------- */

/* Hero de marca (SPEC 0027 §2.2): emblema KG (PNG neutro) + wordmark "KIWEGAME"
   como TEXTO vivo (color por tema, sirve en ambos → nunca el logo completo sobre
   oscuro) + mascota kiwi decorativa. Mobile-first; kiwi ≤180px móvil / ≤240px desktop. */
.rtc-marca-hero {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  margin-bottom: 1.2rem;
}
.rtc-marca-hero__lockup {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  min-width: 0;
}
.rtc-marca-hero__emblema {
  width: auto;
  height: 48px;
  flex-shrink: 0;
}
.rtc-marca-hero__wordmark {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.7rem;
  letter-spacing: 0.02em;
  line-height: 1;
  color: var(--texto);
  white-space: nowrap;
}
.rtc-marca-hero__kiwi {
  width: auto;
  height: 104px;
  flex-shrink: 0;
}
@media (min-width: 720px) {
  .rtc-marca-hero__emblema { height: 72px; }
  .rtc-marca-hero__wordmark { font-size: 2.6rem; }
  .rtc-marca-hero__kiwi { height: 180px; }
}

.rtc-info__bloque {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra-card);
  padding: 1.2rem;
  margin-bottom: 1.2rem;
}
.rtc-info__h2 {
  font-family: var(--font-head);
  font-size: 1.3rem;
  font-weight: 700;
  margin-bottom: 0.6rem;
  color: var(--azul-claro);
}
.rtc-info__p { color: var(--gris-suave); line-height: 1.7; }
.rtc-info__p--lead { font-size: 1.02rem; color: var(--blanco); }

/* "¿Qué es?": destacados con ícono — calendario / directorio / WhatsApp. */
.rtc-info__claves {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 1rem;
}
.rtc-info__clave {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0.7rem 0.9rem;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  color: var(--gris-suave);
  font-size: 0.95rem;
}
.rtc-info__claveico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  color: var(--azul-claro);
}
.rtc-info__claveico svg { width: 22px; height: 22px; }
.rtc-info__clavetxt { line-height: 1.4; }

/* Reglas: cada línea con un escudo-check azul + texto, en lugar de viñeta plana. */
.rtc-info__reglas { list-style: none; display: flex; flex-direction: column; gap: 12px; }
.rtc-info__regla {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  color: var(--gris-suave);
  line-height: 1.5;
}
.rtc-info__reglaico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  margin-top: 1px;
  color: var(--azul);
}
.rtc-info__reglaico svg { width: 22px; height: 22px; }
.rtc-info__reglatxt { line-height: 1.5; }

.rtc-cta-wa {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: var(--tap);
  padding: 0 24px;
  border-radius: 999px;
  background: var(--ok);
  color: var(--verde-tinta);
  text-decoration: none;
  font-weight: 700;
  font-size: 1rem;
}
.rtc-cta-wa__ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25em;
  height: 1.25em;
  flex-shrink: 0;
}
.rtc-cta-wa__ico svg { width: 100%; height: 100%; }

/* Cierre de la página Comunidad: CTA de WhatsApp (o fallback digno) + cross-link
   al directorio. Nunca un hueco mudo cuando whatsapp_url está vacío. */
.rtc-unirse {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  margin-top: 1.4rem;
}
.rtc-unirse__pronto {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-left: 3px solid var(--ok);
  border-radius: var(--radio);
  padding: 0.9rem 1.1rem;
}
.rtc-unirse__prontotit {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.1rem;
  color: var(--blanco);
}
.rtc-unirse__prontosub { color: var(--gris-suave); font-size: 0.9rem; margin-top: 0.2rem; }
.rtc-unirse__dir {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  color: var(--azul-claro);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.95rem;
}
.rtc-unirse__dir:hover,
.rtc-unirse__dir:focus-visible { text-decoration: underline; }

/* ---------------------------------------------------------
   FOOTER
   --------------------------------------------------------- */
.rtc-foot {
  position: relative;
  z-index: 1;
  text-align: center;
  padding: 2rem 1rem;
  border-top: 1px solid var(--borde);
  font-size: 0.85rem;
}

/* ---------------------------------------------------------
   EMBED (shortcodes/widgets Elementor): el motor dentro de otra
   página. Hereda el tema; quita el sticky del top.
   --------------------------------------------------------- */
.rtc--embed { position: relative; }
.rtc--embed .rtc-main { padding-top: 0.5rem; }

/* ---------------------------------------------------------
   DESKTOP: el calendario muestra la rejilla semanal.
   --------------------------------------------------------- */
@media (min-width: 860px) {
  .rtc-sec__titulo { font-size: 2.3rem; }

  /* En escritorio el toggle y la zona vuelven a la misma fila. */
  .rtc-cal__barra {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 1rem;
  }

  /* auto-fit + columnas acotadas: el nº de columnas = nº de cards que caben,
     no un nº fijo. Con 2 streamers → 2 columnas centradas (justify-content:center
     en la base), sin 3ª columna vacía ni cards estiradas. */
  .rtc-dir__grid { grid-template-columns: repeat(auto-fit, minmax(300px, 360px)); }

  /* La vista semana (rejilla de 7 columnas) se define más abajo, junto al resto
     del bloque "CALENDARIO v0.7" para mantener juntas sus reglas. */
}

/* En ≥1100px el auto-fit ya admite hasta 3 columnas (3×360px + gaps), y solo las
   crea si hay 3+ streamers — con 2 quedan 2 centradas, sin columna huérfana. No
   se fuerza repeat(3): eso es lo que dejaba el hueco con pocos streamers. */

/* ---------------------------------------------------------
   HERO con dato vivo (calendario): stats (streamers / en vivo).
   Sin titular de marketing (la jerarquía la lleva el h1 del
   calendario). El gap del .rtc-hero ordena prox + stats.
   --------------------------------------------------------- */
.rtc-hero__stats {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

.rtc-hero__stat {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: 999px;
  padding: 6px 14px;
}

.rtc-hero__statnum {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--blanco);
}

.rtc-hero__statlbl {
  color: var(--gris-suave);
  font-size: 0.82rem;
}

@keyframes rtc-latido {
  0% { box-shadow: 0 0 0 0 rgba(var(--vivo-rgb), 0.5); }
  70% { box-shadow: 0 0 0 7px rgba(var(--vivo-rgb), 0); }
  100% { box-shadow: 0 0 0 0 rgba(var(--vivo-rgb), 0); }
}

/* ---------------------------------------------------------
   TARJETA DE STREAMER: acciones (perfil nativo + enlace externo)
   --------------------------------------------------------- */
.rtc-card__acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin-top: auto;
}

/* El "Ver perfil" reutiliza .rtc-card__cta (gradiente). El enlace externo es secundario. */
.rtc-card__ext {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: var(--tap);
  padding: 0 14px;
  border-radius: 999px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  color: var(--gris-suave);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.88rem;
  transition: border-color 0.2s, color 0.2s;
}
.rtc-card__ext:hover,
.rtc-card__ext:focus-visible {
  border-color: var(--azul);
  color: var(--blanco);
}
.rtc-card__extico { font-size: 0.95rem; line-height: 1; }

.rtc-card__cta:focus-visible,
.rtc-card__ext:focus-visible {
  outline: 2px solid var(--azul);
  outline-offset: 2px;
}

/* ---------------------------------------------------------
   PERFIL PÚBLICO DEL STREAMER (single nativo)
   --------------------------------------------------------- */
.rtc-perfil__volver { margin-bottom: 1rem; }
.rtc-perfil__volverlink {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: var(--tap);
  color: var(--azul-claro);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.95rem;
}
.rtc-perfil__volverlink:hover,
.rtc-perfil__volverlink:focus-visible { text-decoration: underline; }

.rtc-perfil {
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
}

/* Cuerpo del perfil: en móvil una sola columna apilada; en ≥860px rejilla 2 col. */
.rtc-perfil__cuerpo {
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
}

.rtc-perfil__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.9rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 1.6rem 1.2rem;
}

.rtc-perfil__avatar {
  position: relative;
  width: 110px;
  height: 110px;
  border-radius: 50%;
  background: var(--grad-azul);
  padding: 3px;
  flex-shrink: 0;
  box-shadow: 0 8px 30px var(--azul-dim);
}
.rtc-perfil__avatar img,
.rtc-perfil__ini {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  display: flex;
  align-items: center;
  justify-content: center;
}
.rtc-perfil__ini {
  background: var(--azul-oscuro);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 2.4rem;
  color: var(--azul-claro);
}

/* Jerarquía del hero: nombre = foco #1 (dominante); badge EN VIVO = acompañante debajo. */
.rtc-perfil__id { display: flex; flex-direction: column; align-items: center; gap: 0.55rem; }

.rtc-perfil__nombre {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 2.2rem;
  line-height: 1.05;
  color: var(--blanco);
  order: 1;
}
/* El badge queda subordinado al nombre (más pequeño, debajo). */
.rtc-perfil__id .rtc-badge-live { order: 2; }
.rtc-perfil__bio { order: 3; }
.rtc-perfil__bio {
  color: var(--gris-suave);
  font-size: 1rem;
  line-height: 1.5;
  max-width: 52ch;
}

.rtc-perfil__cta {
  display: flex;
  justify-content: center;
}
.rtc-perfil__cta .rtc-btn { padding: 0 32px; min-height: 50px; font-size: 1rem; }

.rtc-perfil__bloque,
.rtc-perfil__suscribir {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 1.2rem;
}

.rtc-perfil__h2 {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.25rem;
  color: var(--azul-claro);
  margin-bottom: 0.8rem;
}

.rtc-perfil__plats {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.rtc-perfil__vacio { color: var(--gris); font-size: 0.95rem; }

/* Indicador de zona del bloque "Próximos streams" (ver .rtc-tzinfo): pegado a
   la cabecera del bloque, con aire antes de la lista. */
.rtc-perfil__tz { margin: -0.4rem 0 0.8rem; }

.rtc-perfil__prox {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.rtc-perfil__proxitem {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-left: 3px solid var(--azul);
  border-radius: var(--radio-sm);
  padding: 10px 14px;
}
.rtc-perfil__proxfecha {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1rem;
  color: var(--azul-claro);
  white-space: nowrap;
}
.rtc-perfil__proxtit {
  color: var(--gris-suave);
  font-size: 0.95rem;
  overflow-wrap: anywhere;
}

/* El bloque "Suscribe su calendario" del perfil reusa el componente
   `.rtc-suscribir` (misma jerarquía: badge+título, primario, WhatsApp, copiar
   fallback). Solo ajusta el margen al ir dentro de la rejilla del perfil. */
.rtc-perfil__suscribir { margin-top: 0; }

/* 404 del perfil (shell oscuro, no el del tema de agencia). */
.rtc-404 {
  text-align: center;
  padding: 3rem 1rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
}
.rtc-404__cod {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 3.4rem;
  line-height: 1;
  background: var(--grad-azul);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
.rtc-404__tit {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.6rem;
  color: var(--blanco);
}
.rtc-404__sub { color: var(--gris-suave); max-width: 40ch; }
.rtc-404 .rtc-btn { margin-top: 0.6rem; }

/* ---------------------------------------------------------
   INFO COMUNIDAD: redes oficiales (lista de pills).
   Reutiliza .rtc-plat; --red es la variante neutra (acento azul en hover).
   --------------------------------------------------------- */
.rtc-info__redes {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 0.6rem;
}
.rtc-plat--red .rtc-plat__ico { color: var(--azul-claro); }

/* ---------------------------------------------------------
   FOOTER on-brand: nav + redes + WhatsApp + copyright.
   --------------------------------------------------------- */
.rtc-foot__in {
  max-width: 1080px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
}

.rtc-foot__nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 8px;
}
.rtc-foot__navlink {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 12px;
  color: var(--gris-suave);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9rem;
  border-radius: 999px;
  transition: color 0.2s, background 0.2s;
}
.rtc-foot__navlink:hover,
.rtc-foot__navlink:focus-visible { color: var(--blanco); background: var(--azul-dim); }

/* Acceso de streamers en el footer: misma familia, con contorno para leerse
   como acción (entrada al panel), no como una sección pública más. */
.rtc-foot__navlink--acceso {
  border: 1px solid var(--borde);
  color: var(--blanco);
}
.rtc-foot__navlink--acceso:hover,
.rtc-foot__navlink--acceso:focus-visible { border-color: var(--azul); }

.rtc-foot__redes {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
}
.rtc-foot__red {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--tap);
  padding: 0 14px;
  border-radius: 999px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  color: var(--gris-suave);
  text-decoration: none;
  font-size: 0.85rem;
  font-weight: 600;
  transition: border-color 0.2s, color 0.2s, transform 0.15s;
}
.rtc-foot__red:hover,
.rtc-foot__red:focus-visible {
  border-color: var(--azul-borde);
  color: var(--blanco);
  transform: translateY(-1px);
}
.rtc-foot__redico { display: inline-flex; width: 18px; height: 18px; }
.rtc-foot__redico svg { width: 18px; height: 18px; }
.rtc-foot__red--wa { border-color: rgba(var(--ok-rgb), 0.4); color: var(--ok); }
.rtc-foot__red--wa:hover,
.rtc-foot__red--wa:focus-visible { border-color: var(--ok); color: var(--ok); }

.rtc-foot__copy { color: var(--gris); font-size: 0.85rem; }

.rtc-foot__navlink:focus-visible,
.rtc-foot__red:focus-visible,
.rtc-perfil__volverlink:focus-visible {
  outline: 2px solid var(--azul);
  outline-offset: 2px;
}

@media (min-width: 860px) {
  .rtc-perfil__head {
    flex-direction: row;
    text-align: left;
    align-items: center;
    gap: 1.4rem;
    padding: 1.8rem;
  }
  .rtc-perfil__id { align-items: flex-start; }
  .rtc-perfil__cta { justify-content: flex-start; }

  /* Cuerpo a 2 columnas: izquierda = "Dónde transmite" + "Suscribe su calendario";
     derecha = "Próximos streams" (la lista más alta). align-items:start evita que las
     cards estiren su alto al de la columna contraria. */
  .rtc-perfil__cuerpo {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "plats prox"
      "susc  prox";
    align-items: start;
    gap: 1.2rem;
  }
  .rtc-perfil__bloque--plats { grid-area: plats; }
  .rtc-perfil__bloque--prox  { grid-area: prox; }
  .rtc-perfil__suscribir     { grid-area: susc; }

  /* Si no hay plataformas, "Próximos" sigue a la derecha y "Suscribe" llena la izquierda. */
  .rtc-perfil__cuerpo:not(:has(.rtc-perfil__bloque--plats)) {
    grid-template-areas: "susc prox";
  }

  /* El bloque del perfil vive en una columna estrecha de la rejilla: anula el
     layout horizontal que `.rtc-suscribir` toma a ≥860px y mantén la pila
     vertical (cabecera arriba, acciones a ancho completo, copiar debajo). */
  .rtc-perfil__suscribir.rtc-suscribir {
    display: flex;
    flex-direction: column;
    grid-template-columns: none;
    grid-template-areas: none;
  }
  .rtc-perfil__suscribir .rtc-suscribir__acciones {
    flex-direction: column;
    justify-content: flex-start;
  }
  .rtc-perfil__suscribir .rtc-suscribir__primario,
  .rtc-perfil__suscribir .rtc-suscribir__wa { width: 100%; }
  .rtc-perfil__suscribir .rtc-suscribir__copiar { justify-self: auto; }

  .rtc-foot__in { flex-direction: row; justify-content: space-between; flex-wrap: wrap; }
  .rtc-foot__nav { justify-content: flex-start; }
  .rtc-foot__copy { width: 100%; text-align: center; order: 3; }
}

/* =========================================================
   CALENDARIO v0.7 — vista SEMANA real, atajo HOY, filtros front.
   (UI inyectada por comunidad.js sobre el DOM ya renderizado.)
   Todo con tokens del tema oscuro; mobile-first; foco azul; ≥44px.
   ========================================================= */

/* --- Atajo "Hoy/Ahora" en la barra del calendario (botón secundario pill). --- */
.rtc-cal__hoybtn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: var(--tap);
  padding: 0 16px;
  border-radius: 999px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  color: var(--blanco);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.9rem;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s;
}
.rtc-cal__hoybtn:hover,
.rtc-cal__hoybtn:focus-visible { border-color: var(--azul); background: var(--azul-dim); }
.rtc-cal__hoybtnico { color: var(--azul-claro); font-size: 0.7rem; line-height: 1; }
.rtc-cal__hoybtn:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

/* --- Pista "Hoy" junto a la cabecera del día/columna. --- */
.rtc-cal__hoy {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 9px;
  border-radius: 999px;
  background: var(--azul-dim);
  border: 1px solid var(--azul-borde);
  color: var(--azul-claro);
  font-family: var(--font-body);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: middle;
}

/* --- BARRA DE FILTROS del calendario (debajo de .rtc-cal__barra).
   COMPACTA: el botón "Filtros · N" es lo único siempre visible; el panel
   (la card) solo aparece al desplegar. Contenedor = columna sin fondo, para
   que el calendario respire y el primer stream suba. --- */
.rtc-cal__filtros {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.6rem;
  margin-bottom: 0.9rem;
}

.rtc-cal__fgrupo {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
}

.rtc-cal__flabel {
  font-size: 0.66rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--gris);
}

.rtc-cal__fpills {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.rtc-cal__fpill {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 14px;
  border-radius: 999px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  color: var(--gris-suave);
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s, color 0.2s;
}
.rtc-cal__fpill:hover { border-color: var(--azul-borde); color: var(--blanco); }
.rtc-cal__fpill[aria-pressed="true"] {
  background: var(--grad-azul);
  border-color: transparent;
  color: var(--sobre-acento);
}
.rtc-cal__fpill:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

.rtc-cal__fselect {
  min-height: var(--tap);
  min-width: 170px;
  max-width: 100%;
  padding: 0 12px;
  border-radius: var(--radio-sm);
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  color: var(--blanco);
  font-family: var(--font-body);
  font-size: 0.85rem;
  cursor: pointer;
}
.rtc-cal__fselect:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }
.rtc-cal__fselect option { background: var(--azul-oscuro); color: var(--blanco); }

.rtc-cal__limpiar {
  align-self: flex-start;
  min-height: var(--tap);
  padding: 0 16px;
  border-radius: 999px;
  background: transparent;
  border: 1px solid var(--borde);
  color: var(--azul-claro);
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s;
}
.rtc-cal__limpiar:hover { border-color: var(--azul); background: var(--azul-dim); }
.rtc-cal__limpiar:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

/* --- VISTA SEMANA (móvil-first): carril horizontal de columnas-día con
   scroll-snap. En desktop pasa a rejilla de 7 (ver @media 860px). --- */
.rtc-cal__lienzo[data-rtc-modo="semana"] {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 6px;
  /* Pista de scroll discreta on-brand. */
  scrollbar-color: var(--azul-borde) transparent;
}
.rtc-cal__lienzo[data-rtc-modo="semana"]::-webkit-scrollbar { height: 8px; }
.rtc-cal__lienzo[data-rtc-modo="semana"]::-webkit-scrollbar-thumb {
  background: var(--azul-borde);
  border-radius: 999px;
}

.rtc-cal__col {
  flex: 0 0 78%;
  max-width: 320px;
  min-width: 0;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}
.rtc-cal__col[data-rtc-hoy="1"] {
  border-color: var(--azul-borde);
  box-shadow: 0 0 0 1px var(--azul-borde) inset;
}
.rtc-cal__col:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

.rtc-cal__colhead {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 8px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--borde);
}
.rtc-cal__coldia {
  font-family: var(--font-head);
  font-size: 0.92rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--azul-claro);
}
.rtc-cal__col[data-rtc-hoy="1"] .rtc-cal__coldia { color: var(--blanco); }

.rtc-cal__colvacio {
  color: var(--gris);
  font-size: 0.82rem;
  padding: 0.4rem 0;
}

.rtc-cal__collista {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.rtc-cal__colitem {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

/* Evento COMPACTO (vista semana): hora · título · meta apilados. */
.rtc-evc {
  display: flex;
  flex-direction: column;
  gap: 3px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-left: 3px solid var(--azul);
  border-radius: var(--radio-sm);
  padding: 8px 10px;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.2s, box-shadow 0.2s, transform 0.15s;
}
.rtc-evc:hover,
.rtc-evc:focus-visible {
  transform: translateY(-1px);
  border-color: var(--azul-borde);
  box-shadow: var(--sombra-hover);
}
.rtc-evc:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-evc--en_vivo { border-left-color: var(--vivo); }
.rtc-evc--finalizado { opacity: 0.6; }
.rtc-evc--cancelado { opacity: 0.55; text-decoration: line-through; }
/* SPEC 0026: acento del evento de admin en la rejilla semana (mismo criterio que
   .rtc-ev--admin: wash layereado sobre --superficie + borde azul interior). */
.rtc-evc--admin {
  background: linear-gradient(var(--admin-ev-wash), var(--admin-ev-wash)), var(--superficie);
  box-shadow: inset 0 0 0 1px var(--azul-borde);
}
.rtc-evc--admin:hover,
.rtc-evc--admin:focus-visible {
  box-shadow: inset 0 0 0 1px var(--azul-borde), var(--sombra-hover);
}

.rtc-evc__hora {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--blanco);
  white-space: nowrap;
}
.rtc-evc__titulo {
  font-weight: 600;
  font-size: 0.92rem;
  overflow-wrap: anywhere;
}
.rtc-evc__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  margin-top: 2px;
  font-size: 0.74rem;
  color: var(--gris);
}

/* En semana las acciones (Avísame/Compartir) son compactas para no romper la
   columna estrecha: el texto se oculta y queda el ícono (sigue accesible por
   aria-label / aria-haspopup). En agenda permanecen completas. */
.rtc-cal__lienzo[data-rtc-modo="semana"] .rtc-ev__acciones { gap: 6px; }
.rtc-cal__lienzo[data-rtc-modo="semana"] .rtc-acc {
  padding: 0 10px;
  min-height: 38px;
}
.rtc-cal__lienzo[data-rtc-modo="semana"] .rtc-acc__txt {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* --- BÚSQUEDA + FILTROS del DIRECTORIO (inyectados por JS). --- */
.rtc-dir__filtros {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  margin-bottom: 1.2rem;
  padding: 1rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.rtc-dir__buscar { display: flex; flex-direction: column; gap: 0.4rem; }
.rtc-dir__buscarlbl {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--gris);
}
.rtc-dir__input {
  width: 100%;
  min-height: var(--tap);
  padding: 0 14px;
  border-radius: var(--radio-sm);
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  color: var(--blanco);
  font-family: var(--font-body);
  font-size: 0.95rem;
}
.rtc-dir__input::placeholder { color: var(--gris); }
.rtc-dir__input:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }

.rtc-dir__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.rtc-dir__chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 44px; /* a11y: área táctil ≥44px (§4) */
  padding: 0 14px;
  border-radius: 999px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  color: var(--gris-suave);
  font-family: var(--font-body);
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s, color 0.2s;
}
.rtc-dir__chip:hover { border-color: var(--azul-borde); color: var(--blanco); }
.rtc-dir__chip[aria-pressed="true"] {
  background: var(--grad-azul);
  border-color: transparent;
  color: var(--sobre-acento);
}
.rtc-dir__chip:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

/* Toggle "En vivo": usa el rojo semántico SOLO cuando está activo. */
.rtc-dir__chiplive { color: var(--vivo); font-size: 0.7rem; line-height: 1; }
.rtc-dir__chip--live.is-on,
.rtc-dir__chip--live[aria-pressed="true"] {
  background: rgba(var(--vivo-rgb), 0.14);
  border-color: rgba(var(--vivo-rgb), 0.4);
  color: var(--vivo);
}
.rtc-dir__chip--live.is-on .rtc-dir__chiplive,
.rtc-dir__chip--live[aria-pressed="true"] .rtc-dir__chiplive { color: var(--vivo); }

/* Toggle "Jugando ahora" (SPEC 0011): violeta semántico SOLO cuando está activo. */
.rtc-dir__chipjugando { color: var(--jugando); font-size: 0.66rem; line-height: 1; }
.rtc-dir__chip--jugando.is-on,
.rtc-dir__chip--jugando[aria-pressed="true"] {
  background: rgba(var(--jugando-rgb), 0.16);
  border-color: rgba(var(--jugando-rgb), 0.45);
  color: var(--jugando);
}
.rtc-dir__chip--jugando.is-on .rtc-dir__chipjugando,
.rtc-dir__chip--jugando[aria-pressed="true"] .rtc-dir__chipjugando { color: var(--jugando); }

/* Filtro por modo — select temado. */
.rtc-dir__modo { display: flex; flex-direction: column; gap: 4px; }
.rtc-dir__modosel {
  min-height: var(--tap);
  padding: 0 12px;
  border-radius: 999px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  color: var(--blanco);
  font: inherit;
}
.rtc-dir__modosel:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

/* Mensaje "sin resultados" del directorio. */
.rtc-dir__sinres {
  color: var(--gris-suave);
  font-size: 0.95rem;
  padding: 1.2rem 0;
  text-align: center;
}
.rtc-dir__limpiar {
  display: inline-flex;
  align-items: center;
  min-height: 38px;
  margin-left: 6px;
  padding: 0 14px;
  border-radius: 999px;
  background: transparent;
  border: 1px solid var(--borde);
  color: var(--azul-claro);
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
}
.rtc-dir__limpiar:hover { border-color: var(--azul); background: var(--azul-dim); }
.rtc-dir__limpiar:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

/* =========================================================
   SKELETONS DE CARGA (v0.7.2) — placeholders fantasma on-brand
   mientras resuelve /streams. Superficie-2 + shimmer azul tenue que
   recorre; respeta prefers-reduced-motion (estático). Decorativos
   (aria-hidden por JS); el lienzo conserva su texto accesible.
   ========================================================= */

/* Texto solo para lectores de pantalla (el skeleton es visual). */
.rtc-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Pieza base: superficie tenue con shimmer azul que recorre. Todas las
   formas fantasma comparten este fondo via .rtc-skel__* (heredan el ::after). */
.rtc-skel__diahead,
.rtc-skel__hora,
.rtc-skel__titulo,
.rtc-skel__meta,
.rtc-skel__ftoggle {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--superficie-2);
  border-radius: var(--radio-sm);
}

.rtc-skel__diahead::after,
.rtc-skel__hora::after,
.rtc-skel__titulo::after,
.rtc-skel__meta::after,
.rtc-skel__ftoggle::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--azul-dim) 50%,
    transparent 100%
  );
  animation: rtc-shimmer 1.4s ease-in-out infinite;
}

@keyframes rtc-shimmer {
  100% { transform: translateX(100%); }
}

/* Skeleton del LIENZO: días fantasma con filas (hora + título + meta). */
.rtc-skel__dia { margin-bottom: 1.4rem; }
.rtc-skel__diahead {
  width: 42%;
  height: 0.95rem;
  margin-bottom: 12px;
}
.rtc-skel__lista {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.rtc-skel__fila {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px 12px;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}
.rtc-skel__hora {
  flex: 0 0 auto;
  width: 46px;
  height: 1.1rem;
}
.rtc-skel__cuerpo {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.rtc-skel__titulo { width: 70%; height: 0.95rem; }
.rtc-skel__meta { width: 45%; height: 0.7rem; }

/* Skeleton de la BARRA DE FILTROS: solo reserva el botón "Filtros" compacto
   (el panel arranca colapsado en todos los tamaños → sin CLS al aparecer). */
.rtc-cal__filtros-skel {
  display: flex;
  margin-bottom: 0.9rem;
}
.rtc-skel__ftoggle {
  width: 116px;
  height: var(--tap);
  border-radius: 999px;
}

/* =========================================================
   FILTROS COLAPSABLES EN TODOS LOS TAMAÑOS (v0.7.5) — botón
   "Filtros · N". El panel (STREAMER + PLATAFORMA + TIPO + Limpiar)
   arranca COLAPSADO en móvil y desktop; el botón lo despliega como
   card. Footprint compacto para que el calendario respire.
   Tokens del tema; foco azul; tap-target ≥44px aunque sea compacto.
   ========================================================= */

/* Botón "Filtros · N": siempre visible. Pill secundaria compacta con
   tap-target real ≥44px (min-height) aunque visualmente sea pequeño. */
.rtc-cal__ftoggle {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: var(--tap);
  padding: 0 15px;
  border-radius: 999px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  color: var(--blanco);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.85rem;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s;
}
.rtc-cal__ftoggle:hover { border-color: var(--azul-borde); }
.rtc-cal__ftoggle:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-cal__ftoggle.is-activo {
  border-color: var(--azul-borde);
  background: var(--azul-dim);
}
.rtc-cal__ftoggleico { color: var(--azul-claro); font-size: 0.8rem; line-height: 1; }
.rtc-cal__fcontador {
  color: var(--azul-claro);
  font-weight: 700;
  font-size: 0.82rem;
}

/* Panel colapsable: oculto hasta is-open (en CUALQUIER viewport). Al abrirse
   es la card (superficie + borde) que agrupa los filtros. */
.rtc-cal__fpanel {
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.7rem 1rem;
  width: 100%;
  padding: 0.8rem 0.9rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}
.rtc-cal__fpanel[data-rtc-colapsable] { display: none; }
.rtc-cal__fpanel[data-rtc-colapsable].is-open { display: flex; }

/* --- DESKTOP: la vista semana pasa de carril a rejilla de 7 columnas. --- */
@media (min-width: 860px) {
  .rtc-cal__lienzo[data-rtc-modo="semana"] {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 8px;
    overflow-x: visible;
    scroll-snap-type: none;
  }
  .rtc-cal__col {
    flex: initial;
    max-width: none;
    padding: 8px;
  }
  .rtc-cal__coldia { font-size: 0.8rem; }
}

/* El colapso de filtros es UNIFICADO (botón "Filtros · N" en todos los
   tamaños): ya no hay @media que fuerce el panel visible en desktop. */

/* ---------------------------------------------------------
   CUENTAS REGRESIVAS (módulo countdown del motor). Etiqueta
   discreta y on-brand que el JS actualiza cada segundo. Hora
   en Rajdhani (números legibles); acento azul; el live usa
   --vivo. Mobile-first, solo tokens del tema, no interactiva.
   --------------------------------------------------------- */
.rtc-cd {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 1px 9px;
  border-radius: 999px;
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 0.74rem;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums; /* MM:SS no "salta" al tickear. */
  white-space: nowrap;
  background: var(--azul-dim);
  color: var(--azul-claro);
  border: 1px solid var(--azul-borde);
}

/* Lejos (>24 h) / próximo (1–24 h): acento azul calmo (heredado).
   --prox no necesita override: el azul base del .rtc-cd ya lo cubre. */
.rtc-cd--lejos { opacity: 0.92; }

/* Urgente (<1 h, MM:SS / "Empezando…"): sube el contraste y un pulso sutil. */
.rtc-cd--urgente {
  color: var(--blanco);
  background: var(--azul-dim);
  border-color: var(--azul);
  animation: rtc-cd-pulso 1.6s ease-in-out infinite;
}

/* En vivo: lenguaje "EN VIVO" (rojo --vivo, único uso semántico). */
.rtc-cd--vivo {
  color: var(--vivo);
  background: rgba(var(--vivo-rgb), 0.14);
  border-color: rgba(var(--vivo-rgb), 0.4);
}
.rtc-cd--vivo::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--vivo);
  box-shadow: 0 0 0 0 rgba(var(--vivo-rgb), 0.5);
  animation: rtc-latido 1.6s ease-out infinite;
}

/* Finalizado / cancelado: apagado (rara vez visible — solo si cruza en pantalla). */
.rtc-cd--fin,
.rtc-cd--cancelado {
  color: var(--gris);
  background: var(--superficie-2);
  border-color: var(--borde);
}

@keyframes rtc-cd-pulso {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.72; }
}

/* HERO "Próximo stream": primer renglón informativo, con su cuenta regresiva.
   El espaciado vertical lo da el gap del .rtc-hero (no margin propio). */
.rtc-hero__prox {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  color: var(--gris-suave);
  font-size: 0.92rem;
}
.rtc-hero__proxlbl {
  font-family: var(--font-head);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.78rem;
  color: var(--azul-claro);
}
.rtc-hero__proxquien {
  color: var(--blanco);
  font-weight: 600;
  overflow-wrap: anywhere;
}
.rtc-cd--hero {
  font-size: 0.82rem;
  padding: 2px 11px;
}

/* PERFIL: la etiqueta relativa vive en su propia celda del grid del item
   (el grid pasa a 3 columnas: fecha | título | countdown alineado al final). */
.rtc-perfil__proxitem { grid-template-columns: auto minmax(0, 1fr) auto; }
.rtc-perfil__proxcd { justify-self: end; }
/* El PRÓXIMO (primero) se destaca con un poco más de peso/borde. */
.rtc-perfil__proxitem--primero { border-left-color: var(--azul-claro); }
.rtc-perfil__proxitem--primero .rtc-perfil__proxfecha { color: var(--blanco); }

/* En móvil estrecho el chip baja a una segunda fila para no comprimir el título. */
@media (max-width: 460px) {
  .rtc-perfil__proxitem {
    grid-template-columns: auto minmax(0, 1fr);
  }
  .rtc-perfil__proxcd {
    grid-column: 1 / -1;
    justify-self: start;
  }
}

/* =========================================================
   ESPÍRITUS / SPRITES (SPEC 0008 · presentación v2 SPEC 0016)
   Cromo `.rtc-esp` reutilizable (tracker · perfil · panel · página por streamer).
   v2: el RECUADRO se colorea por VARIANTE (--marco lo fija .rtc-esp--v-*), y la RAREZA
   es una etiqueta NO cromática (.rtc-esp__rareza). Estado por LUZ: --tengo (marco sólido
   + halo + check) vs --falta (grayscale + opacidad + marco dashed + círculo). Color solo
   por tokens (bloques [data-tema]).
   ========================================================= */

/* Cromo base: cuadrado, marco de VARIANTE, figura, estado (check/círculo), nombre y
   etiqueta de rareza. --marco por defecto = estándar; .rtc-esp--v-* lo reasigna. */
.rtc-esp {
  --marco: var(--var-estandar);
  --marco-rgb: var(--var-estandar-rgb);
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: 100%;
}

/* v2 (R2): el color del recuadro depende de la VARIANTE, no de la rareza. */
.rtc-esp--v-estandar { --marco: var(--var-estandar); --marco-rgb: var(--var-estandar-rgb); }
.rtc-esp--v-gold { --marco: var(--var-gold); --marco-rgb: var(--var-gold-rgb); }
.rtc-esp--v-gummy { --marco: var(--var-gummy); --marco-rgb: var(--var-gummy-rgb); }
.rtc-esp--v-galaxy { --marco: var(--var-galaxy); --marco-rgb: var(--var-galaxy-rgb); }
.rtc-esp--v-holofoil { --marco: var(--var-holofoil); --marco-rgb: var(--var-holofoil-rgb); }

.rtc-esp__fig {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: var(--radio-sm);
  background: var(--superficie-2);
  border: 2px solid rgba(var(--marco-rgb), 0.5);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Marco/halo de VARIANTE (capa decorativa sobre la figura). */
.rtc-esp__marco {
  position: absolute;
  inset: 0;
  border-radius: var(--radio-sm);
  pointer-events: none;
  z-index: 2;
}

.rtc-esp__img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

.rtc-esp__ph {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.6rem;
  color: rgba(var(--marco-rgb), 0.85);
}

/* Insignia de estado (check / ＋) en la esquina.
   v0.51.2 — PROPORCIONAL A LA CELDA. Era 22px FIJOS: sobre la celda de 148px del teaser es el
   2.2 % del área, pero sobre la celda de 60px de la matriz móvil es el 13.4 %, y cae justo
   sobre la CABEZA del sprite, que es donde vive su identidad. El `%` se resuelve contra el
   ancho de `.rtc-esp` (= ancho de celda): 60px → 13.2px, 148px → tope de 22px. El piso de 12px
   protege el área mínima del ícono. El estado no depende de esta insignia (también lo llevan
   grayscale, trama y marco), así que encogerla no quita un canal. */
.rtc-esp__estado {
  position: absolute;
  top: 4px;
  right: 4px;
  z-index: 3;
  width: clamp(12px, 22%, 22px);
  height: auto;
  aspect-ratio: 1 / 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--negro);
}
.rtc-esp__estado svg { width: 68%; height: 68%; }

.rtc-esp__nombre {
  font-size: 0.78rem;
  line-height: 1.15;
  text-align: center;
  color: var(--texto-suave);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Estado TENGO: color + marco sólido de VARIANTE + halo + check verde. */
.rtc-esp--tengo .rtc-esp__marco {
  border: 3px solid var(--marco);
  box-shadow: 0 0 0 1px rgba(var(--marco-rgb), 0.35), 0 0 16px rgba(var(--marco-rgb), 0.28);
}
.rtc-esp--tengo .rtc-esp__estado { color: var(--ok); }
.rtc-esp--tengo .rtc-esp__nombre { color: var(--texto); }

/* Estado FALTA (v3 SPEC 0023 §2.8 #3): grayscale atenuado + marco dashed + trama diagonal
   sobre la figura (lee "ranura por conseguir" en AMBOS temas, sobre todo claro) + ＋ en badge
   dashed en la esquina. Legible AA en oled y claro (paridad de esfuerzo).

   EL MARCO CONSERVA EL COLOR DE LA VARIANTE también aquí (antes `--gris`). El color de
   variante nunca significó "lo tengo": significa IDENTIDAD DE COLUMNA, y por eso sobrevive al
   estado. No colisiona con el contrato v2 de SPEC 0016 ("rareza NO cromática"): esto es
   variante, no rareza.

   ⚠️ v0.51.3 — QUÉ ES Y QUÉ NO ES ESTE BORDE. El comentario de v0.51.2 lo declaraba "el único
   canal de identidad de columna" apoyándose en que 2 de 5 rótulos salían truncados a 390px.
   Las dos mitades de esa afirmación están derogadas:
   1. El truncamiento ya no existe: el rótulo de columna se guiona en vez de recortarse (ver
      `.rtc-espmatriz__colhead-lbl`), y desde v0.51.3 el encabezado además es STICKY en móvil
      mientras no haya scroll-x. La identidad de columna llega por TEXTO, siempre visible.
   2. Este borde NO puede ser canal informativo: `rgba(--marco-rgb, 0.35)` sobre
      `--esp-falta-fondo` mide en tema CLARO 1.53:1 (estándar), 1.54 (dorado), 1.69 (gomoso),
      1.78 (galaxia); en OLED 1.89–2.40:1. Todos por debajo del 3:1 que WCAG 1.4.11 pide a un
      elemento gráfico portador de información.
   ⇒ Se clasifica como REFUERZO DECORATIVO y se deja el alfa en 0.35. No se sube a ≥3:1 (haría
   falta 0.81–0.82 en estándar/dorado) porque un borde de variante a esa fuerza se acerca al
   marco sólido de `--tengo` y erosiona la distinción tengo/falta, que es el canal caro.
   Los canales que SÍ portan información están medidos y todos pasan ≥3:1 contra el fondo de
   la figura: trazo dashed vs solid, grosor 2px vs 3px+halo, grayscale vs color, e insignia
   ＋ vs ✓. En concreto el marco dashed `rgba(--marco-rgb, 0.85)` (abajo) mide 3.22:1
   (estándar), 3.16 (dorado), 3.70 (gomoso), 4.54 (galaxia) en claro y 4.98–8.05:1 en OLED. */
.rtc-esp--falta .rtc-esp__fig {
  border-color: rgba(var(--marco-rgb), 0.35);
  background: var(--esp-falta-fondo);
}
.rtc-esp--falta .rtc-esp__img { filter: grayscale(1); opacity: var(--esp-falta-opacidad); }
.rtc-esp--falta .rtc-esp__ph { color: var(--gris); opacity: var(--esp-falta-opacidad); }
/* Trama diagonal (canal secundario, no texto): repeating-linear-gradient con --esp-falta-patron. */
.rtc-esp--falta .rtc-esp__fig::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: repeating-linear-gradient(45deg, transparent 0 5px, var(--esp-falta-patron) 5px 6px);
}
/* Dashed = "por conseguir"; el COLOR = variante (ver la nota de arriba). Contra `--marco`
   sólido de `--tengo` (3px + halo) sigue siendo inequívoco: trazo discontinuo y más fino. */
.rtc-esp--falta .rtc-esp__marco {
  border: 2px dashed rgba(var(--marco-rgb), 0.85);
}
/* Insignia de estado "falta": ＋ en círculo DASHED (en vez del círculo vacío). */
.rtc-esp--falta .rtc-esp__estado {
  color: var(--gris);
  border: 1px dashed var(--gris);
}

/* Dot de RAREZA por cromo (SPEC 0023 §2.8 #4) — GATED por .rtc-esp--dotrareza (enmienda a R3
   de 0016, condicionada a @guardian-tema). Sin ese modificador el dot NO se muestra → el color
   de rareza queda solo en los chips del desglose (fallback). El TEXTO de rareza y el aria-label
   NO dependen del dot: nunca es color-only. */
.rtc-esp__rarezadot { display: none; }
.rtc-esp--dotrareza .rtc-esp__rarezadot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 5px;
  vertical-align: middle;
  background: var(--rareza-rare);
}
.rtc-esp__rarezadot--rare { background: var(--rareza-rare); }
.rtc-esp__rarezadot--epic { background: var(--rareza-epic); }
.rtc-esp__rarezadot--legendary { background: var(--rareza-legendary); }
.rtc-esp__rarezadot--mythic { background: var(--rareza-mythic); }

/* Variante galaxy: refuerzo del morado con el gradiente de fondo (el color del marco ya
   lo da --marco vía .rtc-esp--v-galaxy). El tinte del nombre por variante se retiró en v2
   (el recuadro ya comunica la variante). */
.rtc-esp--v-galaxy.rtc-esp--tengo .rtc-esp__fig { background-image: var(--grad-galaxy); background-blend-mode: overlay; }

/* Rareza como ETIQUETA no cromática (R3): tercera línea del cromo, tras el nombre.
   MAYÚSCULAS, gris neutro (la rareza también va en el aria-label del cromo → aria-hidden).
   NADA de chip/dot de color (evita el choque galaxy-morado / épica-morada). */
.rtc-esp__rareza {
  /* MAYOR-1: legible AA en ambos temas. ~11.5px + --gris-suave (oled #bccce6 ~11:1). NO
     se atenúa en "me falta" (la rareza es un canal de texto, no debe caer bajo AA).
     §D m3: usa la fuente BODY (no la display) para que MÍTICA/ÉPICA conserven el acento en
     mayúsculas — cobertura de glifos acentuados completa, coherente con los chips del desglose. */
  font: 600 0.72rem/1.1 var(--font-body);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gris-suave);
  text-align: center;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- Rejilla de cromos (tracker + perfil) --- */
.rtc-espgrid {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  gap: 12px;
  margin: 0;
  padding: 0;
}
.rtc-espgrid--perfil { grid-template-columns: repeat(auto-fill, minmax(78px, 1fr)); }
.rtc-espgrid__item { margin: 0; }
.rtc-espgrid__vacio { color: var(--texto-suave); text-align: center; padding: 24px 0; }

/* Botón-toggle del tracker: sin estilo de botón, tap-target ≥44px por la figura. */
.rtc-esp-toggle {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  color: inherit;
  font: inherit;
  border-radius: var(--radio-sm);
}
.rtc-esp-toggle:focus-visible { outline: 2px solid var(--azul); outline-offset: 3px; }

/* --- Layout agrupado por BASE (matriz base × variante, SPEC 0016 §B) ---
   Cada grupo = un espíritu base con sus 4 slots (estandar/gold/gummy/galaxy). Una
   variante ausente = celda vacía, para alinear columnas entre grupos. */
.rtc-espgrupos {
  display: grid;
  gap: 22px;
  margin: 0;
  padding: 0;
}
@media (min-width: 720px) {
  .rtc-espgrupos { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 20px 24px; }
}
.rtc-espgrupo { margin: 0; }

/* SPEC 0023 §2.8 #6 — layout de grupos SIN huecos: grid de 2 columnas con `align-content:
   start` (alturas igualadas por fila; NO `columns`/`masonry`, que no son cross-browser). En
   móvil 1 columna. Los grupos ocultos por filtro/búsqueda (`[hidden]`) no dejan celda fantasma
   (el grid los saca del flujo). El selector del intercambio `.rtc-espsel-grid` NO usa este
   atributo → conserva su rejilla propia. */
.rtc-espgrupos[data-rtc-esp-grid] {
  display: grid;
  grid-template-columns: 1fr;
  gap: 22px;
  align-content: start;
}
.rtc-espgrupos[data-rtc-esp-grid] .rtc-espgrupo { margin: 0; }
/* v0.52.0 (bug v0.51-c) — EL NÚMERO DE COLUMNAS SE DERIVA DEL ANCHO DISPONIBLE, NO DEL VIEWPORT.
   `repeat(2, 1fr)` fijo daba 2 columnas de grupo en cuanto el VIEWPORT pasaba de 720px, pero hoy
   el único emisor de `[data-rtc-esp-grid]` sobre `.rtc-espgrupos` es el TEASER del perfil
   (`espgrupos_html` con `layout:'grupos'`, class-rtc-render.php ~2551; la matriz emite el mismo
   atributo pero sobre `.rtc-espmatriz-wrap`, que no matchea este selector). Ese teaser NO vive en
   el ancho del viewport: vive en una COLUMNA del grid de 2 columnas de `.rtc-perfil__cuerpo`
   (≥860px), o sea ~1/2 del ancho útil. Cuenta a 900px, que reproduce el defecto reportado:
     main 900 − 2×16 padding                     = 868
     columna del cuerpo (868 − 19.2 gap) / 2      = 424.4
     interior del bloque − 2×19.2 padding − 2 bd  = 384
     grupo con `repeat(2,1fr)`: (384 − 24) / 2    = 180
     celda `.rtc-espgrupo__grid`: (180 − 30) / 4  = 37.5px  ⇐ el 37.5 medido por QA
   Y por eso el defecto era una INVERSIÓN (bien en móvil, mal en escritorio): a 390px el cuerpo es
   de 1 columna y esta regla ni entra ⇒ interior del bloque 390 − 32 − 38.4 − 2 = 317.6, y la celda
   sale (317.6 − 24) / 4 = 73.4px — el valor medido por QA.
   ⚠️ PREMISA DEL GAP (se equivocó en v0.52.1 y hay que sostenerla al rehacer la cuenta): el gap
   de `.rtc-espgrupo__grid` NO es constante. Vale **8px** en la regla base (:3364, la que aplica a
   390px ⇒ 3 × 8 = 24) y sube a **10px** solo desde `@media (min-width: 414px)` (:3372 ⇒ 3 × 10 = 30).
   Por eso las cuentas de 900px de arriba usan 30 y esta usa 24. Usar 30 aquí daba 71.9 y ese
   desajuste contra el 73.4 medido se había tapado escribiendo "~73px" en vez de corregir el gap.
   `auto-fit` + un mínimo REAL corrige el conteo midiendo el contenedor: 310px = 4×70 + 3×10, el
   ancho de grupo mínimo para que la celda no baje de 70px (el piso legible que ya tiene en móvil).
   Resultado: 900px → 1 columna, celda 88.5px · 1280px → 1 columna, celda 111px · una vista ancha
   (p. ej. 800px, donde el cuerpo aún es de 1 columna) → 2 columnas, celda 80.5px.
   ⚠️ Si cambia `--esp-cell-min`, el padding del bloque o el gap, REHACER esta cuenta. */
@media (min-width: 720px) {
  .rtc-espgrupos[data-rtc-esp-grid] {
    grid-template-columns: repeat(auto-fit, minmax(310px, 1fr));
    gap: 20px 24px;
  }
}
.rtc-espgrupo__head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0 0 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--borde);
  font: 700 1.05rem var(--font-head);
  color: var(--texto);
}
.rtc-espgrupo__n { font: 600 0.85rem var(--font-head); color: var(--gris); }
/* 4 columnas FIJAS — y el nº de SLOTS que emiten los emisores es INDEPENDIENTE de ese 4.
   Los tres emisores emiten UNA celda por variante PRESENTE en el conjunto que reciben:
     · `RTC_Render::espgrupos_html` → `variantes_presentes($items)` (class-rtc-render.php ~2576);
     · `espGruposSelectorHtml`/`espGruposMultiHtml` → `ordenVariante()` (comunidad-intercambios.js);
     · `pintarEspFijo` → `ordenVariante()` (panel/eventos.js).
   Con el catálogo público de hoy eso son **5** (estandar·gold·gummy·galaxy·holofoil) y serán **6**
   en cuanto se active `gem`. 5 celdas en 4 columnas ⇒ cada grupo ocupa 2 filas: 4 + 1.
   ⚠️ v0.52.1 — este comentario decía "los emisores emiten 4 celdas fijas". Era FALSO desde
   v0.51.0 en PHP y desde v0.52.0 en los dos emisores JS. Se corrige el TEXTO, no el layout:
   el 4 fijo es una decisión medida de v0.51.2 que sigue vigente (ver abajo), y el desborde a
   una 2ª fila es cosmético, no una desalineación.
   POR QUÉ NO SE DERIVAN LAS COLUMNAS DE LOS SLOTS: v0.51.0 usó `repeat(var(--esp-nvar,4),…)` y
   se revirtió en v0.51.2 porque el teaser del perfil recibe un SUBCONJUNTO DISPERSO
   (`array_slice($catalogo, 0, 8)`): si esos 8 ítems son todos `estandar`, `--esp-nvar` vale 1 y
   el cromo se estira a ancho COMPLETO. Con 4 fijas ningún emisor depende de qué traiga su
   subconjunto. Un `max(4, nSlots)` cerraría el desborde, pero cambiaría el divisor de la cuenta
   de arriba (celda del teaser a 900px: (384−30)/4 = 88.5px → /5 = 70.8px) y del `minmax(310px)`
   (= 4×70 + 3×10) ⇒ tocaría re-medir v0.51-c, que ya está verificado en producción.
   LO QUE SÍ GARANTIZA LA CORRESPONDENCIA variante↔columna: `variantes_presentes`/`ordenVariante`
   se calculan UNA vez sobre el conjunto completo, no por grupo, así que TODOS los grupos emiten
   la misma lista ordenada de slots y el slot i-ésimo es la misma variante en todos ellos; las
   variantes que a una base le faltan van como `.rtc-espgrupo__slot--vacio` (`visibility:hidden`,
   NO `display:none` — conservan su celda; ver el crítico de v0.51.x, donde `[hidden]` sí sacaba
   las celdas del flujo y desalineaba la matriz).
   ⚠️ Si cambias este `4`, rehaz las dos cuentas de arriba y vuelve a medir el teaser del perfil,
   el selector de `/intercambios` y el selector "Espíritu fijo" del panel. */
.rtc-espgrupo__grid {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin: 0;
  padding: 0;
}
@media (min-width: 414px) {
  .rtc-espgrupo__grid { gap: 10px; }
}
/* Celda vacía: reserva la columna de una variante ausente (sin borde ni contenido). */
.rtc-espgrupo__slot--vacio { visibility: hidden; }

/* =========================================================
   MATRIZ CONTINUA base × variante (`.rtc-espmatriz`, v0.51.0)
   Una sola rejilla: las columnas de VARIANTE se rotulan UNA vez arriba, la BASE rotula su
   fila, las celdas no repiten texto. Sustituye a la pila de tarjetas independientes, que
   repetía encabezado + nombre de variante + rareza en CADA cromo.

   ⚠️ TODO lo de aquí va scoped a `.rtc-espmatriz*`, JAMÁS bajo `.rtc-espgrupos`: el panel
   "Mis espíritus" y el selector de intercambios se construyen client-side sobre
   `.rtc-espsel`/`.rtc-espgrupos` y se los llevaría por delante.

   ⚠️ NO se copia la geometría de la IMAGEN descargable. Allí `nCols = (nVar <= 5) ? 2 : 1`
   porque el lienzo tiene ALTO FIJO (H = W × 2.2). Aquí el scroll vertical es GRATIS y el
   recurso escaso es el ANCHO ⇒ SIEMPRE UN BLOQUE. Se comparte el modelo de lectura, no el
   conteo de bloques: que nadie "sincronice" `nCols` a la web.
   ========================================================= */
/* Encabezado de la matriz (v0.51.3, MAYOR-A). Mismo peso visual que `.rtc-espmasraro__tit`:
   son los dos `h2` hermanos de la página y deben leerse como el mismo nivel. */
.rtc-espmatriz__tit {
  font: 700 1.1rem var(--font-head);
  color: var(--texto);
  margin: 0 0 10px;
}
.rtc-espmatriz-wrap {
  /* Móvil = "columnas completas": 5 variantes caben ENTERAS hasta 360px sin scroll lateral
     (5 × 52 + 4 × 6 = 284 ≤ 328px de ancho útil a 360). El scroll horizontal queda de
     reserva para cuando el catálogo crezca a 6+ (Cubo/Gema/Cuac). */
  --esp-cell-min: 52px;
  /* Tope del sprite en escritorio: sin él, 5 columnas sobre 1048px darían ~171px. */
  --esp-cell-max: 148px;
  --esp-label-w: 132px;
  --esp-gap: 6px;
  /* Offset del encabezado sticky = alto de `.rtc-top` (sticky, top:0). 56px de `min-height`
     + 1px de `border-bottom`. En ≥900px el header PUEDE envolver a 2-3 filas, así que el
     valor real lo publica `initEspMatriz` (comunidad.js) en `--rtc-top-h`; este 57px es el
     respaldo cuando no hay JS. VERIFICAR EN RENDER (gate QA). */
  --esp-sticky-top: var(--rtc-top-h, 57px);
  margin: 0 0 22px;
}
/* WCAG 2.1.1 — el contenedor con scroll es alcanzable por teclado (`tabindex`/`role`/label
   en el HTML). `overscroll-behavior-x` evita el swipe-back accidental del navegador.

   ⚠️ v0.51.3 — EL SCROLL-X SE CONDICIONA A `--ancho`, EN TODOS LOS VIEWPORTS. Hasta v0.51.2
   el `overflow-x: auto` era incondicional en móvil y solo pasaba a `visible` en ≥600px. Como
   `overflow-x` distinto de `visible` en un ancestro anula `position:sticky`, eso mataba el
   encabezado sticky en móvil SIN que hubiera scroll que proteger: medido a 390px con el
   catálogo de hoy, `.rtc-espmatriz__scroll` da `scrollWidth 326 / clientWidth 326` (5
   variantes, `--ancho` ausente). El CSS lo justificaba como "limitación real de overflow-x +
   position:sticky": la incompatibilidad es real, pero la premisa de que ahí HAY scroll no lo
   era. Ahora el scroll (y por tanto la pérdida del sticky) vive solo donde el servidor marca
   `--ancho`, es decir con 6+ variantes presentes — que es cuando la rejilla sí desborda
   (6×52 + 5×6 = 342 > 328px útiles a 360). No hay umbral escrito a mano aquí.

   PISO DE ANCHO de esta decisión, con la cuenta: con 5 variantes la rejilla exige
   5×52 + 4×6 = 284px, más 2×16 de padding del contenedor = 316px de viewport. Por encima de
   316px cabe y `visible` es seguro; por debajo desbordaría, y como `<body>` lleva
   `overflow-x: clip` (ver la nota de anti scroll-horizontal, arriba) se RECORTARÍA en vez de
   scrollear. 316px queda por debajo del suelo real de los navegadores móviles (320px), así que
   hoy no es alcanzable. Si el catálogo llega a 6 variantes, el servidor pone `--ancho` y vuelve
   el scroll antes de que eso importe. Si algún día se sube `--esp-cell-min`, REHAZ esta cuenta. */
.rtc-espmatriz__scroll {
  overflow-x: visible;
  overscroll-behavior-x: contain;
}
.rtc-espmatriz-wrap--ancho .rtc-espmatriz__scroll { overflow-x: auto; }
.rtc-espmatriz__scroll:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

.rtc-espmatriz {
  display: grid;
  /* Móvil: SIN columna de rótulo (a 360px no cabe — ver `--esp-cell-min`); el rótulo de fila
     ocupa el ancho completo sobre sus celdas. */
  grid-template-columns: repeat(var(--esp-nvar, 5), minmax(var(--esp-cell-min), 1fr));
  gap: var(--esp-gap);
  align-items: stretch;
}

/* ⚠️ COLUMNA EXPLÍCITA (v0.51.2) — LA REGLA QUE SOSTIENE TODA LA MATRIZ.
   Cada encabezado y cada slot (incluidos los `--vacio`) traen su columna sobre las variantes
   VIVAS; el servidor la fija inline y `espAjustarColumnas` (comunidad.js) la reasigna al
   filtrar. Sin esto la colocación depende del ORDEN DE DOM (auto-placement) y basta ocultar UNA
   celda para que todas las siguientes se corran una pista, en cascada: medido a 1440px con "Me
   falta" y un cromo marcado, 76 de 79 celdas caían bajo el encabezado de otra variante; con
   Variante=Dorado, 11 de 18 filas, con el vacío invadiendo la pista del rótulo. NO borres estas
   declaraciones "porque cada fila ya emite un slot por columna": esa premisa solo se cumple
   mientras no se retire ningún nodo del flujo, y el filtro los retira.

   Son DOS variables y no una con `calc(var(--esp-col) + 1)` a propósito: en ≥600px la pista 1
   es el rótulo de fila, así que la columna se desplaza uno. `calc()` donde la gramática pide un
   `<integer>` (línea de grid) tiene soporte desigual y su modo de falla aquí sería el MISMO
   desalineado que este bloque viene a arreglar, solo que en los navegadores que no lo soporten
   ⇒ se emiten los dos valores ya resueltos y no se depende de esa capacidad. */
.rtc-espmatriz__colhead,
.rtc-espmatriz__celda {
  grid-column: var(--esp-col);
}
@media (min-width: 600px) {
  .rtc-espmatriz__colhead,
  .rtc-espmatriz__celda {
    grid-column: var(--esp-col-d);
  }
  .rtc-espmatriz__esquina { grid-column: 1; }
}

@media (min-width: 600px) {
  /* ESTA SOLA DECLARACIÓN cubre 5, 6, 7 y 8 columnas sin una media query nueva (requisito
     duro: el día que salgan Cubo/Gema/Cuac el layout no se toca). `--esp-nvar` lo fija el
     servidor inline desde las variantes REALMENTE presentes. */
  .rtc-espmatriz {
    grid-template-columns: var(--esp-label-w) repeat(var(--esp-nvar, 5), minmax(var(--esp-cell-min), 1fr));
    /* Tope de celda, derivado — no una media query por nº de columnas. */
    max-width: calc(var(--esp-label-w) + var(--esp-nvar, 5) * (var(--esp-cell-max) + var(--esp-gap)));
  }
}

/* Encabezado de columna: muestra de color de la VARIANTE (reusa `.rtc-espfiltros__sw--*`,
   mismo lenguaje que los filtros) + etiqueta. Se pinta UNA vez para toda la matriz. */
.rtc-espmatriz__colhead {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 6px 2px;
  min-width: 0;
  /* 0.72rem = piso tipográfico de §4 (v0.51.0 lo dejó en 0.7rem, por debajo). */
  font: 600 0.72rem var(--font-body);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--gris-suave);
  text-align: center;
}
/* La esquina (cruce rótulo-de-fila × rótulo-de-columna) SOLO existe cuando hay columna de
   rótulo. En móvil no la hay: dejarla ocuparía una de las N columnas de la fila de
   encabezados y la desalinearía con las celdas. */
.rtc-espmatriz__esquina { display: none; }
@media (min-width: 600px) {
  .rtc-espmatriz__esquina { display: block; }
}
.rtc-espmatriz__sw {
  width: 12px;
  height: 12px;
  border-radius: 4px;
  flex: 0 0 auto;
}
/* Móvil: el rótulo ENVUELVE a 2 líneas en vez de recortarse. Medido a 390px la celda da 60px
   (56 útiles tras el padding) y "Estándar" pide ~65px, "Holográfico" ~87 ⇒ salían `ESTÁN…` /
   `HOLOG…`. Ese rótulo es el canal TEXTUAL de identidad de columna: recortarlo lo anula. Dos
   líneas de 11.5px caben en el alto actual del encabezado (42px medidos).

   ⚠️ v0.51.3 — `overflow-wrap: anywhere` (v0.51.2) curaba el recorte pero partía a mitad de
   palabra SIN guion: medido `ESTÁND/AR` y `HOLOGR/ÁFICO` a 390px, y 4 de 5 rótulos partidos a
   360px (`DORAD/O`, `GOMOS/O`, `GALAXI/A`). Se conserva la información pero se lee como error
   de render. Ahora se guiona de verdad con `hyphens: auto`, que corta por sílabas y DIBUJA el
   guion (`ESTÁN-/DAR`), apoyándose en el `lang="es-MX"` que WP pone en `<html>`.
   `overflow-wrap: break-word` queda SOLO de red: actúa cuando una palabra sigue sin caber
   entera y el navegador no tiene diccionario de guionado para `es` — degrada al
   comportamiento anterior en vez de desbordar. No es `anywhere`: `break-word` no parte
   palabras que sí caben en su propia línea. VERIFICAR EN RENDER (gate QA): a 360 y 390 debe
   verse el guion en los rótulos que partan. */
.rtc-espmatriz__colhead-lbl {
  max-width: 100%;
  -webkit-hyphens: auto;
  hyphens: auto;
  overflow-wrap: break-word;
  line-height: 1.1;
}
@media (min-width: 600px) {
  /* Con columna de rótulo hay ancho de sobra: vuelve a una línea con ellipsis de seguridad. */
  .rtc-espmatriz__colhead-lbl {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}
/* Sticky bajo la barra superior, EN TODOS LOS VIEWPORTS (v0.51.3; antes solo ≥600px — ver la
   nota de `.rtc-espmatriz__scroll`). Con 18 filas de matriz, perder el rótulo de columna al
   bajar es perder la identidad de columna justo donde más se marca: en móvil. */
.rtc-espmatriz__colhead,
.rtc-espmatriz__esquina {
  position: sticky;
  top: var(--esp-sticky-top);
  z-index: 2;
  background: var(--negro);
}
@media (min-width: 600px) {
  .rtc-espmatriz__colhead { font-size: 0.75rem; }
}
/* Con 6+ variantes la rejilla excede el contenedor ⇒ vuelve el scroll-x y CAE el sticky (son
   incompatibles: `overflow-x` != `visible` en un ancestro anula `position:sticky`). Se
   declara explícitamente `static` para que el fallo sea un encabezado que scrollea con la
   tabla, no uno que se queda pegado en el sitio equivocado. La clase la pone el servidor a
   partir del nº de variantes PRESENTES; no hay umbral escrito a mano en el CSS. */
.rtc-espmatriz-wrap--ancho .rtc-espmatriz__colhead,
.rtc-espmatriz-wrap--ancho .rtc-espmatriz__esquina { position: static; }

/* Rótulo de FILA: nombre + rareza (etiqueta NO cromática, contrato v2 de SPEC 0016) +
   contador N/M. En móvil ocupa el ancho completo sobre sus celdas. */
.rtc-espmatriz__rot {
  /* En móvil ocupa el ancho completo y, al ser un grid item que abarca todas las pistas,
     FUERZA el salto de línea que separa una fila de la siguiente. Es `<h3>` desde v0.51.2
     (v0.51.0 lo bajó a `<div>` y la página quedó sin un solo `h3`): de ahí `margin:0` y la
     tipografía explícita en `__nom`, para que el `<h3>` no traiga sus defaults. */
  margin: 0;
  grid-column: 1 / -1;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 8px;
  min-width: 0;
  padding: 8px 0 2px;
}
.rtc-espmatriz__nom {
  font: 700 1rem var(--font-head);
  color: var(--texto);
  min-width: 0;
}
.rtc-espmatriz__rareza {
  /* 0.72rem = piso tipográfico de §4 (v0.51.0 lo dejó en 0.68rem, por debajo). */
  font: 600 0.72rem var(--font-body);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gris-suave);
}
.rtc-espmatriz__n {
  font: 600 0.8rem var(--font-head);
  color: var(--gris);
  font-variant-numeric: tabular-nums;
  margin-left: auto;
}
@media (min-width: 600px) {
  .rtc-espmatriz__rot {
    /* Pista 1 EXPLÍCITA (no `auto`): con celdas ancladas por `--esp-col` el rótulo debe
       anclarse igual, o el auto-placement lo mete en el primer hueco que encuentre. */
    grid-column: 1;
    flex-direction: column;
    align-items: flex-start;
    align-self: center;
    justify-content: center;
    gap: 2px;
    padding: 0 8px 0 0;
  }
  .rtc-espmatriz__n { margin-left: 0; }
  /* En escritorio el rótulo es el identificador principal de la fila y competía a 16px contra
     sprites de 148px. Sube un escalón (18px) solo donde hay columna de rótulo. */
  .rtc-espmatriz__nom { font-size: 1.125rem; }
}

/* Celda: el cromo pelado. Dentro de la matriz el nombre de variante y la rareza son
   REDUNDANTES (los dan el encabezado de columna y el rótulo de fila) ⇒ se ocultan AQUÍ y
   solo aquí. `.rtc-esp` (marco, estado, trama, insignia, aria-label) queda intocado: el
   cromo es `role="img"` con `aria-label` completo, que PODA a sus descendientes, así que
   ocultar el texto visible no le quita nada a un lector de pantalla. */
.rtc-espmatriz__celda { min-width: 0; }
.rtc-espmatriz .rtc-esp__nombre,
.rtc-espmatriz .rtc-esp__rareza { display: none; }
/* Fallback de rareza MIXTA en una base: solo esa fila reexpone la rareza por celda (el
   rótulo de fila la omite). El rótulo nunca miente. */
.rtc-espmatriz__celda--conrareza .rtc-esp__rareza { display: block; }
/* Variante ausente = esa variante NO EXISTE para esta base. Hasta v0.51.1 era
   `visibility:hidden`: un hueco MUDO que se leía como "no cargó" o —peor, en una herramienta
   de trades— como "te falta". Confundir "no existe" con "te falta" es el error caro de este
   producto, así que ahora el slot se declara con un guion sobre una superficie plana. Se
   distingue de "te falta" en los tres canales visuales: sin trama diagonal, sin marco dashed
   de variante y sin insignia ＋.
   La columna ya la sostiene `--esp-col` (arriba), no la ocupación del slot.

   ⚠️ v0.51.3 — EL GUION NO LLEGABA POR NINGÚN CANAL, pese a que v0.51.2 lo llamaba "canal de
   texto, no color". Dos defectos medidos: (1) el `opacity: 0.55` de la celda arrastraba al
   guion a 2.14:1 en tema claro (`--gris` #5b6b85 al 55 % sobre el lienzo #eef2f8), bajo el
   4.5:1 de AA para texto — y 3.08:1 en OLED, también bajo; (2) el `<div>` iba
   `aria-hidden="true"`, así que para un lector de pantalla el slot sencillamente no existía.
   Corrección: el `opacity` deja de aplicarse a la celda entera y el guion va a color pleno ⇒
   4.81:1 en claro y 8.51:1 en OLED, ambos AA. La atenuación que buscaba el 0.55 se conserva
   SOLO en el borde, que es decorativo. El nombre accesible lo pone el PHP (`role="img"` +
   `aria-label` "… · no existe") y hay una leyenda bajo la matriz. */
.rtc-espmatriz__celda--vacio {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1;
  border-radius: var(--radio-sm);
  border: 1px solid var(--borde);
}
.rtc-espmatriz__novale {
  font: 600 0.9rem var(--font-body);
  color: var(--gris);
  line-height: 1;
}
/* Leyenda de la matriz: explica el guion en TEXTO, una vez, bajo la rejilla. Sin ella el `—`
   se puede leer como "otra que me falta", que es la confusión cara de esta herramienta. */
.rtc-espmatriz__leyenda {
  margin: 8px 0 0;
  font-size: 0.8rem;
  line-height: 1.35;
  color: var(--texto-suave);
}
.rtc-espmatriz__leyenda b {
  font-weight: 700;
  color: var(--texto);
}

/* --- Sección "Únicos": bases con EXACTAMENTE una variante (misma regla que el canvas).
   Aquí SÍ va el nombre bajo el sprite: fuera de la matriz no hay rótulo de fila. --- */
.rtc-espunicos { margin-top: 24px; }
.rtc-espunicos__tit {
  margin: 0 0 2px;
  font: 700 1rem var(--font-head);
  color: var(--texto);
}
.rtc-espunicos__sub {
  margin: 0 0 10px;
  font-size: 0.85rem;
  color: var(--gris-suave);
}
/* La celda se DERIVA de la matriz, pero NO es la misma celda: aquí el cromo SÍ lleva nombre y
   rareza debajo (tema.md), y la matriz los oculta. Historia de las dos correcciones:

   · v0.51.2 quiso parear la escala y usó `repeat(auto-fill, minmax(--esp-cell-min, 1fr))`.
     Eso deriva el NÚMERO DE COLUMNAS DEL ANCHO, mientras la matriz lo FIJA con
     `repeat(var(--esp-nvar), …)`. Coincidían en móvil por accidente aritmético; en escritorio
     el contenedor de 770px daba floor((770+6)/(52+6)) = 13 columnas ⇒ celda de 53.7px contra
     los 148px de la matriz (0.36×). El `max-width` acota el CONTENEDOR, nunca el conteo.
   · v0.51.3 fija el conteo desde `--esp-nvar` igual que la matriz ⇒ (770 − 4×6)/5 = 149.2px,
     pareado con la matriz. Cero tokens nuevos en este eje.

   MÓVIL — por qué NO se fija a `--esp-nvar` aquí. Con 5 columnas a 360px la celda queda en
   54.4px útiles y el texto que esta sección existe para mostrar no cabe: "Maní Quemado" pide
   89px (medido `scrollWidth` 89 / `clientWidth` 60) y "MÍTICA" desborda a lo ancho y se corta
   contra el borde inferior. Se usa un mínimo PROPIO, `--esp-uni-cell-min`, dimensionado por el
   texto (89px del nombre más largo + 6px de aire = 95 → 96px):
     360px: floor((328 + 6) / (96 + 6)) = 3 columnas de (328 − 2×6)/3 = 105.3px
     390px: floor((358 + 6) / 102)      = 3 columnas de (358 − 12)/3  = 115.3px
   Los 3 únicos caben en UNA fila en ambos y ningún texto se recorta.
   TRADE-OFF ACEPTADO Y MEDIDO: en móvil el sprite de Únicos queda 105/54.4 = 1.94× el de la
   matriz. Es una regresión PARCIAL del pareo de v0.51.2 (que venía de 2.7×), tomada a
   propósito: con 3 ítems y texto obligatorio, la legibilidad del nombre+rareza pesa más que la
   paridad de escala. Si se decide lo contrario, el revert es cambiar `--esp-uni-cell-min` por
   `--esp-cell-min` y `auto-fit` por `repeat(var(--esp-nvar,5), …)` — y volverá el recorte. */
.rtc-espunicos__grid {
  /* Ancho mínimo de celda dictado por el TEXTO, no por el sprite (ver la cuenta de arriba). */
  --esp-uni-cell-min: 96px;
  list-style: none;
  display: grid;
  /* `min(…, 100%)` evita el desbordamiento si el contenedor fuera más estrecho que el mínimo. */
  grid-template-columns: repeat(auto-fit, minmax(min(var(--esp-uni-cell-min), 100%), 1fr));
  gap: var(--esp-gap);
  margin: 0;
  padding: 0;
}
@media (min-width: 600px) {
  .rtc-espunicos__grid {
    /* Mismo conteo que la matriz ⇒ misma anchura de celda (149.2px sobre 770px). */
    grid-template-columns: repeat(var(--esp-nvar, 5), minmax(var(--esp-cell-min), 1fr));
    max-width: calc(var(--esp-nvar, 5) * (var(--esp-cell-max) + var(--esp-gap)));
  }
}
/* El nombre y la rareza de un único NO se recortan: esta sección existe para mostrarlos
   (tema.md). Se permite envolver por PALABRAS — `white-space: normal` sin
   `overflow-wrap: anywhere`, para no repetir el corte a mitad de palabra que hubo que deshacer
   en el rótulo de columna. "Maní Quemado" parte en "Maní" / "Quemado" (~45px, cabe). */
.rtc-espunicos__celda .rtc-esp__nombre,
.rtc-espunicos__celda .rtc-esp__rareza {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
}

/* --- Barra de acciones flotante en móvil (SPEC 0016 §D + MAYOR-2) ---
   Fija al borde inferior del viewport durante el marcado; estática y centrada en ≥720px.
   El contenedor del tracker lleva padding-bottom para que la barra no tape el último grupo. */
.rtc-espbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  align-items: center;
  background: var(--top-bg);
  backdrop-filter: blur(8px);
  border-top: 1px solid var(--borde);
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
}
.rtc-espbar .rtc-btn { min-height: var(--tap); }
/* MAYOR-3: "Guardar mi tracker" es la acción primaria única y va PRIMERO. */
.rtc-espbar__guardar { order: -1; }
.rtc-espbar__hint {
  order: 1;
  flex-basis: 100%;
  margin: 0;
  text-align: center;
  font-size: 0.8rem;
  color: var(--texto-suave);
}
.rtc-esptracker__guardomsg { order: 2; flex-basis: 100%; text-align: center; color: var(--texto-suave); font-size: 0.85rem; }
.rtc-esptracker__guardomsg:empty { display: none; }
/* Deja aire bajo el contenido para la barra flotante (móvil). */
@media (max-width: 719px) {
  .rtc-esptracker, .rtc-espst { padding-bottom: 132px; }
}
@media (min-width: 720px) {
  .rtc-espbar {
    position: static;
    background: none;
    border: 0;
    backdrop-filter: none;
    justify-content: center;
  }
}

/* --- Epic ID opcional del tracker GLOBAL (v0.33.0) ---
   Campo para personalizar la imagen descargable ("Epic: {id}"). Tokens del tema (2 temas),
   input con tap-target ≥44px. No aparece en /streamer/{slug}/espiritus. */
.rtc-espepic {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: 340px;
  margin: 0 auto 16px;
}
.rtc-espepic__label {
  font-family: var(--font-body);
  font-size: 0.85rem;
  color: var(--texto-suave);
}
.rtc-espepic__input {
  width: 100%;
  min-height: var(--tap);
  padding: 0 14px;
  border-radius: var(--radio-sm);
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  color: var(--blanco);
  font-family: var(--font-body);
  font-size: 0.95rem;
}
.rtc-espepic__input::placeholder { color: var(--gris); }
.rtc-espepic__input:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }

/* --- Vista pública /espiritus (tracker) --- */
.rtc-esptracker { max-width: 1000px; margin: 0 auto; padding: 20px 16px 64px; }
.rtc-esptracker__head { text-align: center; margin-bottom: 20px; }
.rtc-esptracker__titulo { font-family: var(--font-head); font-size: 1.9rem; color: var(--texto); }
.rtc-esptracker__sub { color: var(--texto-suave); max-width: 60ch; margin: 8px auto 0; }
.rtc-esptracker__disc {
  display: inline-block;
  margin-top: 12px;
  padding: 4px 12px;
  border: 1px solid var(--borde);
  border-radius: 999px;
  font-size: 0.8rem;
  color: var(--texto-suave);
}
.rtc-esptracker__barra {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}
/* (v3 SPEC 0023) El texto plano `.rtc-esptracker__prog` se reemplazó por el anillo `.rtc-esphero`
   (más abajo). La micro-celebración vive ahora en `.rtc-espmedidor.is-completo`. */
.rtc-esptracker__atajos { display: flex; gap: 8px; }
/* §E — "Marcar todo" / "Limpiar" con área táctil completa (≥44px). */
.rtc-esptracker__atajos .rtc-btn--mini { min-height: var(--tap); }

/* =========================================================
   SPEC 0023 — Sprite Tracker v3: héroe (anillo) · desglose · controles · destacados ·
   "más raro" · datos · confirm. Todo color por tokens de [data-tema] (cero hex suelto).
   ========================================================= */

/* --- Héroe: anillo de progreso (donut conic-gradient + máscara radial) --- */
/* @property registra --pct como <number> interpolable → el anillo TRANSICIONA al marcar
   (bajo prefers-reduced-motion se anula, ver más abajo). Sin soporte, el cambio es instantáneo
   (degradación con gracia). */
@property --pct {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}
/* v0.51.0 — ANILLO → BARRA (`.rtc-espmedidor`).
   Por qué: el donut medía 128px (160 ≥720px) de ALTO y en móvil el fold se agotaba antes del
   primer sprite. La barra apila cifras + pista en ~50px. Coherente con la imagen descargable,
   que ya pasó a barra en v0.50.3. Se REUSAN `--pct` + `@property` (arriba), el token
   `--esp-anillo-track` como pista y los data-hooks del motor: CERO tokens de color nuevos y
   `espActualizarAnillo` (comunidad.js) no cambia una línea.
   Nombre `.rtc-espmedidor` y NO `.rtc-espbarra`: `.rtc-espbar` ya es la barra de acciones. */
.rtc-esphero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  margin: 0 auto 22px;
  width: 100%;
  max-width: 620px;
}
.rtc-esphero__medidor {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  width: 100%;
}
.rtc-espmedidor {
  --pct: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  transition: --pct 0.5s ease;
}
.rtc-espmedidor__cifras {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.rtc-espmedidor__pct {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.9rem;
  line-height: 1;
  color: var(--texto);
  font-variant-numeric: tabular-nums;
}
.rtc-espmedidor__frac {
  font-size: 0.85rem;
  color: var(--gris-suave);
  font-variant-numeric: tabular-nums;
}
.rtc-espmedidor__pista {
  display: block;
  height: 12px;
  border-radius: 999px;
  background: var(--esp-anillo-track);
  overflow: hidden;
}
/* El relleno se deriva de --pct igual que lo hacía el conic-gradient del aro. El color sale del
   alias `--esp-medidor-fill`, que cada tema define con la cuenta hecha (oled 5.76:1 con --azul;
   claro 3.66:1 con --azul-claro; ambos ≥3:1 de objeto gráfico contra su pista — números
   recalculados en v0.51.3; v0.51.2 publicaba 3.75 en claro, que no se reproduce). NO hay `inset`
   de contorno: el que llevaba v0.51.1 medía 2.23:1 compuesto contra el propio relleno, es decir
   no dibujaba nada. */
.rtc-espmedidor__fill {
  display: block;
  height: 100%;
  width: calc(var(--pct) * 1%);
  border-radius: 999px;
  background: var(--esp-medidor-fill);
}
/* Completa (N/N): relleno --ok + glow (reusa is-completo) + "¡Colección completa!".
   `--ok` NO se toca: mide 3.40:1 contra la pista en claro, ya pasa. */
.rtc-espmedidor.is-completo .rtc-espmedidor__fill { background: var(--ok); }
.rtc-espmedidor.is-completo { filter: drop-shadow(0 0 10px rgba(var(--ok-rgb), 0.45)); }
/* "¡Colección completa!" — se usa --oro-texto (oro AA para TEXTO en ambos temas), NO
   --var-gold (que en claro es marco 3:1, no AA de texto). Honra "gold en claro solo como
   dot/gráfico, jamás texto". */
.rtc-espmedidor__completa {
  margin: 0;
  font: 700 1rem var(--font-head);
  letter-spacing: 0.02em;
  color: var(--oro-texto);
  text-align: center;
}
/* ≥720px — el héroe pasa a DOS COLUMNAS (medidor izquierda · desglose derecha). Antes el
   donut iba centrado y dejaba ~230px muertos a cada lado; la barra ocupa el ancho útil y el
   desglose sube a la misma banda en vez de apilarse debajo. */
@media (min-width: 720px) {
  .rtc-esphero {
    flex-direction: row;
    align-items: center;
    gap: 24px;
    max-width: 900px;
  }
  .rtc-esphero__medidor { flex: 1 1 0; }
  .rtc-esphero .rtc-espdesglose { flex: 1 1 0; }
  .rtc-espmedidor__pct { font-size: 2.3rem; }
}

/* --- Desglose por rareza y por variante (chips) --- */
.rtc-espdesglose {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  max-width: 560px;
}
/* v0.51.2 — el desglose salió del héroe y va SUELTO debajo de la matriz (ver `esp_anillo_html`):
   dentro del flex del héroe heredaba centrado y separación; aquí se los da él mismo. */
.rtc-espdesglose--pie {
  margin: 26px auto 0;
}
/* §D M4 — cada eje (rareza / variante) es un grupo con su etiqueta encima de sus chips. */
.rtc-espdesglose__grupo {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.rtc-espdesglose__eje {
  font: 700 0.72rem/1.1 var(--font-head);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--texto-suave);
}
.rtc-espdesglose__fila {
  display: flex;
  flex-wrap: wrap;      /* móvil incluido: las chips ENVUELVEN a varias filas en vez de scroll-x
                           horizontal, que cortaba Épica/Rara a la mitad y se leía como roto. */
  gap: 8px;
  padding-bottom: 2px;
}
.rtc-espchip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  padding: 5px 10px;
  border-radius: var(--radio-sm);
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  font-size: 0.8rem;
  /* --chip-c / --chip-rgb los fijan los modificadores de rareza/variante (dot + mini-barra). */
  --chip-c: var(--gris);
  --chip-rgb: 147, 166, 198;
}
.rtc-espchip__dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex: 0 0 auto;
  background: var(--chip-c);
}
.rtc-espchip__lbl { color: var(--gris-suave); }
/* La fracción SIEMPRE en --texto (blindaje AA), nunca el color del chip. */
.rtc-espchip__frac { color: var(--texto); font-weight: 700; font-variant-numeric: tabular-nums; }
.rtc-espchip__barra {
  width: 34px;
  height: 3px;
  border-radius: 2px;
  overflow: hidden;
  background: rgba(var(--chip-rgb), 0.20);
  flex: 0 0 auto;
}
.rtc-espchip__fill { display: block; height: 100%; background: var(--chip-c); }
/* Colores del chip por rareza / variante (solo dot + mini-barra, no el número). */
.rtc-espchip--r-rare { --chip-c: var(--rareza-rare); --chip-rgb: var(--rareza-rare-rgb); }
.rtc-espchip--r-epic { --chip-c: var(--rareza-epic); --chip-rgb: var(--rareza-epic-rgb); }
.rtc-espchip--r-legendary { --chip-c: var(--rareza-legendary); --chip-rgb: var(--rareza-legendary-rgb); }
.rtc-espchip--r-mythic { --chip-c: var(--rareza-mythic); --chip-rgb: var(--rareza-mythic-rgb); }
.rtc-espchip--v-estandar { --chip-c: var(--var-estandar); --chip-rgb: var(--var-estandar-rgb); }
.rtc-espchip--v-gold { --chip-c: var(--var-gold); --chip-rgb: var(--var-gold-rgb); }
.rtc-espchip--v-gummy { --chip-c: var(--var-gummy); --chip-rgb: var(--var-gummy-rgb); }
.rtc-espchip--v-galaxy { --chip-c: var(--var-galaxy); --chip-rgb: var(--var-galaxy-rgb); }
.rtc-espchip--v-holofoil { --chip-c: var(--var-holofoil); --chip-rgb: var(--var-holofoil-rgb); }

/* --- Controles: búsqueda + orden --- */
.rtc-espctrl { display: flex; flex-wrap: wrap; gap: 10px; flex: 1 1 260px; }
.rtc-espctrl__campo { display: flex; align-items: center; gap: 6px; }
.rtc-espctrl__campo--buscar { flex: 1 1 200px; }
.rtc-espctrl__campo--orden { flex: 0 0 auto; }
.rtc-espctrl__lbl { color: var(--texto-suave); font-size: 0.85rem; font-weight: 600; }
.rtc-espctrl__input,
.rtc-espctrl__select {
  min-height: var(--tap);
  padding: 0 12px;
  border-radius: var(--radio-sm);
  background: var(--superficie);
  border: 1px solid var(--borde);
  color: var(--texto);
  font: 600 0.9rem var(--font-body);
}
.rtc-espctrl__input { width: 100%; }
.rtc-espctrl__input::placeholder { color: var(--gris); }
.rtc-espctrl__input:focus-visible,
.rtc-espctrl__select:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }
/* §D M1/M2 — en pantallas muy angostas (<520px) la fila búsqueda + Orden + atajos hace WRAP
   a filas propias full-width, para que el control "Orden" + su <select> queden completos y
   alcanzables (sin recortarse). min-width:0 permite que el select encoja sin desbordar. */
@media (max-width: 519px) {
  .rtc-espctrl { flex-basis: 100%; }
  .rtc-espctrl__campo--buscar,
  .rtc-espctrl__campo--orden { flex: 1 1 100%; min-width: 0; }
  .rtc-espctrl__campo--orden { justify-content: space-between; }
  .rtc-espctrl__select { flex: 1 1 auto; min-width: 0; }
  .rtc-esptracker__atajos { flex: 1 1 100%; }
  .rtc-esptracker__atajos .rtc-btn--mini { flex: 1 1 0; }
}

/* --- "Lo más raro que te falta" --- */
.rtc-espmasraro { margin: 0 0 20px; }
.rtc-espmasraro__tit { font: 700 1.1rem var(--font-head); color: var(--texto); margin: 0 0 10px; }
.rtc-espmasraro__lista { list-style: none; display: flex; flex-wrap: wrap; gap: 10px; margin: 0; padding: 0; }
.rtc-espmasraro__item { margin: 0; }

/* --- Destacados de la página del streamer ("Lo que le falta" / "Lo que tiene raro") --- */
.rtc-espdestacados { display: grid; grid-template-columns: 1fr; gap: 16px; margin: 0 0 22px; }
@media (min-width: 620px) { .rtc-espdestacados { grid-template-columns: 1fr 1fr; } }
.rtc-espdestacados__bloque {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 14px 16px;
}
.rtc-espdestacados__tit { font: 700 1rem var(--font-head); color: var(--texto); margin: 0 0 10px; }
.rtc-espdestacados__lista { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; }
.rtc-espdestacados__item { margin: 0; }

/* --- SPEC 0024 · Matcher de trades (Ofrécele = V\S · Pídele = S\V) ---
   Sustituye a los destacados genéricos cuando el visitante trae colección. Color por tokens:
   Ofrécele = --ok (lo que das), Pídele = --azul (lo que quieres). Ambos temas por variable. */
.rtc-espmatch { margin: 0 0 22px; }
.rtc-espmatch__resumen {
  font: 600 0.95rem var(--font-head);
  color: var(--texto);
  margin: 0 0 12px;
  text-align: center;
}
.rtc-espmatch__resumen:empty { display: none; }
.rtc-espmatch__cols { display: grid; grid-template-columns: 1fr; gap: 16px; }
@media (min-width: 620px) { .rtc-espmatch__cols { grid-template-columns: 1fr 1fr; } }
.rtc-espmatch__col {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-left: 3px solid var(--azul);
  border-radius: var(--radio);
  padding: 14px 16px;
}
.rtc-espmatch__col--ofrece { border-left-color: var(--ok); }
.rtc-espmatch__col--pide { border-left-color: var(--azul); }
.rtc-espmatch__tit { font: 700 1rem var(--font-head); color: var(--texto); margin: 0 0 10px; }
.rtc-espmatch__lista { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; }
.rtc-espmatch__lista:empty { display: none; }
.rtc-espmatch__item { margin: 0; }
.rtc-espmatch__vacio { color: var(--texto-suave); font-size: 0.9rem; margin: 4px 0 0; }
.rtc-espmatch__acc {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  margin: 16px 0 0;
}
.rtc-espmatch__acc .rtc-btn { min-height: var(--tap); }

/* CTA del empty-state (visible sin colección del visitante). */
.rtc-espmatch-cta {
  text-align: center;
  margin: 0 0 22px;
}
.rtc-espmatch-cta .rtc-btn { min-height: var(--tap); }
.rtc-espmatch-cta__sub {
  display: block;
  color: var(--texto-suave);
  font-size: 0.9rem;
  margin-top: 8px;
}

/* Nota neutra (colecciones idénticas / streamer viéndose). */
.rtc-espmatch-nota {
  text-align: center;
  color: var(--texto-suave);
  font-size: 0.92rem;
  margin: 0 0 22px;
}

/* Tanda consolidada v0.36.x (§A): "copiar-WhatsApp" + "export/import (JSON)" retirados →
   `.rtc-espdatos*` eliminado. El modal `.rtc-espconfirm` se conserva (lo usa "Limpiar"). */

/* --- Pie del tracker (disclaimer bajado, hallazgo #5) --- */
.rtc-esptracker__pie { text-align: center; margin-top: 26px; }
.rtc-esptracker__disc--pie { margin-top: 0; }

/* --- Confirmación on-brand accesible (la usa "Limpiar") --- */
.rtc-espconfirm {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: var(--scrim);
}
.rtc-espconfirm__caja {
  width: 100%;
  max-width: 360px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra-modal);
  padding: 20px;
}
.rtc-espconfirm__msg { color: var(--texto); margin: 0 0 16px; line-height: 1.4; }
.rtc-espconfirm__acc { display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap; }
.rtc-espconfirm__acc .rtc-btn { min-height: var(--tap); }

@media (prefers-reduced-motion: reduce) {
  .rtc-espmedidor { transition: none; }
}

/* Filtros colapsables (patrón calendario). */
.rtc-espfiltros { margin-bottom: 16px; }
.rtc-espfiltros__toggle {
  min-height: var(--tap);
  padding: 10px 16px;
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  background: var(--superficie);
  color: var(--texto);
  font: 600 0.95rem var(--font-body);
  cursor: pointer;
}
.rtc-espfiltros__toggle:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-espfiltros__n { color: var(--azul); }
.rtc-espfiltros__panel {
  margin-top: 12px;
  padding: 16px;
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  background: var(--superficie);
  display: grid;
  gap: 16px;
}
.rtc-espfiltros__grupo { border: 0; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center; }
.rtc-espfiltros__leg { font-family: var(--font-head); font-weight: 600; color: var(--texto); width: 100%; margin-bottom: 4px; }
.rtc-espfiltros__op { display: inline-flex; align-items: center; gap: 6px; min-height: 32px; color: var(--texto-suave); cursor: pointer; }
/* MENOR-1 (R4): muestra de color por variante en el filtro (variante=color, rareza=texto). */
.rtc-espfiltros__sw { width: 14px; height: 14px; border-radius: 4px; flex: 0 0 auto; border: 1px solid var(--borde); }
.rtc-espfiltros__sw--estandar { background: var(--var-estandar); }
.rtc-espfiltros__sw--gold { background: var(--var-gold); }
.rtc-espfiltros__sw--gummy { background: var(--var-gummy); }
.rtc-espfiltros__sw--galaxy { background: var(--var-galaxy); }
/* Holofoil: swatch iridiscente (gradiente tornasol) para diferenciar el acabado holográfico. */
.rtc-espfiltros__sw--holofoil { background: var(--grad-holofoil); }

/* Mensaje de error de la descarga (aria-live): la imagen se compone en memoria y se baja
   en un paso, así que no hay preview; solo se muestra texto si falla toBlob/share. */
.rtc-espbar__err {
  order: 3;
  flex-basis: 100%;
  margin: 0;
  text-align: center;
  font-size: 0.85rem;
  color: var(--error);
}
.rtc-espbar__err:empty { display: none; }

/* --- Bloque "Espíritus que tiene" en el perfil público --- */
.rtc-perfil__bloque--esp .rtc-espgrid { margin-top: 4px; }
.rtc-perfil__espcompartir { margin-top: 14px; }
.rtc-perfil__espnota { margin-top: 10px; font-size: 0.8rem; color: var(--texto-suave); }
.rtc-perfil__espmas {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 12px;
  font-weight: 600;
  color: var(--azul);
}

/* --- Página por streamer /streamer/{slug}/espiritus (SPEC 0016 §E) --- */
.rtc-espst { max-width: 1000px; margin: 0 auto; padding: 16px 16px 64px; }
.rtc-espst__volver { margin-bottom: 12px; }
.rtc-espst__volverlink { display: inline-flex; align-items: center; gap: 4px; color: var(--texto-suave); min-height: var(--tap); }
.rtc-espst__head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 16px;
}
.rtc-espst__avatar {
  flex: 0 0 auto;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--superficie-2);
  display: flex;
  align-items: center;
  justify-content: center;
}
.rtc-espst__avatar img { width: 100%; height: 100%; object-fit: cover; }
.rtc-espst__ini { font-family: var(--font-head); font-weight: 700; font-size: 1.3rem; color: var(--azul); }
.rtc-espst__nombre { font-family: var(--font-head); font-size: 1.5rem; color: var(--texto); margin: 0; }
.rtc-espst__cont { color: var(--azul); font-family: var(--font-head); font-weight: 600; margin: 2px 0 0; }
.rtc-espst__disc {
  display: inline-block;
  margin: 12px 0 20px;
  padding: 4px 12px;
  border: 1px solid var(--borde);
  border-radius: 999px;
  font-size: 0.8rem;
  color: var(--texto-suave);
}
/* Bloque de contacto PROMINENTE (el corazón del feature). */
.rtc-espst__contacto {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-left: 3px solid var(--azul);
  border-radius: var(--radio);
  padding: 16px 18px;
  margin-bottom: 24px;
}
.rtc-espst__contacto-tit { font-family: var(--font-head); font-size: 1.1rem; color: var(--texto); margin: 0 0 4px; }
.rtc-espst__contacto-sub { color: var(--texto-suave); margin: 0 0 12px; }
/* SPEC 0023 §2.8 #8 — redes como BOTONES (contacto primario): canal principal a ancho
   completo, el resto en rejilla; todos ≥44px (min-height del .rtc-plat). */
.rtc-espst__redes {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin: 0;
  padding: 0;
}
.rtc-espst__redes li { margin: 0; }
.rtc-espst__redes li:first-child { grid-column: 1 / -1; }
.rtc-espst__redes .rtc-plat { width: 100%; justify-content: center; font-size: 0.92rem; padding: 0 16px; }
/* §D m5 — en desktop el canal principal (p. ej. Twitch) NO debe estirarse a todo el ancho del
   panel: se le pone un max-width razonable y se centra dentro de su fila. */
@media (min-width: 720px) {
  .rtc-espst__redes li:first-child .rtc-plat { max-width: 360px; margin-inline: auto; }
}

/* Selector "Espíritu fijo" del panel (#rtc-int-fijo, SPEC 0009) — v0.52.0, bug v0.51-e.
   El contenedor es un `.rtc-espgrupos` normal (grid de grupos); lo único propio es acotar su
   alto dentro del formulario de alta, para que los ~18 grupos del catálogo de hoy no empujen el
   CTA "Crear" fuera de la pantalla.
   ⚠️ v0.52.2 — aquí había una cuenta ("18 grupos a 2 columnas ⇒ ~9 filas ⇒ ~2 300px") cuya
   premisa era FALSA: `#rtc-int-fijo` (class-rtc-panel.php) NO lleva `data-rtc-esp-grid`, así que
   NO matchea `.rtc-espgrupos[data-rtc-esp-grid]` y nunca recibe el `repeat(auto-fit, minmax(310px,1fr))`
   de ≥720px. Cae en el `grid-template-columns: 1fr` de la regla base `.rtc-espgrupos` ⇒ **1 columna
   / 18 filas**, no 2 columnas / 9 filas. La cuenta se RETIRA en vez de rehacerse: el tope es `52vh`
   —relativo al viewport— así que el alto natural del contenido no entra en la decisión; sea 9 filas
   o 18, el clamp es el mismo y el scroll interno absorbe el resto.
   Mismo tope y mismo mecanismo que `.rtc-espsel-det__body`, el contenedor con el que el selector
   PÚBLICO de /intercambios resuelve el mismo problema (52vh + scroll propio).
   Solo layout: cero color, cero token nuevo. */
.rtc-espgrupos--espfijo {
  max-height: 52vh;
  overflow-y: auto;
  padding-right: 4px;
}

/* --- Selector de espíritus en el panel (reusa .rtc-modosel; cromo dentro del chip) --- */
.rtc-espsel { gap: 10px; }
.rtc-espsel__chip { width: 88px; padding: 6px; align-items: stretch; }
.rtc-espsel__cont { font-weight: 600; color: var(--azul); }

/* --- Fila del catálogo de espíritus (admin) --- */
.rtc-esp-fila {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  padding: 10px 0;
  border-bottom: 1px solid var(--borde);
}
.rtc-esp-fila .rtc-campo__in { flex: 1 1 120px; min-width: 0; }
.rtc-esp-fila__foto {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--tap);
  padding: 0 12px;
  border: 1px dashed var(--borde);
  border-radius: var(--radio-sm);
  color: var(--texto-suave);
  cursor: pointer;
  white-space: nowrap;
}
.rtc-esp-fila__reord { display: inline-flex; gap: 4px; }
/* Disponibilidad por ítem (SPEC 0025): switch Disponible/Próximamente + fecha. */
.rtc-esp-fila__disp {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: var(--tap);
  padding: 0 10px;
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  color: var(--texto-suave);
  cursor: pointer;
  white-space: nowrap;
  font-size: 0.9rem;
}
.rtc-esp-fila__disp input { width: 20px; height: 20px; accent-color: var(--azul); cursor: pointer; }
/* Ítem "Próximamente" (switch apagado): atenuado, para distinguir los ocultos. */
.rtc-esp-fila__disp:has(input:not(:checked)) { color: var(--texto-suave); opacity: 0.75; border-style: dashed; }
.rtc-esp-fila__fecha { flex: 0 1 150px; min-height: var(--tap); }

/* --- Accesibilidad: respeta "reduce motion". --- */
@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;
  }

  /* Skeletons: sin shimmer animado → placeholder estático (superficie tenue). */
  .rtc-skel__diahead::after,
  .rtc-skel__hora::after,
  .rtc-skel__titulo::after,
  .rtc-skel__meta::after,
  .rtc-skel__ftoggle::after {
    display: none !important;
  }
}

/* =========================================================
   LOBBY (SPEC 0010) — apartar lugar en un stream
   Bloque dentro de la ficha del evento. Solo tokens del tema (cero hex suelto).
   ========================================================= */
.rtc-lobby {
  margin: 8px 0 2px;
  padding: 12px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
}
.rtc-lobby__tit {
  margin: 0 0 8px;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--blanco);
}

/* Barra de cupo */
.rtc-lobby__cupo {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.rtc-lobby__barra {
  position: relative;
  flex: 1 1 120px;
  height: 8px;
  min-width: 120px;
  /* m4 (uxui): track de VACÍO neutro (no azul-dim) para que 0 inscritos no parezca medio
     lleno; el fill --azul crece desde 0%. Borde sutil delimita el track completo. */
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-radius: 999px;
  overflow: hidden;
}
.rtc-lobby__barrafill {
  display: block;
  height: 100%;
  background: var(--azul);
  border-radius: 999px;
  transition: width 0.3s ease;
}
.rtc-lobby__cuenta {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--blanco);
}
.rtc-lobby__estado {
  font-size: 0.78rem;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 999px;
}
.rtc-lobby__estado--lleno {
  color: var(--azul-claro);
  background: var(--azul-dim);
}
.rtc-lobby__estado--cerrado {
  /* Lleno/cerrado NO es un error → tinte NEUTRO (el rojo se reserva a errores reales). */
  color: var(--texto-suave);
  background: var(--superficie);
  border: 1px solid var(--borde);
}

/* Chips de inscritos públicos (Epic + posición); NUNCA WhatsApp */
.rtc-lobby__lista {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  /* row-gap holgado: deja aire para la sombra escalonada de --pila sin pisar la fila de abajo,
     y alinea el wrapping de los chips CON y SIN boletos apilados. */
  gap: 9px 7px;
  align-items: center;
}
.rtc-lobby__chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 30px;
  padding: 3px 9px;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: 999px;
  font-size: 0.82rem;
}
/* Inscrito NO elegible (p. ej. sin contacto): se lista pero no cuenta como boleto. Discreto. */
.rtc-lobby__chip--noelegible { opacity: 0.6; }
.rtc-lobby__chipnota {
  color: var(--gris);
  font-size: 0.74rem;
  font-style: italic;
}
.rtc-lobby__chippos {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--azul-claro);
}
.rtc-lobby__chipepic {
  color: var(--texto);
  overflow-wrap: anywhere;
}
/* Microcopy bajo la lista de participantes (boletos = oportunidades). */
.rtc-eventos__pista {
  margin: 8px 0 0;
  color: var(--gris);
  font-size: 0.8rem;
  line-height: 1.4;
}
.rtc-lobby__espera {
  margin: 8px 0 0;
  font-size: 0.82rem;
  color: var(--texto-suave);
}

/* M1 (uxui) — aviso de "cupo lleno → lista de espera" sobre el form/acción. */
.rtc-lobby__llenoaviso {
  margin: 10px 0 6px;
  padding: 8px 10px;
  border-radius: var(--radio-sm);
  background: var(--superficie-2);
  border: 1px solid var(--azul-borde);
  color: var(--texto);
  font-size: 0.85rem;
  font-weight: 600;
}

/* Empty-state con gancho cuando aún no hay inscritos */
.rtc-lobby__vacio {
  margin: 10px 0 0;
  font-size: 0.85rem;
  color: var(--gris);
}

/* Franja full-width de lobbies bajo la rejilla SEMANA (desktop). En el grid de 7
   columnas ocupa toda la fila (grid-column:1/-1); las tarjetas de lobby van a un
   ancho de lectura cómodo, no embutidas en la columna del día (MAYOR-1). */
.rtc-cal__lobbies { margin-top: 4px; }
.rtc-cal__lobbieshead {
  margin: 8px 0;
  font-size: 1rem;
  font-weight: 600;
  color: var(--blanco);
}
.rtc-cal__lobbieswrap {
  display: grid;
  gap: 12px;
  grid-template-columns: 1fr;
}
.rtc-cal__lobbyitem {
  padding: 12px;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
}
.rtc-cal__lobbytit {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--blanco);
}
.rtc-cal__lobbysub {
  margin: 2px 0 0;
  font-size: 0.82rem;
  color: var(--texto-suave);
}
.rtc-cal__lobbyitem .rtc-lobby {
  margin: 10px 0 0;
  background: var(--superficie-2);
}
@media (min-width: 860px) {
  .rtc-cal__lienzo[data-rtc-modo="semana"] .rtc-cal__lobbies {
    grid-column: 1 / -1;
  }
  /* Varias tarjetas lado a lado, cada una a ancho cómodo para el formulario. */
  .rtc-cal__lobbieswrap {
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  }
}

/* Formulario de inscripción */
.rtc-lobby__form {
  margin-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.rtc-lobby__campo {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.rtc-lobby__lbl {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--blanco);
}
.rtc-lobby__in {
  min-height: var(--tap);
  padding: 10px 12px;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  color: var(--texto);
  font: inherit;
}
.rtc-lobby__in:focus-visible {
  outline: 2px solid var(--azul);
  outline-offset: 1px;
  border-color: var(--azul-borde);
}
.rtc-lobby__ayuda {
  font-size: 0.78rem;
  color: var(--texto-suave);
}

/* Honeypot: fuera de vista, accesible-oculto (no display:none, para que un bot lo vea) */
.rtc-lobby__hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Consentimiento (reusable por otros formularios de inscripción) */
.rtc-consent {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}
.rtc-consent__chk {
  margin-top: 3px;
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
  accent-color: var(--azul);
}
.rtc-consent__lbl {
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--texto-suave);
}
.rtc-consent__link {
  color: var(--azul-claro);
  text-decoration: underline;
}
.rtc-consent__link:focus-visible {
  outline: 2px solid var(--azul);
  outline-offset: 2px;
}

/* Botones del lobby (áreas táctiles ≥44px) */
.rtc-btnlobby {
  min-height: var(--tap);
  padding: 10px 16px;
  border-radius: var(--radio-sm);
  border: 1px solid transparent;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.rtc-btnlobby--enviar {
  /* CTA primario canónico (igual que "Suscribir calendario"): gradiente + sobre-acento.
     AA en ambos temas (antes usaba --azul-oscuro, token de superficie que invierte → ~2.3:1). */
  background: var(--grad);
  color: var(--sobre-acento);
}
.rtc-btnlobby--enviar:hover { filter: brightness(1.06); }
.rtc-btnlobby--enviar[disabled] { opacity: 0.6; cursor: default; }
.rtc-btnlobby--cancelar {
  background: transparent;
  color: var(--error);
  border-color: var(--borde);
}
.rtc-btnlobby:focus-visible {
  outline: 2px solid var(--azul);
  outline-offset: 2px;
}

.rtc-lobby__miestado {
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-start;
}
.rtc-lobby__ok { margin: 0; color: var(--ok); font-weight: 600; }
.rtc-lobby__cerradomsg { margin: 10px 0 0; color: var(--texto-suave); }

/* Mensaje de estado (éxito / error) */
.rtc-lobby__msg {
  margin: 10px 0 0;
  font-size: 0.85rem;
  font-weight: 600;
}
.rtc-lobby__msg--ok { color: var(--ok); }
.rtc-lobby__msg--error { color: var(--error); }

/* =========================================================
   AVISO DE PRIVACIDAD (SPEC 0017) — vista /privacidad
   Reusa .rtc-info (tipografía). Bloque propio .rtc-aviso-priv (distinto del
   componente .rtc-aviso de recordatorios, para no colisionar).
   ========================================================= */
.rtc-aviso-priv__bloque--destacado {
  padding: 14px 16px;
  background: var(--azul-dim);
  border: 1px solid var(--azul-borde);
  border-radius: var(--radio-sm);
}
.rtc-aviso-priv__contacto {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  color: var(--azul-claro);
  text-decoration: underline;
  font-weight: 600;
}
.rtc-aviso-priv__fecha {
  color: var(--texto-suave);
  font-size: 0.85rem;
}

/* Sello "BORRADOR — pendiente de aprobación" */
.rtc-sello {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0 0 18px;
  padding: 12px 14px;
  border-radius: var(--radio-sm);
  font-size: 0.88rem;
  font-weight: 600;
}
.rtc-sello--borrador {
  color: var(--blanco);
  background: rgba(var(--error-rgb), 0.12);
  border: 1px dashed var(--error);
}
.rtc-sello__ico { flex: 0 0 auto; color: var(--error); }
.rtc-sello__txt { line-height: 1.45; }

/* =========================================================
   TORNEOS (SPEC 0013) y SORTEOS (SPEC 0014)
   Mobile-first, BEM, solo tokens. Reutiliza .rtc-lobby__* (cupo/form/consent/chip) y
   .rtc-modlobby (panel del dueño). Componentes nuevos: .rtc-torneo/.rtc-sorteo,
   .rtc-premios, .rtc-podio, .rtc-estado, .rtc-nota-com, .rtc-modochip, .rtc-requisitos,
   .rtc-modganadores, .rtc-sortear, .rtc-histsorteo, .rtc-btnmini.
   ========================================================= */
.rtc-eventos { max-width: 960px; margin: 0 auto; padding: 8px 0 40px; }
.rtc-eventos__lista {
  display: grid;
  grid-template-columns: 1fr;
  gap: 18px;
  margin-top: 18px;
}
@media (min-width: 760px) {
  .rtc-eventos__lista { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.rtc-eventos__cargando,
.rtc-eventos__vacio {
  color: var(--texto-suave);
  text-align: center;
  padding: 28px 12px;
}
.rtc-eventos__h3 {
  font-family: var(--font-head);
  font-size: 0.92rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--texto-suave);
  margin: 14px 0 8px;
}
.rtc-eventos__fecha,
.rtc-eventos__org { color: var(--texto-suave); font-size: 0.9rem; }

.rtc-torneo,
.rtc-sorteo {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra-card);
  padding: 16px 16px 18px;
  display: flex;
  flex-direction: column;
}
.rtc-torneo__titfila {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.rtc-torneo__tit,
.rtc-sorteo__tit {
  font-family: var(--font-head);
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--texto);
  margin: 0;
  line-height: 1.2;
}
.rtc-torneo__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 12px;
  margin-top: 8px;
}
.rtc-sorteo__desc { color: var(--texto-suave); margin: 10px 0 0; line-height: 1.5; }

/* Chip de modo del torneo. */
.rtc-modochip {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--azul-dim);
  border: 1px solid var(--azul-borde);
  color: var(--azul-claro);
  font-size: 0.82rem;
  font-weight: 600;
}

/* Badge de estado. */
.rtc-estado {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  border: 1px solid transparent;
  white-space: nowrap;
}
.rtc-estado--abierto { color: var(--ok); background: rgba(var(--ok-rgb), 0.14); border-color: rgba(var(--ok-rgb), 0.45); }
/* TEMA (guardian-tema): en claro el verde --ok sobre su tinte .14 cae a 3.47:1 (< AA).
   Se sirve como RELLENO SÓLIDO con texto --verde-tinta (mismo par AA del CTA WhatsApp). */
[data-tema="claro"] .rtc-estado--abierto { color: var(--verde-tinta); background: var(--ok); border-color: var(--ok); }
.rtc-estado--cerrado { color: var(--texto-suave); background: var(--superficie-2); border-color: var(--borde); }
.rtc-estado--curso { color: var(--jugando); background: rgba(var(--jugando-rgb), 0.16); border-color: rgba(var(--jugando-rgb), 0.45); }
.rtc-estado--fin { color: var(--azul-claro); background: var(--azul-dim); border-color: var(--azul-borde); }
.rtc-estado--lleno { color: var(--texto); background: var(--superficie-2); border-color: var(--azul-borde); }

/* Premios por lugar. */
.rtc-premios { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.rtc-premios__item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
}
.rtc-premios__medalla {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--superficie);
  border: 1px solid var(--borde);
  color: var(--texto-suave);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 0.9rem;
}
.rtc-premios__medalla--oro {
  color: var(--negro);
  background: var(--var-gold);
  border-color: var(--var-gold);
}
/* TEMA (guardian-tema, MENOR): en claro el --var-gold es token de MARCO (3:1) y falla como
   relleno con texto (3.55:1). En claro la medalla del 1º se sirve como ARO oro + número
   --texto (acento gráfico, no texto de color); el oro de espíritus no se toca. */
[data-tema="claro"] .rtc-premios__medalla--oro {
  color: var(--texto);
  background: transparent;
  border: 2px solid var(--var-gold);
}
.rtc-premios__txt { color: var(--texto); font-weight: 500; }
.rtc-premios__sin { color: var(--texto-suave); font-style: normal; }

/* Podio de ganadores. */
.rtc-podio { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.rtc-podio__item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--azul-dim);
  border: 1px solid var(--azul-borde);
  border-radius: var(--radio-sm);
}
.rtc-podio__pos {
  flex: 0 0 auto;
  font-family: var(--font-head);
  font-weight: 700;
  color: var(--azul-claro);
  min-width: 34px;
}
/* Oro del podio atado al oro de PREMIOS vía --oro-texto (AA en ambos temas). */
.rtc-podio__pos--oro { color: var(--oro-texto); }
.rtc-podio__epic { font-weight: 600; color: var(--texto); }
.rtc-podio__premio { color: var(--texto-suave); margin-left: auto; text-align: right; }

/* m5 (uxui) — jerarquía del podio: el 1º lugar se realza (aro oro + tamaño + trofeo). */
.rtc-podio__item:first-child {
  border-color: var(--var-gold);
  background: rgba(var(--var-gold-rgb), 0.10);
}
.rtc-podio__item:first-child .rtc-podio__pos {
  font-size: 1.15rem;
  color: var(--oro-texto);
}
.rtc-podio__item:first-child .rtc-podio__pos::before {
  content: "\1F3C6"; /* 🏆 trofeo — acento del 1er lugar */
  margin-right: 4px;
  font-size: 1em;
}

/* Micro-celebración CSS-only al revelar los ganadores (sobria). */
.rtc-podio-wrap.is-celebra .rtc-podio__item {
  animation: rtc-podio-pop 480ms ease-out both;
}
.rtc-podio-wrap.is-celebra .rtc-podio__item:nth-child(2) { animation-delay: 90ms; }
.rtc-podio-wrap.is-celebra .rtc-podio__item:nth-child(3) { animation-delay: 180ms; }
@keyframes rtc-podio-pop {
  0% { opacity: 0; transform: translateY(8px) scale(0.98); }
  100% { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .rtc-podio-wrap.is-celebra .rtc-podio__item { animation: none; }
}

/* Requisitos del sorteo. */
.rtc-requisitos { list-style: none; margin: 0; padding: 0; display: grid; gap: 5px; }
.rtc-requisitos__item {
  position: relative;
  padding-left: 20px;
  color: var(--texto-suave);
  line-height: 1.45;
}
.rtc-requisitos__item::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 0.6em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  /* Marcador NEUTRO (0014 §0-quater.4): requisitos informativos/honor-system → viñeta
     apagada, no el azul de acción que sugeriría "verificado/cumplido". */
  background: var(--texto-suave);
}

/* Sorteo sin cupo (participación abierta). */
.rtc-sorteo__cupoabierto { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 12px 0 0; color: var(--texto-suave); }
.rtc-sorteo__transp { color: var(--texto-suave); font-size: 0.86rem; margin: 8px 0 0; }

/* Notas de comunidad obligatorias. */
.rtc-nota-com {
  margin: 10px 0 0;
  padding: 8px 12px;
  border-radius: var(--radio-sm);
  font-size: 0.86rem;
  line-height: 1.45;
  border: 1px solid var(--borde);
}
/* Nota bajo el CTA de participar SUAVIZADA (0014 §0-quater.4): menos alarmante —sin caja
   ni rojo—, más chica y en gris terciario, conservando el contenido obligatorio. */
.rtc-nota-com--participante {
  color: var(--gris);
  background: transparent;
  border-color: transparent;
  padding: 6px 2px 0;
  font-size: 0.8rem;
}
.rtc-nota-com--streamer { color: var(--texto); background: rgba(var(--error-rgb), 0.10); border-color: rgba(var(--error-rgb), 0.35); }

/* Panel de gestión (reusa .rtc-modlobby si existe; añade utilidades propias). */
.rtc-eventos__gestion { margin-top: 14px; }
.rtc-modlobby__botones { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0; }
.rtc-modlobby__h4 {
  font-family: var(--font-head);
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--texto-suave);
  margin: 12px 0 6px;
}
.rtc-modlobby__vacio { color: var(--texto-suave); }
.rtc-modlobby__lista { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.rtc-modlobby__fila {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 10px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
}
.rtc-modlobby__fila.is-retirado { opacity: 0.55; }
.rtc-modlobby__epic { font-weight: 600; color: var(--texto); }
.rtc-modlobby__wa { color: var(--azul-claro); font-variant-numeric: tabular-nums; }
/* m6 (uxui): WhatsApp click-to-chat (wa.me). Afordancia de enlace + tap-target. */
.rtc-modlobby__wa--link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 32px;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.rtc-modlobby__wa--link:hover { text-decoration: none; }
.rtc-modlobby__wa--link:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-modlobby__wa--vacio { color: var(--texto-suave); }
.rtc-modlobby__fila .rtc-btnmini { margin-left: auto; }

/* ADENDA v2 (§0-bis D2) — curaduría de dadores dentro de la gestión gateada. SOLO layout;
   color/tipografía por tokens existentes (cero hex literal). Reusa .rtc-modosel (pills de
   tipo), .rtc-espgrupos/.rtc-espopt (multi-selección de espíritu ofrecido) y .rtc-consent. */
.rtc-modlobby__dadores {
  margin: 12px 0;
  padding: 10px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
}
.rtc-modlobby__cupolleno { margin: 8px 0 0; }
.rtc-daform { margin-top: 10px; }
.rtc-daform__sum {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  list-style: none;
}
.rtc-daform__sum::-webkit-details-marker { display: none; }
.rtc-daform__sum:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-daform__body { display: grid; gap: 10px; margin-top: 10px; }
.rtc-daform__tipo { flex-wrap: wrap; }
.rtc-daform__camino { display: grid; gap: 10px; }
.rtc-daform__prev { min-height: 20px; }
.rtc-daform__prevok { color: var(--azul-claro); font-weight: 600; }
.rtc-daform__esp { margin-top: 4px; }

/* Botón secundario compacto (área táctil ≥44px). */
.rtc-btnmini {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  padding: 6px 14px;
  border-radius: var(--radio-sm);
  background: var(--superficie);
  border: 1px solid var(--azul-borde);
  color: var(--azul-claro);
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 0.9rem;
  cursor: pointer;
}
.rtc-btnmini:hover { background: var(--azul-dim); }
.rtc-btnmini[disabled] { opacity: 0.6; cursor: default; }
.rtc-btnmini:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-btnmini--quitar { color: var(--error); border-color: rgba(var(--error-rgb), 0.45); }
.rtc-btnmini--quitar:hover { background: rgba(var(--error-rgb), 0.12); }

/* Sortear: acción destacada del dueño. */
.rtc-sortear {
  color: var(--sobre-acento);
  background: var(--grad);
  border-color: transparent;
}
.rtc-sortear:hover { filter: brightness(1.06); background: var(--grad); }

/* Marcar ganadores por lugar. */
.rtc-modganadores { display: grid; gap: 8px; margin-top: 8px; }
.rtc-modganadores__fila {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.rtc-modganadores__lugar { font-family: var(--font-head); font-weight: 700; color: var(--texto); min-width: 34px; }
.rtc-modganadores__sel {
  flex: 1 1 160px;
  min-height: var(--tap);
  padding: 6px 10px;
  border-radius: var(--radio-sm);
  background: var(--superficie);
  border: 1px solid var(--borde);
  color: var(--texto);
}

/* Historial de sorteos (auditoría). */
.rtc-histsorteo { margin-top: 12px; }
.rtc-histsorteo__lista { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.rtc-histsorteo__item {
  color: var(--texto-suave);
  font-size: 0.85rem;
  padding: 6px 10px;
  background: var(--superficie-2);
  border-radius: var(--radio-sm);
}

/* =========================================================
   EXPANSIÓN v-next de sorteos/torneos (SPEC 0014 §0-ter + 0028)
   Banner del premio, countdown de la fecha límite (`inscripcion_hasta`),
   requisitos fijos (checklist), boleto 🎟×N (oportunidades públicas) y stepper
   +/− de oportunidades en la gestión. Solo tokens del tema; mobile-first, BEM.
   ========================================================= */

/* Banner del premio (misma clase en .rtc-sorteo y .rtc-torneo). Sangra a los bordes de
   la tarjeta con margen negativo = padding de la tarjeta (16px), sin tocar su padding. */
.rtc-sorteo__banner {
  margin: -16px -16px 8px;
  border-radius: var(--radio) var(--radio) 0 0;
  overflow: hidden;
  background: var(--superficie-2);
  line-height: 0;
  /* Hairline inferior por token (qa · OLED): un banner casi-negro nunca se funde
     con la superficie de la tarjeta — el borde lo separa en oled y en claro. */
  border-bottom: 1px solid var(--borde);
}
.rtc-sorteo__bannerimg {
  display: block;
  width: 100%;
  height: auto;
  max-height: 220px;
  object-fit: cover;
}

/* Countdown de la fecha límite de inscripción del SORTEO/TORNEO. ACOTADO a su
   propio modificador `.rtc-cd--evento` (regresión guardian-tema): antes redefinía
   `.rtc-cd` global y pisaba el chip de countdown de calendario/hero/perfil (:2916)
   y `.rtc-cd--hero` (:2997). Hereda la base `.rtc-cd` (familia, tabular-nums…) y
   solo ajusta márgen/padding/tamaño para el contexto de la tarjeta del evento. */
.rtc-cd--evento {
  gap: 6px;
  margin: 8px 0 0;
  padding: 4px 10px;
  font-size: 0.82rem;
  font-weight: 600;
}
.rtc-cd--evento.rtc-cd--cerrado {
  background: var(--superficie-2);
  border-color: var(--borde);
  color: var(--texto-suave);
}
.rtc-cd--evento svg { flex: 0 0 auto; }

/* Requisitos fijos. Coexisten con `.rtc-requisitos` (texto libre). Marcador NEUTRO (viñeta
   apagada por ::before), NO el ✓ azul (0014 §0-quater.4): son informativos/honor-system,
   un ✓ fingiría "verificado/cumplido". */
.rtc-reqfijos { list-style: none; margin: 0 0 6px; padding: 0; display: grid; gap: 6px; }
.rtc-reqfijos__item {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  color: var(--texto);
  line-height: 1.4;
}
.rtc-reqfijos__item::before {
  content: "";
  flex: 0 0 auto;
  margin-top: 0.55em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--texto-suave);
}

/* Boleto 🎟×N (oportunidades PÚBLICAS del sorteo, azul de marca). */
.rtc-boleto {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--azul-dim);
  border: 1px solid var(--azul-borde);
  color: var(--azul-claro);
  font-size: 0.78rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.rtc-boleto--uno {
  background: transparent;
  border-color: transparent;
  color: var(--texto-suave);
  padding: 1px 3px;
}
/* N>1 → "boletos apilados" (0028 §0-bis): sombra escalonada por tokens (superficie/borde),
   NO N chips literales. Da la sensación de varias entradas sin inflar el DOM. */
.rtc-boleto--pila {
  position: relative;
  margin-right: 7px;
  box-shadow:
    3px 3px 0 -1px var(--superficie), 3px 3px 0 var(--azul-borde),
    6px 6px 0 -1px var(--superficie), 6px 6px 0 var(--azul-borde);
}
.rtc-boleto svg { flex: 0 0 auto; }
.rtc-boleto__x { font-family: var(--font-head); }

/* Fecha ANUNCIADA etiquetada ("SORTEO:"/"TORNEO:"), para no confundirla con la fecha límite
   de inscripción ("Cierra en…" del countdown). Etiqueta en lenguaje de chip (azul-claro). */
.rtc-fechaet {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  color: var(--texto-suave);
  font-size: 0.86rem;
}
.rtc-fechaet__et {
  font-family: var(--font-head);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.72rem;
  color: var(--azul-claro);
}

/* Stepper +/− de oportunidades en la gestión (dueño/admin). */
.rtc-oport {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 6px;
  border-radius: 999px;
  background: var(--superficie);
  border: 1px solid var(--azul-borde);
}
.rtc-oport__lbl { font-size: 0.9rem; line-height: 1; }
.rtc-oport__val {
  min-width: 1.5em;
  text-align: center;
  font-family: var(--font-head);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--azul-claro);
}
.rtc-oport__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  min-height: var(--tap);
  border-radius: 50%;
  background: var(--azul-dim);
  border: 1px solid var(--azul-borde);
  color: var(--azul-claro);
  font-family: var(--font-head);
  font-size: 1.2rem;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
}
.rtc-oport__btn:hover { background: var(--azul); color: var(--sobre-acento); }
.rtc-oport__btn:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-oport__btn[disabled] { opacity: 0.5; cursor: default; }

/* Nota de "otorga oportunidades" en la gestión (sin fingir verificación). */
.rtc-modlobby__nota {
  margin: 0 0 8px;
  color: var(--texto-suave);
  font-size: 0.82rem;
  line-height: 1.4;
}

/* =========================================================
   TÓMBOLA DE REVELADO DEL GANADOR (SPEC 0029)
   Tira de boletos VIRTUALIZADA que desfila (rAF + transform, GPU) y frena sobre el
   GANADOR que devolvió el servidor. Mobile-first, BEM. Solo tokens de color existentes;
   las únicas variables NUEVAS son de DIMENSIÓN/TIEMPO (--tombola-*), no de color.
   ========================================================= */
.rtc-tombola {
  /* Dimensión/tiempo del componente (NO color; iguales en ambos temas). */
  --tombola-dur: 5000ms;      /* giro completo (≥~50 nombres cruzan la mira) */
  --tombola-dur-rm: 900ms;    /* reduced-motion: giro corto con señal visible */
  --tombola-boleto-w: 148px;  /* ancho de cada boleto (paso de la virtualización) */
  --tombola-alto: 76px;
  margin: 14px 0;
}
/* Placeholder vacío en sorteos abiertos: no ocupa espacio hasta que se llena. */
.rtc-tombola:empty { display: none; }

.rtc-tombola__viewport {
  position: relative;
  overflow: hidden;                 /* la tira desborda SOLO aquí → sin overflow-x de página */
  height: var(--tombola-alto);
  border-radius: var(--radio-sm);
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  contain: layout paint;
}
.rtc-tombola__tira {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  will-change: transform;           /* el desplazamiento vive en el compositor */
}
.rtc-tombola__boleto {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--tombola-boleto-w);
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 10px;
  border-right: 1px solid var(--borde);
}
.rtc-tombola__boletotxt {
  display: inline-block;
  max-width: 100%;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1rem;
  color: var(--texto);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Mira central: dónde aterriza el ganador. */
.rtc-tombola__mira {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 0;
  transform: translateX(-50%);
  border-left: 2px solid var(--azul);
  box-shadow: 0 0 12px var(--azul);
  pointer-events: none;
  z-index: 2;
}
/* Fase B (crucero): estela por desenfoque. Nunca en reduced-motion. */
.rtc-tombola__tira--streak .rtc-tombola__boleto { filter: blur(1.4px); }
/* Revelado: el resto se apaga y el ganador se realza (keyframe CSS puro). */
.rtc-tombola__tira--revelado .rtc-tombola__boleto { opacity: 0.32; }
.rtc-tombola__tira--revelado .rtc-tombola__boleto--ganador { opacity: 1; z-index: 3; }
.rtc-tombola__tira--revelado .rtc-tombola__boleto--ganador .rtc-tombola__boletotxt {
  color: var(--sobre-acento);
  /* Fill AA (blanco sobre azul): --azul-fuerte = 6.35:1 oled / 7.99:1 claro (tema.md §2),
     no el --azul de marca que sobre blanco caía bajo AA. Glow/scale se conservan. */
  background: var(--azul-fuerte);
  padding: 5px 14px;
  border-radius: 999px;
  box-shadow: var(--sombra-hover);
  animation: rtc-tombola-gana 720ms cubic-bezier(0.22, 1.2, 0.36, 1) both;
}
/* Micro-realce del momento ganador: pop algo más marcado + glow azul que asienta. */
@keyframes rtc-tombola-gana {
  0%   { transform: scale(0.9); box-shadow: 0 0 0 0 var(--azul-dim), var(--sombra-hover); }
  55%  { transform: scale(1.26); box-shadow: 0 0 0 6px var(--azul-dim), var(--sombra-hover); }
  100% { transform: scale(1.18); box-shadow: 0 0 0 3px var(--azul-dim), var(--sombra-hover); }
}

.rtc-tombola__anuncio {
  margin: 10px 0 0;
  min-height: 1.2em;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--texto);
}
.rtc-tombola__controles {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
}
/* Botón "Ver el sorteo / Repetir": reusa .rtc-sortear (grad + --sobre-acento). */
.rtc-tombola__play[disabled] { opacity: 0.6; cursor: default; }
.rtc-tombola__hist {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 8px;
  background: transparent;
  border: none;
  color: var(--azul-claro);
  font-family: var(--font-head);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.rtc-tombola__hist:hover { text-decoration: none; }
.rtc-tombola__hist:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-tombola__err { color: var(--error); margin: 8px 0 0; }

/* Reduced-motion: sin estela ni "pop" del ganador — pero el realce (pill + glow) queda
   ESTÁTICO (señal visible) y la tira igual desplaza (giro corto por --tombola-dur-rm). */
@media (prefers-reduced-motion: reduce) {
  .rtc-tombola__tira--streak .rtc-tombola__boleto { filter: none; }
  .rtc-tombola__tira--revelado .rtc-tombola__boleto--ganador .rtc-tombola__boletotxt { animation: none; }
}

/* =========================================================
   INTERCAMBIOS DE ESPÍRITUS (SPEC 0009)
   Tarjeta de lobby + componente `.rtc-equipo` (dos grupos dador↔receptor con
   emparejamiento), selector de rol (pills) y selector de espíritu (rejilla .rtc-esp).
   Solo tokens del tema (azul/blanco/negro por [data-tema]); mobile-first, BEM.
   ========================================================= */

/* Reusa el marco de tarjeta de torneo/sorteo. */
.rtc-intercambio {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra-card);
  padding: 16px 16px 18px;
  display: flex;
  flex-direction: column;
}
.rtc-intercambio__tit {
  font-family: var(--font-head);
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--texto);
  margin: 0;
  line-height: 1.2;
}
.rtc-intercambio__espfijo { display: inline-flex; }

/* Componente de equipo: dos grupos + flecha de reparto. */
.rtc-equipo {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
  margin: 14px 0 4px;
  align-items: start;
}
.rtc-equipo__flecha {
  display: none;
  align-self: center;
  color: var(--azul-claro);
  font-size: 1.4rem;
}
@media (min-width: 620px) {
  .rtc-equipo { grid-template-columns: 1fr auto 1fr; }
  .rtc-equipo__flecha { display: block; }
}
.rtc-equipo__col {
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  padding: 10px 12px 12px;
}
.rtc-equipo__col--dador { border-color: var(--azul-borde); }
.rtc-equipo__rol {
  font-family: var(--font-head);
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--texto-suave);
  margin: 0 0 8px;
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.rtc-equipo__cupo {
  font-variant-numeric: tabular-nums;
  color: var(--azul-claro);
  font-weight: 700;
}
.rtc-equipo__espera { color: var(--texto-suave); font-weight: 500; font-size: 0.78rem; }
.rtc-equipo__slots { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.rtc-equipo__slot {
  border-radius: var(--radio-sm);
  padding: 8px 10px;
  min-height: var(--tap);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
}
.rtc-equipo__slot--ocupado { background: var(--superficie); border: 1px solid var(--borde); }
.rtc-equipo__slot--vacio {
  /* m1 (uxui): sin cursiva y con más peso/contraste (legible en claro). */
  color: var(--texto);
  border: 1px dashed var(--azul-borde);
  font-size: 0.88rem;
  font-weight: 600;
  align-items: center;
  flex-direction: row;
}
.rtc-equipo__ident { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.rtc-equipo__epic { font-weight: 600; color: var(--texto); }
.rtc-equipo__epic--link { color: var(--azul-claro); text-decoration: none; }
.rtc-equipo__epic--link:hover { text-decoration: underline; }
.rtc-equipo__badge {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--azul-claro);
  background: var(--azul-dim);
  border: 1px solid var(--azul-borde);
  border-radius: 999px;
  padding: 1px 7px;
}
.rtc-equipo__sinsp { font-size: 0.8rem; color: var(--texto-suave); font-style: italic; }
.rtc-equipo__esp { display: inline-flex; }

/* Emparejamiento "quién le pasa a quién". */
.rtc-equipo__pares { list-style: none; margin: 6px 0 0; padding: 0; display: grid; gap: 4px; }
.rtc-equipo__par {
  font-size: 0.9rem;
  color: var(--texto-suave);
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

/* Cromo de espíritu en tamaño MINI (dentro de slots/pares). */
.rtc-esp--mini {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 6px;
  border-radius: var(--radio-sm);
  background: rgba(var(--marco-rgb), 0.10);
  border: 1px solid var(--marco);
}
.rtc-esp--mini .rtc-esp__fig { width: 26px; height: 26px; border: 0; padding: 0; }
.rtc-esp--mini .rtc-esp__img { width: 26px; height: 26px; }
.rtc-esp--mini .rtc-esp__nombre { font-size: 0.78rem; color: var(--texto); margin: 0; }

/* Selector de rol (pills). Reusa la idea de .rtc-modosel, autocontenido en el público. */
.rtc-equipo__rolsel,
.rtc-modosel {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 6px 0 10px;
}
.rtc-modosel__lbl { color: var(--texto-suave); font-size: 0.85rem; font-weight: 600; }
.rtc-modosel__op {
  min-height: var(--tap);
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid var(--borde);
  background: var(--superficie);
  color: var(--texto);
  font-weight: 600;
  cursor: pointer;
}
.rtc-modosel__op:hover { background: var(--azul-dim); }
.rtc-modosel__op:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-modosel__op.is-active {
  background: var(--azul-dim);
  border-color: var(--azul);
  color: var(--azul-claro);
}
.rtc-modosel__op[disabled] { opacity: 0.55; cursor: not-allowed; }
.rtc-modosel__lleno { font-size: 0.75rem; color: var(--texto-suave); }

/* Selector de espíritu — v2 (C1/M1/M2): COLAPSADO en <details> (no empuja el CTA) y
   AGRUPADO por base reusando `.rtc-espgrupos` (columnas de variante, sin truncar). */
.rtc-espsel-wrap { margin: 8px 0 10px; }
.rtc-espsel--fijo { display: inline-flex; }

/* Acordeón "Elige tu espíritu ▸" — dispara la rejilla; colapsado por defecto. */
.rtc-espsel-det { margin: 4px 0 10px; }
.rtc-espsel-det__sum {
  cursor: pointer;
  list-style: none;
  min-height: var(--tap);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: var(--radio-sm);
  background: var(--superficie-2);
  border: 1px solid var(--azul-borde);
  color: var(--azul-claro);
  font-weight: 600;
}
.rtc-espsel-det__sum::-webkit-details-marker { display: none; }
.rtc-espsel-det__sum::before {
  content: "\25B8"; /* ▸ */
  transition: transform 0.2s ease;
}
.rtc-espsel-det[open] .rtc-espsel-det__sum::before { transform: rotate(90deg); }
.rtc-espsel-det__sum:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-espsel-det__sel { color: var(--texto); font-weight: 500; }
.rtc-espsel-det__body {
  margin-top: 10px;
  max-height: 52vh;
  overflow-y: auto;
  padding-right: 4px;
}
.rtc-espsel__de {
  margin: 0 0 8px;
  font-weight: 700;
  color: var(--texto);
}
/* En el selector, la rejilla agrupada respira más en 1 columna dentro del form. */
.rtc-espsel-grid { gap: 16px; }
@media (min-width: 720px) {
  .rtc-espsel-grid { grid-template-columns: 1fr; }
}
.rtc-lobby__aviso-esp {
  margin: 4px 0 8px;
  padding: 8px 10px;
  border-radius: var(--radio-sm);
  background: var(--superficie-2);
  border: 1px dashed var(--azul-borde);
  color: var(--texto);
  font-size: 0.85rem;
}

/* Opción seleccionable del selector (cromo .rtc-esp clicable). */
.rtc-espopt {
  cursor: pointer;
  background: var(--superficie);
  border-radius: var(--radio-sm);
  padding: 6px;
  text-align: center;
}
/* Dentro de la rejilla agrupada, la opción ocupa toda la celda de su variante. */
.rtc-espgrupo__grid .rtc-espopt { width: 100%; }
.rtc-espopt:hover { background: var(--azul-dim); }
.rtc-espopt:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.rtc-espopt.is-sel {
  outline: 2px solid var(--azul);
  outline-offset: 1px;
  background: var(--azul-dim);
}
.rtc-equipo__paresp { display: inline-flex; }

/* ---------------------------------------------------------
   FAB de WhatsApp (SPEC 0018 §D) — botón flotante en vistas públicas. Verde de
   marca por tokens (--ok / --verde-tinta), sombra vía rgba(var(--ok-rgb),…). El
   tooltip .rtc-fab__label solo aparece en desktop-hover. Colisión con la barra
   .rtc-espbar del tracker: en <720px la barra es full-width → se oculta el FAB en
   .rtc-vista-espiritus; en ≥720px la barra es estática y el FAB se muestra normal.
   --------------------------------------------------------- */
.rtc-fab--wa {
  position: fixed;
  right: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom));
  z-index: 30;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 999px;
  background: var(--ok);
  color: var(--verde-tinta);
  border: 0;
  box-shadow: 0 4px 14px rgba(var(--ok-rgb), 0.35);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  animation: rtc-fab-in 0.3s ease-out 0.1s both;
}
.rtc-fab--wa svg { width: 26px; height: 26px; }
.rtc-fab--wa:hover { transform: translateY(-2px); box-shadow: 0 8px 22px rgba(var(--ok-rgb), 0.45); }
.rtc-fab--wa:active { transform: translateY(0) scale(0.96); }
.rtc-fab--wa:focus-visible { outline: 2px solid var(--azul); outline-offset: 3px; }
@keyframes rtc-fab-in {
  from { opacity: 0; transform: scale(0.6) translateY(8px); }
  to { opacity: 1; transform: scale(1) translateY(0); }
}
.rtc-fab__label {
  position: absolute;
  right: calc(100% + 10px);
  white-space: nowrap;
  background: var(--superficie-2);
  color: var(--texto);
  border: 1px solid var(--borde);
  border-radius: 999px;
  padding: 6px 12px;
  font: 600 0.85rem var(--font-body);
  box-shadow: var(--sombra-card);
  opacity: 0;
  transform: translateX(6px);
  pointer-events: none;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
@media (hover: hover) and (min-width: 720px) {
  .rtc-fab--wa:hover .rtc-fab__label,
  .rtc-fab--wa:focus-visible .rtc-fab__label { opacity: 1; transform: translateX(0); }
}
@media (max-width: 719px) {
  .rtc-fab__label { display: none; }
  .rtc-vista-espiritus .rtc-fab--wa { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .rtc-fab--wa { animation: none; }
  .rtc-fab--wa:hover { transform: none; }
  .rtc-fab__label { transition: none; transform: none; }
}
