@import url('https://fonts.googleapis.com/css2?family=ABeeZee&family=Righteous&display=swap');

:root {
  /* MF — Turquesa (primary) */
  --turquesa-100: #cdfffb;
  --turquesa-400: #18f8f6;
  --turquesa-600: #00bec8;
  --turquesa-700: #088b96;

  /* MF — Rosa (acciones críticas, eliminar, miss) */
  --rosa-500: #e11d48;
  --rosa-600: #e11d48;
  --rosa-700: #be123c;

  /* MF — Tulip Tree (dorado, info importante, scores destacados) */
  --tulip-tree-400: #facc15;
  --tulip-tree-500: #eab308;
  --tulip-tree-600: #ca8a04;

  /* MF — Verde (éxito, OK, badges done) */
  --color-success: #10b981;
  --color-success-light: #d1fae5;
  --color-success-dark: #047857;

  /* MF — Naranja (warning, badges working) */
  --color-warning: #f59e0b;
  --color-warning-light: #fef3c7;
  --color-warning-dark: #d97706;

  /* MF — Rojo error (badges error) */
  --color-error: #ef4444;
  --color-error-light: #fee2e2;
  --color-error-dark: #dc2626;

  /* MF — Grises (texto, fondos, bordes) */
  --gris-50: #f9fafb;
  --gris-100: #f3f4f6;
  --gris-200: #e5e7eb;
  --gris-300: #d1d5db;
  --gris-400: #9ca3af;
  --gris-500: #6b7280;
  --gris-600: #4b5563;
  --gris-700: #374151;
  --gris-800: #1f2937;
  --gris-900: #111827;

  /* Fuentes */
  --font-display: 'Righteous', Arial, sans-serif;
  --font-sans: 'ABeeZee', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-mono: 'Consolas', 'Courier New', monospace;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; overflow: hidden; }
body {
  font-family: var(--font-sans);
  background: #000;
  color: #fff;
  user-select: none;
}

/* SCROLLBARS — integran con la paleta turquesa→dorado del logo Sincro.
   API estándar (Firefox + Chromium moderno) sobre html para herencia global;
   los pseudo-elementos WebKit aplican universalmente vía `*` para que toda
   zona con overflow (.screen, .modal, listas, biblioteca, resultados…) herede
   el styling sin enumerar selectores uno por uno. El padding visual del thumb
   (2px alrededor) se consigue con border transparent + background-clip
   padding-box — único patrón fiable para "estrechar" el thumb sin cambiar su
   tamaño real ni usar márgenes negativos. */
html {
  scrollbar-width: thin;
  scrollbar-color: var(--turquesa-600) rgba(0,0,0,0.3);
}
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track {
  background: rgba(0,0,0,0.25);
  border-radius: 8px;
}
*::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, var(--turquesa-600), var(--turquesa-700));
  border-radius: 8px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(180deg, var(--turquesa-400), var(--turquesa-600));
  background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:active {
  background: linear-gradient(180deg, var(--turquesa-400), var(--tulip-tree-500));
  background-clip: padding-box;
}
*::-webkit-scrollbar-corner { background: transparent; }

/* TOP NAV */
#topbar {
  position: fixed; top: 0; left: 0; right: 0; height: 50px;
  background: rgba(0,0,0,0.85); border-bottom: 1px solid rgba(0,190,200,0.4);
  display: flex; align-items: center; padding: 0 20px;
  z-index: 100; backdrop-filter: blur(8px);
}
/* Durante la partida (body.playing) ocultamos el topbar para liberar
   pantalla — el menú de pausa (ESC) ya ofrece "Salir al menú", así que
   la nav no es necesaria. Mismo patrón que GH (`gh-play.html`).
   `.screen` tiene `top: 50px` global para dejar hueco al topbar fijo;
   cuando body.playing lo oculta, hay que mover el #play-screen a top:0
   para que el canvas APROVECHE esos 50px liberados — sin esta regla, el
   canvas seguiría empezando 50px más abajo y quedaría un vacío negro
   arriba. */
body.playing #topbar { display: none; }
body.playing { padding-top: 0 !important; }
body.playing #play-screen { top: 0 !important; }
#topbar .logo {
  font-family: var(--font-display);
  font-weight: 800; font-size: 1.1em;
  background: linear-gradient(90deg, var(--turquesa-600), var(--turquesa-400), var(--tulip-tree-500));
  -webkit-background-clip: text; background-clip: text;
  color: transparent; cursor: pointer;
}
#topbar .crumb { color: var(--gris-400); margin-left: 14px; font-size: 0.9em; }
#topbar .spacer { flex: 1; }
/* Pill de estado del pad/dispositivo: fondo claro para contraste alto.
   Indicador circular de estado a la izquierda mantiene el código de color
   (verde conectado / rojo desconectado) sin teñir el texto. Trunca con
   ellipsis cuando el nombre del gamepad es largo (ej. "PLAYSTATION(R)3..."). */
#topbar .pill {
  background: #fff; color: var(--gris-900);
  padding: 4px 12px; border-radius: 12px;
  font-size: 0.78em; font-weight: 600;
  margin-left: 10px;
  border: 1px solid var(--color-success);
  box-shadow: 0 0 8px rgba(16,185,129,0.35);
  max-width: 240px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
  display: inline-flex; align-items: center; gap: 6px;
}
#topbar .pill::before {
  content: '';
  display: inline-block;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--color-success);
  box-shadow: 0 0 6px var(--color-success);
  flex-shrink: 0;
}
#topbar .pill.off {
  border-color: var(--rosa-600);
  box-shadow: 0 0 8px rgba(225,29,72,0.35);
  color: var(--gris-700);
}
#topbar .pill.off::before {
  background: var(--rosa-500);
  box-shadow: 0 0 6px var(--rosa-500);
}

/* Navegación rápida en topbar (Bailar / Tocar / Equipo / Tutorial) */
#topbar .topbar-nav {
  display: flex; gap: 4px; margin-right: 10px;
}
#topbar .topbar-link {
  background: transparent; border: 1px solid rgba(255,255,255,0.08);
  color: var(--gris-300); padding: 6px 12px; border-radius: 7px;
  font-family: inherit; font-size: 0.85em; cursor: pointer;
  transition: all 0.15s; white-space: nowrap;
}
#topbar .topbar-link:hover {
  background: rgba(0,190,200,0.18); border-color: rgba(0,190,200,0.5);
  color: #fff;
}
@media (max-width: 900px) {
  #topbar .topbar-link {
    padding: 6px 8px; font-size: 0; /* solo emoji en móvil */
  }
  #topbar .topbar-link::first-letter { font-size: 16px; }
  #topbar .crumb { display: none; }
}

/* ==== Dashboard secciones (Bailar / Tocar) ====
   Wrapper con border de marca por sección + título como BANDA full-width
   dentro del wrapper (no pill). El title ocupa el ancho completo del
   contenedor (=ancho del grid de 3 cards), pintado con el gradient turquesa
   oscuro / dorado oscuro de marca. `overflow: hidden` en el wrapper es
   imprescindible para que el background del title llene las esquinas
   redondeadas del border — sin él aparecerían franjas del fondo decorativo
   en las esquinas. */
.dashboard-section {
  max-width: 940px;
  margin: 0 auto 28px;
  border-radius: 16px;
  overflow: hidden;
  text-align: center;
}
.dashboard-section .section-title {
  display: block;
  width: 100%;
  font-family: var(--font-display);
  font-size: 1.8em; letter-spacing: 0.02em;
  text-transform: uppercase;
  margin: 0;
  padding: 14px 24px;
  border: 0;
  border-radius: 0;
}
.dashboard-section .menu-grid {
  margin: 22px auto;
  max-width: 900px;
  padding: 0 16px;
}
.dashboard-section .section-subtitle {
  color: var(--gris-500); font-size: 0.7em;
  font-weight: 400; letter-spacing: 0;
  font-family: var(--font-sans);
}
.dashboard-section.sm-section {
  border: 2px solid rgba(0,190,200,0.4);
}
.dashboard-section.sm-section .section-title {
  color: var(--turquesa-400);
  background: linear-gradient(135deg, rgba(8,139,150,0.55), rgba(2,40,45,0.92));
}
.dashboard-section.gh-section {
  border: 2px solid rgba(250,204,21,0.5);
}
.dashboard-section.gh-section .section-title {
  color: var(--tulip-tree-400);
  background: linear-gradient(135deg, rgba(202,138,4,0.55), rgba(35,25,0,0.92));
}
.dashboard-section.common-section {
  border: 2px solid rgba(255,255,255,0.15);
}
.dashboard-section.common-section .section-title {
  color: var(--gris-300);
  background: rgba(0,0,0,0.7);
}

/* Dashboard pegado al topbar: .screen lleva padding:24px global (lo necesitan
   otras vistas con sticky bars top:8px como #songs-screen) que aquí no nos
   sirven — no hay sticky bar, solo cards. Reducimos padding-top a 16px para
   que la primera dashboard-section tenga aire mínimo bajo el header sin que
   se vea como franja muerta (el dashboard ya no tiene h1+subtitle que dieran
   respiro propio — el branding "Sincro" vive en el logo del topbar).

   Fondo decorativo: imagen WebP (2752×1536, 129KB tras conversión desde PNG
   de 4.6MB) cubriendo todo el .screen + overlay NEGRO al 70% que atenúa la
   imagen lo justo para que las cards (rgba(0,0,0,0.8)) y pills (gradient
   turquesa/dorado oscuro) destaquen como elementos accionables, mientras
   las flechas neón siguen visibles "perforando" el overlay por su alta
   luminancia. `background-attachment: fixed` ata la imagen al viewport para
   que no scrollee con el contenido. En multi-background, el primer item es
   la capa SUPERIOR (el overlay precede a la url() en background-image). */
