:root {
  --engine-bg: #040405;
  --engine-panel: rgba(15, 11, 24, 0.88);
  --engine-panel-soft: rgba(255, 255, 255, 0.05);
  --engine-line: rgba(255, 255, 255, 0.16);
  --engine-text: #fff9ff;
  --engine-muted: #d7cdf5;
  --engine-cyan: #8eefff;
  --engine-blue: #8aa2ff;
  --engine-violet: #a96ae7;
  --engine-pink: #e55ab1;
  --engine-grad: linear-gradient(135deg, var(--engine-cyan) 0%, var(--engine-blue) 26%, var(--engine-violet) 56%, var(--engine-pink) 100%);
  --engine-shadow: 0 22px 54px rgba(0, 0, 0, 0.4);
}

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

body {
  min-height: 100vh;
  /* Fallback móvil */
  min-height: 100dvh;
  color: var(--engine-text);
  font-family: "Nunito", sans-serif;
  background:
    radial-gradient(circle at top left, rgba(229, 90, 177, 0.16), transparent 24%),
    radial-gradient(circle at 85% 12%, rgba(138, 162, 255, 0.18), transparent 26%),
    radial-gradient(circle at 50% 100%, rgba(169, 106, 231, 0.12), transparent 28%),
    var(--engine-bg);
}

a,
button,
input,
textarea,
select {
  font: inherit;
}

button,
input,
textarea,
select {
  color: inherit;
}

/* Opciones del <select>: fondo oscuro + texto claro */
option,
optgroup {
  background-color: #181026;
  color: #fff9ff;
}

button {
  cursor: pointer;
}

/* ── Fondo animado ── */
.engine-bg {
  position: fixed;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}

.engine-blob {
  position: absolute;
  border-radius: 999px;
  filter: blur(18px);
  opacity: 0.55;
}

.engine-blob-a {
  top: 4%;
  left: -8%;
  width: 26rem;
  height: 26rem;
  background: radial-gradient(circle, rgba(229, 90, 177, 0.34) 0%, transparent 72%);
}

.engine-blob-b {
  right: -8%;
  bottom: 12%;
  width: 30rem;
  height: 30rem;
  background: radial-gradient(circle, rgba(138, 162, 255, 0.28) 0%, transparent 74%);
}

.engine-grid {
  position: absolute;
  inset: 0;
  opacity: 0.08;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
  background-size: 42px 42px;
  mask-image: radial-gradient(circle at center, rgba(0, 0, 0, 0.9), transparent 92%);
}

/* ── Shell principal ── */
.engine-shell {
  /* Por encima del escudo de contraste del tema synthwave */
  position: relative;
  z-index: 2;
  max-width: 1400px;
  margin: 0 auto;
  padding: 1.2rem;
}

/* ── Topbar y panel cards ── */
.engine-topbar,
.panel-card {
  position: relative;
  overflow: hidden;
  background: var(--engine-panel);
  border: 1px solid var(--engine-line);
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.05) inset,
    var(--engine-shadow);
}

.engine-topbar {
  padding: 1rem 1.1rem;
  border-radius: 30px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.engine-brand {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}

.back-link,
.text-link {
  color: var(--engine-cyan);
  text-decoration: none;
  font-weight: 800;
}

.engine-brand-main {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.engine-brand-logo {
  width: 4.5rem;
  max-width: 100%;
  filter: drop-shadow(0 0 16px rgba(142, 239, 255, 0.25));
}

/* ── Pills y kickers ── */
.engine-brand-mini,
.card-kicker,
.status-pill,
.meta-chip,
.output-label {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.28rem 0.76rem;
  border-radius: 999px;
  font-size: 0.76rem;
  font-weight: 800;
  letter-spacing: 0.04em;
}

.engine-brand-mini,
.card-kicker,
.status-pill,
.meta-chip {
  color: #0a0a0a;
  background: var(--engine-grad);
}

/* Espacio bajo el kicker antes del h2/h3 */
.card-kicker {
  margin-bottom: 0.55rem;
}

/* ── Tipografía de headings ── */
.engine-brand-copy h1,
.panel-card h2,
.panel-card h3,
.player-card h3,
.summary-card h3 {
  font-family: "Baloo 2", cursive;
  line-height: 0.98;
}

.engine-brand-copy h1 {
  margin-top: 0.55rem;
  font-size: clamp(2rem, 4vw, 3rem);
}

/* ── Título de marca ── */
.engine-title {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.55rem;
}

.engine-title-engine {
  background: var(--engine-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 0 20px rgba(169, 106, 231, 0.35));
}

.panel-card h2 {
  margin-top: 0.2rem;
  line-height: 1.1;
}

.panel-card h3 {
  margin-top: 0.15rem;
  line-height: 1.15;
}

/* ── Status en topbar ── */
.engine-topbar-status {
  max-width: 22rem;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.55rem;
}

.status-copy {
  color: var(--engine-muted);
  text-align: right;
}

/* ── Layout principal ── */
.engine-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(300px, 0.85fr);
  gap: 1rem;
  margin-top: 1rem;
}

/* ── Layout del editor: columna única centrada ── */
.engine-single {
  max-width: 880px;
  margin: 1.1rem auto 0;
  display: flex;
  flex-direction: column;
}

.engine-main,
.engine-sidebar {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* ── Reproductor público (game.html): escenario + ranking lateral ── */
.player-layout {
  grid-template-columns: minmax(0, 1.7fr) minmax(300px, 0.85fr);
  align-items: stretch;   /* barra lateral hasta el fondo del panel */
}
.player-layout .engine-sidebar { align-self: stretch; min-height: 0; }
.player-layout .leaderboard-panel {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
/* Lista de ranking: vacía se centra, con filas se apila desde arriba */
.player-layout .leaderboard-list { flex: 1 1 auto; min-height: 0; }
/* Centrado del mensaje vacío */
.player-layout .leaderboard-list > .leaderboard-empty {
  margin: auto 0;
  transform: translateY(-1.8rem);
}

.mode-switch-btn,
.ghost-btn,
.primary-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 3rem;
  padding: 0.8rem 1.2rem;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  text-decoration: none;
  transition: transform 0.25s ease, background-color 0.25s ease, border-color 0.25s ease;
}

.mode-switch-btn,
.ghost-btn {
  color: #fff;
  background: rgba(255, 255, 255, 0.04);
}

.mode-switch-btn.active,
.primary-btn {
  color: #090909;
  background: var(--engine-grad);
  border-color: transparent;
  box-shadow: 0 14px 34px rgba(229, 90, 177, 0.22);
  font-weight: 800;
  letter-spacing: 0.01em;
}

.mode-switch-btn:hover,
.ghost-btn:hover,
.primary-btn:hover {
  transform: translateY(-2px);
}

.engine-editor {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* Oculta el hueco de la guía cuando está vacío */
#engine-guia:empty { display: none; }

/* ── Panel cards ── */
.panel-card {
  padding: 1.6rem;
  border-radius: 30px;
}

.panel-card p,
.leaderboard-subcopy,
.inline-status,
.field span,
.setup-list,
.player-empty p,
.player-media-note,
.summary-copy {
  color: var(--engine-muted);
  line-height: 1.7;
}

.panel-card-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
}

.panel-card-header p {
  margin-top: 0.5rem;
  line-height: 1.65;
}

.panel-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem;
  justify-content: flex-end;
}

/* ── Selector de tipo de actividad ── */
.activity-type-panel {
  padding: 1.1rem 1.3rem;
}

/* Grid auto-fit: reparte columnas según el ancho disponible */
.activity-type-switch {
  display: grid;
  /* 104px: los seis tipos entran en una fila */
  grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
  gap: 0.6rem;
}

.activity-type-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 1rem 0.6rem;
  border-radius: 22px;
  border: 1px solid var(--engine-line);
  background: var(--engine-panel-soft);
  color: var(--engine-muted);
  font-weight: 800;
  font-size: 0.86rem;
  letter-spacing: 0.01em;
  transition: transform 0.25s ease, border-color 0.25s ease, background-color 0.25s ease, color 0.25s ease;
}

