/* ════════════════════════════════════════════════════
   css/galaxial.css — Galaxial
   La interfaz completa: barra superior, riel de secciones,
   cajón de parámetros, HUD, modales y avisos.

   Regla del proyecto: el lienzo ocupa la ventana entera y TODO lo
   demás flota encima con `backdrop-filter`. Ningún panel es opaco
   del todo — la galaxia se sigue viendo detrás, que es el punto.
════════════════════════════════════════════════════ */

/* ═══ Lienzo ═══════════════════════════════════════════════════════ */

#lienzo {
  position: fixed; inset: 0; width: 100%; height: 100%;
  z-index: var(--z-lienzo);
  display: block; cursor: grab; touch-action: none;
  opacity: 0; transition: opacity 1.6s ease;
}
#lienzo.listo { opacity: 1; }
/* Cambiar de galaxia entera (plantilla, sorpresa, .json, galería) apaga el
   lienzo de una —sin transición: así no se alcanza a ver la cámara y la
   paleta nuevas encima de los puntos viejos— y lo devuelve con un fundido
   corto cuando la galaxia nueva ya está generada y dibujada. */
#lienzo.mudando  { opacity: 0; transition-duration: 0s; }
#lienzo.volviendo { transition-duration: .5s; }
#lienzo.arrastrando { cursor: grabbing; }
body.sin-seleccion { user-select: none; -webkit-user-select: none; }

/* Modo "presentación": todo el cromo se va y queda solo la galaxia. */
body.limpio .barra,
body.limpio .riel,
body.limpio .cajon,
body.limpio .hud,
body.limpio .pista { opacity: 0; pointer-events: none; }

/* ═══ Barra superior ═══════════════════════════════════════════════ */

.barra {
  /* Las env(safe-area-inset-*) valen 0 en escritorio; en un iPhone con
     viewport-fit=cover evitan que la barra quede bajo el notch. */
  position: fixed; top: 0; left: 0; right: 0; height: calc(var(--barra-h) + env(safe-area-inset-top, 0px));
  display: flex; align-items: center; gap: var(--fs-m);
  padding: env(safe-area-inset-top, 0px) max(10px, env(safe-area-inset-right, 0px)) 0 max(10px, env(safe-area-inset-left, 0px));
  z-index: var(--z-panel);
  background: color-mix(in srgb, var(--bg) 58%, transparent);
  border-bottom: 1px solid var(--border);
  /* Sin backdrop-filter: sobre un lienzo WebGL no todos los navegadores lo
     aplican (depende de cómo compongan por GPU). El desenfoque de lo que
     queda bajo la barra lo hace el motor — ver renderizar() en galaxia.js;
     el borde inferior tapa la costura entre la franja borrosa y la nítida. */
  transition: opacity var(--t-media) ease;
}

.marca {
  display: flex; align-items: center; gap: 6px; flex: none;
  font-family: var(--mono); font-size: var(--fs-ui-l); font-weight: 500;
  letter-spacing: .22em; text-transform: uppercase; color: var(--txt-bright);
}
/* El logotipo va incrustado (ver logoInline en index.php): las letras toman
   el color del texto y la capa `borde` el acento que sale de la galaxia. */
.marca .logo { display: block; height: 30px; width: auto; transition: color var(--t-rapida); }
@media (max-width: 520px) { .marca .logo { height: 26px; } }
.logo-borde { fill: var(--accent); }
/* Es un botón (abre "Acerca de"): mínimo 28 px de alto, por encima de los
   24 px que exige WCAG 2.5.8 para un objetivo táctil. */
.marca { min-height: 28px; padding: 4px 2px; cursor: pointer; }
.marca:hover .logo { color: var(--accent); }
.marca i {
  font-style: normal; font-size: var(--fs-ui-xs); letter-spacing: .1em;
  color: var(--accent);
}

.acciones { flex: none; margin-left: auto; display: flex; align-items: center; gap: 4px; }

/* Español / inglés, junto al nombre */
.idioma {
  flex: none; min-height: 24px; padding: 2px 6px;
  border: 1px solid var(--border2); border-radius: var(--r-chip); background: transparent;
  font-family: var(--mono); font-size: var(--fs-ui-s); letter-spacing: .12em; color: var(--txt-dim);
  transition: color var(--t-rapida), border-color var(--t-rapida);
}
.idioma:hover { color: var(--txt-bright); border-color: var(--accent); }

/* ═══ Botones ══════════════════════════════════════════════════════ */

.icono {
  width: 28px; height: 28px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border2); border-radius: var(--r-chip);
  background: var(--bg3); color: var(--txt-dim);
  transition: color var(--t-rapida), border-color var(--t-rapida), background var(--t-rapida);
}
.icono:hover { color: var(--txt-bright); border-color: var(--accent); }
.icono[aria-pressed="true"] { color: var(--accent); border-color: var(--accent); background: var(--bg4); }
.icono svg { width: 15px; height: 15px; display: block; }
.icono[hidden] { display: none; }   /* .icono pone inline-flex y le ganaría a [hidden] */
.icono[disabled] { opacity: .35; pointer-events: none; }

.boton {
  min-height: 28px;   /* con 10 px de letra y 5 px de relleno medía 22 px: bajo el mínimo de WCAG 2.5.8 */
  padding: 5px 12px; border: 1px solid var(--border2); border-radius: var(--r-chip);
  background: var(--bg3); color: var(--txt);
  font-family: var(--mono); font-size: var(--fs-ui-m); letter-spacing: .1em;
  text-transform: uppercase;
  transition: color var(--t-rapida), border-color var(--t-rapida), background var(--t-rapida);
}
.boton:hover { color: var(--txt-bright); border-color: var(--accent); }
.boton-fuerte { border-color: var(--accent); color: var(--accent); }
.boton-fuerte:hover { background: var(--accent); color: #001018; }
.boton[disabled] { opacity: .45; pointer-events: none; }

/* ═══ Riel de secciones ════════════════════════════════════════════ */

.riel {
  position: fixed; top: calc(var(--barra-h) + env(safe-area-inset-top, 0px)); bottom: 0; left: 0; width: var(--riel-w);
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 8px 0; z-index: var(--z-panel);
  /* 85 %: con GPU el navegador no aplica el backdrop-filter sobre el lienzo
     WebGL, y a 62 % el riel dejaba ver la galaxia nítida detrás. */
  background: color-mix(in srgb, var(--bg) 85%, transparent);
  border-right: 1px solid var(--border);
  backdrop-filter: blur(14px);
  transition: opacity var(--t-media) ease;
}
.riel-btn {
  position: relative; width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  border-left: 2px solid transparent; color: var(--txt-dim);
  transition: color var(--t-rapida);
}
.riel-btn svg { width: 17px; height: 17px; display: block; }
.riel-btn:hover { color: var(--txt-bright); }
.riel-btn[aria-pressed="true"] { color: var(--accent); border-left-color: var(--accent); }
/* Rótulo emergente — el riel es solo iconos, así que necesita nombre */
.riel-btn::after {
  content: attr(data-rotulo); position: absolute; left: calc(100% + 8px);
  padding: 3px 7px; border: 1px solid var(--border2); background: var(--bg2);
  font-family: var(--mono); font-size: var(--fs-ui-s); letter-spacing: .08em;
  text-transform: uppercase; color: var(--txt-bright); white-space: nowrap;
  opacity: 0; pointer-events: none; transition: opacity var(--t-rapida);
}
.riel-btn:hover::after, .riel-btn:focus-visible::after { opacity: 1; }

/* ═══ Cajón de parámetros ══════════════════════════════════════════ */

.cajon {
  position: fixed; top: calc(var(--barra-h) + env(safe-area-inset-top, 0px)); bottom: 0; left: var(--riel-w);
  width: var(--panel-w); display: flex; flex-direction: column;
  z-index: var(--z-panel);
  background: color-mix(in srgb, var(--bg) 85%, transparent);   /* ver .riel */
  border-right: 1px solid var(--border);
  backdrop-filter: blur(16px);
  transition: transform var(--t-media) ease, opacity var(--t-media) ease;
}
.cajon.cerrado { transform: translateX(calc(-100% - var(--riel-w))); opacity: 0; pointer-events: none; }

.cajon-cab {
  flex: none; display: flex; align-items: center; justify-content: space-between;
  gap: 8px; padding: 10px 10px 8px; border-bottom: 1px solid var(--border);
}
.cajon-cab h2 {
  font-family: var(--mono); font-size: var(--fs-ui-l); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--txt-bright);
}
.cajon-cuerpo { flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain; padding: 10px; }
.cajon-cuerpo::-webkit-scrollbar { width: 8px; }
.cajon-cuerpo::-webkit-scrollbar-thumb { background: var(--border2); }
.cajon-nota {
  font-size: var(--fs-s); line-height: 1.5; color: var(--dim);
  padding: 0 0 12px; border-bottom: 1px solid var(--border); margin-bottom: 12px;
}