#menu-screen {
  padding-top: 16px;
  overflow: hidden;
  background-image:
    linear-gradient(rgba(0,0,0,0.80), rgba(0,0,0,0.80)),
    url('../../fondo_dashboard.webp');
  background-size: auto, cover;
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
  background-attachment: fixed, fixed;
}

/* Card "próximamente" */
.menu-card.disabled {
  opacity: 0.55; cursor: not-allowed;
  background: rgba(0,0,0,0.4);
  border: 1px dashed rgba(255,255,255,0.18) !important;
}
.menu-card.disabled:hover {
  transform: none !important;
  box-shadow: none !important;
}
.menu-card .coming-soon {
  display: inline-block;
  font-size: 0.65em; font-weight: 400;
  margin-left: 6px; padding: 2px 8px;
  background: rgba(250,204,21,0.18); color: var(--tulip-tree-500);
  border-radius: 10px; vertical-align: middle;
  letter-spacing: 0.04em; text-transform: uppercase;
  font-family: var(--font-sans);
}

/* SCREENS */
.screen {
  position: fixed; top: 50px; left: 0; right: 0; bottom: 0;
  overflow: auto; padding: 24px;
  background: linear-gradient(135deg, var(--gris-900) 0%, #000 100%);
}
.screen.hidden { display: none; }
.container { max-width: 1100px; margin: 0 auto; }
/* songs-screen lleva el panel del Groove Radar como columna lateral —
   1200px es el mismo ancho que #gh-songs-screen (GH) para mantener
   coherencia visual entre ambos selectores. Antes 1500px (cuando no había
   panel lateral y la config-card horizontal exigía más espacio). */
#songs-screen .container { max-width: 1200px; }
#library-screen .container { max-width: 1200px; }

h1 {
  font-family: var(--font-display);
  text-align: center;
  background: linear-gradient(90deg, var(--turquesa-600), var(--turquesa-400), var(--tulip-tree-500));
  -webkit-background-clip: text; background-clip: text;
  color: transparent; font-size: 2.4em; margin-bottom: 6px;
}
.subtitle { color: var(--gris-400); text-align: center; margin-bottom: 24px; font-size: 0.9em; }

/* MENU */
.menu-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px; margin: 30px auto; max-width: 900px;
}
.menu-card {
  padding: 28px 22px; background: rgba(0,0,0,0.8);
  border: 2px solid rgba(0,190,200,0.3);
  border-radius: 16px; cursor: pointer; transition: all 0.2s;
  text-align: center;
}
.menu-card:hover {
  border-color: var(--turquesa-600);
  background: linear-gradient(135deg, rgba(0,190,200,0.15), rgba(234,179,8,0.12));
  transform: translateY(-4px);
  box-shadow: 0 10px 30px rgba(0,190,200,0.25);
}
.menu-card .icon { font-size: 3em; margin-bottom: 10px; }
.menu-card .title { font-family: var(--font-display); font-size: 1.2em; font-weight: 700; margin-bottom: 6px; }
.menu-card .desc  { color: var(--gris-400); font-size: 0.85em; line-height: 1.4; }

/* BUTTONS — selector sin prefijo de tag para que la misma clase funcione en
   <button>, <label>, <a> y cualquier elemento que actúe como botón. Antes
   estaba `button.action-btn` y los <label class="action-btn"> (usados para
   inputs file ocultos: Importar archivos / Importar paquete / Restaurar) no
   recibían padding, fondo ni borde — quedaban como texto plano roto. */
.action-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 10px 22px;
  background: linear-gradient(90deg, var(--turquesa-600), var(--turquesa-700));
  border: none; color: white; border-radius: 8px;
  cursor: pointer; font-weight: 600; font-size: 0.95em;
  text-decoration: none; line-height: 1.2; white-space: nowrap;
  transition: opacity 0.2s;
}
.action-btn:hover { opacity: 0.85; }
.action-btn:disabled, .action-btn[aria-disabled="true"] { opacity: 0.4; cursor: not-allowed; }
.action-btn.secondary {
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.15);
}
.action-btn.danger {
  background: linear-gradient(90deg, var(--rosa-600), var(--rosa-700));
}

.card {
  background: rgba(0,0,0,0.4); border-radius: 14px;
  padding: 20px 24px; border: 1px solid rgba(0,190,200,0.25);
  margin-bottom: 18px;
}

/* Banner de estado de calibración (alfombra/guitarra). Igual al de gh-play.html
   pero ahora reusable desde el motor SM. Variantes: warn (default amarillo),
   error (rojo) y ok (verde). El strong hereda el color del borde. */
.calib-banner {
  padding: 12px 16px; border-radius: 10px;
  background: rgba(250,204,21,0.10); border-left: 4px solid var(--tulip-tree-500);
  font-size: 0.9em; line-height: 1.5;
}
.calib-banner strong { color: var(--tulip-tree-500); }
.calib-banner.error { background: rgba(239,68,68,0.10); border-left-color: var(--color-error); }
.calib-banner.error strong { color: var(--color-error); }
.calib-banner.ok { background: rgba(16,185,129,0.10); border-left-color: var(--color-success); }
.calib-banner.ok strong { color: var(--color-success); }
.card h2 {
  font-family: var(--font-display);
  color: var(--turquesa-400); font-size: 1.05em; margin-bottom: 14px;
  border-bottom: 1px solid rgba(0,190,200,0.3); padding-bottom: 8px;
}

/* PAD TEST */
.pad-grid {
  display: grid; grid-template-columns: repeat(3, 130px);
  grid-template-rows: repeat(3, 130px); gap: 8px;
  padding: 20px; background: rgba(0,0,0,0.4); border-radius: 16px;
  margin: 20px auto; width: max-content;
  box-shadow: inset 0 0 30px rgba(0,190,200,0.2);
}
.pad-cell {
  border-radius: 14px; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  transition: all 0.05s ease-out; position: relative; overflow: hidden;
}
.pad-cell.arrow {
  background: linear-gradient(135deg, var(--gris-800), var(--gris-900));
  border: 3px solid var(--gris-700); color: var(--gris-400);
}
.pad-cell.empty { background: transparent; border: 2px dashed rgba(255,255,255,0.05); }
.pad-cell.center {
  background: rgba(0,0,0,0.3); border: 2px solid rgba(255,255,255,0.1);
  color: var(--gris-500); font-size: 0.7em; text-align: center; padding: 8px;
}
.pad-cell.arrow .arrow-icon { font-size: 3em; line-height: 1; }
.pad-cell.arrow .label { font-size: 0.72em; margin-top: 4px; opacity: 0.7; }
.pad-cell.arrow .count {
  position: absolute; top: 4px; right: 6px;
  font-size: 0.75em; background: rgba(0,0,0,0.5);
  padding: 2px 8px; border-radius: 10px; color: #fff;
}
.pad-cell.active {
  background: linear-gradient(135deg, var(--turquesa-600), var(--tulip-tree-500)) !important;
  border-color: #fff !important; color: #fff !important;
  transform: scale(0.94);
  box-shadow: 0 0 30px rgba(0,190,200,0.6);
}

/* QUEUE / SONG LIST */
.queue { background: rgba(0,0,0,0.3); border-radius: 10px; overflow: hidden; }
.queue-row {
  display: grid; grid-template-columns: 1fr 80px 90px 110px 100px;
  gap: 8px; align-items: center; padding: 10px 14px;
  border-bottom: 1px solid rgba(255,255,255,0.05); font-size: 0.88em;
}
.queue-row.header {
  background: rgba(0,190,200,0.15); color: var(--gris-300);
  font-weight: 600; font-size: 0.78em; text-transform: uppercase;
}
.queue-row.selected { background: rgba(0,190,200,0.15); }
.queue-row .name { color: #fff; word-break: break-word; }
.queue-row .badge {
  display: inline-block; padding: 3px 8px; border-radius: 6px;
  font-size: 0.78em; font-weight: 600;
}
.badge.pending { background: rgba(255,255,255,0.08); color: var(--gris-300); }
.badge.working { background: var(--color-warning-light); color: var(--color-warning-dark); }
.badge.done    { background: rgba(16,185,129,0.2); color: var(--color-success); }
.badge.error   { background: var(--color-error-light); color: var(--color-error-dark); }
.icon-btn {
  background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.1);
  color: #fff; padding: 4px 10px; border-radius: 6px; cursor: pointer;
  font-size: 0.8em; transition: all 0.15s;
}
.icon-btn:hover { background: rgba(0,190,200,0.3); }
.icon-btn.danger:hover { background: rgba(225,29,72,0.4); }

.drop-zone {
  border: 2px dashed rgba(0,190,200,0.5); border-radius: 12px;
  padding: 26px; text-align: center; cursor: pointer; transition: all 0.2s;
  background: rgba(0,190,200,0.05); display: block;
}
.drop-zone:hover, .drop-zone.dragover {
  border-color: var(--turquesa-400); background: rgba(0,190,200,0.12);
}
.drop-zone.loaded {
  border-style: solid; border-color: var(--color-success);
  background: rgba(16,185,129,0.08);
}
.drop-zone .big-icon, .drop-zone .icon { font-size: 2.6em; margin-bottom: 8px; }
.drop-zone .filename { color: var(--color-success); font-family: var(--font-mono); margin-top: 4px; font-size: 0.85em; word-break: break-all; }
.drop-zone p { margin: 4px 0; }
input[type="file"] { display: none; }

/* Files grid: 2 cols desktop, 1 col mobile. Usado en la card de "Importar" */
.files-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 12px;
}
@media (max-width: 700px) { .files-grid { grid-template-columns: 1fr; } }

/* Lib-row: fila flex (no tabla) para la biblioteca de canciones. Patrón
   compartido entre StepMania y Guitar Hero. Cada fila lleva un checkbox de
   selección múltiple + nombre/meta + botones de acción individuales. El
   accent (turquesa) lo override gh-play.html en naranja localmente. */