.activity-type-ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 999px;
  font-size: 1.3rem;
  background: rgba(255, 255, 255, 0.06);
  transition: transform 0.25s ease, background 0.25s ease;
}

.activity-type-btn[data-activity-type="quiz"] .activity-type-ico {
  background: linear-gradient(135deg, rgba(141, 238, 255, 0.28), rgba(138, 162, 255, 0.2));
}
.activity-type-btn[data-activity-type="crossword"] .activity-type-ico {
  background: linear-gradient(135deg, rgba(169, 106, 231, 0.28), rgba(229, 90, 177, 0.18));
}
.activity-type-btn[data-activity-type="wordsearch"] .activity-type-ico {
  background: linear-gradient(135deg, rgba(229, 90, 177, 0.28), rgba(255, 171, 64, 0.2));
}
.activity-type-btn[data-activity-type="chrono"] .activity-type-ico {
  background: linear-gradient(135deg, rgba(255, 201, 74, 0.28), rgba(61, 220, 151, 0.2));
}
.activity-type-btn[data-activity-type="carto"] .activity-type-ico {
  background: linear-gradient(135deg, rgba(61, 220, 151, 0.28), rgba(141, 239, 255, 0.2));
}
.activity-type-btn[data-activity-type="rpq"] .activity-type-ico {
  background: linear-gradient(135deg, rgba(255, 107, 138, 0.28), rgba(169, 106, 231, 0.22));
}

.activity-type-btn:hover {
  transform: translateY(-2px);
  border-color: rgba(255, 255, 255, 0.28);
}

.activity-type-btn.active {
  color: var(--engine-text);
  background: var(--engine-panel);
}
.activity-type-btn.active .activity-type-ico {
  transform: scale(1.08);
}
.activity-type-btn.active[data-activity-type="quiz"] {
  border-color: var(--engine-cyan);
  box-shadow: 0 10px 26px rgba(142, 239, 255, 0.18);
}
.activity-type-btn.active[data-activity-type="crossword"] {
  border-color: var(--engine-violet);
  box-shadow: 0 10px 26px rgba(169, 106, 231, 0.2);
}
.activity-type-btn.active[data-activity-type="wordsearch"] {
  border-color: var(--engine-pink);
  box-shadow: 0 10px 26px rgba(229, 90, 177, 0.2);
}
.activity-type-btn.active[data-activity-type="chrono"] {
  border-color: #ffc94a;
  box-shadow: 0 10px 26px rgba(255, 201, 74, 0.2);
}
.activity-type-btn.active[data-activity-type="carto"] {
  border-color: #3ddc97;
  box-shadow: 0 10px 26px rgba(61, 220, 151, 0.2);
}
.activity-type-btn.active[data-activity-type="rpq"] {
  border-color: #ff6b8a;
  box-shadow: 0 10px 26px rgba(255, 107, 138, 0.2);
}