/* ═══ Controles ════════════════════════════════════════════════════ */

.ctl { margin-bottom: 11px; }
.ctl-fila {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  margin-bottom: 3px;
}
.ctl-fila label {
  flex: 1 1 auto; min-width: 0;   /* un nombre largo se parte en dos líneas; el campo no se encoge */
  font-family: var(--mono); font-size: var(--fs-ui-m); letter-spacing: .04em;
  line-height: 1.3; color: var(--txt-dim);
}
/* 7.5em alcanza para "1500000" o "-0.00050" en Martian Mono, que es
   ancha. Sin las flechitas nativas, que se comían un tercio del campo:
   el valor se sigue cambiando escribiendo, con ↑↓ o con el deslizador. */
.ctl input[type="number"] {
  width: 7.5em; flex: none; padding: 2px 5px;
  font-variant-numeric: tabular-nums;
  -moz-appearance: textfield; appearance: textfield;
  border: 1px solid var(--border); border-radius: 0; background: var(--bg3);
  color: var(--accent); font-family: var(--mono); font-size: var(--fs-ui-m);
  text-align: right;
}
.ctl input[type="number"]:hover { border-color: var(--border2); }
.ctl input[type="number"]::-webkit-inner-spin-button,
.ctl input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

/* Deslizador: pista fina y pulgar cuadrado, sin el look nativo */
.ctl input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 14px; margin: 0; cursor: ew-resize;
  /* Muesca del valor de partida: una rayita de 1 px sobre la pista. El
     centro del pulgar (9 px de ancho) recorre de 4,5 px a 100 % - 4,5 px,
     así que la posición se calcula en ese mismo tramo. --muesca < 0: sin muesca. */
  --muesca: -1;
  --x-muesca: calc(4.5px + (100% - 9px) * var(--muesca));
  background: linear-gradient(90deg,
      transparent calc(var(--x-muesca) - 0.5px), var(--txt-dim) calc(var(--x-muesca) - 0.5px),
      var(--txt-dim) calc(var(--x-muesca) + 0.5px), transparent calc(var(--x-muesca) + 0.5px))
    center / 100% 9px no-repeat;
}
/* Control distinto de su valor de partida: un punto de acento antes del nombre */
.ctl.modificado .ctl-fila label::before {
  content: ''; display: inline-block; width: 5px; height: 5px; margin: 0 6px 1px 0;
  border-radius: var(--r-circulo); background: var(--accent); vertical-align: middle;
}
:is(.ctl, .linea) input[type="range"]::-webkit-slider-runnable-track { height: 2px; background: var(--border2); }
:is(.ctl, .linea) input[type="range"]::-moz-range-track { height: 2px; background: var(--border2); }
:is(.ctl, .linea) input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 9px; height: 13px; margin-top: -5.5px;
  background: var(--accent); border: none; border-radius: 1px;
}
:is(.ctl, .linea) input[type="range"]::-moz-range-thumb {
  width: 9px; height: 13px; background: var(--accent); border: none; border-radius: 1px;
}
:is(.ctl, .linea) input[type="range"]:hover::-webkit-slider-thumb { background: #fff; }
:is(.ctl, .linea) input[type="range"]:hover::-moz-range-thumb { background: #fff; }

/* Interruptores */
.ctl-sw { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 9px; }
.ctl-sw span {
  font-family: var(--mono); font-size: var(--fs-ui-m); letter-spacing: .04em; color: var(--txt-dim);
}
.sw {
  flex: none; width: 32px; height: 16px; padding: 2px;
  border: 1px solid var(--border2); border-radius: var(--r-pildora);
  background: var(--bg3); transition: border-color var(--t-rapida);
}
.sw i { display: block; width: 10px; height: 10px; border-radius: var(--r-circulo);
        background: var(--txt-dim); transition: transform var(--t-rapida), background var(--t-rapida); }
.sw[aria-pressed="true"] { border-color: var(--accent); }
.sw[aria-pressed="true"] i { background: var(--accent); transform: translateX(16px); }

/* Colores */
.paleta { display: grid; grid-template-columns: repeat(5, 1fr); gap: 5px; margin-bottom: 12px; }
.muestra {
  display: block; height: 34px; padding: 0;
  border: 1px solid var(--border2); cursor: pointer;
  transition: border-color var(--t-rapida);
}
.muestra:hover { border-color: var(--accent); }
.muestra-chica { width: 46px; height: 20px; flex: none; }
.rotulo {
  display: block; margin: 14px 0 6px;
  font-family: var(--mono); font-size: var(--fs-ui-s); letter-spacing: .16em;
  text-transform: uppercase; color: var(--dim);
}
.rotulo.primero { margin-top: 0; }

/* Botones anchos dentro del cajón */
.cajon-acciones { display: grid; grid-template-columns: 1fr 1fr; gap: 5px; margin-top: 4px; }
.cajon-acciones .boton { width: 100%; text-align: center; }
.cajon-acciones .ancho { grid-column: 1 / -1; }

/* Encabezado de bloque dentro de una sección (Mejoras / Rendimiento) */
.grupo {
  display: flex; align-items: center; gap: 8px; margin: 22px 0 10px;
  font-family: var(--mono); font-size: var(--fs-ui-l); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--txt-bright);
}
.grupo::after { content: ''; flex: 1; height: 1px; background: var(--border2); }
.grupo.primero { margin-top: 0; }

/* Controles que dependen de un interruptor apagado: se ven, se pueden
   ajustar de antemano, pero se leen como "en espera". */
[data-inactivo] { opacity: .4; transition: opacity var(--t-rapida); }
[data-dep] { transition: opacity var(--t-rapida); }

/* ═══ Costo de rendimiento ═════════════════════════════════════════
   Un rombo ámbar pequeño y tenue junto al nombre del control. La idea
   es que se note al buscarlo, no que grite. */
.costo {
  display: inline-block; width: 5px; height: 5px; margin: 0 0 1px 6px;
  vertical-align: middle; background: var(--color-aviso); opacity: .7;
  transform: rotate(45deg);
}
.aviso-costo {
  margin: 0 0 12px; padding: 7px 9px;
  border-left: 1px solid color-mix(in srgb, var(--color-aviso) 55%, transparent);
  background: color-mix(in srgb, var(--color-aviso) 4%, transparent);
  font-size: var(--fs-ui-xl); line-height: 1.55; color: var(--dim);
}
.aviso-costo .costo { margin: 0 2px 1px; }
.ctl-nota { margin: -2px 0 12px; font-size: var(--fs-ui-xl); line-height: 1.55; color: var(--dim); }

/* ═══ Plantillas ═══════════════════════════════════════════════════ */

.plantillas { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.plantilla[hidden] { display: none; }   /* .plantilla pone display: flex y le ganaría a [hidden] */

/* Filtros por tipo */
.filtros { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 10px; }
.filtro {
  min-height: 26px; padding: 4px 8px;
  border: 1px solid var(--border2); border-radius: var(--r-chip); background: var(--bg3);
  font-family: var(--mono); font-size: var(--fs-ui-s); letter-spacing: .06em;
  text-transform: uppercase; color: var(--txt-dim);
  transition: color var(--t-rapida), border-color var(--t-rapida);
}
.filtro:hover { color: var(--txt-bright); border-color: var(--accent); }
.filtro[aria-pressed="true"] { color: var(--accent); border-color: var(--accent); background: var(--bg4); }

/* Sorpréndeme: la primera tarjeta, con un destello en vez de miniatura */
.sorprendeme .plantilla-img {
  display: flex; align-items: center; justify-content: center; color: var(--accent);
  background: radial-gradient(ellipse 55% 50% at 50% 50%, color-mix(in srgb, var(--accent) 26%, transparent), transparent 72%), var(--bg);
}
.sorprendeme .plantilla-img svg { width: 38px; height: 38px; transition: transform var(--t-media) ease; }
.sorprendeme:hover .plantilla-img svg { transform: rotate(18deg) scale(1.08); }
.plantilla {
  display: flex; flex-direction: column; overflow: hidden; text-align: left;
  border: 1px solid var(--border2); background: var(--bg3);
  transition: border-color var(--t-rapida);
}
.plantilla:hover { border-color: var(--accent); }
.plantilla[aria-pressed="true"] { border-color: var(--accent); }
.plantilla-img {
  position: relative; display: block; aspect-ratio: 280 / 176; overflow: hidden;
  background: var(--bg);
}
/* Mientras la miniatura se genera: un barrido suave en vez de un hueco */
.plantilla-img.cargando {
  background: linear-gradient(100deg, var(--bg2) 30%, var(--bg4) 50%, var(--bg2) 70%);
  background-size: 240% 100%;
  animation: barrido 1.3s linear infinite;
}
@keyframes barrido { from { background-position: 120% 0; } to { background-position: -120% 0; } }
.plantilla-img img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity var(--t-lenta) ease, transform var(--t-lenta) ease;
}
.plantilla-img img.lista { opacity: 1; }
.plantilla:hover .plantilla-img img.lista { transform: scale(1.06); }
.plantilla-nombre {
  padding: 6px 8px 4px; font-family: var(--mono); font-size: var(--fs-ui-s);
  letter-spacing: .08em; text-transform: uppercase; color: var(--txt-dim);
}
.plantilla[aria-pressed="true"] .plantilla-nombre { color: var(--accent); }
.plantilla-nombre + .plantilla-tipo { margin-top: -4px; }
.plantilla-tipo {
  padding: 0 8px 7px; font-size: var(--fs-ui-l); line-height: 1.3; color: var(--dim);
}

/* ═══ Paletas con vista previa ═════════════════════════════════════ */

.paletas { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.paleta-op {
  height: 52px; padding: 0; border: 1px solid var(--border2);
  transition: border-color var(--t-rapida), box-shadow var(--t-rapida);
}
.paleta-op:hover { border-color: var(--txt-dim); }
.paleta-op[aria-pressed="true"] { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }

/* ═══ HUD ══════════════════════════════════════════════════════════
   Arriba a la izquierda, bajo la barra y dentro del espacio libre
   (app.js pone --libre-arr y --libre-izq). Se pliega hacia su esquina
   y deja solo el botón para volver a desplegarlo. */

.hud {
  position: fixed; left: calc(var(--libre-izq, var(--riel-w)) + 10px);
  top: calc(var(--libre-arr, var(--barra-h)) + 10px);
  display: flex; align-items: flex-start; gap: 8px; z-index: var(--z-hud);
  padding: 6px 6px 6px 10px; border: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg) 55%, transparent);
  backdrop-filter: blur(10px); pointer-events: none;
  transition: opacity var(--t-media) ease;
}
.hud-datos { display: flex; gap: 14px; flex-wrap: wrap; }
.hud-datos > div { display: flex; flex-direction: column; gap: 1px; }
.hud.plegado { padding: 3px; }
.hud.plegado .hud-datos { display: none; }
.hud .k {
  font-family: var(--mono); font-size: var(--fs-ui-m); letter-spacing: .12em;   /* 10 px: a 8 costaba leerlos */
  text-transform: uppercase; color: var(--dim);
}
.hud .v {
  font-family: var(--mono); font-size: var(--fs-ui-xl); color: var(--txt-bright);
  font-variant-numeric: tabular-nums;   /* cifras de ancho fijo: el número no baila al cambiar */
}
.hud .v.alerta { color: var(--color-aviso); }
.hud .v.pausado { color: var(--dim); }   /* "pausa" (sin foco) o "quieta" (nada se mueve) */