.lib-row {
  display: flex; justify-content: space-between; align-items: center;
  gap: 10px; padding: 12px 14px;
  background: rgba(0,0,0,0.3);
  border-radius: 8px;
  margin-bottom: 8px;
  border-left: 3px solid transparent;
  transition: background 0.15s, border-color 0.15s;
}
.lib-row.in-playlist {
  background: rgba(0,190,200,0.10);
  border-left-color: var(--turquesa-600);
}
.lib-row .lib-row-actions { display: flex; gap: 6px; flex-shrink: 0; }

/* PRESETS */
.preset-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px;
}
.preset {
  padding: 14px 16px; border-radius: 12px;
  background: rgba(255,255,255,0.03);
  border: 2px solid rgba(255,255,255,0.08);
  cursor: pointer; transition: all 0.15s;
}
.preset:hover { border-color: rgba(0,190,200,0.5); background: rgba(0,190,200,0.08); }
.preset.selected {
  border-color: var(--turquesa-600);
  background: linear-gradient(135deg, rgba(0,190,200,0.15), rgba(234,179,8,0.10));
}
.preset-name { font-weight: 700; font-size: 1em; margin-bottom: 4px; }
.preset-desc { color: var(--gris-400); font-size: 0.82em; line-height: 1.4; }

.form-row { display: flex; gap: 12px; align-items: center; margin-bottom: 10px; flex-wrap: wrap; }
.form-row label { color: var(--gris-300); min-width: 100px; font-size: 0.9em; }
.form-row input[type="text"], .form-row select {
  background: rgba(0,0,0,0.5); border: 1px solid rgba(0,190,200,0.4);
  color: #fff; padding: 6px 10px; border-radius: 6px; flex: 1; font-family: inherit;
}

.progress-bar {
  height: 10px; background: rgba(255,255,255,0.08);
  border-radius: 5px; overflow: hidden; margin: 10px 0;
}
.progress-bar .fill {
  height: 100%; background: linear-gradient(90deg, var(--turquesa-700), var(--turquesa-400), var(--tulip-tree-500));
  transition: width 0.15s; width: 0%;
}