@media (max-width: 560px) {
  /* Dos columnas en móvil */
  .activity-type-switch {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .activity-type-btn {
    flex-direction: row;
    justify-content: flex-start;
    gap: 0.6rem;
    padding: 0.6rem 0.7rem;
    font-size: 0.8rem;
  }
  .activity-type-ico { width: 2rem; height: 2rem; font-size: 1rem; }
}

/* ── Editor form ── */
.editor-form {
  display: flex;
  flex-direction: column;
  gap: 1.6rem;   /* más aire entre filas de campos */
}

.editor-grid,
.player-loader-grid,
.question-grid,
.question-options,
.summary-stats {
  display: grid;
  gap: 1rem;
}

.editor-grid {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.25rem;   /* columnas de ajustes menos pegadas */
}

/* Opción con checkbox (orden aleatorio, etc.). */
/* ── Aire entre las opciones del final del formulario ─────────────
   Debajo de los campos de la ficha (título, categoría, descripción)
   vienen tres opciones sueltas: orden aleatorio, música de fondo y
   portada. Cada una arrastra su propio texto de ayuda, así que sin
   separación el bloque entero se leía como un muro y costaba ver dónde
   acababa una y empezaba la siguiente.

   Cada una se separa de la anterior con una línea tenue: marca el
   cambio de zona sin tener que meter subtítulos.

   Los valores tienen en cuenta que .editor-form es flex con gap:1.6rem,
   y que en flex el margin se SUMA al gap en vez de solaparse como haría
   entre bloques. Por eso el margin propio es pequeño: el hueco real es
   el gap más este margin más el padding. */
.field-check,
.field-check ~ .field-full {
  margin-top: 0.6rem;
  padding-top: 1.6rem;
  border-top: 1px solid var(--engine-line);
}

/* `.field.field-check` y no `.field-check` a secas: las dos clases van
   siempre juntas en el mismo elemento, y `.field { flex-direction:
   column }` está declarado MÁS ABAJO en este archivo. Con la misma
   especificidad gana el último, así que la casilla se apilaba encima
   del texto en vez de ponerse a su lado. Duplicando la clase, esta
   regla pesa más y ya no depende del orden del archivo. */
.field.field-check {
  flex-direction: row;
  /* Centrada contra el bloque entero (título + descripción), que es lo
     que hace que se lea como UNA sola línea con su casilla al lado, en
     vez de una casilla suelta arriba a la izquierda. */
  align-items: center;
  gap: 0.75rem;
  cursor: pointer;
}
.field-check input[type="checkbox"] {
  width: 1.2rem; height: 1.2rem;
  accent-color: var(--engine-violet, #a96ae7);
  cursor: pointer; flex-shrink: 0;
}
/* Pista bajo un campo. Cambia de color según lo que se haya escrito
   (ver refrescarPistaMusica en app.js): neutra mientras está vacío,
   verde si el enlace vale, ámbar si no. */
.field-hint {
  font-weight: 600; font-size: 0.78rem; letter-spacing: 0;
  color: var(--engine-muted); line-height: 1.45;
}
.field-hint.is-good { color: #7ef7d0; }
.field-hint.is-bad  { color: #ffc94d; }

.field-check-copy { display: flex; flex-direction: column; gap: 0.25rem; }
.field-check-copy small { font-weight: 600; font-size: 0.78rem; letter-spacing: 0; color: var(--engine-muted); }

.player-loader-grid {
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: end;
}

/* ── Fields (labels + inputs) ── */
.field {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
}

.field span {
  font-size: 0.85rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  line-height: 1;
}

.field-grow {
  min-width: 0;
}

.field-full {
  width: 100%;
}

/* Margen entre el bloque de explicación y la fila de tipo de media */
.field.field-full + .question-grid {
  margin-top: 0.65rem;
}

/* Los campos se leen como un hueco EXCAVADO en la tarjeta, no como un
   rectángulo casi invisible pegado encima. Con fondo semitransparente
   blanco al 4% sobre una tarjeta ya oscura, el campo se fundía con la
   tarjeta y toda la sección se veía como un bloque gris uniforme — es
   justo lo que hacía sentir el editor "un formulario aburrido": nada
   invitaba a tocar nada porque nada se distinguía de nada.
   La sombra interior es lo que vende el efecto "hueco": sin ella,
   oscurecer el fondo no basta, se ve plano igual. */
.field input,
.field textarea,
.field select {
  width: 100%;
  padding: 0.9rem 1.05rem;
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.13);
  background: rgba(4, 2, 10, 0.34);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.35);
  outline: none;
  transition: border-color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}

/* El placeholder no hereda el gris genérico del navegador: usa el mismo
   lila apagado que el resto de textos secundarios, para que hasta un
   campo vacío se sienta parte de la paleta y no un control del sistema. */
.field input::placeholder,
.field textarea::placeholder {
  color: rgba(215, 205, 245, 0.4);
}

/* Al enfocar: el hueco se ilumina por dentro (deja de sentirse "cerrado")
   y un halo suave lo separa del resto de la tarjeta. Las dos señales
   entran a la vez porque una sola —solo el borde, o solo el fondo—
   se notaba poco sobre un panel ya de por sí oscuro. */
.field input:focus,
.field textarea:focus,
.field select:focus {
  background: rgba(20, 14, 34, 0.55);
  border-color: rgba(142, 239, 255, 0.6);
  box-shadow:
    inset 0 1px 3px rgba(0, 0, 0, 0.25),
    0 0 0 4px rgba(142, 239, 255, 0.14);
}

/* ── Toolbar del editor ── */
.editor-toolbar {
  display: flex;
  flex-wrap: wrap;
  margin-top: 1rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--engine-line);
  gap: 0.8rem 1rem;
}

/* La barra de "Abrir constructor de…" lleva un único botón, y con el
   relleno normal quedaba casi pegado a la línea de separación: se leía
   como si el botón formara parte del borde en vez de ser una acción
   aparte.

   Va con la clase DUPLICADA (.editor-toolbar.editor-toolbar-lanzar) y
   no suelta: más abajo, en el bloque "Barra de acciones", hay otro
   `.editor-toolbar { padding-top: 0.3rem }`. Con la misma
   especificidad gana el último por estar después en el archivo, así
   que la versión suelta de esta regla no llegaba a aplicarse nunca y
   el botón seguía pegado a la línea. Es el mismo tropiezo que hubo con
   .field-check. */
.editor-toolbar.editor-toolbar-lanzar {
  margin-top: 1.8rem;
  padding-top: 2.4rem;
  padding-bottom: 0.6rem;
}

/* ── Status messages ── */
.inline-status {
  min-height: 1.6rem;
  padding-top: 0.1rem;
  font-size: 0.9rem;
  font-weight: 700;
}

.inline-status.is-error {
  color: #ffb9d6;
}

.inline-status.is-success {
  color: #c8fff8;
}

/* Botón "Deshacer" que acompaña al aviso de pregunta eliminada. Va
   dentro de la propia línea de estado en vez de en un mensaje flotante
   aparte: ahí es donde el editor ya cuenta lo que acaba de pasar, y no
   hay que inventar otro sitio ni taparle nada al formulario. */
.deshacer-btn {
  margin-left: 0.5rem;
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
  border: 1px solid var(--engine-violet, #a96ae7);
  background: rgba(169, 106, 231, 0.14);
  color: var(--engine-text, #fff9ff);
  font: inherit;
  font-size: 0.82rem;
  cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease;
}
.deshacer-btn:hover { background: rgba(169, 106, 231, 0.3); }
.deshacer-btn:focus-visible {
  outline: 2px solid var(--engine-cyan, #8eefff);
  outline-offset: 2px;
}

/* ── Micro-interacciones ───────────────────────────────────────────
   Todas animan solo transform y opacity. Son las dos propiedades que el
   navegador puede resolver sin volver a calcular la maqueta ni repintar,
   así que van fluidas también en equipos flojos. Animar height, top o
   box-shadow costaría un recálculo por fotograma. */

/* Pregunta recién añadida: entra desde abajo y se señala sola, para que
   no haya que buscarla con la vista después del desplazamiento. */
@keyframes preguntaEntra {
  from { opacity: 0; transform: translateY(12px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}

.question-card.is-nueva {
  animation: preguntaEntra 0.38s cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* Confirmación de guardado: el mensaje da un pulso corto. Es un acuse de
   recibo, no un adorno — sin él no se distingue un guardado nuevo de un
   mensaje que ya estaba en pantalla desde antes. */
@keyframes acuseGuardado {
  0%   { opacity: 0; transform: translateY(4px); }
  55%  { opacity: 1; transform: translateY(0) scale(1.015); }
  100% { opacity: 1; transform: none; }
}

.inline-status.is-success {
  animation: acuseGuardado 0.45s ease-out;
}

/* Los botones responden al pulsar, no solo al pasar por encima: en móvil
   no existe el hover y sin esto el botón parece que no reaccionó. */
.primary-btn:active,
.ghost-btn:active {
  transform: translateY(1px) scale(0.985);
}

@media (prefers-reduced-motion: reduce) {
  .question-card.is-nueva,
  .inline-status.is-success {
    animation: none;
  }
  .primary-btn:active,
  .ghost-btn:active {
    transform: none;
  }
}

/* ── Question cards ── */
.question-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.question-card,
.player-card,
.summary-card {
  position: relative;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 26px;
  padding: 1.5rem;
}

/* ── Realce al pasar el mouse ─────────────────────────────────────
   RETIRADO: el "brillo" que barría una franja diagonal por encima de
   la tarjeta. Era un ::after con inset:0 que se pintaba SOBRE todo el
   contenido, y por eso daba problemas en todas partes: sobre el
   formulario del editor parecía que el campo se hubiera roto, y sobre
   una pregunta del reproductor cortaba el enunciado y las opciones con
   una banda gris a media lectura. Encima, al cubrir tarjetas enteras y
   animarse con el puntero, obligaba al navegador a repintar áreas
   grandes en cada movimiento del ratón.

   En su lugar, un realce que NO tapa nada: el borde se enciende y la
   tarjeta levanta un poco la sombra. Se anima solo border-color y
   box-shadow, sin ninguna capa nueva por encima del texto. */
.player-card,
.summary-card,
.panel-card {
  transition: border-color 0.25s ease, box-shadow 0.25s ease;
}

/* El editor queda fuera del realce: es un formulario que se está
   escribiendo, no una tarjeta que se explora, y encenderle el borde al
   pasar por encima solo distrae. */
.player-card:hover,
.summary-card:hover,
.panel-card:not(.editor-form):hover {
  border-color: rgba(169, 106, 231, 0.55);
  box-shadow: 0 18px 42px -24px rgba(169, 106, 231, 0.55);
}

.question-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.4rem;
}

.question-index {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 16px;
  background: var(--engine-grad);
  color: #090909;
  font-weight: 900;
}

.question-grid {
  column-gap: 1.25rem;
  row-gap: 1.5rem;
  grid-template-columns: minmax(0, 1.25fr) minmax(220px, 0.5fr);
}

.question-options {
  column-gap: 1.25rem;
  row-gap: 1.5rem;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* Separación explícita entre el bloque de opciones y el de explicación */
.question-options + .field {
  margin-top: 0.5rem;
}

.question-grid + .question-options {
  margin-top: 1.5rem;
}

.question-options + .field {
  margin-top: 1.25rem; /* antes estaba en 0.5rem */
}

/* Margen superior en la última fila (tipo de media) */
.question-card .question-grid:last-of-type {
  margin-top: 0.5rem;
}

.audio-summary {
  margin-top: 0.5rem;
  display: block;
  color: #fff;
  font-size: 0.85rem;
  font-weight: 700;
  line-height: 1.4;
}

/* ── Player ── */
.player-stage {
  min-height: 24rem;
  /* Ancla de la capa de transición, que va absolute sobre este mismo
     recuadro (ver .player-transicion). */
  position: relative;
}

/* ── Transición entre preguntas: la pieza que encaja ──────────────
   Los tiempos están calcados de play/player.js (T_SALIDA, T_ICONO,
   T_CAPA). Si se cambian allá, hay que cambiarlos aquí: JS no puede
   pasarle constantes al CSS, así que la única forma de que la capa se
   retire justo cuando la pieza terminó es que ambos lados usen los
   mismos números.

   Todo lo que se anima es transform y opacity — las dos propiedades
   que el navegador resuelve en la GPU sin recalcular el diseño de la
   página. Nada de animar width/top/filter, que obligan a repintar en
   cada fotograma y son justo lo que hace que una animación se sienta
   pesada en un móvil. */
.player-card.is-saliendo {
  animation: playerCardOut 220ms ease forwards;  /* T_SALIDA */
  pointer-events: none;   /* ya no se puede responder: la pregunta se está yendo */
}

@keyframes playerCardOut {
  to { opacity: 0; transform: translateY(-10px) scale(0.985); }
}

.player-transicion {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  z-index: 2;
  pointer-events: none;
  /* El fondo acompaña con un velo muy suave: sin él, la pieza flota
     sobre la tarjeta a medio desvanecer y se ve sucio. */
  background: radial-gradient(60% 60% at 50% 50%,
    rgba(10, 8, 22, 0.55), rgba(10, 8, 22, 0) 70%);
  animation: ptCapaIn 160ms ease both;
}
.player-transicion.is-yendose {
  animation: ptCapaOut 200ms ease forwards;      /* T_CAPA */
}

@keyframes ptCapaIn  { from { opacity: 0; } to { opacity: 1; } }
@keyframes ptCapaOut { to   { opacity: 0; } }

/* El icono (🧩 / 🔍 / 💡, lo rota player.js por pregunta). La capa es
   un grid con place-items:center, así que aro e icono quedan
   superpuestos y centrados sin posicionar nada a mano: los dos ocupan
   la misma celda. */
.pt-icono,
.pt-aro {
  grid-area: 1 / 1;
}

.pt-icono {
  font-size: 2.8rem;
  line-height: 1;
  /* El emoji se pinta con la fuente de color del sistema; el filtro es
     solo para despegarlo del fondo oscuro. */
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.55));
  animation: ptIconoEntra 620ms cubic-bezier(0.22, 1.15, 0.36, 1) both;  /* T_ICONO */
}

/* Gira una vuelta entera mientras entra y frena al llegar. El giro es
   lo que da la sensación de "cargando"; el rebote del final es lo que
   lo convierte en "ya está", en vez de dejarlo dando vueltas sin
   resolverse. */
@keyframes ptIconoEntra {
  0%   { opacity: 0; transform: rotate(-180deg) scale(0.35); }
  45%  { opacity: 1; }
  100% { opacity: 1; transform: rotate(0deg) scale(1); }
}

/* El aro que gira alrededor: es el que sostiene la espera cuando hay
   que aguardar a que cargue una imagen (ver T_ESPERA_MAX en
   player.js). El icono ya se asentó, pero el aro sigue dando vueltas,
   así que la pausa se lee como "cargando" y no como "se colgó".
   El arco abierto (border-*-color: transparent en tres lados) es lo
   que hace visible el giro: un aro completo giraría sin que se note. */
.pt-aro {
  width: 76px;
  height: 76px;
  border-radius: 50%;
  border: 3px solid rgba(169, 106, 231, 0.22);
  border-top-color: rgba(169, 106, 231, 0.9);
  animation: ptAroGira 900ms linear infinite,
             ptAroAparece 300ms ease both;
}

@keyframes ptAroGira    { to { transform: rotate(360deg); } }
@keyframes ptAroAparece { from { opacity: 0; } to { opacity: 1; } }

/* Con el ajuste del sistema activo, player.js ni siquiera monta la
   capa; esto es el cinturón de seguridad por si algo la creara igual. */
@media (prefers-reduced-motion: reduce) {
  .player-card.is-saliendo,
  .player-transicion,
  .pt-icono,
  .pt-aro {
    animation: none;
  }
  .player-transicion { display: none; }
}

.player-empty,
.leaderboard-empty {
  text-align: center;
  padding: 2rem 1rem;
}

.player-stats,
.leaderboard-header,
.summary-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
}

.player-stats-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

/* `> span` y no `span` a secas: con el selector de descendencia, un
   <span> anidado dentro de una etiqueta heredaba la misma píldora y se
   veían dos fondos, uno detrás del otro. Limitándolo a los hijos
   directos, el estilo cae solo en las etiquetas de verdad. */
.player-stats-list > span,
.summary-stat {
  padding: 0.45rem 0.8rem;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.05);
  font-size: 0.84rem;
  font-weight: 800;
}

.player-media {
  margin-top: 1.5rem;   /* separación de las etiquetas de arriba */
  margin-bottom: 1rem;
}

/* ── Explicaciones al final del quiz ─────────────────────────────
   Antes cada explicación se enseñaba un instante pegado a la pausa
   antes de avanzar de pregunta (ver handleAnswer en play/player.js) —
   muy poco tiempo para leerla con calma, pero alargar esa pausa habría
   hecho que el quiz se sintiera lento entre pregunta y pregunta. Ahora
   se juntan todas acá, en la pantalla de resultados, donde ya no hay
   apuro: el jugador se queda leyendo el tiempo que quiera. */
.explicaciones {
  margin-top: 1.6rem;
  padding-top: 1.4rem;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}
.explicaciones-titulo {
  font-family: "Baloo 2", var(--font-heading, inherit);
  font-weight: 800;
  font-size: 1rem;
  margin: 0 0 0.9rem;
}
.explicaciones-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.8rem;
  /* Con un quiz largo esto puede crecer bastante: se acota su propia
     altura con scroll interno en vez de alargar sin límite toda la
     pantalla de resultados (y de paso el scroll de la página). */
  max-height: 26rem;
  overflow-y: auto;
  padding-right: 0.3rem; /* la barra de scroll no tapa el texto */
}
.explicacion-item {
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(255, 255, 255, 0.03);
  padding: 0.9rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
/* (.es-fallo se retiró: al resumen ya solo llegan preguntas
   acertadas, así que no hay variante de fallo que pintar.) */
.explicacion-pregunta {
  font-weight: 800;
  font-size: 0.88rem;
  line-height: 1.35;
  display: flex;
  align-items: flex-start;
  gap: 0.45rem;
}
.explicacion-icono { flex-shrink: 0; line-height: 1.35; }
.explicacion-correcta {
  font-size: 0.78rem;
  font-weight: 700;
  color: #7ef7d0;
}
.explicacion-texto {
  font-size: 0.85rem;
  color: var(--engine-muted);
  line-height: 1.55;
}

/* Entrada suave de cada pregunta (barato: solo opacidad + desplazamiento). */
@keyframes playerCardIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
.player-card { animation: playerCardIn 0.28s ease both; }
/* La imagen aparece con un fade cuando termina de cargar (lo revela player.js
   poniendo la opacidad; así, sin JS, se ve igual). */
@media (prefers-reduced-motion: reduce) {
  .player-card { animation: none; }
}

.player-media iframe,
.player-media audio {
  width: 100%;
  border: none;
  border-radius: 20px;
}

.player-media iframe {
  aspect-ratio: 16 / 9;
}

/* Imagen / GIF dentro de la pregunta */
.player-media-img {
  display: block;
  width: 100%;
  max-height: 22rem;
  object-fit: contain;
  border-radius: 20px;
  border: 1px solid var(--engine-line);
  background: rgba(0, 0, 0, 0.25);
}

/* Vista previa pequeña en el editor (pregunta y portada) */
/* El [hidden] va aquí y no en el HTML porque `display:block` de la
   línea siguiente lo pisaba: el editor abría SIEMPRE con un icono de
   imagen rota debajo de la portada, como si algo hubiera fallado. */
.media-preview[hidden] { display: none; }

.media-preview {
  display: block;
  margin-top: 0.6rem;
  max-width: 220px;
  max-height: 140px;
  width: auto;
  border-radius: 12px;
  border: 1px solid var(--engine-line);
  object-fit: cover;
}

.player-prompt {
  margin-top: 1.5rem;
  font-size: 1.1rem;
  font-weight: 800;
  line-height: 1.6;
}

/* Fallo con vidas restantes: la opción parpadea en rojo y se reintenta. */
@keyframes answerFlashRed {
  0%, 100% { border-color: #ef4444; background: rgba(239, 68, 68, 0.22); }
  50%      { border-color: rgba(239, 68, 68, 0.35); background: rgba(239, 68, 68, 0.05); }
}
.answer-btn.is-flash {
  animation: answerFlashRed 0.3s ease 2;
  color: inherit;
}

.player-options {
  display: grid;
  gap: 0.8rem;
  margin-top: 1rem;
}

.answer-btn {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  padding: 1rem;
  border-radius: 20px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.04);
  color: #fff;
  text-align: left;
  transition: transform 0.18s ease, border-color 0.18s ease, background-color 0.18s ease;
}

/* Número de atajo. Va visible para que se descubra solo: un atajo que
   hay que adivinar no lo usa nadie. */
.answer-key {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.06);
  font-family: inherit;
  font-size: 0.75rem;
  font-weight: 800;
  color: var(--engine-muted, #d7cdf5);
}

.answer-txt { flex: 1; min-width: 0; }

/* Destello al contestar con el teclado: sin esto la respuesta se
   registra sin que nada confirme QUÉ botón se pulsó. */
.answer-btn.is-teclado {
  transform: scale(0.985);
  border-color: rgba(142, 239, 255, 0.55);
  background: rgba(142, 239, 255, 0.1);
}

/* En pantallas táctiles el número no aporta nada: no hay teclado. */
@media (hover: none) and (pointer: coarse) {
  .answer-key { display: none; }
}

.answer-btn:hover:not(:disabled) {
  transform: translateY(-1px);
  border-color: rgba(255, 255, 255, 0.28);
}

.answer-btn.is-correct {
  border-color: rgba(142, 239, 255, 0.6);
  background: rgba(142, 239, 255, 0.14);
}

.answer-btn.is-wrong {
  border-color: rgba(229, 90, 177, 0.65);
  background: rgba(229, 90, 177, 0.14);
}

.player-feedback {
  min-height: 1.5rem;
  margin-top: 0.9rem;
  font-weight: 800;
}

.player-feedback.is-good {
  color: #b9fff4;
}

.player-feedback.is-bad {
  color: #ffbfdc;
}

/* ── Timer ── */
.timer-wrap {
  margin-top: 1rem;
}

.timer-track {
  width: 100%;
  height: 0.75rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
}

.timer-fill {
  width: 100%;
  height: 100%;
  border-radius: inherit;
  background: var(--engine-grad);
  transform-origin: left center;
}

/* ── Summary / resultado ── */
.summary-card {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* auto-fit y no 3 columnas fijas: el resumen pasó a tener cuatro datos
   (puntos, aciertos, fallos y precisión) y el cuarto caía solo a una
   segunda fila. Así se acomodan los que haya. */
.summary-stats {
  grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
}

.summary-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.25rem;
}

.summary-stat strong {
  font-family: "Baloo 2", cursive;
  font-size: 2rem;
  line-height: 0.9;
}

/* ── Leaderboard ── */
.leaderboard-panel {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.leaderboard-list {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.leaderboard-row {
  display: grid;
  grid-template-columns: 4rem 1fr auto auto;
  gap: 0.9rem;
  align-items: center;
  padding: 0.85rem 0.95rem;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.leaderboard-rank {
  font-family: "Baloo 2", cursive;
  font-size: 1.4rem;
}

.leaderboard-name {
  font-weight: 800;
}

.leaderboard-meta {
  color: var(--engine-muted);
  font-size: 0.85rem;
  font-weight: 700;
}

.rank-form {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  align-items: end;
}

.rank-form .field {
  flex: 1 1 14rem;
}

/* ── Sidebar ── */
.side-card {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.output-block {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.output-label {
  align-self: flex-start;
  color: #fff;
  background: rgba(255, 255, 255, 0.08);
  margin-bottom: 0.1rem;
}

.output-block code,
.json-preview {
  display: block;
  padding: 0.95rem 1rem;
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.08);
  color: #fff;
  font-size: 0.88rem;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.json-preview {
  min-height: 18rem;
  max-height: 32rem;
  overflow: auto;
}

/* ── Opciones avanzadas ────────────────────────────────────────────
   Un <details> nativo. Se le quita el triangulito del sistema y se le
   pone el nuestro, pero el comportamiento (teclado, lectores de
   pantalla, abrir/cerrar sin JS) sigue siendo el del navegador. */
.side-advanced {
  border-radius: 30px;
  border: 1px solid var(--engine-line);
  background: var(--engine-panel);
  box-shadow: var(--engine-shadow);
  overflow: hidden;
}

.side-advanced > summary {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 1.15rem 1.3rem;
  cursor: pointer;
  list-style: none;              /* Firefox */
  user-select: none;
  transition: background-color 0.25s ease;
}

/* El marcador por defecto de Safari/Chrome se quita aparte: list-style
   solo lo tumba en Firefox. */
.side-advanced > summary::-webkit-details-marker {
  display: none;
}

.side-advanced > summary:hover {
  background: rgba(255, 255, 255, 0.04);
}

/* Se marca el foco de teclado, que es justo lo que se pierde cuando
   alguien reemplaza un <details> por divs. */
.side-advanced > summary:focus-visible {
  outline: 2px solid var(--engine-cyan);
  outline-offset: -2px;
}

.side-advanced-icon {
  font-size: 1.15rem;
  opacity: 0.85;
}

.side-advanced > summary strong {
  display: block;
  color: var(--engine-text);
  font-weight: 800;
}

.side-advanced > summary small {
  display: block;
  margin-top: 0.15rem;
  color: var(--engine-muted);
  font-size: 0.78rem;
}

.side-advanced-chevron {
  margin-left: auto;
  color: var(--engine-muted);
  transition: transform 0.25s ease;
}

.side-advanced[open] .side-advanced-chevron {
  transform: rotate(180deg);
}

.side-advanced-body {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  padding: 0 1.3rem 1.3rem;
}

.side-advanced-note {
  color: var(--engine-muted);
  font-size: 0.8rem;
  line-height: 1.5;
}

/* Dentro del desplegable el JSON no necesita ser un muro de 18rem. */
.side-advanced .json-preview {
  min-height: 9rem;
  max-height: 20rem;
  font-size: 0.8rem;
}

.setup-list li + li {
  margin-top: 0.5rem;
}

/* ══════════════════════════════════════════════════
   RESPONSIVE
══════════════════════════════════════════════════ */

@media (max-width: 1180px) {
  .engine-layout {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 920px) {
  .engine-topbar {
    flex-direction: column;
    align-items: flex-start;
  }

  .engine-topbar-status {
    align-items: flex-start;
    text-align: left;
  }

  .editor-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .player-loader-grid,
  .question-grid,
  .question-options,
  .summary-stats,
  .leaderboard-row,
  .explicaciones-grid {
    grid-template-columns: 1fr;
  }

  .explicaciones-grid {
    max-height: 20rem;
  }
}

@media (max-width: 640px) {
  .engine-shell {
    padding: 0.8rem;
  }

  .panel-card,
  .engine-topbar,
  .question-card,
  .player-card,
  .summary-card {
    border-radius: 24px;
  }

  .engine-brand-main {
    flex-direction: column;
    align-items: flex-start;
  }

  .editor-grid {
    grid-template-columns: 1fr;
  }

  .editor-toolbar,
  .summary-actions,
  .rank-form {
    flex-direction: column;
  }

  .mode-switch {
    width: 100%;
    flex-direction: column;
  }

  .mode-switch-btn,
  .ghost-btn,
  .primary-btn {
    width: 100%;
  }
}
/* ══════════════════════════════════════════════════════════════════
   LAVADO DE CARA DEL EDITOR
   ------------------------------------------------------------------
   Todo lo que se mueve aquí anima SOLO transform y opacity. Son las dos
   propiedades que el navegador resuelve en la GPU sin recalcular la
   maqueta ni repintar, y es lo que permite que con cincuenta preguntas
   en pantalla siga yendo suelto. Animar height, box-shadow o filter
   costaría un recálculo por fotograma y con veinte tarjetas se notaría.
   ══════════════════════════════════════════════════════════════════ */

/* ── Tarjetas de pregunta: más aire y bordes más marcados ── */
.question-list {
  display: flex;
  flex-direction: column;
  gap: 1.15rem;
}

.question-card {
  padding: 1.5rem 1.6rem;
  border-radius: 22px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  background: rgba(20, 14, 32, 0.72);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.05) inset,
    0 16px 34px rgba(0, 0, 0, 0.28);
  /* La transición NO incluye box-shadow: solo el desplazamiento.
     Levantarla al pasar por encima la hace sentir "tocable" sin coste. */
  transition: transform 0.22s ease;
}

.question-card:hover {
  transform: translateY(-2px);
}

/* La tarjeta con el cursor dentro se distingue del resto: cuando hay
   quince, saber en cuál estás escribiendo importa más que el adorno. */
.question-card:focus-within {
  border-color: rgba(141, 238, 255, 0.42);
}

.question-card-header {
  align-items: center;
}

/* El número de la pregunta como ficha, no como texto suelto. */
.question-index {
  display: inline-grid;
  place-items: center;
  min-width: 2rem;
  height: 2rem;
  padding: 0 0.5rem;
  border-radius: 999px;
  background: var(--engine-grad);
  color: #0a0a0a;
  font-family: "Baloo 2", cursive;
  font-size: 0.95rem;
  font-weight: 800;
}

/* ── Papelera ──────────────────────────────────────────────────────
   Dibujada con dos span en vez de un emoji, para poder abrir la tapa.
   El texto "Eliminar" sobraba: una papelera se entiende sola y liberaba
   una fila entera en la cabecera de cada tarjeta. */
.question-del {
  position: relative;
  width: 2.2rem;
  height: 2.2rem;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

/* Tapa */
.question-del-lid {
  position: absolute;
  top: 0.55rem;
  left: 50%;
  width: 1.05rem;
  height: 0.16rem;
  margin-left: -0.525rem;
  border-radius: 2px;
  background: #cbbde8;
  transform-origin: left center;
  transition: transform 0.24s cubic-bezier(0.34, 1.4, 0.64, 1), background-color 0.2s ease;
}

/* Asa de la tapa */
.question-del-lid::before {
  content: "";
  position: absolute;
  top: -0.22rem;
  left: 0.3rem;
  width: 0.45rem;
  height: 0.22rem;
  border: 0.11rem solid #cbbde8;
  border-bottom: 0;
  border-radius: 2px 2px 0 0;
}

/* Cubo */
.question-del-can {
  position: absolute;
  top: 0.82rem;
  left: 50%;
  width: 0.85rem;
  height: 0.8rem;
  margin-left: -0.425rem;
  border: 0.11rem solid #cbbde8;
  border-top: 0;
  border-radius: 0 0 3px 3px;
  transition: border-color 0.2s ease;
}

.question-del:hover {
  background: rgba(229, 90, 177, 0.14);
  border-color: rgba(229, 90, 177, 0.5);
}

/* La tapa se levanta al pasar por encima: el gesto anticipa lo que va a
   pasar antes de pulsar. */
.question-del:hover .question-del-lid {
  transform: rotate(-22deg) translateY(-1px);
}

.question-del:hover .question-del-lid,
.question-del:hover .question-del-can {
  background-color: #ff9ecb;
  border-color: #ff9ecb;
}

.question-del:hover .question-del-lid::before {
  border-color: #ff9ecb;
}

.question-del:focus-visible {
  outline: 2px solid var(--engine-cyan);
  outline-offset: 2px;
}

/* ── Salida al eliminar ────────────────────────────────────────────
   Se encoge y se apaga. Antes desaparecía de golpe y todo lo de abajo
   pegaba un salto: con quince preguntas no había forma de seguir con la
   vista qué se acababa de borrar. */
@keyframes preguntaSale {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: scale(0.9); }
}

.question-card.is-yendose {
  animation: preguntaSale 0.26s ease-in forwards;
  pointer-events: none;
}

/* ── Entrada, con un rebote corto ── */
@keyframes preguntaEntra {
  0%   { opacity: 0; transform: translateY(16px) scale(0.97); }
  60%  { opacity: 1; transform: translateY(-3px) scale(1.006); }
  100% { opacity: 1; transform: none; }
}

.question-card.is-nueva {
  animation: preguntaEntra 0.42s cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* ── Estado vacío ──────────────────────────────────────────────────
   Lo primero que ve quien entra a crear. Se le pide algo, no se le
   informa de que no hay nada. */
.question-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.9rem;
  padding: 3rem 1.6rem 3.2rem;
  border-radius: 26px;
  border: 1px dashed rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.025);
  text-align: center;
}

.question-empty h3 {
  font-family: "Baloo 2", cursive;
  font-size: clamp(1.3rem, 3vw, 1.7rem);
  line-height: 1.15;
}

.question-empty p {
  max-width: 30rem;
  color: var(--engine-muted);
  line-height: 1.65;
}

/* Tres piezas flotando con desfase. Solo transform, y el recorrido es
   corto a propósito: tiene que sentirse vivo, no distraer de la tarea. */
.question-empty-art {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-bottom: 0.2rem;
  font-size: 2rem;
}

.qe-piece {
  display: inline-block;
  animation: qeFlota 3.4s ease-in-out infinite;
}

.qe-piece-a { animation-delay: 0s;    opacity: 0.9; }
.qe-piece-b { animation-delay: 0.35s; font-size: 2.6rem; }
.qe-piece-c { animation-delay: 0.7s;  opacity: 0.9; }

@keyframes qeFlota {
  0%, 100% { transform: translateY(0) rotate(-4deg); }
  50%      { transform: translateY(-8px) rotate(4deg); }
}

/* ── Acuse de guardado ─────────────────────────────────────────────
   La marca se DIBUJA: el trazo entra de un extremo al otro. Un icono
   que aparece de golpe se lee como un dato más; uno que se dibuja se
   siente como una respuesta a lo que acabas de hacer. */
.inline-status.is-success {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

.ok-check {
  flex-shrink: 0;
  width: 1.15rem;
  height: 1.15rem;
  fill: none;
  stroke: #7ef0c8;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ok-check circle {
  stroke-dasharray: 64;
  stroke-dashoffset: 64;
  opacity: 0.5;
  animation: okTrazo 0.45s ease-out forwards;
}

.ok-check path {
  stroke-dasharray: 20;
  stroke-dashoffset: 20;
  animation: okTrazo 0.32s ease-out 0.28s forwards;
}

@keyframes okTrazo {
  to { stroke-dashoffset: 0; }
}

/* El borde del editor da un pulso verde al guardar: así la confirmación
   se ve aunque estés mirando la última pregunta y no la barra de arriba. */
.editor-form.is-guardado {
  animation: pulsoGuardado 0.9s ease-out;
}

@keyframes pulsoGuardado {
  0%   { box-shadow: 0 0 0 0 rgba(126, 240, 200, 0.45); }
  100% { box-shadow: 0 0 0 14px rgba(126, 240, 200, 0); }
}

/* ── Barra de acciones: la principal manda ── */
.editor-toolbar {
  gap: 0.6rem;
  padding-top: 0.3rem;
}

.editor-toolbar .primary-btn {
  margin-left: auto;   /* publicar se separa del resto: no es "una más" */
}

@media (max-width: 640px) {
  .editor-toolbar .primary-btn { margin-left: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .question-card,
  .question-del,
  .question-del-lid,
  .question-del-can,
  .field input,
  .field textarea,
  .field select { transition: none; }

  .question-card:hover { transform: none; }
  .question-del:hover .question-del-lid { transform: none; }

  .question-card.is-nueva,
  .question-card.is-yendose,
  .qe-piece,
  .editor-form.is-guardado { animation: none; }

  .ok-check circle,
  .ok-check path { animation: none; stroke-dashoffset: 0; }
}

/* ══════════════════════════════════════════════════════════════════
   EDITOR DE PREGUNTAS — tarjetas plegables
   ------------------------------------------------------------------
   Sustituye a .question-card. Lo que cambia y por qué:

   · Plegadas por defecto. Con diez preguntas abiertas había que
     recorrer más de ochenta campos para llegar a una; ahora se ve el
     enunciado y el estado, y se abre la que se toca.
   · La correcta se marca en la propia opción. El desplegable de antes
     obligaba a traducir número → texto, que es exactamente donde se
     cuelan los errores con opciones parecidas.
   · Un punto de color dice si la pregunta está lista sin abrirla.
   ══════════════════════════════════════════════════════════════════ */

.editor-seccion {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  margin-top: 1.6rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--engine-line);
}

.editor-seccion-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.editor-seccion-tit {
  margin: 0;
  font-size: 1.05rem;
  letter-spacing: 0.02em;
  color: var(--engine-text);
}

/* ── Barra de avance ──────────────────────────────────────────────
   El termómetro de "cuánto me queda". Es lo que hace que apetezca
   completar la que falta en vez de dejarlo a medias. */
.q-progreso {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.q-progreso-barra {
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
}

.q-progreso-relleno {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: var(--engine-grad);
  transition: width 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

.q-progreso-txt {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--engine-muted);
}

.q-progreso.is-completo .q-progreso-txt { color: #7ee7a8; }

/* ── Tarjeta ── */
.q-card {
  border: 1px solid var(--engine-line);
  border-radius: 16px;
  background: var(--engine-panel-soft);
  overflow: hidden;
  transition: border-color 0.2s ease, background 0.2s ease;
}

.q-card + .q-card { margin-top: 0.6rem; }
.q-card:hover { border-color: rgba(255, 255, 255, 0.26); }
.q-card.is-abierta {
  border-color: rgba(169, 106, 231, 0.5);
  background: rgba(255, 255, 255, 0.06);
}

/* ── Cabecera plegable ── */
.q-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  padding: 0.75rem 0.9rem;
  cursor: pointer;
  user-select: none;
}

.q-head:focus-visible {
  outline: 2px solid var(--engine-cyan);
  outline-offset: -2px;
}

.q-num {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.08);
  font-weight: 800;
  font-size: 0.82rem;
  color: var(--engine-muted);
}

.q-card.is-abierta .q-num {
  background: var(--engine-grad);
  color: #16031f;
}

.q-resumen {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.12rem;
}

.q-resumen-txt {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--engine-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.q-resumen-meta {
  font-size: 0.73rem;
  color: var(--engine-muted);
  opacity: 0.8;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Estado: se lee de un vistazo si la pregunta está lista. No es solo
   color — lleva un signo dentro, porque el color por sí solo no lo
   distingue todo el mundo. */
.q-estado {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 1.4rem;
  height: 1.4rem;
  border-radius: 50%;
  font-size: 0.75rem;
  font-weight: 900;
  background: rgba(255, 176, 71, 0.16);
  border: 1px solid rgba(255, 176, 71, 0.5);
  color: #ffc266;
}

.q-card.is-lista .q-estado {
  background: rgba(126, 231, 168, 0.16);
  border-color: rgba(126, 231, 168, 0.5);
  color: #7ee7a8;
}

.q-chevron {
  flex-shrink: 0;
  color: var(--engine-muted);
  transition: transform 0.24s ease;
}

.q-card.is-abierta .q-chevron { transform: rotate(180deg); }

/* ── Cuerpo ──────────────────────────────────────────────────────
   Se oculta con display:none y no con una altura animada: animar la
   altura de un bloque con textareas obliga al navegador a recalcular
   la maquetación en cada fotograma, que es justo lo que se sentía
   pesado con muchas preguntas. */
.q-body {
  display: none;
  flex-direction: column;
  gap: 0.85rem;
  padding: 0.2rem 0.9rem 0.95rem;
}

.q-card.is-abierta .q-body { display: flex; }

/* ── Opciones con la correcta marcable ── */
.q-opciones-label {
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  flex-wrap: wrap;
}

.q-opciones-label small {
  font-weight: 600;
  opacity: 0.7;
  text-transform: none;
  letter-spacing: 0;
}

.q-opciones {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}

.q-opcion {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.3rem 0.45rem 0.3rem 0.3rem;
  border-radius: 12px;
  border: 1px solid transparent;
  transition: border-color 0.18s ease, background 0.18s ease;
}

.q-opcion.is-correcta {
  border-color: rgba(126, 231, 168, 0.45);
  background: rgba(126, 231, 168, 0.08);
}

.q-opcion input[type="text"] {
  flex: 1;
  min-width: 0;
}

/* El círculo de marcar. Vacío por defecto, relleno cuando es la buena. */
.q-marcar {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 1.7rem;
  height: 1.7rem;
  padding: 0;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.24);
  background: transparent;
  cursor: pointer;
  transition: border-color 0.18s ease, background 0.18s ease, transform 0.18s ease;
}

.q-marcar:hover { border-color: rgba(126, 231, 168, 0.7); transform: scale(1.1); }

.q-marcar:focus-visible {
  outline: 2px solid var(--engine-cyan);
  outline-offset: 2px;
}

.q-marcar-ico {
  font-size: 0.8rem;
  font-weight: 900;
  color: #06120b;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.q-opcion.is-correcta .q-marcar {
  border-color: #7ee7a8;
  background: #7ee7a8;
}

.q-opcion.is-correcta .q-marcar-ico { opacity: 1; }

@keyframes qMarcarPop {
  0%   { transform: scale(0.7); }
  55%  { transform: scale(1.25); }
  100% { transform: scale(1); }
}

.q-marcar.is-pop { animation: qMarcarPop 0.34s cubic-bezier(0.34, 1.56, 0.64, 1); }

/* ── Media, plegada mientras no se use ── */
.q-media {
  border: 1px solid var(--engine-line);
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.16);
}

.q-media > summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.75rem;
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--engine-muted);
  list-style: none;
}

.q-media > summary::-webkit-details-marker { display: none; }
.q-media > summary small { margin-left: auto; opacity: 0.75; font-weight: 600; }
.q-media[open] > summary { border-bottom: 1px solid var(--engine-line); }

.q-media-body {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  padding: 0.75rem;
}

/* ── Acciones de la pregunta ── */
.q-acciones {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
  flex-wrap: wrap;
}

.q-acciones .ghost-btn { font-size: 0.78rem; padding: 0.4rem 0.75rem; }
.q-del:hover { border-color: rgba(255, 107, 107, 0.6); color: #ff8f8f; }

/* ── Entrada y salida: reusan los keyframes de .question-card ── */
.q-card.is-yendose {
  animation: preguntaSale 0.26s ease-in forwards;
  pointer-events: none;
}

.q-card.is-nueva {
  animation: preguntaEntra 0.42s cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* ── Barra final: publicar manda ── */
.editor-toolbar-final { align-items: center; }
.editor-toolbar-sep { flex: 1; }
.btn-publicar { font-size: 0.95rem; padding: 0.7rem 1.5rem; }

/* ── Lista de lo que falta para publicar ── */
.engine-problemas ul {
  margin: 0.4rem 0 0;
  padding-left: 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.engine-problemas-tit { margin: 0; font-weight: 800; }

.engine-problema-link {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.engine-problema-link:hover { color: var(--engine-cyan); }

@media (max-width: 620px) {
  .q-head { padding: 0.65rem 0.7rem; gap: 0.55rem; }
  .q-body { padding: 0.2rem 0.7rem 0.8rem; }
  .q-resumen-meta { display: none; }   /* en móvil manda el enunciado */
  .editor-seccion-top { gap: 0.6rem; }
  .btn-anadir { width: 100%; }

  /* ── Blancos de toque cómodos ──
     El círculo de "esta es la correcta" medía 27px, y es el botón que más
     se pulsa de todo el editor: una vez por opción y por pregunta. Con el
     pulgar, 27px se falla y se acaba marcando la opción de al lado —el
     peor error posible aquí, porque deja el quiz con la respuesta mal sin
     avisar de nada. 2.4rem son ~38px, el mínimo con el que un dedo no
     tiene que apuntar. En escritorio se queda como estaba: el ratón es
     preciso y el círculo grande desequilibraría la fila. */
  .q-marcar { width: 2.4rem; height: 2.4rem; }
  .back-link { display: inline-block; padding: 0.45rem 0; min-height: 38px; }
}

@media (prefers-reduced-motion: reduce) {
  .q-card, .q-chevron, .q-marcar, .q-progreso-relleno { transition: none; }
  .q-card.is-nueva, .q-card.is-yendose, .q-marcar.is-pop { animation: none; }
  .q-marcar:hover { transform: none; }
}


/* ════════════════════════════════════════════════════════════════
   ZONAS DEL FORMULARIO (ficha · reglas · preguntas)
   ----------------------------------------------------------------
   El editor era una única columna de campos sin jerarquía: título,
   categoría, vidas y tiempo compartían fila y peso visual, y debajo
   caían opciones sueltas separadas solo por líneas finas. Quien entra
   por primera vez no tiene forma de saber qué es imprescindible y qué
   es decoración.

   Las zonas lo dicen sin explicarlo: un número, un nombre corto y una
   línea de para qué sirve. Es el mismo formulario —ni un campo menos—
   leído como tres decisiones seguidas en vez de como quince huecos.
   ════════════════════════════════════════════════════════════════ */
.editor-zona {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  padding: 1.15rem 1.15rem 1.25rem;
  border: 1px solid var(--engine-line);
  border-radius: 18px;
  background: var(--engine-panel-soft);
}

.editor-zona-tit {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0;
  font-size: 1rem;
  letter-spacing: 0.02em;
  color: var(--engine-text);
}

.editor-zona-num {
  display: inline-grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--engine-bg);
  background: var(--engine-cyan);
}

.editor-zona-sub {
  margin: -0.55rem 0 0;
  font-size: 0.82rem;
  color: var(--engine-muted);
}

/* Dos columnas y no cuatro: cuatro campos en fila dejaban las etiquetas
   partidas en dos renglones ("Tiempo por pregunta / (segundos)") y
   convertían el título del quiz en una casilla estrecha del mismo
   tamaño que "vidas". */
.editor-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

@media (max-width: 620px) {
  .editor-grid-2 { grid-template-columns: 1fr; }
  .editor-zona { padding: 1rem 0.9rem 1.1rem; }
}

/* La primera zona ya viene separada por el rótulo, así que la línea de
   .field-check dentro de una zona sobra: se ve el borde de la zona. */
.editor-zona .field-check {
  margin-top: 0.2rem;
  padding-top: 1rem;
}

/* La cabecera de "Construye una actividad" convivía con la guía de
   pasos diciendo lo mismo dos veces y con el mismo peso. Se queda —el
   texto explica cosas que la guía no dice— pero en tamaño de apoyo. */
#editor-intro {
  padding: 0.85rem 1.1rem;
  gap: 0.5rem;
}
#editor-intro h2 { font-size: 1rem; }
#editor-intro p { font-size: 0.82rem; line-height: 1.5; }
#editor-intro .card-kicker { font-size: 0.62rem; }

/* ── Barra de publicar, siempre a mano ───────────────────────────
   Con veinte preguntas escritas, «Publicar» quedaba a un scroll largo
   del sitio donde estabas trabajando; y el atajo Ctrl+S solo guarda
   borrador. Ahora la barra se queda pegada al fondo de la ventana
   mientras el formulario siga en pantalla. */
.editor-toolbar-final {
  position: sticky;
  bottom: 0;
  z-index: 5;
  margin: 0 -1.2rem -1.2rem;
  padding: 0.9rem 1.2rem;
  border-top: 1px solid var(--engine-line);
  border-radius: 0 0 var(--engine-radius, 22px) var(--engine-radius, 22px);
  background: color-mix(in srgb, var(--engine-panel) 92%, transparent);
  backdrop-filter: blur(10px);
}

/* El semáforo del kit se cuela dentro de esta barra: que no se estire
   como un botón más. */
.editor-toolbar-final .bk-listo { flex: 0 0 auto; }

/* ════════════════════════════════════════════════════════════════
   DOS COSAS QUE EL TELÉFONO HACE POR SU CUENTA
   ----------------------------------------------------------------
   1. `text-size-adjust`. Sin esto, Safari en iOS AGRANDA el texto por
      su cuenta al girar el teléfono a horizontal —para "aprovechar" el
      ancho— y deja unos tamaños que no se parecen en nada a los que
      hay puestos. Es la razón de que la misma página se vea con otras
      proporciones según cómo tengas el móvil. Con 100% se le dice que
      respete lo que pone la hoja de estilos.

   2. La letra de los campos. Safari acerca la página cuando enfocas un
      campo cuya letra mide menos de 16px, y NO la aleja al salir: te
      quedas con la página ampliada y desplazada. 16px es el mínimo
      exacto que lo desactiva, y solo hace falta en pantallas de
      teléfono; en escritorio los tamaños compactos se quedan igual.

   Los interruptores (casilla, radio, deslizador, color) quedan fuera:
   no llevan texto que escribir y no disparan el zoom.
   ════════════════════════════════════════════════════════════════ */
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

@media (max-width: 780px) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]),
  textarea,
  select {
    font-size: 16px;
  }
}