/* ─── Plegar / desplegar ─────────────────────────────────────────────
   El mismo botón para los dos, con el mismo dibujo: una comilla angular.
   Apunta hacia donde va la barra al plegarse (el HUD hacia la izquierda,
   la línea de tiempo hacia la derecha) y se voltea al plegarse, para
   apuntar hacia donde va a salir. Un solo SVG y un scaleX, no cuatro
   iconos que habría que mantener de a cuatro. */
.plegar {
  flex: none; display: grid; place-items: center; width: 18px; height: 18px;
  pointer-events: auto; color: var(--dim);
  transition: color var(--t-rapida);
}
.plegar:hover { color: var(--txt-bright); }
.plegar svg { width: 12px; height: 12px; transition: transform var(--t-media) ease; }
.hud.plegado .plegar svg,
.linea .plegar svg { transform: scaleX(-1); }
.linea.plegado .plegar svg { transform: scaleX(1); }
/* En modo presentación las dos barras están invisibles: su botón no puede
   seguir recibiendo clics (ni foco con Tab) desde detrás de la nada. */
body.limpio .plegar { pointer-events: none; }
/* Con el cajón abierto el HUD no sube de z-index (quedaría encima del
   panel): se corre con el espacio libre, que app.js mide en --libre-izq. */

.pista {
  position: fixed; right: calc(var(--libre-der, 0px) + 12px); bottom: 54px; z-index: var(--z-hud);
  font-family: var(--mono); font-size: var(--fs-ui-s); letter-spacing: .1em;
  text-transform: uppercase; color: var(--dim); text-align: right;
  pointer-events: none; transition: opacity var(--t-lenta) ease;
}
.pista.ido { opacity: 0; }
.pista kbd {
  font-family: inherit; border: 1px solid var(--border2); padding: 0 3px; color: var(--txt-dim);
}