.log {
  background: #000; border: 1px solid rgba(131,56,236,0.4);
  padding: 10px; border-radius: 6px; font-family: 'Consolas', monospace;
  font-size: 0.8em; max-height: 180px; overflow-y: auto; white-space: pre-wrap;
  margin-top: 10px;
}
.log .ok { color: #00ff64; }
.log .warn { color: #ffaa00; }
.log .bad { color: #ff3366; }
.log .info { color: #3a86ff; }

/* PLAY SCREEN — full-screen game */
#play-screen { padding: 0; overflow: hidden; }
#gameCanvas { display: block; }

/* HUD persistente como FOOTER delgado.
   Antes vivía en la esquina superior izquierda (top:60px; left:20px) y tapaba
   las flechas en pantallas verticales. Ahora es una barra de ~52px pegada al
   borde inferior con título de canción + score + combo en columnas, dejando
   todo el ancho del playfield libre arriba. */
.gameHUD {
  position: fixed; left: 0; right: 0; bottom: 0;
  height: 52px; padding: 0 18px;
  display: flex; align-items: center; gap: 18px;
  background: rgba(0,0,0,0.78);
  border-top: 1px solid rgba(0,190,200,0.35);
  backdrop-filter: blur(8px);
  color: #fff; font-family: 'Consolas', monospace; font-weight: 700;
  font-size: 0.9em; z-index: 20;
  text-shadow: 0 1px 2px rgba(0,0,0,0.9);
}
.gameHUD .hud-cell { display: flex; align-items: center; gap: 6px; }
.gameHUD .hud-cell .lbl {
  font-size: 0.7em; color: var(--gris-400);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.gameHUD .hud-song {
  flex: 1; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  color: var(--gris-300); font-weight: 500;
}
.gameHUD .score { font-size: 1.5em; color: #ffbe0b; line-height: 1; }
.gameHUD .combo { font-size: 1.2em; color: #00ff64; line-height: 1; }
/* Judgment text — vive como hijo de #play-screen (NO de .gameHUD) para no
   heredar el stacking context z-index:20 del HUD. La posición vertical (top)
   la calcula showJudgment() en JS proporcional a receptorY × uiScale, así
   queda CLARAMENTE encima del receptor sin importar la resolución. Antes era
   `top:24%` fijo del CSS, que en algunos viewports caía sobre los receptores.
   z-index 1000 garantiza que NUNCA quede tapado por canvas, HUD o capas de
   notas; el `top:0` inicial es solo placeholder antes del primer hit. */
.judgment {
  position: fixed; left: 50%; top: 0;
  transform: translate(-50%, -50%);
  font-family: var(--font-display); font-size: 2.6em; font-weight: 800;
  opacity: 0; pointer-events: none; z-index: 1000;
  background: rgba(0,0,0,0.55); padding: 6px 22px; border-radius: 10px;
  text-shadow: 0 0 16px currentColor, 0 1px 3px rgba(0,0,0,0.9);
  transition: opacity 0.18s, transform 0.18s;
  white-space: nowrap;
}
.judgment.show { opacity: 1; transform: translate(-50%, -50%) scale(1.15); }
/* Tier differentiation — size + glow + animation. El cerebro lee tres canales
   redundantes (color, tamaño, energía) y clasifica antes de leer la palabra.
     marvelous → enorme, glow triple + halo blanco, pop elástico
     perfect   → grande, glow doble dorado
     great     → grande con glow verde (acierto bueno — recompensa visible)
     good      → mediano con glow azul (acierto correcto pero sin fanfarria)
     bad       → discreto, sin tanto brillo (acierto raspado, casi miss)
     miss      → glow rojo + shake (oculto en runtime, ver showJudgment)
*/
.judgment.show.marvelous {
  font-size: 3.8em; color: #00f5d4;
  text-shadow: 0 0 36px currentColor, 0 0 14px currentColor, 0 0 4px #fff, 0 1px 3px rgba(0,0,0,0.9);
  animation: smJudgmentMarvelousPop 0.5s cubic-bezier(.2,1.6,.5,1);
}
.judgment.show.perfect {
  font-size: 3.2em; color: #ffbe0b;
  text-shadow: 0 0 28px currentColor, 0 0 10px currentColor, 0 1px 3px rgba(0,0,0,0.9);
  animation: smJudgmentPop 0.4s cubic-bezier(.2,1.6,.5,1);
}
.judgment.show.great {
  font-size: 2.9em; color: #00ff64;
  text-shadow: 0 0 22px currentColor, 0 0 8px currentColor, 0 1px 3px rgba(0,0,0,0.9);
  animation: smJudgmentPop 0.4s cubic-bezier(.2,1.6,.5,1);
}
.judgment.show.good {
  font-size: 2.5em; color: #3a86ff;
  text-shadow: 0 0 18px currentColor, 0 0 6px currentColor, 0 1px 3px rgba(0,0,0,0.9);
}
.judgment.show.bad {
  font-size: 2em; color: #ff006e;
  text-shadow: 0 0 14px currentColor, 0 1px 3px rgba(0,0,0,0.9);
}
.judgment.show.miss {
  font-size: 2.4em; color: #ff3366;
  text-shadow: 0 0 22px currentColor, 0 0 10px currentColor, 0 1px 3px rgba(0,0,0,0.9);
  animation: smJudgmentMissShake 0.30s ease-in-out;
}
@keyframes smJudgmentMarvelousPop {
  0%   { transform: translate(-50%, -50%) scale(0.4); }
  35%  { transform: translate(-50%, -50%) scale(1.6); }
  100% { transform: translate(-50%, -50%) scale(1.15); }
}
@keyframes smJudgmentPop {
  0%   { transform: translate(-50%, -50%) scale(0.6); }
  40%  { transform: translate(-50%, -50%) scale(1.3); }
  100% { transform: translate(-50%, -50%) scale(1.15); }
}
@keyframes smJudgmentMissShake {
  0%, 100% { transform: translate(-50%, -50%) scale(1.15); }
  25%      { transform: translate(-54%, -50%) scale(1.15); }
  75%      { transform: translate(-46%, -50%) scale(1.15); }
}

/* ===== Combo meter (estilo SM clásico) =====
   Número grande centrado en mid-playfield, etiqueta COMBO debajo. Se muestra
   a partir de combo ≥ 4 (los primeros hits no merecen UI dedicada). Pulse
   en cada hit, escalada de color/glow por hitos (50/100/200/500). La caja
   es semi-transparente para no tapar notas que pasen por detrás, y vive en
   z-index 999 (justo por debajo del judgment text en z:1000) para que el
   texto del juicio puntual prevalezca cuando ambos coinciden temporalmente.
   `pointer-events:none` deja pasar cualquier interacción al canvas debajo
   por si en futuro se añade input táctil en mid-playfield. */
.combo-meter {
  position: fixed; left: 50%; top: 52%;
  transform: translate(-50%, -50%) scale(0.9);
  display: none; flex-direction: column; align-items: center;
  pointer-events: none; z-index: 999;
  font-family: var(--font-display); font-weight: 800;
  text-shadow: 0 0 14px currentColor, 0 1px 3px rgba(0,0,0,0.9);
  opacity: 0; transition: opacity 0.18s, transform 0.18s;
}
.combo-meter.show { display: flex; opacity: 0.92; }
.combo-meter .combo-number {
  font-size: 4em; line-height: 1; letter-spacing: -0.02em;
}
.combo-meter .combo-label {
  font-size: 1em; letter-spacing: 0.22em;
  margin-top: 2px; opacity: 0.85;
}
/* Pulse en cada hit — `pulse` se añade desde JS y se quita 220ms después. */
.combo-meter.pulse {
  animation: smComboPulse 0.22s cubic-bezier(.3,1.4,.5,1);
}
@keyframes smComboPulse {
  0%   { transform: translate(-50%, -50%) scale(0.95); }
  50%  { transform: translate(-50%, -50%) scale(1.08); }
  100% { transform: translate(-50%, -50%) scale(1.0); }
}
/* Tiers de combo — cuanto más combo, más canales visuales encendidos. La
   primera capa (4-49) es discreta: blanco con halo turquesa suave. A partir
   de 50 entra dorado, 100 naranja con tamaño mayor, 200 rojo "fuego", 500
   gradiente de marca con halo enorme. Cada salto debe sentirse como hito. */
.combo-meter.tier-1 { color: #e0fbfc; }
.combo-meter.tier-1 .combo-label { color: rgba(0,245,212,0.75); }
.combo-meter.tier-2 {
  color: #ffbe0b;
  text-shadow: 0 0 22px currentColor, 0 0 8px currentColor, 0 1px 3px rgba(0,0,0,0.9);
}
.combo-meter.tier-3 {
  color: #f97316;
  text-shadow: 0 0 28px currentColor, 0 0 10px currentColor, 0 1px 3px rgba(0,0,0,0.9);
}
.combo-meter.tier-3 .combo-number { font-size: 4.6em; }
.combo-meter.tier-4 {
  color: #ff3366;
  text-shadow: 0 0 34px currentColor, 0 0 14px currentColor, 0 0 4px #fff, 0 1px 3px rgba(0,0,0,0.9);
}
.combo-meter.tier-4 .combo-number { font-size: 5em; }
.combo-meter.tier-5 {
  color: #00f5d4;
  text-shadow: 0 0 40px currentColor, 0 0 18px #ffbe0b, 0 0 6px #fff, 0 1px 3px rgba(0,0,0,0.9);
}
.combo-meter.tier-5 .combo-number { font-size: 5.4em; }

.results {
  background: linear-gradient(180deg, rgba(0,190,200,0.06), rgba(0,0,0,0.85) 60%);
  padding: 32px 40px; border-radius: 20px;
  border: 1px solid rgba(0,190,200,0.4); max-width: 720px;
  margin: 40px auto;
  box-shadow: 0 12px 40px rgba(0,190,200,0.15), inset 0 1px 0 rgba(255,255,255,0.05);
}
.results h2 {
  font-family: var(--font-display); font-size: 2em; margin-bottom: 18px; text-align: center;
  background: linear-gradient(90deg, var(--turquesa-400), var(--tulip-tree-500));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  letter-spacing: 0.02em;
}
.results .stat-line {
  display: flex; justify-content: space-between; align-items: center;
  padding: 8px 4px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  font-family: 'Consolas', monospace;
  font-size: 0.95em;
  transition: background 0.15s;
}
.results .stat-line:hover { background: rgba(255,255,255,0.03); }
.results .stat-line .key { color: var(--gris-400); }

/* ===== Resumen al estilo StepMania 5 =====
   - Cabecera con Grade gigante + Score + Accuracy + Max Combo en una fila.
   - Grid 2 columnas con cada judgment (Marvelous → Miss): nombre coloreado,
     count y barra horizontal (ancho proporcional al % del total). */
.results-header {
  display: grid; grid-template-columns: auto 1fr; gap: 22px;
  align-items: center; margin-bottom: 22px;
}
.results-grade {
  font-family: var(--font-display); font-size: 5em; line-height: 1;
  text-align: center; min-width: 110px;
  text-shadow: 0 0 30px currentColor, 0 0 14px rgba(0,0,0,0.85);
}
.results-grade.g-aaa, .results-grade.g-s { color: #00f5d4; }
.results-grade.g-aa, .results-grade.g-a  { color: #ffbe0b; }
.results-grade.g-b                       { color: #00ff64; }
.results-grade.g-c                       { color: #3a86ff; }
.results-grade.g-d, .results-grade.g-f   { color: #ff3366; }
.results-summary {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;
}
.results-summary .cell {
  background: rgba(0,0,0,0.4); border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px; padding: 10px 12px; text-align: center;
}
.results-summary .cell .lbl {
  color: var(--gris-400); font-size: 0.72em;
  text-transform: uppercase; letter-spacing: 0.06em;
}
.results-summary .cell .val {
  font-family: var(--font-display); font-size: 1.4em; color: #fff;
  margin-top: 2px;
}
.results-judgments {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px 18px;
}
@media (max-width: 540px) {
  .results-header { grid-template-columns: 1fr; }
  .results-judgments { grid-template-columns: 1fr; }
}
.judgment-row {
  display: grid; grid-template-columns: 90px 1fr 50px;
  align-items: center; gap: 10px; padding: 6px 4px;
  font-family: 'Consolas', monospace; font-size: 0.92em;
}
.judgment-row .jname { font-weight: 700; }
.judgment-row .jbar {
  height: 8px; background: rgba(255,255,255,0.06); border-radius: 4px;
  overflow: hidden;
}
.judgment-row .jbar > i {
  display: block; height: 100%;
  background: currentColor; opacity: 0.85;
  transition: width 0.4s ease-out;
}
.judgment-row .jcount { text-align: right; color: #fff; font-weight: 700; }
.j-marvelous { color: #00f5d4; }
.j-perfect   { color: #ffbe0b; }
.j-great     { color: #00ff64; }
.j-good      { color: #3a86ff; }
.j-bad       { color: #ff006e; }
.j-miss      { color: #ff3366; }

.help { color: var(--gris-500); font-size: 0.85em; line-height: 1.5; margin-top: 6px; }

/* tabs in pad test */
.tabs { display:flex; gap:4px; flex-wrap:wrap; margin-bottom:16px; }
.tab-btn {
  background: rgba(0,0,0,0.3); border: 1px solid rgba(0,190,200,0.3);
  color: var(--gris-300); padding: 8px 16px; border-radius: 8px;
  cursor: pointer; font-size: 0.88em;
}
.tab-btn.active {
  background: linear-gradient(135deg, var(--turquesa-600), var(--turquesa-700));
  color: #fff; border-color: transparent;
}
.tab-content { display: none; }
.tab-content.active { display: block; }

.button-grid {
  display: grid; grid-template-columns: repeat(8, 1fr); gap: 4px;
}
.btn-led {
  background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1);
  border-radius: 6px; padding: 6px 2px; text-align: center;
  font-family: 'Consolas', monospace; font-size: 0.7em; color: var(--gris-500);
}
.btn-led.on { background: var(--color-success); color: var(--gris-900); box-shadow: 0 0 12px var(--color-success); }

details summary { cursor: pointer; color: var(--gris-300); padding: 6px 0; }
details summary:hover { color: #fff; }

.param {
  background: rgba(0,0,0,0.3); border: 1px solid rgba(255,255,255,0.06);
  border-radius: 10px; padding: 12px 14px; margin-bottom: 10px;
}
.param-header {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 6px;
}
.param-label { font-weight: 600; }
.param-value {
  background: rgba(0,190,200,0.18); color: var(--tulip-tree-400);
  font-family: monospace; padding: 3px 10px; border-radius: 6px; font-size: 0.85em;
}
.param input[type="range"] { width: 100%; }
.param-help { color: var(--gris-400); font-size: 0.8em; margin-top: 6px; line-height: 1.4; }

/* SEARCH + SORT in song select */
.toolbar { display:flex; gap:8px; flex-wrap:wrap; margin-bottom:14px; align-items:center; }
.toolbar input[type="text"], .toolbar select {
  background: rgba(0,0,0,0.4); border: 1px solid rgba(0,190,200,0.3);
  color: #fff; padding: 8px 12px; border-radius: 8px; font-size: 0.9em;
}
.toolbar input[type="text"] { flex: 1; min-width: 180px; }
.toolbar input[type="text"]::placeholder { color: var(--gris-500); }

.grade-pill {
  display: inline-block; padding: 2px 10px; border-radius: 10px;
  font-weight: 800; font-size: 0.75em; letter-spacing: 0.05em;
  font-family: 'Consolas', monospace;
}
.grade-AAA { background: linear-gradient(90deg,#00f5d4,#ffbe0b); color:#000; }
.grade-AA  { background: rgba(0,245,212,0.2); color: #00f5d4; }
.grade-A   { background: rgba(0,255,100,0.2); color: #66ff99; }
.grade-B   { background: rgba(58,134,255,0.2); color: #88b4ff; }
.grade-C   { background: rgba(255,190,11,0.2); color: #ffbe0b; }
.grade-D   { background: rgba(255,51,102,0.2); color: #ff6688; }

/* MODIFIERS PANEL on diff screen */
.mods-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px,1fr)); gap: 10px; }
/* Grid 3×3 fijo para el container de variantes en songs-screen.
   Las 9 variantes (mirror, left, right, shuffle, hidden, sudden, solo,
   full, randomFixed) caben exactas en 3 filas de 3 — visualmente más
   ordenado que el auto-fit que las repartía en 4-5 columnas según ancho. */
#globalModsContainer { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 700px) {
  /* En móvil-tablet pequeño, 2 columnas para no apretar */
  #globalModsContainer { grid-template-columns: repeat(2, 1fr); }
}
.mod-toggle {
  background: rgba(0,0,0,0.3); border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px; padding: 10px 12px; cursor: pointer; user-select:none;
  transition: all 0.15s;
}
.mod-toggle.on {
  border-color: var(--turquesa-600);
  background: linear-gradient(135deg, rgba(0,190,200,0.18), rgba(234,179,8,0.12));
  box-shadow: 0 0 14px rgba(0,190,200,0.25);
}
.mod-toggle .mod-name { font-weight: 700; }
.mod-toggle .mod-help { color: var(--gris-400); font-size: 0.78em; margin-top: 3px; }

/* Comparador de densidad por dificultad: 5 barras de altura creciente,
   la activa se enciende en turquesa. Las alturas reflejan el cap NPS de
   difficulty-tiers.js (1.0/2.0/3.5/5.5/9.0) escalado al rango visual. */
.diff-density-bars {
  display: inline-flex;
  align-items: flex-end;
  gap: 4px;
  height: 28px;
  padding: 2px 6px;
  background: rgba(0,0,0,0.35);
  border: 1px solid rgba(0,190,200,0.18);
  border-radius: 6px;
}
.diff-density-bars .db-bar {
  width: 7px;
  background: rgba(255,255,255,0.18);
  border-radius: 2px 2px 0 0;
  transition: background 0.2s, box-shadow 0.2s;
}
.diff-density-bars .db-bar[data-tier="Beginner"]  { height: 18%; }
.diff-density-bars .db-bar[data-tier="Easy"]      { height: 34%; }
.diff-density-bars .db-bar[data-tier="Medium"]    { height: 52%; }
.diff-density-bars .db-bar[data-tier="Hard"]      { height: 74%; }
.diff-density-bars .db-bar[data-tier="Challenge"] { height: 100%; }
.diff-density-bars .db-bar.on {
  background: linear-gradient(180deg, var(--turquesa-400), var(--turquesa-600));
  box-shadow: 0 0 8px rgba(24,248,246,0.55);
}

/* COUNTDOWN: NO hay overlay HTML — se pinta dentro del canvas del highway
   con ctx2d.fillText en render() cuando audioTime<0. Decisión consciente:
   overlay HTML grande con beep + scale-pop dejaba "1 residual" al final
   y duplicaba lo que ya tenía el canvas. Mismo patrón que `gh-play.html`. */

/* PAUSE OVERLAY — menú de pausa del motor DDR. z-index 1500 queda POR ENCIMA
   de combo-meter (z:999) y judgment (z:1000) para que ningún elemento del
   playfield se cuele a través del overlay al pausar. Antes era z:150 y la
   usuaria veía el "5 COMBO" pintado sobre el botón Reanudar del menú —
   visualmente confuso. Backdrop opaco + blur para señalar inequívocamente
   "estado pausado". El settings modal (z:200) ya no es alcanzable desde
   la pausa así que no hay conflicto en ese sentido. */
.pause-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.78);
  backdrop-filter: blur(8px);
  z-index: 1500;
  display: none; align-items: center; justify-content: center;
  animation: pauseFadeIn 0.18s ease-out;
}
.pause-overlay.show { display: flex; }
.pause-panel {
  background: linear-gradient(135deg, var(--gris-900) 0%, #000 100%);
  border: 1px solid rgba(0,190,200,0.5);
  border-radius: 16px;
  padding: 28px 36px;
  max-width: 460px; width: calc(100% - 40px);
  text-align: center;
  box-shadow: 0 0 60px rgba(0,190,200,0.25), 0 0 20px rgba(0,0,0,0.8);
}
.pause-panel h2 {
  font-family: var(--font-display);
  color: var(--turquesa-400);
  font-size: 1.6em;
  margin: 0 0 6px;
  letter-spacing: 0.02em;
}
.pause-panel .pause-hint {
  color: var(--gris-400);
  font-size: 0.92em;
  margin: 0 0 22px;
}
.pause-actions {
  display: flex; flex-direction: column; gap: 10px;
}
.pause-actions .action-btn {
  width: 100%; padding: 12px 18px;
  font-size: 1em;
  justify-content: center;
  display: inline-flex; align-items: center; gap: 8px;
}
.pause-actions .pause-resume {
  /* Botón destacado: gradiente turquesa→dorado de la marca para clavar la
     decisión por defecto (volver a jugar es lo que la mayoría hará). */
  box-shadow: 0 0 18px rgba(0,190,200,0.4);
}
.pause-actions .pause-quit {
  /* Tono más apagado: salir es la opción menos común. */
  opacity: 0.85;
}
.pause-actions .kbd {
  display: inline-block;
  padding: 2px 8px;
  background: rgba(0,0,0,0.45);
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 4px;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.75em;
  letter-spacing: 0.05em;
  color: var(--gris-300);
}
@keyframes pauseFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@media (max-width: 480px) {
  .pause-panel { padding: 20px 22px; }
  .pause-panel h2 { font-size: 1.35em; }
}

/* SETTINGS MODAL */
.modal-overlay {
  position: fixed; inset: 0; background: rgba(0,0,0,0.75);
  z-index: 200; display: none; align-items: center; justify-content: center;
  backdrop-filter: blur(4px);
}
.modal-overlay.show { display: flex; }
.modal {
  background: linear-gradient(135deg, var(--gris-900) 0%, #000 100%);
  border: 1px solid rgba(0,190,200,0.5);
  border-radius: 16px; padding: 24px 28px; max-width: 480px; width: calc(100% - 40px);
  max-height: 80vh; overflow: auto;
}
.modal h2 {
  font-family: var(--font-display);
  color: var(--turquesa-400); font-size: 1.1em; margin-bottom: 14px;
  border-bottom: 1px solid rgba(0,190,200,0.3); padding-bottom: 8px;
}
.modal .close-row { display:flex; justify-content:flex-end; margin-top: 14px; }

/* ============================================================================
   DIFF SCREEN — Selección de dificultad + CTA "Jugar" (patrón arcade)
   ============================================================================
   La selección de chart y el arranque del juego son dos pasos separados:
   1) Pulsar una fila de dificultad la marca como seleccionada (no lanza nada).
   2) Aparece el CTA gigante "▶ Jugar" abajo, que arranca la partida.
   El patrón sigue Clone Hero / DDR cabinet: "elegir → confirmar".
============================================================================ */

#diffsContainer {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.chart-row {
  display: grid;
  grid-template-columns: 1fr 80px 100px 70px 36px;
  gap: 12px;
  align-items: center;
  padding: 14px 16px;
  background: rgba(0,0,0,0.35);
  border: 2px solid rgba(255,255,255,0.06);
  border-radius: 12px;
  font-size: 0.92em;
  transition: all 0.15s;
  position: relative;
}
.chart-row:hover {
  border-color: rgba(0,190,200,0.45);
  background: rgba(0,190,200,0.08);
  transform: translateX(2px);
}
.chart-row.selected {
  border-color: var(--turquesa-400);
  background: linear-gradient(90deg, rgba(0,190,200,0.22), rgba(234,179,8,0.10));
  box-shadow: 0 0 20px rgba(0,190,200,0.35), inset 0 0 0 1px rgba(0,245,212,0.4);
  transform: translateX(4px);
}
.chart-row.selected::before {
  content: '▸';
  position: absolute;
  left: -18px; top: 50%;
  transform: translateY(-50%);
  color: var(--turquesa-400);
  font-size: 1.4em;
  text-shadow: 0 0 10px var(--turquesa-400);
  animation: chart-row-pointer 0.6s ease-out;
}
@keyframes chart-row-pointer {
  0%   { opacity: 0; transform: translate(-12px, -50%); }
  100% { opacity: 1; transform: translate(0, -50%); }
}
.chart-row-name { color: #fff; font-size: 1.05em; word-break: break-word; }
.chart-row-rating {
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--tulip-tree-500);
  letter-spacing: 0.04em;
}
.chart-row-rating .chart-row-stars { color: var(--tulip-tree-500); }
.chart-row-meta { color: var(--gris-400); font-size: 0.88em; font-family: var(--font-mono); }
.chart-row-grade { text-align: center; }
.chart-row-empty { color: var(--gris-700); }
.chart-row-action { text-align: right; }

@media (max-width: 600px) {
  .chart-row {
    grid-template-columns: 1fr 60px 70px 60px 30px;
    gap: 8px;
    padding: 12px 12px;
    font-size: 0.85em;
  }
  .chart-row.selected::before { display: none; }
}

/* ----- Big "Jugar" CTA bar (arcade-style "Press Start") -------------------
   Posición: sticky-top en diff-screen para que el botón siga al usuario por
   el scroll. Cuando elige dificultad abajo, el CTA arriba se enciende —
   pero no necesita volver a hacer scroll up para pulsarlo. */
.play-cta-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin: 6px 0 18px;
  padding: 14px 18px;
  background: linear-gradient(180deg, rgba(15,15,20,0.92), rgba(15,15,20,0.85));
  border: 1px solid rgba(0,190,200,0.28);
  border-radius: 16px;
  position: sticky;
  /* .screen es position:fixed; overflow:auto y empieza a top:50px del viewport
     (justo debajo de #topbar). Por tanto el scroll container de este sticky
     es .screen, no el viewport — el offset se mide desde el borde superior
     de .screen, no desde la topbar. */
  top: 8px;
  z-index: 20;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 6px 24px rgba(0,0,0,0.4);
}
.play-cta-center {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  flex: 1;
}
.play-cta-hint {
  color: var(--gris-400);
  font-size: 0.85em;
  letter-spacing: 0.02em;
  font-family: var(--font-mono);
}
.play-cta-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 16px;
  padding: 18px 56px;
  font-family: var(--font-display);
  font-size: 1.6em;
  letter-spacing: 0.06em;
  color: #fff;
  background: linear-gradient(135deg, var(--gris-700), var(--gris-800));
  border: 2px solid rgba(255,255,255,0.08);
  border-radius: 14px;
  cursor: pointer;
  text-transform: uppercase;
  transition: all 0.2s ease;
  min-width: 280px;
  justify-content: center;
}
.play-cta-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  filter: grayscale(0.5);
}
.play-cta-btn .play-cta-icon {
  font-size: 0.9em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  border-radius: 50%;
  background: rgba(255,255,255,0.1);
  transition: transform 0.2s ease;
}
.play-cta-btn.ready {
  background: linear-gradient(135deg, var(--turquesa-600) 0%, var(--turquesa-700) 50%, var(--tulip-tree-500) 130%);
  border-color: var(--turquesa-400);
  color: #001416;
  text-shadow: 0 1px 0 rgba(255,255,255,0.18);
  box-shadow:
    0 0 0 4px rgba(0,190,200,0.18),
    0 8px 24px rgba(0,190,200,0.35),
    inset 0 1px 0 rgba(255,255,255,0.3);
  animation: play-cta-pulse 1.6s ease-in-out infinite;
}
.play-cta-btn.ready .play-cta-icon {
  background: rgba(0,0,0,0.25);
  color: #fff;
}
.play-cta-btn.ready:hover {
  transform: translateY(-2px) scale(1.02);
  animation-play-state: paused;
  box-shadow:
    0 0 0 4px rgba(0,190,200,0.3),
    0 12px 32px rgba(0,190,200,0.5),
    inset 0 1px 0 rgba(255,255,255,0.4);
}
.play-cta-btn.ready:hover .play-cta-icon { transform: scale(1.15); }
.play-cta-btn.ready:active { transform: translateY(0) scale(0.99); }
@keyframes play-cta-pulse {
  0%, 100% {
    box-shadow:
      0 0 0 4px rgba(0,190,200,0.18),
      0 8px 24px rgba(0,190,200,0.35),
      inset 0 1px 0 rgba(255,255,255,0.3);
  }
  50% {
    box-shadow:
      0 0 0 8px rgba(0,190,200,0.10),
      0 12px 36px rgba(0,190,200,0.55),
      inset 0 1px 0 rgba(255,255,255,0.45);
  }
}
@media (max-width: 600px) {
  .play-cta-bar {
    flex-wrap: wrap;
    padding: 12px;
  }
  .play-cta-btn {
    min-width: 0;
    width: 100%;
    padding: 16px 24px;
    font-size: 1.3em;
  }
}
@media (prefers-reduced-motion: reduce) {
  .play-cta-btn.ready { animation: none; }
  .chart-row.selected::before { animation: none; }
}

/* ============================================================================
   CARD HEADERS — Refinamiento de jerarquía visual
   ============================================================================ */
.card h2 {
  display: flex;
  align-items: center;
  gap: 10px;
  letter-spacing: 0.02em;
}

/* Empty-state genérico (lista vacía, biblioteca vacía...) */
.empty-state {
  text-align: center;
  padding: 36px 20px;
  color: var(--gris-400);
}
.empty-state .empty-icon {
  font-size: 3em;
  margin-bottom: 10px;
  opacity: 0.5;
}
.empty-state .empty-title {
  font-family: var(--font-display);
  color: var(--gris-300);
  font-size: 1.1em;
  margin-bottom: 6px;
}
.empty-state .empty-desc {
  font-size: 0.9em;
  margin-bottom: 14px;
  line-height: 1.5;
}

/* Queue-row: highlight más claro al hover (usado en song list) */
.queue-row[onclick]:hover,
.queue-row[style*="cursor:pointer"]:hover {
  background: rgba(0,190,200,0.08);
}

/* ============================================================================
   PLAYLIST MODE — selección múltiple en la biblioteca + sesión continua.
   El usuario marca varias canciones, elige una dificultad común, y se tocan
   en cadena con countdown automático entre cada una.
   ============================================================================ */
.playlist-checkbox {
  width: 22px; height: 22px;
  cursor: pointer;
  accent-color: var(--turquesa-600);
  flex-shrink: 0;
}
.queue-row.in-playlist {
  background: rgba(0,190,200,0.10);
  border-left: 3px solid var(--turquesa-600);
}

/* Barra sticky-top dentro de songs-screen — siempre visible (en idle muestra
   un hint, con selección activa muestra contador y CTAs habilitados). El
   scroll context es .screen (position:fixed; overflow:auto), así que el
   offset top:8px se mide desde el borde superior de .screen, ya bajo la
   #topbar fija. */
.playlist-bar {
  position: sticky;
  top: 8px;
  margin: 6px 0 18px;
  padding: 14px 22px;
  display: flex;
  align-items: center;
  gap: 14px;
  background: linear-gradient(180deg, rgba(15,15,20,0.92), rgba(15,15,20,0.85));
  border: 2px solid rgba(0,190,200,0.35);
  border-radius: 14px;
  box-shadow: 0 6px 24px rgba(0,0,0,0.4);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  z-index: 30;
  transition: border-color 0.2s, box-shadow 0.2s;
}
/* Estado activo: brilla cuando hay selección. */
.playlist-bar.has-selection {
  border-color: var(--turquesa-600);
  box-shadow: 0 8px 28px rgba(0,190,200,0.35), 0 0 0 4px rgba(0,190,200,0.12);
}
.playlist-bar.hidden { display: none; }
.playlist-bar .count {
  font-family: var(--font-display);
  color: #fff;
  font-size: 1.1em;
  flex: 1;
}
.playlist-bar .count small {
  color: var(--gris-400);
  font-family: var(--font-sans);
  font-size: 0.78em;
  display: block;
  letter-spacing: 0.02em;
  margin-top: 2px;
}
.playlist-bar button {
  white-space: nowrap;
}

/* Modal genérico para setup de playlist */
.modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.75);
  backdrop-filter: blur(4px);
  z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.modal-backdrop.hidden { display: none; }
.modal-content {
  background: linear-gradient(180deg, var(--gris-900), #000);
  border: 1px solid rgba(0,190,200,0.4);
  border-radius: 16px;
  padding: 28px;
  max-width: 460px; width: 100%;
  box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
.modal-content h3 {
  font-family: var(--font-display);
  color: var(--turquesa-400);
  font-size: 1.3em;
  margin-bottom: 12px;
}
.modal-content .modal-help {
  color: var(--gris-400);
  font-size: 0.88em;
  margin: 8px 0 18px;
  line-height: 1.5;
}
.modal-content label {
  display: block;
  color: var(--gris-300);
  font-size: 0.88em;
  margin-bottom: 6px;
  letter-spacing: 0.02em;
}
.modal-content select,
.modal-content input[type="text"] {
  width: 100%;
  background: rgba(0,0,0,0.5);
  border: 1px solid rgba(0,190,200,0.3);
  color: #fff;
  padding: 10px 12px;
  border-radius: 8px;
  font-family: var(--font-sans);
  font-size: 1em;
  margin-bottom: 14px;
}
.modal-actions {
  display: flex; gap: 10px; justify-content: flex-end;
  margin-top: 18px;
}

/* Banner de "Siguiente canción" en results-screen cuando hay sesión activa.
   Ocupa la parte superior del bloque results con countdown destacado. */
.session-next-banner {
  margin: 0 0 18px;
  padding: 16px 20px;
  background: linear-gradient(135deg, rgba(0,190,200,0.18), rgba(234,179,8,0.10));
  border: 2px solid var(--turquesa-600);
  border-radius: 12px;
  text-align: center;
}
.session-next-banner .label {
  color: var(--gris-300);
  font-size: 0.78em;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 4px;
}
.session-next-banner .next-title {
  font-family: var(--font-display);
  color: #fff;
  font-size: 1.25em;
  margin-bottom: 8px;
}
.session-next-banner .countdown {
  font-family: var(--font-display);
  font-size: 2.4em;
  color: var(--tulip-tree-500);
  text-shadow: 0 0 14px rgba(234,179,8,0.6);
  line-height: 1;
}
.session-next-banner .progress-text {
  color: var(--gris-400);
  font-size: 0.85em;
  margin-top: 6px;
}
.session-summary {
  margin: 14px 0;
  padding: 14px 18px;
  background: rgba(0,190,200,0.06);
  border-left: 3px solid var(--turquesa-600);
  border-radius: 8px;
}
.session-summary .row {
  display: flex; justify-content: space-between;
  padding: 6px 0;
  border-bottom: 1px dashed rgba(255,255,255,0.08);
  font-size: 0.92em;
}
.session-summary .row:last-child { border-bottom: none; }

/* Chip + edit inline del jugador en el banner de "siguiente canción".
   Cuando hay sesión activa con autoguardado, mostramos qué nombre se está
   usando y permitimos cambiarlo entre canciones (caso multijugador en casa:
   madre y peque alternan partidas). Durante la edición el countdown se
   pausa para no perder el input — la lógica de pause/resume vive en JS. */
.session-player-chip {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 10px;
  padding: 6px 12px;
  background: rgba(0,0,0,0.35);
  border: 1px solid rgba(0,190,200,0.32);
  border-radius: 999px;
  font-size: 0.9em;
  color: var(--gris-200);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.session-player-chip:hover {
  border-color: var(--turquesa-400);
  background: rgba(0,190,200,0.10);
}
.session-player-chip .chip-label {
  color: var(--gris-400);
  font-size: 0.85em;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.session-player-chip .chip-name {
  color: var(--tulip-tree-500);
  font-weight: 700;
}
.session-player-chip .chip-edit {
  color: var(--gris-400);
  font-size: 0.85em;
}
.session-player-edit {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: 10px;
  padding: 4px 6px 4px 10px;
  background: rgba(0,0,0,0.50);
  border: 1px solid var(--turquesa-400);
  border-radius: 999px;
}
.session-player-edit input[type="text"] {
  background: transparent;
  border: none;
  color: #fff;
  font-size: 0.95em;
  font-family: inherit;
  padding: 4px 2px;
  min-width: 140px;
  outline: none;
}
.session-player-edit .edit-ok {
  background: var(--turquesa-400);
  color: #001f22;
  border: none;
  border-radius: 999px;
  padding: 5px 14px;
  font-weight: 700;
  cursor: pointer;
  font-size: 0.88em;
}
.session-player-edit .edit-ok:hover { background: var(--turquesa-300, #4dd0d7); }
.session-player-edit .edit-cancel {
  background: transparent;
  color: var(--gris-400);
  border: none;
  cursor: pointer;
  padding: 4px 8px;
  font-size: 1.1em;
  line-height: 1;
}

/* Aviso de autoguardado tras canción en sesión (sustituye al form de nombre). */
.score-saved-notice {
  margin: 18px 0 0;
  padding: 12px 16px;
  background: rgba(0,190,200,0.08);
  border-left: 3px solid var(--turquesa-400);
  border-radius: 8px;
  color: var(--gris-200);
  font-size: 0.95em;
  text-align: center;
}

/* Tag con nombre del jugador junto a cada fila del resumen final. */
.session-summary .player-tag {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 8px;
  background: rgba(234,179,8,0.14);
  border: 1px solid rgba(234,179,8,0.32);
  border-radius: 999px;
  font-size: 0.78em;
  color: var(--tulip-tree-500);
  font-weight: 600;
}
.session-summary .players-breakdown {
  margin-bottom: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(255,255,255,0.10);
  font-size: 0.88em;
  color: var(--gris-300);
}
.session-summary .players-breakdown strong { color: var(--tulip-tree-500); }

/* Modal de "Tu nombre para esta partida" al inicio de sesión multijugador.
   Sustituye al prompt() nativo del navegador (que en PWA standalone iOS se
   ve feo y a veces Safari lo bloquea). Reutilizado por SM y GH — ambos
   archivos cargan styles.css. La lógica vive en cada motor (askSessionPlayerName
   en song-select.js para SM, copia inline en gh-play.html para GH) porque
   no comparten JS, solo CSS. */
.session-name-modal {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.78);
  z-index: 99999;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  animation: snmFadeIn 0.15s ease-out;
}
@keyframes snmFadeIn { from { opacity: 0 } to { opacity: 1 } }
.session-name-box {
  background: linear-gradient(180deg, rgba(15,23,42,0.96), rgba(15,23,42,0.92));
  border: 1px solid rgba(0,190,200,0.36);
  border-radius: 16px;
  padding: 24px 26px;
  max-width: 480px; width: 100%;
  box-shadow: 0 24px 60px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.04);
  animation: snmSlideIn 0.18s ease-out;
}
@keyframes snmSlideIn {
  from { transform: translateY(8px); opacity: 0 }
  to   { transform: translateY(0);   opacity: 1 }
}
.session-name-box h3 {
  margin: 0 0 8px;
  font-family: var(--font-display);
  color: var(--turquesa-400);
  font-size: 1.3em;
}
.session-name-box .snm-sub {
  margin: 0 0 16px;
  color: var(--gris-300);
  font-size: 0.92em;
  line-height: 1.5;
}
.session-name-box .snm-input {
  width: 100%;
  padding: 12px 14px;
  background: rgba(0,0,0,0.45);
  border: 1px solid rgba(0,190,200,0.30);
  border-radius: 10px;
  color: #fff;
  font-size: 1.05em;
  font-family: inherit;
  box-sizing: border-box;
  transition: border-color 0.18s, box-shadow 0.18s;
}
.session-name-box .snm-input:focus {
  outline: none;
  border-color: var(--turquesa-400);
  box-shadow: 0 0 0 3px rgba(0,190,200,0.22);
}
.session-name-box .snm-input::placeholder { color: var(--gris-500); }
.session-name-box .snm-actions {
  display: flex; gap: 10px; justify-content: flex-end;
  margin-top: 16px;
  flex-wrap: wrap;
}

/* ============================================================================
   PUNTUACIONES / RANKINGS — formulario de guardar al acabar, panel de
   ranking en results, modal de scores en song-select y library.
   ============================================================================ */

/* Form inline en results-screen tras acabar canción. Mismo lenguaje visual
   que .ranking-panel (radius 14px, fondo translúcido) para que ambos se
   lean como bloques hermanos — el form se transforma en panel tras guardar. */
.score-save-form {
  display: flex; align-items: center; gap: 12px;
  margin: 18px 0 0;
  padding: 16px 18px;
  background: linear-gradient(180deg, rgba(0,190,200,0.10), rgba(0,190,200,0.04));
  border: 1px solid rgba(0,190,200,0.28);
  border-radius: 14px;
  flex-wrap: wrap;
}
.score-save-form label {
  color: var(--gris-300); font-size: 0.92em; font-weight: 600;
  letter-spacing: 0.01em;
}
.score-save-form input[type="text"] {
  flex: 1; min-width: 180px;
  padding: 10px 14px;
  background: rgba(0,0,0,0.45);
  border: 1px solid rgba(0,190,200,0.35);
  color: #fff; border-radius: 8px;
  font-size: 1em; font-family: inherit;
  transition: border-color 0.18s, box-shadow 0.18s;
}
.score-save-form input[type="text"]:focus {
  outline: none; border-color: var(--turquesa-400);
  box-shadow: 0 0 0 3px rgba(0,190,200,0.22);
}
.score-save-form input[type="text"]::placeholder { color: var(--gris-500); }
.score-save-form .action-btn { flex-shrink: 0; }

/* Aviso "✓ Guardado como X" en modo sesión (playlist), reemplaza al form
   porque el nombre se fijó al iniciar la partida. Mismo lenguaje visual que
   .score-save-form para que se lea como bloque hermano. */
.score-saved-notice {
  margin: 18px 0 0;
  padding: 12px 18px;
  background: linear-gradient(180deg, rgba(0,255,100,0.10), rgba(0,255,100,0.04));
  border: 1px solid rgba(0,255,100,0.28);
  border-radius: 14px;
  color: var(--gris-200);
  font-size: 0.95em;
  text-align: center;
}
.score-saved-notice strong { color: #00ff64; }
.action-btn.primary {
  background: linear-gradient(90deg, var(--turquesa-400), var(--turquesa-600));
  color: #001f22; font-weight: 700;
}

/* Pill de posición en el ranking panel */
.position-pill {
  display: inline-block;
  padding: 9px 18px;
  margin: 0 0 12px;
  background: rgba(255,190,11,0.15);
  border: 1px solid rgba(255,190,11,0.4);
  border-radius: 999px;
  font-weight: 700; color: #ffbe0b;
  font-size: 0.96em;
  letter-spacing: 0.02em;
}
.position-pill.is-top {
  background: linear-gradient(90deg, var(--turquesa-400), #ffbe0b);
  color: #001f22; border-color: transparent;
  box-shadow: 0 4px 18px rgba(255,190,11,0.4);
  animation: pos-pulse 1.5s ease-out;
}
@keyframes pos-pulse {
  0%   { transform: scale(0.85); opacity: 0; }
  50%  { transform: scale(1.05); }
  100% { transform: scale(1); opacity: 1; }
}

/* Delta numérico (+1240 / -340) */
.ranking-delta-wrap { margin: 0 0 14px; }
.ranking-delta {
  display: inline-block;
  font-family: 'Consolas', monospace;
  font-size: 0.88em; font-weight: 700;
  padding: 3px 10px; border-radius: 6px;
  white-space: nowrap;
}
.ranking-delta.delta-up   { color: #00ff64; background: rgba(0,255,100,0.12); }
.ranking-delta.delta-down { color: #ff6688; background: rgba(255,51,102,0.12); }
.ranking-delta.delta-zero { color: var(--gris-400); background: rgba(255,255,255,0.05); }

/* Tabs CSS-only en el panel de ranking (radio inputs + sibling selectors).
   `display:none` en los radios + label como pestaña visible. Los panes
   muestran/oculatan según qué radio está `:checked`. */
.ranking-panel {
  margin-top: 18px;
  background: linear-gradient(180deg, rgba(255,255,255,0.04), rgba(255,255,255,0.02));
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 14px;
  padding: 18px 20px 20px;
}
.ranking-tabs {
  display: flex; flex-wrap: wrap; gap: 0;
  border-bottom: 1px solid rgba(255,255,255,0.1);
}
.ranking-tabs input[type="radio"] { display: none; }
.ranking-tab {
  padding: 11px 20px;
  cursor: pointer;
  color: var(--gris-400);
  font-weight: 600; font-size: 0.95em;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color 0.18s, border-color 0.18s, background-color 0.18s;
  user-select: none;
}
.ranking-tab:hover { color: #fff; background: rgba(255,255,255,0.03); }
.ranking-tab.disabled { opacity: 0.4; cursor: not-allowed; }
.ranking-tab.disabled:hover { color: var(--gris-400); background: transparent; }
/* Selector agnóstico de IDs concretos (SM usa rkTabTop/rkTabMine, GH usa
   ghRkTabTop/ghRkTabMine). Usamos :nth-of-type sobre los radios dentro de
   .ranking-tabs para identificar 1º/2º. El label "activo" se identifica por
   posición vía hermanos siguientes con `:nth-of-type(N)` sobre `.ranking-tab`. */
.ranking-tabs > input[type="radio"]:nth-of-type(1):checked ~ .ranking-tab:nth-of-type(1),
.ranking-tabs > input[type="radio"]:nth-of-type(2):checked ~ .ranking-tab:nth-of-type(2) {
  color: var(--turquesa-400);
  border-bottom-color: var(--turquesa-400);
}
.ranking-pane { display: none; width: 100%; padding-top: 14px; }
.ranking-tabs > input[type="radio"]:nth-of-type(1):checked ~ .ranking-pane-top,
.ranking-tabs > input[type="radio"]:nth-of-type(2):checked ~ .ranking-pane-mine {
  display: block;
}

/* Lista de runs en cualquier ranking (panel de results, modal de chart, modal
   de song). Estructura: <ol class="ranking-list"><li class="ranking-row">…</li></ol>
   Grid de 4 columnas (num, name, grade, score) en Top; en "Mi progresión" la
   1ª columna es la fecha y no hay rank-num — los selectores adaptan layout. */
.ranking-list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: 6px;
}
.ranking-row {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  background: rgba(255,255,255,0.035);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: 10px;
  font-size: 0.94em;
  transition: background 0.18s, border-color 0.18s;
}
.ranking-row:hover {
  background: rgba(255,255,255,0.06);
  border-color: rgba(255,255,255,0.1);
}
.ranking-pane-mine .ranking-row {
  grid-template-columns: auto auto 1fr auto;
}
.ranking-row .rank-name {
  min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Botón delete en la lista de "todas las partidas" — único elemento que se
   alinea al final (resto del row va pegado a la izquierda). */
.ranking-row .run-delete-btn { margin-left: auto; }
.ranking-row.is-me {
  background: rgba(0,190,200,0.12);
  border-color: rgba(0,190,200,0.28);
}
.ranking-row.is-just-saved {
  animation: just-saved-pulse 1.6s ease-out;
  border-left: 3px solid var(--turquesa-400);
}
@keyframes just-saved-pulse {
  0%   { background: rgba(0,245,212,0.5); }
  100% { background: rgba(0,190,200,0.12); }
}
.ranking-row .rank-num   { color: var(--gris-400); font-family: 'Consolas', monospace; font-weight: 700; min-width: 32px; }
.ranking-row .rank-date  { color: var(--gris-400); font-size: 0.86em; font-family: 'Consolas', monospace; }
.ranking-row .rank-grade { font-family: 'Consolas', monospace; font-weight: 800; font-size: 0.86em; padding: 3px 9px; border-radius: 6px; letter-spacing: 0.06em; justify-self: end; }
.ranking-row .rank-score { color: #ffbe0b; font-family: 'Consolas', monospace; font-weight: 700; text-align: right; min-width: 70px; justify-self: end; }
.ranking-row .rank-name  { color: #fff; font-weight: 600; }
.ranking-empty {
  color: var(--gris-500); padding: 18px 12px;
  text-align: center; font-style: italic;
  background: rgba(255,255,255,0.02);
  border-radius: 10px;
}

/* Coloreado de grades en las pills compactas (.rank-grade y .champ-grade).
   Los selectores con .grade-AAA ya existen para las pills de song-select
   (uppercase), aquí extendemos para el formato lowercase usado en runs. */
.rank-grade.g-aaa, .champ-grade.g-aaa { background: linear-gradient(90deg,#00f5d4,#ffbe0b); color:#000; }
.rank-grade.g-aa,  .champ-grade.g-aa  { background: rgba(0,245,212,0.2); color: #00f5d4; }
.rank-grade.g-a,   .champ-grade.g-a   { background: rgba(0,255,100,0.2); color: #66ff99; }
.rank-grade.g-b,   .champ-grade.g-b   { background: rgba(58,134,255,0.2); color: #88b4ff; }
.rank-grade.g-c,   .champ-grade.g-c   { background: rgba(255,190,11,0.2); color: #ffbe0b; }
.rank-grade.g-d,   .champ-grade.g-d   { background: rgba(255,51,102,0.2); color: #ff6688; }

/* Línea de campeón en la fila de biblioteca */
.lib-row-champion {
  margin-top: 6px;
  display: flex; align-items: center; gap: 8px;
  color: var(--gris-300); font-size: 0.86em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lib-row-champion.empty { color: var(--gris-500); font-style: italic; }
.lib-row-champion strong { color: #fff; }
.lib-row-champion .champ-diff {
  color: var(--gris-400); font-size: 0.88em;
}
.lib-row-champion .champ-grade {
  font-family: 'Consolas', monospace; font-weight: 700; font-size: 0.82em;
  padding: 2px 7px; border-radius: 5px;
}
.lib-row-champion .champ-score {
  font-family: 'Consolas', monospace; font-weight: 700; color: #ffbe0b;
  margin-left: auto;
}

/* Variante del champion para pantallas "Mis canciones" (SM + GH): chip
   compacto en columna a la derecha del título, en UNA sola línea
   (👑 jugador · diff · grade · score). Ancho fijo para evitar saltos
   horizontales cuando hay/no hay campeón. */
.lib-row-champion-col {
  display: flex; align-items: center; justify-content: flex-end; gap: 6px;
  min-width: 260px; max-width: 320px;
  color: var(--gris-300); font-size: 0.85em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lib-row-champion-col strong { color: #fff; }
.lib-row-champion-col .champ-sep { color: var(--gris-500); }
.lib-row-champion-col .champ-diff { color: var(--gris-400); font-size: 0.92em; }
.lib-row-champion-col .champ-grade {
  font-family: 'Consolas', monospace; font-weight: 700; font-size: 0.82em;
  padding: 2px 7px; border-radius: 5px;
}
.lib-row-champion-col .champ-score {
  font-family: 'Consolas', monospace; font-weight: 700; color: #ffbe0b;
}
.lib-row-champion-col.empty { color: var(--gris-500); font-style: italic; font-size: 0.82em; justify-content: flex-end; }
/* Variante COMPACTA para las pantallas "Tocar" (SM songs-screen + GH gh-
   songs-screen): solo 👑 + nombre + grade-pill (sin diff ni score). Cabe
   en columna más estrecha y la lista respira mejor. */
.lib-row-champion-col.compact {
  min-width: 0; max-width: 200px; font-size: 0.88em;
  justify-content: flex-start;
}

/* Contador de partidas debajo del pill en song-select */
.chart-row-plays {
  color: var(--gris-500); font-size: 0.78em; margin-top: 2px;
}

/* Modal de scores — overlay flotante reusable en song-select y library */
.scores-modal {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.7);
  display: flex; align-items: center; justify-content: center;
  z-index: 9999;
  padding: 20px;
  animation: fade-in 0.2s ease-out;
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
.scores-modal-inner {
  background: var(--gris-900, #0f172a);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 14px;
  max-width: 640px; width: 100%; max-height: 90vh;
  overflow-y: auto;
  padding: 24px 28px;
  position: relative;
  box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
.scores-modal-inner h2 {
  margin: 0 0 4px;
  color: #fff; font-size: 1.3em;
}
.scores-modal-inner h3 {
  margin: 12px 0 8px;
  color: var(--turquesa-400); font-size: 0.95em;
  text-transform: uppercase; letter-spacing: 0.08em;
}
.scores-modal-sub {
  color: var(--gris-400); font-size: 0.9em;
  margin: 0 0 14px;
}
.scores-modal-section { margin-bottom: 18px; }
.scores-modal-section .muted { color: var(--gris-500); font-weight: 400; font-size: 0.85em; }
.scores-modal-close {
  position: absolute; top: 12px; right: 14px;
  width: 32px; height: 32px;
  background: transparent; border: none;
  color: var(--gris-300); font-size: 1.4em;
  cursor: pointer; border-radius: 50%;
  transition: background 0.15s;
}
.scores-modal-close:hover { background: rgba(255,255,255,0.1); color: #fff; }
.scores-modal-actions {
  display: flex; gap: 10px; justify-content: flex-end;
  margin-top: 16px; padding-top: 14px;
  border-top: 1px solid rgba(255,255,255,0.08);
  flex-wrap: wrap;
}
.scores-modal-chart {
  background: rgba(255,255,255,0.02);
  border-radius: 8px;
  margin-bottom: 8px;
  padding: 4px 12px;
}
.scores-modal-chart > summary {
  cursor: pointer;
  padding: 8px 4px;
  list-style: none;
  display: flex; align-items: center; gap: 10px;
}
.scores-modal-chart > summary::-webkit-details-marker { display: none; }
.scores-modal-chart > summary::before {
  content: '▸'; color: var(--turquesa-400); transition: transform 0.15s;
}
.scores-modal-chart[open] > summary::before { transform: rotate(90deg); }
.scores-modal-chart > summary strong { color: #fff; }

/* La lista "todas las partidas" añade un botón delete por fila */
.scores-all-list .ranking-row {
  grid-template-columns: auto 1fr auto auto auto;
}
.scores-all-list .ranking-row .run-delete-btn {
  width: 26px; height: 26px;
  padding: 0; line-height: 1;
}

/* ============================================================================
   GROOVE RADAR — panel lateral de dificultad estilo SM5
   ============================================================================
   Estructura: .songs-with-radar es un grid 2-col. La tabla de canciones queda
   en la izquierda (columna fluida) y el panel del radar a la derecha (columna
   fija). En viewports estrechos colapsa a 1-col con el radar abajo.
*/
.songs-with-radar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 440px;
  gap: 18px;
  align-items: start;
}

.radar-panel {
  background: rgba(0, 190, 200, 0.05);
  border: 1px solid rgba(0, 190, 200, 0.25);
  border-radius: 12px;
  padding: 14px 14px 12px;
  position: sticky;
  top: 12px;
  min-height: 400px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.radar-panel .radar-title {
  font-family: var(--font-display, 'Righteous', sans-serif);
  color: var(--turquesa-400);
  font-size: 0.92em;
  letter-spacing: 0.04em;
  text-align: center;
  text-transform: uppercase;
}
.radar-panel .radar-svg-wrap {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 280px;
}
.radar-panel .radar-svg-wrap.radar-empty {
  color: var(--gris-500);
  font-size: 0.85em;
  text-align: center;
  padding: 18px 12px;
  line-height: 1.45;
}
.radar-panel .radar-placeholder {
  opacity: 0.85;
}
.radar-panel .radar-foot {
  font-size: 0.78em;
  color: var(--gris-400);
  text-align: center;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  padding-top: 6px;
}
.radar-panel .radar-foot #radarFootSong,
.radar-panel .radar-foot #radarFootDiff,
.radar-panel .radar-foot #ghRadarFootSong,
.radar-panel .radar-foot #ghRadarFootDiff {
  color: rgba(255, 255, 255, 0.78);
  font-weight: 600;
}

/* Variante con paleta Guitar Hero (dorado). El JS añade .radar-gh al panel. */
.radar-panel.radar-gh {
  background: rgba(255, 190, 11, 0.05);
  border-color: rgba(255, 190, 11, 0.28);
}
.radar-panel.radar-gh .radar-title { color: #ffd166; }

/* Responsive: por debajo de 900px el panel pasa debajo del listado en una
   sola columna. Por debajo de 540px lo ocultamos completamente — la usuaria
   ya está fuera del soporte oficial (la landing ya filtra <1024×600), pero
   el bloqueo solo afecta a la primera entrada; si ya está dentro del motor
   no queremos romper el layout en horizontal estrecho de tablet. */
@media (max-width: 900px) {
  .songs-with-radar {
    grid-template-columns: 1fr;
  }
  .radar-panel {
    position: static;
    min-height: 260px;
  }
}
@media (max-width: 540px) {
  .radar-panel { display: none; }
}