/* ═══ Portada de carga ═════════════════════════════════════════════
   Lo primero que se ve, con el logotipo grande. Se va cuando la primera
   galaxia ya está generada y nunca antes de dos segundos; quien la quita
   es app.js, agregándole la clase .ido. */

.precarga {
  position: fixed; inset: 0; z-index: var(--z-precarga);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 24px;
  background: var(--bg);
  /* Red de seguridad: si app.js nunca llega —un módulo que no carga, un
     bloqueador, un navegador sin módulos— la portada se va sola a los 10 s
     en vez de dejar la página secuestrada detrás del logo. */
  animation: precarga-rescate .6s ease 10s forwards;
}
.precarga .logo-grande {
  /* El ancho está DUPLICADO a propósito en un <style> crítico, inline, al
     principio de <head> en index.php: ese tamaño tiene que valer desde el
     primer byte pintado, no desde que este archivo externo termine de
     cargar. Si se cambia acá, cambiar también allá. */
  width: min(420px, 62vw); height: auto; color: var(--txt-bright);
  animation: precarga-entrar .9s ease both;
}
.precarga-barra { width: min(420px, 62vw); height: 2px; background: var(--border); overflow: hidden; }
.precarga-barra i { display: block; width: 38%; height: 100%; background: var(--accent);
                    animation: precarga-correr 1.4s ease-in-out infinite; }
.precarga.ido {
  opacity: 0; visibility: hidden; animation: none;
  transition: opacity var(--t-lenta) ease, visibility 0s linear var(--t-lenta);
}
@keyframes precarga-entrar { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes precarga-correr { from { transform: translateX(-110%); } to { transform: translateX(370%); } }
@keyframes precarga-rescate { to { opacity: 0; visibility: hidden; } }
@media (prefers-reduced-motion: reduce) {
  .precarga .logo-grande { animation: none; }
  .precarga-barra i { width: 100%; animation: none; }
}

/* ═══ Modales ══════════════════════════════════════════════════════ */

.velo {
  position: fixed; inset: 0; z-index: var(--z-overlay);
  display: flex; align-items: center; justify-content: center; padding: 16px;
  background: color-mix(in srgb, #000 70%, transparent);
  backdrop-filter: blur(6px);
}
.velo[hidden] { display: none; }

.modal {
  width: min(620px, 100%); max-height: min(86vh, 760px); overflow-y: auto;
  scrollbar-width: thin; scrollbar-color: var(--border2) transparent;
  overscroll-behavior: contain; z-index: var(--z-modal);
  background: var(--bg2); border: 1px solid var(--border2);
}
.modal-cab {
  position: sticky; top: 0; display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 12px 14px; background: var(--bg2); border-bottom: 1px solid var(--border);
}
.modal-cab h2 {
  font-family: var(--mono); font-size: var(--fs-ui-xl); font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase; color: var(--txt-bright);
}
.modal-cuerpo { padding: 14px; }
:is(.modal, .hoja) p { font-size: var(--fs-s); line-height: 1.6; color: var(--txt-dim); }
:is(.modal, .hoja) p + p { margin-top: 8px; }
:is(.modal, .hoja) code {
  font-family: var(--mono); font-size: .92em; color: var(--accent);
  background: var(--bg3); padding: 1px 4px;
}

/* Elegir formato de exportación */
.formatos { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 6px; margin-bottom: 16px; }
.formato {
  display: flex; flex-direction: column; gap: 4px; align-items: flex-start;
  padding: 11px; border: 1px solid var(--border2); background: var(--bg3);
  text-align: left; transition: border-color var(--t-rapida), background var(--t-rapida);
}
.formato:hover { border-color: var(--accent); }
.formato[aria-pressed="true"] { border-color: var(--accent); background: var(--bg4); }
.formato b {
  font-family: var(--mono); font-size: var(--fs-ui-l); font-weight: 500;
  letter-spacing: .1em; text-transform: uppercase; color: var(--txt-bright);
}
.formato[aria-pressed="true"] b { color: var(--accent); }
.formato span { font-size: var(--fs-ui-xl); line-height: 1.45; color: var(--dim); }

.opciones { border-top: 1px solid var(--border); padding-top: 14px; }
.opcion { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.opcion > label {
  font-family: var(--mono); font-size: var(--fs-ui-m); letter-spacing: .06em;
  text-transform: uppercase; color: var(--txt-dim);
}
.opcion select, .opcion input[type="number"] {
  padding: 4px 6px; border: 1px solid var(--border2); border-radius: 0;
  background: var(--bg3); color: var(--txt-bright);
  font-family: var(--mono); font-size: var(--fs-ui-m);
}
.opcion select { min-width: 10em; }
.opcion[hidden] { display: none; }

/* Una opción que no cabe en una línea: el rótulo arriba y el control debajo */
.opcion-bloque { display: block; }
.opcion-bloque > label { display: block; margin-bottom: 7px; }

/* ─── Proporción de la imagen ─────────────────────────────────────────
   Cada ficha lleva un rectángulo con su misma forma: la lista va de la más
   apaisada a la más vertical, y el dibujo se lee de un vistazo mucho antes
   que el número. El rectángulo se dimensiona desde app.js (los dos lados
   salen de la proporción, así que escribirlos acá sería una segunda lista). */
.proporciones {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(58px, 1fr)); gap: 4px;
}
.prop {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 6px 2px 5px; border: 1px solid var(--border); border-radius: 0;
  background: var(--bg3); color: var(--txt-dim); cursor: pointer;
  transition: border-color var(--t-rapida), color var(--t-rapida);
}
.prop:hover { border-color: var(--border2); color: var(--txt-bright); }
.prop[aria-checked="true"] { border-color: var(--accent); color: var(--accent); }
/* La caja es cuadrada y siempre del mismo tamaño: lo que cambia entre una
   ficha y otra es el rectángulo de adentro, que es justamente el dato. */
.prop-caja { display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; }
.prop-caja i { display: block; border: 1px solid currentColor; background: color-mix(in srgb, currentColor 16%, transparent); }
.prop-rotulo {
  font-family: var(--mono); font-size: var(--fs-ui-s); letter-spacing: .02em;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

.salida {
  width: 100%; height: 9rem; margin-top: 10px; padding: 8px;
  border: 1px solid var(--border); border-radius: 0;
  background: #000; color: var(--txt-dim);
  font-family: var(--mono); font-size: var(--fs-ui-m); line-height: 1.5; resize: vertical;
}
.salida[hidden] { display: none; }
.salida.corta { height: 5.2rem; word-break: break-all; }   /* el enlace: una sola "palabra" larguísima */

.atajos { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; align-items: baseline; }
.atajos kbd {
  font-family: var(--mono); font-size: var(--fs-ui-m); color: var(--accent);
  border: 1px solid var(--border2); padding: 2px 6px; white-space: nowrap;
}
.atajos span { font-size: var(--fs-s); color: var(--txt-dim); }

/* Acerca de: más ancho que los otros modales, porque lleva fórmulas. */
.modal-acerca { width: min(680px, 100%); }
.modal .acerca-entrada { font-size: var(--fs-base); color: var(--txt); }
.modal h3 {
  margin: 16px 0 4px;
  font-family: var(--mono); font-size: var(--fs-ui-l); font-weight: 500;
  letter-spacing: .08em; color: var(--txt-bright);
}
.modal h3 + p { margin-top: 0; }
.modal a { color: var(--accent); text-underline-offset: 2px; }
/* .modal .formula y no .formula a secas: `.modal code` es más específico
   y le imponía su relleno mínimo y su color de acento. */
.modal .formula {
  display: block; margin: 8px 0 4px; padding: 7px 10px;
  overflow-x: auto; white-space: nowrap;   /* en angosto se desplaza la fórmula, no la página */
  border-left: 2px solid var(--accent); background: var(--bg3);
  font-family: var(--mono); font-size: var(--fs-ui-xl); line-height: 1.8; color: var(--txt-bright);
}
.modal .formula sub, .modal .formula sup { font-size: .72em; line-height: 0; }
.modal .formula-nota { margin-top: 2px; font-size: var(--fs-ui-xl); color: var(--dim); }

/* ═══ Selector de color ════════════════════════════════════════════
   Velo translúcido a pantalla completa: la galaxia se sigue viendo
   detrás, y como cada color que se prueba se aplica en el acto, se ve el
   efecto mientras se elige. La rueda la dibuja js/selector-color.js. */

.selector {
  position: fixed; inset: 0; z-index: var(--z-modal);
  display: flex; padding: 16px; overflow-y: auto;
  background: color-mix(in srgb, #000 38%, transparent);
}
.selector[hidden] { display: none; }
.selector-caja {
  /* margin: auto centra y, a diferencia de align-items: center, no corta
     el borde de arriba cuando la caja no cabe y hay que desplazarse. */
  margin: auto;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  width: min(94vw, 540px);
  animation: selector-entra var(--t-media) ease both;
}
@keyframes selector-entra {
  from { opacity: 0; transform: scale(.94); }
  to   { opacity: 1; transform: none; }
}

.selector-cab, .selector-pie {
  width: 100%; display: flex; align-items: center; gap: 10px; padding: 7px 10px;
  border: 1px solid var(--border2);
  /* Casi opacas: con más transparencia se mezclaban con el HUD de abajo. */
  background: color-mix(in srgb, var(--bg) 93%, transparent);
}
.selector-cab { justify-content: space-between; flex-wrap: wrap; }
.selector-cab h2 {
  font-family: var(--mono); font-size: var(--fs-ui-l); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--txt-bright);
}
.selector-pista {
  font-family: var(--mono); font-size: var(--fs-ui-s); letter-spacing: .06em; color: var(--dim);
}

.rueda {
  /* El alto descuenta cabecera, armonías y pie para que todo quepa sin desplazarse */
  display: block; width: max(220px, min(74vmin, 460px, calc(100dvh - 300px))); height: auto;
  filter: drop-shadow(0 0 22px rgba(0, 0, 0, .7));
  outline: none; touch-action: manipulation;
}
.rueda:focus-visible {
  /* Un contorno rectangular alrededor de una rueda se ve mal: el foco se
     marca con un halo de acento que sigue la silueta (drop-shadow respeta
     la forma, outline no). */
  outline: none;
  filter: drop-shadow(0 0 22px rgba(0, 0, 0, .7)) drop-shadow(0 0 1.5px var(--accent)) drop-shadow(0 0 5px var(--accent));
}
.rueda .seg { cursor: pointer; }
.rueda .marca-hover      { fill: none; stroke: rgba(255, 255, 255, .6); stroke-width: 1.5; pointer-events: none; }
.rueda .marca-sel-sombra { fill: none; stroke: #000; stroke-width: 6; pointer-events: none; }
.rueda .marca-sel        { fill: none; stroke: #fff; stroke-width: 2.5; pointer-events: none; }

.selector-pie { flex-wrap: wrap; }
.selector-par { display: flex; flex: none; border: 1px solid var(--border2); }
.selector-par i { display: block; width: 28px; height: 24px; }
.selector-hex {
  width: 7.5em; padding: 4px 6px; font-variant-numeric: tabular-nums;
  border: 1px solid var(--border2); border-radius: 0; background: var(--bg3);
  color: var(--accent); font-family: var(--mono); font-size: var(--fs-ui-xl); text-transform: lowercase;
}
.selector-hex.invalido { border-color: var(--color-error); color: var(--color-error); }
.selector-botones { margin-left: auto; display: flex; gap: 6px; }

/* Armonías y recientes */
.selector-extra {
  --col-rotulo: calc(var(--fs-ui-s) * 7.5);   /* en unidades del rótulo, no de la fila */
  width: 100%; display: flex; flex-direction: column; gap: 6px; padding: 7px 10px;
  border: 1px solid var(--border2);
  background: color-mix(in srgb, var(--bg) 93%, transparent);
}
/* Rótulo | chips | muestras: las muestras no se separan de su fila aunque
   los chips necesiten dos renglones. En angosto, las muestras bajan a un
   renglón propio (ver la media query de abajo). */
.selector-fila {
  display: grid; grid-template-columns: var(--col-rotulo) 1fr auto; align-items: center; gap: 6px 8px; min-height: 26px;
}
.selector-fila[hidden] { display: none; }
.selector-fila[data-fila="recientes"] > .selector-muestras { grid-column: 3; }
@media (max-width: 520px) {
  .selector-fila { grid-template-columns: var(--col-rotulo) 1fr; }
  .selector-fila > .selector-chips + .selector-muestras { grid-column: 1 / -1; }
  .selector-fila[data-fila="recientes"] > .selector-muestras { grid-column: 2; }
}
.selector-rotulo {
  width: var(--col-rotulo);
  font-family: var(--mono); font-size: var(--fs-ui-s); letter-spacing: .1em; text-transform: uppercase; color: var(--dim);
}
.selector-chips { display: flex; flex-wrap: wrap; gap: 3px; }
.selector-chip {
  padding: 3px 5px; border: 1px solid var(--border2); background: var(--bg3);
  font-family: var(--mono); font-size: var(--fs-ui-s); letter-spacing: .04em; color: var(--txt-dim);
  transition: color var(--t-rapida), border-color var(--t-rapida);
}
.selector-chip:hover { color: var(--txt-bright); border-color: var(--accent); }
.selector-chip[aria-pressed="true"] { color: var(--accent); border-color: var(--accent); }
.selector-muestras { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 4px; }
.selector-muestra { width: 24px; height: 24px; padding: 0; border: 1px solid var(--border2); }
.selector-muestra:hover { border-color: var(--txt-bright); }
.selector-muestra[aria-pressed="true"] { outline: 2px solid var(--txt-bright); outline-offset: 1px; }
.selector-nota { font-family: var(--mono); font-size: var(--fs-ui-s); color: var(--dim); }

/* Cuentagotas */
.selector-gotero {
  flex: none; display: flex; align-items: center; justify-content: center; width: 30px; height: 28px;
  border: 1px solid var(--border2); background: var(--bg3); color: var(--txt-dim);
  transition: color var(--t-rapida), border-color var(--t-rapida);
}
.selector-gotero[hidden] { display: none; }
.selector-gotero:hover, .selector-gotero[aria-pressed="true"] { color: var(--accent); border-color: var(--accent); }
.selector-gotero svg { width: 16px; height: 16px; }
.selector.muestreando { background: transparent; cursor: crosshair; }
.selector.muestreando .selector-caja { visibility: hidden; }
.selector-lupa {
  position: fixed; left: 0; top: 0; pointer-events: none;
  display: flex; align-items: center; gap: 6px; margin: 16px 0 0 16px; padding: 4px 8px 4px 4px;
  border: 1px solid var(--border2); background: color-mix(in srgb, var(--bg) 90%, transparent);
  font-family: var(--mono); font-size: var(--fs-ui-xl); font-variant-numeric: tabular-nums; color: var(--txt-bright);
}
.selector-lupa[hidden] { display: none; }
.selector-lupa i { display: block; width: 26px; height: 26px; border: 1px solid rgba(255, 255, 255, .55); }

/* Nota junto a una opción del modal de exportación (tamaño real en px) */
.opcion-nota { font-family: var(--mono); font-size: var(--fs-ui-s); color: var(--dim); font-variant-numeric: tabular-nums; }

/* Modo presentación: el único control visible. Aparece al mover el mouse
   o tocar la pantalla y se desvanece solo; sin él, en una pantalla táctil
   no había forma de volver (la tecla H no existe ahí). */
.salir-limpio {
  position: fixed; z-index: var(--z-panel);
  top: calc(10px + env(safe-area-inset-top, 0px)); right: calc(10px + env(safe-area-inset-right, 0px));
  width: 36px; height: 36px; opacity: 0; transition: opacity var(--t-media) ease;
}
.salir-limpio.despierto, .salir-limpio:focus-visible { opacity: 1; }

/* Sin WebGL 2 no hay galaxia: se explica en vez de dejar la pantalla negra. */
.sin-webgl {
  position: fixed; inset: 0; z-index: var(--z-modal);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.sin-webgl[hidden] { display: none; }
.sin-webgl p {
  max-width: 34rem; padding: 16px 18px; border: 1px solid var(--border2); background: var(--bg2);
  font-size: var(--fs-s); line-height: 1.6; color: var(--txt);
}
.sin-webgl b { color: var(--txt-bright); }

/* ═══ Avisos ═══════════════════════════════════════════════════════ */

.brindis {
  position: fixed; left: 50%; bottom: 104px; transform: translate(-50%, 12px);   /* encima de la línea de tiempo */
  z-index: var(--z-toast); padding: 8px 16px;
  border: 1px solid var(--accent); background: var(--bg2);
  backdrop-filter: blur(10px);
  font-family: var(--mono); font-size: var(--fs-ui-m); letter-spacing: .08em;
  text-transform: uppercase; color: var(--txt-bright);
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-media) ease, transform var(--t-media) ease;
}
.brindis.visible { opacity: 1; transform: translate(-50%, 0); }
.brindis.error { border-color: var(--color-error); color: var(--color-error); }

/* Barra de progreso de una exportación larga */
.progreso { height: 2px; background: var(--border); margin-top: 12px; }
.progreso i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .1s linear; }
.progreso[hidden] { display: none; }

/* ═══ Angosto ══════════════════════════════════════════════════════ */

@media (max-width: 760px) {
  :root { --riel-w: 0px; --panel-w: 100%; }

  .barra {
    height: auto; flex-wrap: wrap; gap: 8px;
    padding: calc(6px + env(safe-area-inset-top, 0px)) max(8px, env(safe-area-inset-right, 0px)) 6px max(8px, env(safe-area-inset-left, 0px));
  }
  /* Diez botones: en angosto ocupan su propia fila entera y se reparten. */
  .acciones { flex: 1 1 100%; margin-left: 0; justify-content: space-between; gap: 2px; }

  /* El riel pasa a ser una fila fija abajo y el cajón, una hoja inferior */
  .riel {
    top: auto; bottom: 0; left: 0; right: 0; width: auto; height: calc(44px + env(safe-area-inset-bottom, 0px));
    flex-direction: row; justify-content: space-around; gap: 0; padding: 0 4px env(safe-area-inset-bottom, 0px);
    border-right: none; border-top: 1px solid var(--border);
  }
  .riel-btn { border-left: none; border-bottom: 2px solid transparent; }
  .riel-btn[aria-pressed="true"] { border-left-color: transparent; border-bottom-color: var(--accent); }
  .riel-btn::after { left: 50%; bottom: calc(100% + 6px); transform: translateX(-50%); }

  .cajon {
    top: auto; left: 0; right: 0; bottom: calc(44px + env(safe-area-inset-bottom, 0px)); width: auto; height: min(52vh, 420px);
    border-right: none; border-top: 1px solid var(--border);
  }
  .cajon.cerrado { transform: translateY(100%); }

  .hud { left: 8px; top: calc(var(--libre-arr, var(--barra-h)) + 8px); gap: 8px; }
  .hud-datos { gap: 10px; }
  /* En angosto el cajón es una hoja inferior y no hay a dónde correr el
     HUD: mientras esté abierto, el HUD se va. */
  body.cajon-abierto .hud { left: 8px; opacity: 0; }
  body.cajon-abierto .hud .plegar { pointer-events: none; }
  .pista { display: none; }
  .brindis { bottom: calc(146px + env(safe-area-inset-bottom, 0px)); }
}

/* ═══ Panel de exportación ═════════════════════════════════════════
   A la derecha, del mismo material que el cajón. No es modal: la galaxia
   queda a la vista, centrada en lo que dejan libre los dos paneles. */

.hoja {
  position: fixed; top: calc(var(--barra-h) + env(safe-area-inset-top, 0px)); right: 0; bottom: 0;
  width: 340px; overflow-y: auto; overscroll-behavior: contain;
  z-index: var(--z-panel);
  background: color-mix(in srgb, var(--bg) 85%, transparent);   /* ver .riel */
  border-left: 1px solid var(--border);
  backdrop-filter: blur(16px);
  scrollbar-width: thin; scrollbar-color: var(--border2) transparent;
  transition: transform var(--t-media) ease, opacity var(--t-media) ease;
}
.hoja.cerrada { transform: translateX(100%); opacity: 0; pointer-events: none; }
.hoja .modal-cab { background: color-mix(in srgb, var(--bg2) 94%, transparent); }
.hoja .formatos { grid-template-columns: 1fr 1fr; }
.hoja .formato { padding: 9px; }
.hoja .formato span { font-size: var(--fs-ui-l); }
.hoja-nota { margin-top: 14px; }
.opcion-par { display: flex; align-items: center; gap: 8px; }
body.limpio .hoja { opacity: 0; pointer-events: none; }

/* El marco de la imagen: lo de afuera se oscurece, lo de adentro es lo que
   se exporta. La sombra gigante evita cuatro rectángulos para el velo. */
.marco { position: fixed; inset: 0; z-index: var(--z-hud); pointer-events: none; overflow: hidden; }
.marco[hidden] { display: none; }
.marco-ventana {
  --guia: color-mix(in srgb, #fff 26%, transparent);
  position: absolute; left: 0; top: 0; width: 0; height: 0;
  outline: 1px solid color-mix(in srgb, #fff 55%, transparent);
  box-shadow: 0 0 0 200vmax color-mix(in srgb, #000 58%, transparent);
  transition: left var(--t-media) ease, top var(--t-media) ease, width var(--t-media) ease, height var(--t-media) ease;
}
.marco[data-guias="tercios"] .marco-ventana {
  background:
    linear-gradient(to right, transparent calc(33.333% - .5px), var(--guia) 0, var(--guia) calc(33.333% + .5px), transparent 0,
                              transparent calc(66.667% - .5px), var(--guia) 0, var(--guia) calc(66.667% + .5px), transparent 0),
    linear-gradient(to bottom, transparent calc(33.333% - .5px), var(--guia) 0, var(--guia) calc(33.333% + .5px), transparent 0,
                               transparent calc(66.667% - .5px), var(--guia) 0, var(--guia) calc(66.667% + .5px), transparent 0);
}
.marco[data-guias="centro"] .marco-ventana {
  background:
    linear-gradient(to right, transparent calc(50% - .5px), var(--guia) 0, var(--guia) calc(50% + .5px), transparent 0),
    linear-gradient(to bottom, transparent calc(50% - .5px), var(--guia) 0, var(--guia) calc(50% + .5px), transparent 0);
}
.marco-medida {
  position: absolute; left: 0; top: calc(100% + 6px); white-space: nowrap;
  font-family: var(--mono); font-size: var(--fs-ui-s); letter-spacing: .06em;
  font-variant-numeric: tabular-nums; color: var(--txt-dim);
}

@media (max-width: 760px) {
  /* Una hoja inferior más, encima del riel; nunca abierta a la vez que el cajón. */
  .hoja {
    top: auto; left: 0; bottom: calc(44px + env(safe-area-inset-bottom, 0px)); width: auto; height: min(56vh, 460px);
    border-left: none; border-top: 1px solid var(--border);
  }
  .hoja.cerrada { transform: translateY(100%); }
  body.hoja-abierta .hud { opacity: 0; }
  body.hoja-abierta .hud .plegar { pointer-events: none; }
  .marco-medida { top: auto; bottom: calc(100% + 4px); }
}

/* ═══ Fondo de pantalla (?wallpaper) ═══════════════════════════════
   Solo la galaxia. !important porque varias de estas piezas se muestran
   y se esconden por JS con clases o [hidden], y aquí no debe asomar ninguna. */
body.fondo-pantalla :is(.barra, .riel, .cajon, .hoja, .marco, .linea, .hud, .pista, .brindis, .salir-limpio) { display: none !important; }
body.fondo-pantalla #lienzo { cursor: none; }

/* ═══ Línea de tiempo ══════════════════════════════════════════════
   Abajo a la derecha, dentro del espacio libre. El ancho se calcula en vez
   de estirarse entre left y right: así, al plegarse, la barra se encoge
   hasta el botón en lugar de dejar una franja vacía. */

.linea {
  position: fixed; z-index: var(--z-hud); bottom: 10px;
  right: calc(var(--libre-der, 0px) + 10px); left: auto;
  width: min(520px, calc(100% - var(--libre-izq, 0px) - var(--libre-der, 0px) - 20px));
  display: flex; align-items: center; gap: 6px; padding: 4px 5px 4px 5px;
  border: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg) 55%, transparent);
  backdrop-filter: blur(10px);
  transition: opacity var(--t-media) ease;
}
.linea.plegado { width: auto; padding: 3px; }
.linea.plegado > :not(.plegar) { display: none; }
.linea .icono { width: 26px; height: 26px; }
.linea .icono svg { width: 13px; height: 13px; }
.linea input[type="range"] {
  -webkit-appearance: none; appearance: none;
  flex: 1 1 auto; min-width: 60px; height: 14px; margin: 0 4px; background: transparent; cursor: ew-resize;
}
.linea-k { font-family: var(--mono); font-size: var(--fs-ui-m); color: var(--dim); }
.linea-t {
  min-width: 5ch; text-align: right;
  font-family: var(--mono); font-size: var(--fs-ui-xl); font-variant-numeric: tabular-nums; color: var(--txt-bright);
}
body.limpio .linea { opacity: 0; pointer-events: none; }

@media (max-width: 760px) {
  .linea { right: 8px; width: calc(100% - 16px); bottom: calc(50px + env(safe-area-inset-bottom, 0px)); }
  .linea.plegado { width: auto; }
  body.cajon-abierto .linea, body.hoja-abierta .linea { opacity: 0; pointer-events: none; }
  body.cajon-abierto .linea .plegar, body.hoja-abierta .linea .plegar { pointer-events: none; }
  body.cajon-abierto .hud { opacity: 0; }
  body.cajon-abierto .hud .plegar { pointer-events: none; }
}

/* ═══ Galería ══════════════════════════════════════════════════════ */

.galeria-guardar { display: flex; gap: 6px; margin-bottom: 12px; }
.galeria-nombre, .galeria-renombre {
  flex: 1 1 auto; min-width: 0; padding: 5px 7px;
  border: 1px solid var(--border2); border-radius: 0; background: var(--bg3);
  color: var(--txt-bright); font-family: var(--mono); font-size: var(--fs-ui-m);
}
.galeria-item { position: relative; }
.galeria-item .plantilla { width: 100%; }
.galeria-acciones {
  position: absolute; top: 4px; right: 4px; display: flex; gap: 3px;
  opacity: 0; transition: opacity var(--t-rapida);
}
.galeria-item:hover .galeria-acciones, .galeria-item:focus-within .galeria-acciones { opacity: 1; }
@media (hover: none) { .galeria-acciones { opacity: 1; } }
.galeria-acciones .icono { width: 24px; height: 24px; background: color-mix(in srgb, var(--bg) 82%, transparent); }
.galeria-acciones .icono svg { width: 13px; height: 13px; }
.galeria-acciones [data-borrar][aria-pressed="true"] { color: var(--color-error); border-color: var(--color-error); background: var(--bg2); }
.galeria-renombre { position: absolute; left: 4px; right: 4px; bottom: 20px; z-index: 1; }
.cajon-cuerpo .galeria-vacia { font-size: var(--fs-s); line-height: 1.6; color: var(--dim); }

/* ═══ Paneles a la derecha (preferencia) ═══════════════════════════ */

@media (min-width: 761px) {
  body.panel-derecha .riel { left: auto; right: 0; border-right: none; border-left: 1px solid var(--border); }
  body.panel-derecha .riel-btn { border-left: none; border-right: 2px solid transparent; }
  body.panel-derecha .riel-btn[aria-pressed="true"] { border-right-color: var(--accent); }
  body.panel-derecha .riel-btn::after { left: auto; right: calc(100% + 8px); }
  body.panel-derecha .cajon { left: auto; right: var(--riel-w); border-right: none; border-left: 1px solid var(--border); }
  body.panel-derecha .cajon.cerrado { transform: translateX(calc(100% + var(--riel-w))); }
  body.panel-derecha .hoja { right: auto; left: 0; border-left: none; border-right: 1px solid var(--border); }
  body.panel-derecha .hoja.cerrada { transform: translateX(-100%); }
}

/* ═══ Paleta de comandos ═══════════════════════════════════════════ */

.velo-comandos { align-items: flex-start; padding-top: min(14vh, 120px); }
.modal.comandos {
  width: min(560px, 100%); max-height: min(70vh, 560px);
  display: flex; flex-direction: column; overflow: hidden;
}
.comandos-buscar {
  flex: none; width: 100%; padding: 13px 14px;
  border: none; border-bottom: 1px solid var(--border); border-radius: 0; outline: none;
  background: transparent; color: var(--txt-bright); font-family: var(--mono); font-size: var(--fs-ui-xl);
}
.comandos-lista {
  flex: 1 1 auto; overflow-y: auto; list-style: none; margin: 0; padding: 4px 0;
  scrollbar-width: thin; scrollbar-color: var(--border2) transparent;
}
.comandos-lista [role="option"] { display: flex; align-items: center; gap: 10px; padding: 7px 14px; cursor: pointer; }
.comandos-lista [aria-selected="true"] { background: var(--bg4); box-shadow: inset 2px 0 0 var(--accent); }
.comando-nombre {
  flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fs-s); color: var(--txt);
}
.comando-nombre small { margin-left: 6px; font-size: var(--fs-ui-l); color: var(--dim); }
[aria-selected="true"] .comando-nombre { color: var(--txt-bright); }
.comando-grupo {
  flex: none; font-family: var(--mono); font-size: var(--fs-ui-s); letter-spacing: .08em;
  text-transform: uppercase; color: var(--dim);
}
.comandos kbd {
  flex: none; font-family: var(--mono); font-size: var(--fs-ui-s); color: var(--accent);
  border: 1px solid var(--border2); padding: 1px 5px; white-space: nowrap;
}
.comandos-nada { padding: 14px; font-size: var(--fs-s); color: var(--dim); }
.comandos .comandos-pie {
  flex: none; margin: 0; padding: 7px 14px; border-top: 1px solid var(--border);
  font-family: var(--mono); font-size: var(--fs-ui-s); line-height: 1.4; color: var(--dim);
}

/* ═══ Reconstruyendo… ══════════════════════════════════════════════ */

.reconstruyendo {
  position: fixed; z-index: var(--z-hud); right: calc(var(--libre-der, 0px) + 10px); bottom: 76px;
  display: flex; align-items: center; gap: 7px; padding: 5px 10px;
  border: 1px solid var(--border); background: color-mix(in srgb, var(--bg) 70%, transparent);
  backdrop-filter: blur(10px);
  font-family: var(--mono); font-size: var(--fs-ui-s); letter-spacing: .1em; text-transform: uppercase; color: var(--txt-dim);
  opacity: 0; pointer-events: none; transition: opacity var(--t-rapida) ease;
}
.reconstruyendo.visible { opacity: 1; }
.reconstruyendo i { display: block; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); animation: latido .9s ease-in-out infinite; }
@keyframes latido { 50% { opacity: .25; transform: scale(.7); } }
@media (prefers-reduced-motion: reduce) { .reconstruyendo i { animation: none; } }
body.limpio .reconstruyendo { display: none; }
@media (max-width: 760px) {
  .reconstruyendo { right: 8px; bottom: calc(140px + env(safe-area-inset-bottom, 0px)); }
}

/* ═══ Galaxial+ ════════════════════════════════════════════════════ */

.opcion-licencia {
  margin: 4px 0 8px; padding: 7px 9px; border-left: 2px solid var(--color-aviso, #d9a441);
  background: color-mix(in srgb, var(--bg3) 80%, transparent);
  font-size: var(--fs-ui-xl); line-height: 1.5; color: var(--txt-dim);
}
.opcion-licencia.plus { border-left-color: var(--accent); }
.opcion-licencia[hidden] { display: none; }
.boton-plus { width: 100%; margin-bottom: 6px; }
.boton-plus[hidden] { display: none; }
.opcion select option:disabled { color: var(--dim); }

/* La marca de agua en la vista previa del marco (tamaño en px desde app.js) */
.marco-marca {
  position: absolute; right: 1.1em; bottom: 1.1em;
  display: flex; align-items: center; gap: .5em;
  font-family: var(--mono); font-weight: 500; line-height: 1; white-space: nowrap;
  color: #fff; opacity: .75; text-shadow: 0 0 .4em rgba(0, 0, 0, .75);
  pointer-events: none;
}
.marco-marca svg { width: 1.5em; height: 1.5em; flex: none; filter: drop-shadow(0 0 .2em rgba(0, 0, 0, .75)); }
.marco-marca[hidden] { display: none; }

/* Modal de compra */
.modal-compra { width: min(540px, 100%); }
.compra-opciones { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 12px 0 14px; }
.compra-opcion {
  position: relative; display: flex; flex-direction: column; gap: 4px; padding: 12px;
  border: 1px solid var(--border2); background: var(--bg3); cursor: pointer;
  transition: border-color var(--t-rapida), background var(--t-rapida);
}
.compra-opcion:hover { border-color: var(--accent); }
.compra-opcion:has(input:checked) { border-color: var(--accent); background: var(--bg4); }
.compra-opcion:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.compra-nombre {
  font-family: var(--mono); font-size: var(--fs-ui-l); font-weight: 500; letter-spacing: .08em;
  text-transform: uppercase; color: var(--txt-bright);
}
.compra-opcion:has(input:checked) .compra-nombre { color: var(--accent); }
.compra-precio { font-family: var(--mono); font-size: 1.3rem; color: var(--txt-bright); font-variant-numeric: tabular-nums; }
.compra-specs { margin: 4px 0 0; padding-left: 1.1em; font-size: var(--fs-ui-xl); line-height: 1.5; color: var(--txt-dim); }
.compra-correo { display: flex; flex-direction: column; gap: 5px; margin-bottom: 10px; }
.compra-correo span { font-family: var(--mono); font-size: var(--fs-ui-m); letter-spacing: .06em; text-transform: uppercase; color: var(--txt-dim); }
.compra-correo input {
  padding: 8px 9px; border: 1px solid var(--border2); border-radius: 0; background: var(--bg3);
  color: var(--txt-bright); font-family: var(--mono); font-size: var(--fs-ui-xl);
}
.compra-correo input:focus { outline: none; border-color: var(--accent); }
.compra-aviso { margin: 0 0 10px; color: var(--color-error); font-size: var(--fs-ui-xl); }
.compra-aviso[hidden] { display: none; }
.modal .compra-pie { margin-top: 12px; font-size: var(--fs-ui-xl); color: var(--dim); }
@media (max-width: 520px) { .compra-opciones { grid-template-columns: 1fr; } }
