/*
 * La estructura y estilo general de UI se consideran estables.
 * Los siguientes desarrollos deben priorizar funcionalidad.
 * No modificar layout, paleta o componentes generales salvo
 * requerimiento funcional explícito.
 */

/*
 * Sistema de temas: SOLO color (ver #data-theme abajo). Ningún tema puede
 * tocar layout, dimensiones, fuente, padding, altura de filas, bordes
 * estructurales, posición de paneles ni Normal/Maximizado — eso sigue
 * viviendo, sin variables, en el resto de este fichero.
 *
 * :root (sin atributo data-theme) = EGA Azul, con los MISMOS valores que
 * la app ya usaba antes de este sistema: una instalación existente sin
 * preferencia de tema guardada no cambia de aspecto. js/app.js aplica el
 * tema guardado escribiendo data-theme en <html> (y un script inline en
 * <head> lo hace antes del primer pintado, para evitar flash).
 */
:root {
  --desktop-bg: #05060c;
  --desktop-tint: rgba(70, 90, 140, 0.05);

  --app-bg: rgb(0, 0, 168);
  --panel-bg: rgb(168, 168, 168);
  --panel-bg-text: rgb(0, 0, 0);
  --button-bg: rgb(255, 255, 255);

  --text: #fff;
  --border: #fff;

  --focus: rgb(255, 255, 0);
  --focus-text: rgb(0, 0, 0);

  --disabled: rgb(168, 168, 168);
  --disabled-text: rgb(90, 90, 90);

  --mode-dungeon: rgb(255, 176, 0);
  --mode-dungeon-text: #000;
  --mode-wilderness: rgb(0, 168, 168);
  --mode-wilderness-text: #000;
  --mode-combat: rgb(168, 0, 0);
  --mode-combat-text: #fff;

  --warning: rgb(255, 176, 0);
  --critical: rgb(255, 0, 0);

  --progress-empty: rgba(0, 0, 0, 0.4);
  --progress-normal: rgb(0, 255, 255);
  --progress-warning: rgb(255, 176, 0);
  --progress-critical: rgb(255, 0, 0);
  --progress-dimmed: rgba(255, 255, 255, 0.45);
}

/* DOS Ámbar: monitor monocromo ámbar, fondo muy oscuro. */
:root[data-theme="amber"] {
  --desktop-bg: #0a0700;
  --desktop-tint: rgba(140, 90, 20, 0.05);

  --app-bg: rgb(40, 24, 4);
  --panel-bg: rgb(200, 140, 40);
  --panel-bg-text: rgb(0, 0, 0);
  --button-bg: rgb(255, 196, 92);

  --text: rgb(255, 191, 64);
  --border: rgb(255, 191, 64);

  --focus: rgb(255, 255, 255);
  --focus-text: rgb(0, 0, 0);

  --disabled: rgb(120, 90, 40);
  --disabled-text: rgb(200, 170, 120);

  --mode-dungeon: rgb(255, 191, 0);
  --mode-dungeon-text: #000;
  --mode-wilderness: rgb(190, 150, 60);
  --mode-wilderness-text: #000;
  /* Ámbar oscuro, no rojo: mismo hueco naranja/ámbar que el resto del
     tema, solo más oscuro y saturado para leerse como "alerta". */
  --mode-combat: rgb(140, 70, 0);
  --mode-combat-text: rgb(255, 210, 150);

  --warning: rgb(255, 191, 0);
  --critical: rgb(200, 100, 0);

  --progress-empty: rgba(0, 0, 0, 0.4);
  --progress-normal: rgb(255, 180, 60);
  --progress-warning: rgb(255, 140, 0);
  --progress-critical: rgb(200, 100, 0);
  --progress-dimmed: rgba(255, 220, 180, 0.4);
}

/* Monocromo: negro/grises/blanco. Los modos se distinguen por contraste
   (peso del gris), no por matiz. */
:root[data-theme="mono"] {
  --desktop-bg: #040404;
  --desktop-tint: rgba(60, 60, 60, 0.05);

  --app-bg: rgb(30, 30, 30);
  --panel-bg: rgb(190, 190, 190);
  --panel-bg-text: rgb(0, 0, 0);
  --button-bg: rgb(235, 235, 235);

  --text: rgb(235, 235, 235);
  --border: rgb(210, 210, 210);

  --focus: rgb(255, 255, 255);
  --focus-text: rgb(0, 0, 0);

  --disabled: rgb(90, 90, 90);
  --disabled-text: rgb(180, 180, 180);

  --mode-dungeon: rgb(220, 220, 220);
  --mode-dungeon-text: #000;
  --mode-wilderness: rgb(140, 140, 140);
  --mode-wilderness-text: #000;
  --mode-combat: rgb(60, 60, 60);
  --mode-combat-text: #fff;

  --warning: rgb(220, 220, 220);
  --critical: rgb(255, 255, 255);

  --progress-empty: rgba(0, 0, 0, 0.4);
  --progress-normal: rgb(140, 140, 140);
  --progress-warning: rgb(200, 200, 200);
  --progress-critical: rgb(255, 255, 255);
  --progress-dimmed: rgba(150, 150, 150, 0.4);
}

/* CGA Retro: cyan/magenta/blanco/negro, inspirado en CGA (no reproduce
   limitaciones de hardware al pie de la letra). */
:root[data-theme="cga"] {
  --desktop-bg: #040206;
  --desktop-tint: rgba(90, 40, 90, 0.05);

  --app-bg: rgb(8, 8, 10);
  --panel-bg: rgb(0, 255, 255);
  --panel-bg-text: rgb(0, 0, 0);
  --button-bg: rgb(255, 255, 255);

  --text: rgb(255, 255, 255);
  --border: rgb(0, 255, 255);

  --focus: rgb(255, 0, 255);
  --focus-text: rgb(255, 255, 255);

  --disabled: rgb(90, 90, 90);
  --disabled-text: rgb(180, 180, 180);

  --mode-dungeon: rgb(255, 255, 255);
  --mode-dungeon-text: #000;
  --mode-wilderness: rgb(0, 255, 255);
  --mode-wilderness-text: #000;
  --mode-combat: rgb(255, 0, 80);
  --mode-combat-text: #fff;

  --warning: rgb(0, 255, 255);
  --critical: rgb(255, 0, 0);

  --progress-empty: rgba(0, 0, 0, 0.4);
  --progress-normal: rgb(0, 255, 255);
  --progress-warning: rgb(255, 255, 255);
  --progress-critical: rgb(255, 0, 0);
  --progress-dimmed: rgba(180, 180, 180, 0.4);
}

/* Fósforo Verde: monitor monocromo de fósforo verde. Únicamente
   tonalidades de verde (con negro para fondo/contraste) — sin azul, cyan,
   rojo, amarillo, magenta ni blanco puro. Misma geometría y componentes
   que el resto de temas, solo cambia la paleta. */
:root[data-theme="phosphor"] {
  --desktop-bg: #000c00;
  --desktop-tint: rgba(0, 150, 0, 0.05);

  --app-bg: rgb(0, 30, 0);
  --panel-bg: rgb(40, 110, 40);
  --panel-bg-text: rgb(0, 0, 0);
  --button-bg: rgb(60, 255, 60);

  --text: rgb(60, 255, 60);
  --border: rgb(40, 200, 40);

  --focus: rgb(190, 255, 190);
  --focus-text: rgb(0, 0, 0);

  --disabled: rgb(30, 80, 30);
  --disabled-text: rgb(120, 180, 120);

  --mode-dungeon: rgb(150, 255, 150);
  --mode-dungeon-text: #000;
  --mode-wilderness: rgb(90, 210, 90);
  --mode-wilderness-text: #000;
  --mode-combat: rgb(15, 110, 15);
  --mode-combat-text: rgb(190, 255, 190);

  --warning: rgb(150, 255, 150);
  --critical: rgb(0, 255, 0);

  --progress-empty: rgba(0, 0, 0, 0.4);
  --progress-normal: rgb(60, 255, 60);
  --progress-warning: rgb(150, 255, 150);
  --progress-critical: rgb(0, 255, 0);
  --progress-dimmed: rgba(120, 180, 120, 0.4);
}

.app-window.mode-dungeon {
  --current-mode-color: var(--mode-dungeon);
  --current-mode-text: var(--mode-dungeon-text);
}

.app-window.mode-wilderness {
  --current-mode-color: var(--mode-wilderness);
  --current-mode-text: var(--mode-wilderness-text);
}

.app-window.mode-combat {
  --current-mode-color: var(--mode-combat);
  --current-mode-text: var(--mode-combat-text);
}

html, body {
  margin: 0;
  min-height: 100%;
  background: var(--desktop-bg);
  color: var(--text);
  font-family: "Lucida Console", "Courier New", monospace;
}

* {
  box-sizing: border-box;
}

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

.hidden {
  display: none !important;
}

.app-shell {
  width: 100%;
  min-height: 100vh;
  /* svh = alto de viewport "pequeño" (asume la barra de direcciones del
     móvil siempre visible). dvh (dinámico) parecía mejor opción pero se
     recalcula EN VIVO mientras el usuario hace scroll y la barra se
     oculta/aparece — eso es lo que hacía "saltar" la ventana/footer a
     mitad de scroll. svh es un valor estable, no cambia durante el
     scroll, a costa de un margen sin usar cuando la barra se oculta. Se
     declara después de vh a propósito: si el navegador no soporta svh,
     ignora esta línea y se queda con vh. */
  min-height: 100svh;
  display: flex;
  align-items: safe center;
  justify-content: safe center;
  padding: 10px;
  /* Textura de "escritorio" retro DOS/EGA: micro-dither muy sutil sobre
     negro azulado. background-color de respaldo por si el gradient no
     renderiza; el tile de 4px no cambia con la resolución/DPI. */
  background-color: var(--desktop-bg);
  background-image:
    repeating-linear-gradient(45deg, var(--desktop-tint) 0px, var(--desktop-tint) 1px, transparent 1px, transparent 4px),
    repeating-linear-gradient(-45deg, var(--desktop-tint) 0px, var(--desktop-tint) 1px, transparent 1px, transparent 4px);
  background-size: 4px 4px;
  overflow: auto;
}

.app-window {
  /* Normal: ancho fijo razonable, altura según contenido (con tope
     generoso). Un ratio 16:10 estricto (≈800×500) resultó demasiado bajo
     para el contenido real y forzaba scroll — mejor ancho fijo + alto
     libre hasta max-height. Solo .maximized (abajo) usa el viewport. */
  width: min(920px, 100%);
  max-height: 92vh;
  max-height: 92svh;
  margin: auto;
  padding: 0;
  display: flex;
  flex-direction: column;
  background: var(--app-bg);
  color: var(--text);
  box-shadow: 10px 10px black;
  border: 2px solid var(--border);
  transition: all 0.15s ease;
  overflow: hidden;
}

.app-window.maximized {
  /* Tope ~1920×1080 (no un mínimo): en monitores 2K/4K se queda ahí y se
     centra; en viewports menores usa el espacio real disponible. */
  width: min(1920px, 98vw);
  max-width: min(1920px, 98vw);
  height: min(1080px, 95vh);
  height: min(1080px, 95svh);
  max-height: min(1080px, 95vh);
  max-height: min(1080px, 95svh);
}

/* Scanlines (CRT): opt-in desde Ajustes, no forma parte de ningún tema.
   Líneas horizontales finas y sutiles, sin glow/blur/flicker/curvatura —
   solo la textura. La clase va en <html> (no en .app-window) para que
   alcance también a los popups (.modal-window), que son hermanos fuera
   de .app-window en el DOM. pointer-events:none para no interferir con
   clics; .tui-window ya trae position:relative, así que ::after se
   ancla a cada ventana sin tocar su layout. */
html.scanlines-on .app-window::after,
html.scanlines-on .modal-window::after,
html.scanlines-on .dos-menu-panel.is-open::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  background-image: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.12) 0px,
    rgba(0, 0, 0, 0.12) 1px,
    transparent 1px,
    transparent 3px
  );
}

/* Normal (~920px de ancho): reducir gaps/padding antes que permitir
   overflow. Ningún atajo ni información desaparece, solo se compacta. */
.app-window:not(.maximized) .status-strip {
  gap: 8px;
  padding: 4px 6px;
}

.app-window:not(.maximized) .dungeon-clock {
  letter-spacing: 0;
}

.app-window:not(.maximized) .app-statusbar {
  gap: 6px;
  padding: 4px 6px;
}

.app-fieldset {
  margin: 0;
  border: none;
  padding: 0;
  /* min-height:0 (no 100%) es lo que de verdad permite que este flex
     item se encoja dentro de .app-window y su propio overflow-y:auto
     haga el scroll interno. flex:1 ya se encarga de que rellene el
     espacio cuando el contenido es corto; min-height:100% no ayudaba
     ahí y en su lugar bloqueaba el encogido cuando el contenido es
     largo — sobre todo en Safari/iOS, donde el bug del footer "saltando"
     al hacer scroll venía de aquí, no de las unidades de viewport. */
  min-height: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  flex: 1;
  overflow-y: auto;
}

.dos-menu-container {
  position: relative;
  width: 100%;
  margin: 0 0 10px;
  /* Ahora es hermano de .app-fieldset (no hijo) dentro de .app-window,
     para quedarse fijo arriba mientras solo .app-fieldset scrollea
     internamente; flex-shrink:0 evita que .app-fieldset (flex:1) lo
     encoja. */
  flex-shrink: 0;
}

.dos-menu-bar {
  display: flex;
  align-items: center;
  gap: 2px;
  min-height: 24px;
  width: 100%;
  background: var(--panel-bg);
  color: var(--panel-bg-text);
  border-bottom: 2px solid #000;
  padding: 0;
  /* En viewports estrechos (.app-window ya se limita a 100% de ancho) los
     4 grupos + nombre + reloj no caben: sin esto, .app-window's overflow:
     hidden recorta "Ayuda" y parte de "Herramientas", dejándolos
     inalcanzables. Mismo patrón que .status-strip/.initiative-rail, pero
     aquí es navegación primaria, así que además se oculta la barra de
     scroll nativa (fea/inesperada en móvil) y en la media query de abajo
     se libera espacio para que quepa sin necesidad de deslizar. */
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}

.dos-menu-bar::-webkit-scrollbar {
  display: none;
}

.dos-menu-icon {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--panel-bg-text);
  line-height: 1;
  padding: 4px 8px;
  cursor: pointer;
}

.dos-menu-icon::before {
  content: '[';
}

.dos-menu-icon::after {
  content: ']';
}

.dos-menu-icon:hover {
  background: var(--app-bg);
  color: var(--text);
}

.dos-app-name {
  padding: 0 10px 0 2px;
  font-weight: bold;
  white-space: nowrap;
}

.dos-menu-group {
  display: flex;
  align-items: stretch;
  gap: 0;
}

.dos-menu-trigger,
.dos-menu-panel button {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--panel-bg-text);
  line-height: 1;
  cursor: pointer;
  text-transform: none;
}

.dos-menu-trigger {
  min-width: unset;
  margin: 0;
  padding: 5px 10px;
  flex-shrink: 0;
}

.dos-menu-trigger::first-letter {
  text-decoration: underline;
}

.dos-menu-trigger:hover,
.dos-menu-trigger.is-active {
  background: var(--app-bg);
  color: var(--text);
}

.dos-menu-panel button:hover {
  background: var(--app-bg);
  color: var(--text);
}

.dos-menu-bar-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.dos-clock {
  letter-spacing: 0.03em;
  white-space: nowrap;
}

.dos-window-button {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--panel-bg-text);
  font-family: inherit;
  line-height: 1;
  padding: 4px 6px;
  cursor: pointer;
  flex-shrink: 0;
}

.dos-window-button::before {
  content: '[';
}

.dos-window-button::after {
  content: ']';
}

.dos-window-button:hover {
  background: var(--app-bg);
  color: var(--text);
}

.dos-menu-dropdown {
  position: absolute;
  top: 100%;
  left: 4px;
  z-index: 1000;
  display: block;
  background: transparent;
  pointer-events: none;
}

.dos-menu-dropdown:not(.hidden) {
  pointer-events: auto;
}

.dos-menu-panel {
  position: relative;
  display: none;
  background: var(--panel-bg);
  border: 2px solid #000;
  border-top: 1px solid #fff;
  border-left: 1px solid #fff;
  min-width: 200px;
  padding: 2px 0;
  margin: 0;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.4);
}

.dos-menu-panel.is-open {
  display: grid;
}

.dos-menu-panel button {
  width: 100%;
  text-align: left;
  border: none;
  border-bottom: 1px solid transparent;
  padding: 2px 24px 2px 12px;
  background: transparent;
  color: var(--panel-bg-text);
  cursor: pointer;
  appearance: none;
}

.dos-menu-panel button:hover {
  background: var(--app-bg);
  color: var(--text);
}

.dos-menu-panel button:last-child {
  border-bottom: none;
}

.dos-menu-separator {
  height: 1px;
  margin: 3px 6px;
  background: rgba(0, 0, 0, 0.35);
}

.tui-panel {
  border: 1px solid rgba(255, 255, 255, 0.35);
  min-width: 0;
}

.tui-panel-content {
  overflow-x: hidden;
}

.btn-primary {
  border: 2px solid var(--focus) !important;
  font-weight: bold;
}

.tui-button.disabled,
.tui-button:disabled {
  text-decoration: none !important;
  background: var(--disabled) !important;
  color: var(--disabled-text) !important;
  box-shadow: none !important;
  cursor: default !important;
}

.tui-button:focus-visible,
.mode-btn:focus-visible,
.dos-menu-trigger:focus-visible,
.dos-menu-icon:focus-visible,
.dos-window-button:focus-visible,
.panel-add-btn:focus-visible,
.tui-input:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.app-campaign-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: auto;
  min-width: 0;
  margin: 0 8px 10px;
  padding: 5px 10px;
  background: rgba(0, 0, 0, 0.2);
  border: 2px solid rgba(255, 255, 255, 0.5);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  appearance: none;
}

.app-campaign-bar:hover {
  background: rgba(255, 255, 255, 0.12);
  border-color: var(--border);
}

#campaignBarLabel {
  /* min-width:0 es imprescindible: sin él, un flex item con
     white-space:nowrap nunca encoge por debajo de su contenido y el
     ellipsis no llega a activarse — el nombre largo empuja la barra fuera
     de la ventana en vez de truncarse. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

#campaignBarStatus {
  flex-shrink: 0;
  text-transform: uppercase;
  white-space: nowrap;
}

.mode-name-accent {
  display: inline-block;
  padding: 0 4px;
  background: var(--current-mode-color, rgba(255, 255, 255, 0.2));
  color: var(--current-mode-text, #fff);
  font-weight: bold;
}

.mode-name-accent::before {
  content: '[ ';
}

.mode-name-accent::after {
  content: ' ]';
}

.mode-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 8px 12px;
}

.mode-btn {
  min-width: 110px;
}

.mode-btn.active {
  background: var(--current-mode-color, rgb(255, 255, 0)) !important;
  color: var(--current-mode-text, #000) !important;
}

.mode-btn.active::before {
  content: '[ ';
}

.mode-btn.active::after {
  content: ' ]';
}

.workspace-grid {
  display: grid;
  grid-template-columns: 340px minmax(0, 1fr);
  grid-template-areas:
    "sidebar main"
    "log     log";
  gap: 12px;
  align-items: start;
  margin: 0 8px;
  min-height: 0;
}

/* Solo en maximizado .app-window tiene una altura REAL definida (95vh), así
   que solo ahí puede sobrar espacio vertical que absorber. En normal la
   ventana mide lo que mide su contenido — darle flex:1 aquí también
   generaba un hueco vacío entre los paneles y el Log sin motivo. */
.app-window.maximized .workspace-grid {
  flex: 1;
  /* La fila "main" (sidebar+principal+secundaria) se queda con TODO el
     espacio sobrante (1fr); la fila "log" mide solo su contenido (auto).
     Sin esto, el espacio extra del flex:1 se quedaba como hueco vacío
     DESPUÉS del Log en vez de empujarlo pegado abajo. */
  grid-template-rows: minmax(0, 1fr) auto;
}

.side-column,
.main-column {
  display: grid;
  gap: 12px;
  min-width: 0;
}

.side-column {
  grid-area: sidebar;
}

.main-column {
  grid-area: main;
}

.log-panel {
  grid-area: log;
}

.side-panel {
  min-height: unset;
}

.tui-panel-header {
  position: relative;
  background: var(--panel-bg) !important;
  color: var(--panel-bg-text);
}

/* Contador reutilizable de cabecera (Grupo [4], Efectos [2]...). Preparado
   también para futuras cabeceras del Codex (Monstruos [214]...). */
.tui-count {
  opacity: 0.7;
  font-weight: normal;
}

.panel-add-btn {
  appearance: none;
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  line-height: 1;
  padding: 0 4px;
  border: none;
  background: transparent;
  color: var(--panel-bg-text);
  cursor: pointer;
}

.panel-add-btn::before {
  content: '[';
}

.panel-add-btn::after {
  content: ']';
}

.panel-add-btn:hover {
  background: var(--app-bg);
  color: var(--text);
}

.compact-list,
.action-list,
.session-log {
  display: grid;
  gap: 6px;
}

.compact-list {
  margin-bottom: 0;
}

.log-entry,
.summary-box,
.combatant-row {
  background: rgba(0, 0, 0, 0.18);
  border: 2px solid rgba(255, 255, 255, 0.45);
  color: var(--text);
  padding: 4px 8px;
}

/* Patrón común de estado vacío: texto atenuado y compacto, sin caja. Nombre
   .tui-empty-state pensado para reutilizar en el Codex; .empty-row sigue
   funcionando igual (alias) para no tocar el HTML/JS ya existente. */
.empty-row,
.tui-empty-state {
  color: color-mix(in srgb, var(--text) 60%, transparent);
  padding: 2px 4px;
}

.list-item {
  background: transparent;
  border: none;
  color: var(--text);
  padding: 2px 2px;
}

.link-button {
  background: transparent;
  border: none;
  color: var(--mode-wilderness);
  text-decoration: underline;
  cursor: pointer;
  padding: 0;
  font: inherit;
}

.combatant-row {
  display: grid;
  grid-template-columns: 34px 1fr 40px 68px 130px;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}

.combatant-row-header {
  font-weight: bold;
  opacity: 0.75;
  cursor: default;
  /* Cabecera fija durante el scroll interno de la tabla. Fondo sólido
     propio (no heredado) para que las filas que pasan por debajo no se
     transparenten. */
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--app-bg);
}

.combatant-row .col-ini,
.combatant-row .col-ac,
.combatant-row .col-hp {
  text-align: right;
  white-space: nowrap;
}

.combatant-row .col-name,
.combatant-row .col-status {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.combatant-row.selected {
  background: var(--focus) !important;
  color: var(--focus-text) !important;
  border-color: var(--focus-text);
}

/* Actor con el turno actual: indicador discreto (glifo), nunca el mismo
   amarillo sólido de la selección — son conceptos distintos. */
.tui-actor-marker {
  font-weight: bold;
  opacity: 0.85;
}

.combatant-row.defeated,
.combatant-row.withdrawn {
  opacity: 0.55;
}

.status-chip-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.status-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: rgba(0, 0, 0, 0.18);
  border: 2px solid rgba(255, 255, 255, 0.45);
  color: var(--text);
  padding: 2px 6px;
}

.status-chip button {
  appearance: none;
  border: none;
  background: transparent;
  color: inherit;
  cursor: pointer;
  padding: 0 2px;
  line-height: 1;
}

.status-chip button:hover {
  color: var(--focus);
}

.party-row {
  display: grid;
  grid-template-columns: 1fr 54px 30px 56px;
  align-items: baseline;
  gap: 6px;
  padding: 2px 2px;
  color: var(--text);
}

.party-row-header {
  font-weight: bold;
  opacity: 0.75;
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--app-bg);
}

#partyList {
  max-height: 200px;
  overflow-y: auto;
}

.party-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.party-class {
  white-space: nowrap;
}

.party-ac {
  white-space: nowrap;
  text-align: right;
}

.party-hp {
  white-space: nowrap;
  text-align: right;
}

.list-item {
  display: block;
}

.duration-block {
  display: grid;
  gap: 3px;
  width: 100%;
}

.duration-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.duration-row .name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.duration-row .remaining {
  flex-shrink: 0;
  white-space: nowrap;
}

.ascii-progress.tui-progress-bar {
  width: 100%;
  height: 10px;
  background-color: rgba(0, 0, 0, 0.4);
  border: 1px solid rgba(255, 255, 255, 0.35);
}

.ascii-progress .tui-progress {
  background-color: var(--progress-normal);
}

.ascii-progress.warning .tui-progress {
  background-color: var(--progress-warning);
}

.ascii-progress.critical .tui-progress {
  background-color: var(--progress-critical);
}

.ascii-progress.dimmed .tui-progress {
  background-color: var(--progress-dimmed);
}

.light-row {
  cursor: pointer;
}

.light-row:hover {
  background: rgba(255, 255, 255, 0.08);
}

.effect-row {
  cursor: pointer;
}

.effect-row:hover {
  background: rgba(255, 255, 255, 0.08);
}

.effect-targets-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  flex-wrap: wrap;
}

.effect-targets-actions {
  display: flex;
  gap: 10px;
}

.effect-targets-list {
  /* Override de "display: grid" heredado de .compact-list: en grid, cada
     fila es un grid item con align-self "stretch" por defecto y se reparte
     el alto sobrante en vez de quedarse en su contenido (mismo motivo que
     .session-log más abajo) — con overflow-y:auto eso se veía como filas
     recortadas/aplastadas en vez de una lista compacta con scroll. */
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 160px;
  overflow-y: auto;
  padding: 6px;
  background: rgba(0, 0, 0, 0.18);
  border: 2px solid rgba(255, 255, 255, 0.45);
}

.effect-target-checkbox {
  flex: 0 0 auto;
  padding-top: 2px;
  padding-bottom: 2px;
}

.effect-targets-error {
  color: var(--critical);
  font-size: 0.9em;
}

.effect-detail-name {
  font-weight: bold;
  font-size: 1.05em;
}

.effect-detail-section {
  display: grid;
  gap: 4px;
}

/* --- Statblock Importer ------------------------------------------------ */
.statblock-textarea {
  min-height: 180px;
  resize: vertical;
  font-family: inherit;
  padding: 6px 8px;
}

.statblock-textarea-small {
  min-height: 70px;
  resize: vertical;
  font-family: inherit;
  padding: 6px 8px;
}

.statblock-warnings {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: 4px;
}

.statblock-warning-item {
  color: var(--warning);
  opacity: 0.9;
  font-size: 0.9em;
}

.statblock-attacks-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 220px;
  overflow-y: auto;
  padding: 6px;
  background: rgba(0, 0, 0, 0.18);
  border: 2px solid rgba(255, 255, 255, 0.45);
}

.statblock-attack-row {
  display: grid;
  grid-template-columns: 1.4fr 0.7fr 0.7fr 0.9fr auto;
  gap: 6px;
  align-items: center;
}

.statblock-attack-row .sb-attack-remove {
  padding: 2px 8px;
}

.statblock-ability-row {
  display: grid;
  grid-template-columns: 1fr 2fr auto;
  gap: 6px;
  align-items: center;
}

.statblock-ability-row .sb-ability-remove {
  padding: 2px 8px;
}

.statblock-scope-options {
  display: flex;
  gap: 20px;
}

/* --- Codex ------------------------------------------------------------ */
.codex-tabs {
  display: flex;
  gap: 6px;
  margin-bottom: 8px;
}

.codex-tab-btn.active {
  background: var(--focus) !important;
  color: var(--focus-text) !important;
}

.codex-toolbar {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}

.codex-search-field {
  flex: 1;
  min-width: 160px;
}

.codex-scope-field {
  min-width: 140px;
}

.codex-result-count {
  opacity: 0.75;
  white-space: nowrap;
  padding-bottom: 6px;
}

/* Flex-column deliberado (no .compact-list/grid): mismo motivo que
   .session-log — cada fila debe medir solo su propio contenido, no
   repartirse el alto sobrante del contenedor. */
.codex-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 320px;
  overflow-y: auto;
  margin-bottom: 8px;
}

.codex-row {
  display: grid;
  grid-template-columns: 1fr 44px 44px 108px 84px;
  gap: 10px;
  align-items: center;
  padding: 3px 6px;
  cursor: pointer;
}

.codex-list--encounters .codex-row {
  grid-template-columns: 1fr 2fr 84px;
}

/* Sin min-width:0 un grid item nunca encoge por debajo del ancho de su
   contenido (mismo motivo que #campaignBarLabel más arriba): "Personalizado"
   desbordaba su columna en vez de recortarse, invadiendo la de Ámbito. */
.codex-row > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.codex-row-header {
  font-weight: bold;
  opacity: 0.75;
  cursor: default;
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--app-bg);
}

.codex-row:not(.codex-row-header):hover {
  background: rgba(255, 255, 255, 0.08);
}

.codex-row.selected {
  background: var(--focus) !important;
  color: var(--focus-text) !important;
}

.codex-detail-body {
  max-height: 70vh;
  max-height: 70svh;
  overflow-y: auto;
}

.codex-creature-results {
  max-height: 200px;
}

.codex-creature-pick-row {
  cursor: pointer;
}

.codex-creature-pick-row:hover {
  background: rgba(255, 255, 255, 0.08);
}

/* Reutiliza .statblock-attack-row (fila flex + botón eliminar ya
   delegado) pero con solo 3 columnas: nombre resuelto / cantidad / quitar. */
.codex-creature-row {
  grid-template-columns: 2fr 1fr auto;
}

.travel-compass {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
}

.travel-compass-row {
  display: flex;
  gap: 6px;
}

.travel-compass button,
.travel-compass-center {
  width: 56px;
  height: 56px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.travel-compass-center {
  background: rgba(255, 255, 255, 0.1);
  border: 2px solid rgba(255, 255, 255, 0.35);
  color: color-mix(in srgb, var(--text) 60%, transparent);
  font-weight: bold;
}

.travel-compass-note {
  font-size: 0.85em;
  opacity: 0.65;
  margin-bottom: 8px;
}

.form-field {
  display: grid;
  gap: 4px;
}

.form-field label {
  color: var(--panel-bg-text);
  letter-spacing: 0.04em;
}

.compact-field {
  gap: 3px;
}

.two-up {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.tui-input {
  width: 100%;
  min-height: 30px;
}

.main-column .view {
  display: none;
  gap: 12px;
}

.main-column .view.active {
  display: grid;
}

.status-strip {
  display: none;
  flex-wrap: nowrap;
  gap: 14px;
  align-items: center;
  width: auto;
  min-width: 0;
  margin: 0 8px 12px;
  padding: 6px 10px;
  background: rgba(0, 0, 0, 0.15);
  border: 2px solid rgba(255, 255, 255, 0.5);
  overflow-x: auto;
  white-space: nowrap;
  scrollbar-width: none;
}

.status-strip::-webkit-scrollbar {
  display: none;
}

.status-strip.active {
  display: flex;
  border-color: var(--current-mode-color, rgba(255, 255, 255, 0.5));
}

.status-strip strong {
  margin-right: 4px;
}

.strip-divider {
  opacity: 0.5;
}

/* Agrupa Turno+Hora / Encuentro+Descanso (y Día+Hora / Terreno+Hex en
   Exterior) para poder partir la tira en 2 líneas en móvil sin tocar
   JS. display:contents en desktop = el wrapper no existe para el
   layout, todo sigue en una sola línea igual que antes. */
.status-row {
  display: contents;
}

.two-col {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.grid-two {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.action-list {
  display: grid;
  gap: 8px;
}

/* Subcabecera de grupo dentro del panel Acciones (DJ / Jugadores): mismo
   tratamiento discreto que .encounter-field-label, no un nuevo componente. */
.action-group-label {
  font-weight: bold;
  opacity: 0.7;
  font-size: 0.85em;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 10px 0 4px;
}

.action-group-label:first-child {
  margin-top: 0;
}

.encounter-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

.summary-box {
  min-height: 0;
}

#combatantsList {
  max-height: 260px;
  overflow-y: auto;
}

.log-panel {
  /* Sin flex:1 a propósito: el panel Log NO debe crecer para rellenar el
     alto de la ventana (esa era la causa de que en pantallas altas se
     estirara). Su altura la determina el contenido: cabecera +
     .session-log, que tiene una altura fija de ~5 filas (ver abajo). */
  min-height: 0;
  margin: 12px 8px 0;
  display: flex;
  flex-direction: column;
}

.log-panel .tui-panel-content {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.session-log {
  /* Override deliberado de "display: grid" (heredado de la regla
     compartida con .compact-list/.action-list): en grid, cada .log-entry
     es un grid item con align-self "stretch" por defecto, así que se
     repartía el alto sobrante de la fila en vez de quedarse en su
     contenido. En flex-column, sin flex-grow, cada entrada solo ocupa la
     altura de su propio texto. */
  display: flex;
  flex-direction: column;
  /* Altura fija ≈ 5 entradas de una línea: line-height de .log-entry
     (1.45em) + su padding/borde vertical (4px arriba/abajo + 2px de borde
     arriba/abajo = 12px) por cada una de las 5 filas, más los 4 huecos de
     6px entre ellas (gap heredado de la regla compartida con
     .compact-list/.action-list). A partir de la 6ª entrada, scroll. */
  height: calc(5 * (1.45em + 12px) + 4 * 6px);
  overflow-y: auto;
}

.log-entry {
  display: block;
  flex: 0 0 auto;
  line-height: 1.45;
}

.log-entry:last-child {
  border-bottom: none;
}

.app-statusbar {
  /* Antes "overflow:hidden" recortaba en seco lo que no cabía (el "F10
     Menú" cortado). flex-wrap deja que pase a una segunda línea si hace
     falta en vez de perder contenido; min-width:0 permite que el propio
     footer encoja dentro de la ventana en vez de forzarla a ensancharse. */
  width: auto;
  min-width: 0;
  margin: 8px 0 0;
  background: var(--panel-bg);
  color: var(--panel-bg-text);
  border-top: 2px solid #000;
  padding: 4px 8px;
  display: flex;
  flex-wrap: wrap;
  row-gap: 2px;
  align-items: center;
  overflow: visible;
  /* Ahora es hermano de .app-fieldset (no hijo) dentro de .app-window,
     para quedarse fijo abajo mientras solo .app-fieldset scrollea
     internamente; flex-shrink:0 evita que .app-fieldset (flex:1) lo
     encoja. */
  flex-shrink: 0;
}

.app-statusbar span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.statusbar-save-indicator {
  margin-left: auto;
  padding-left: 12px;
  flex-shrink: 0;
  opacity: 0.85;
}

.tui-overlap {
  position: fixed !important;
  top: 0 !important;
  left: 0 !important;
  right: 0 !important;
  bottom: 0 !important;
  background: rgba(0, 0, 0, 0.55);
}

.tui-modal {
  position: fixed !important;
  top: 0 !important;
  left: 0 !important;
  right: 0 !important;
  bottom: 0 !important;
  align-items: safe center;
  justify-content: safe center;
  padding: 20px;
  overflow-y: auto;
}

.tui-modal.active {
  display: flex !important;
}

/* Patrón común de popup: 3 tamaños. small (por defecto, .modal-window) para
   confirmaciones/inputs breves; --medium para herramientas sin listas
   grandes (Dados/PX/Reglas/Acerca de); --large reservado para futuras
   herramientas de listado (Codex/Tablas/Compendio) — cabe en normal
   (~800px) sin desbordar y no crece indefinidamente en maximizado. */
.modal-window {
  display: block;
  width: 380px;
  max-width: 92vw;
  max-height: 80vh;
  max-height: 80svh;
  margin: auto;
  overflow-y: auto;
}

.modal-window-wide,
.modal-window--medium {
  width: 640px;
  max-width: 94vw;
}

.modal-window--large {
  width: min(1000px, 92vw);
  max-height: 85vh;
  max-height: 85svh;
}

.modal-body {
  display: grid;
  gap: 10px;
  margin-top: 6px;
}

.modal-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-end;
  margin-top: 4px;
}

/* Pie de atajos reutilizable de popup: una línea discreta, solo los atajos
   relevantes de ESE popup (no un listado genérico repetido). */
.tui-popup-footer {
  margin-top: 6px;
  padding-top: 4px;
  border-top: 1px solid rgba(255, 255, 255, 0.25);
  font-size: 0.85em;
  opacity: 0.7;
  text-align: center;
  white-space: nowrap;
}

.log-modal-body {
  /* Mismo motivo que .session-log: sin este override hereda
     "display: grid" de .modal-body y las entradas se estirarían también
     aquí, en el log expandido. */
  display: flex;
  flex-direction: column;
  max-height: 60vh;
  max-height: 60svh;
  overflow-y: auto;
}

.tables-modal-section {
  margin-bottom: 10px;
}

.tables-modal-section:last-child {
  margin-bottom: 0;
}

.tables-modal-section h4 {
  margin: 0 0 4px;
}

.about-modal-body {
  text-align: center;
}

.about-logo {
  margin: 0 0 8px;
  line-height: 1.15;
  text-align: center;
  font-size: 0.6em;
}

.about-title {
  margin: 0 0 4px;
  font-weight: bold;
  letter-spacing: 0.08em;
}

.about-facts {
  display: grid;
  gap: 2px;
  text-align: left;
  line-height: 1.4;
  margin: 8px 0 12px;
  padding: 4px 8px;
  background: rgba(0, 0, 0, 0.18);
  border: 2px solid rgba(255, 255, 255, 0.45);
  max-height: calc(5 * 1.4em + 4 * 2px);
  overflow-y: auto;
}

.about-facts a {
  color: inherit;
  text-decoration: underline;
}

.about-facts a:hover {
  color: var(--app-bg);
}

.about-startup-checkbox {
  margin: 0 0 8px;
  font-size: 0.85em;
}

@media (max-width: 980px) {
  .workspace-grid,
  .two-col {
    display: grid;
    grid-template-columns: 1fr;
  }

  .workspace-grid {
    grid-template-areas:
      "sidebar"
      "main"
      "log";
  }
}

/* Dungeon Clocks: glifo compacto junto al valor numérico ya existente en
   el status strip. Puramente informativo, no sustituye el número. */
.dungeon-clock {
  opacity: 0.75;
  letter-spacing: 1px;
}

/* Periodo del día: descriptor derivado de la hora, sin implicar luz solar
   ni reglas. Texto discreto junto a la hora. */
.day-period {
  opacity: 0.7;
  text-transform: uppercase;
  font-size: 0.85em;
}

/* Aviso global de oscuridad en el panel Luz. Ámbar de advertencia (no
   rojo: no es un peligro real, es un aviso de procedimiento). */
.lighting-status {
  font-weight: bold;
  color: var(--warning);
  border: 1px solid var(--warning);
  padding: 3px 6px;
  margin-bottom: 6px;
  text-align: center;
}

/* Initiative Rail: deriva del orden real del tracker. El actor con el
   turno actual usa el mismo amarillo de foco/selección que el resto de la
   app; derrotados/retirados quedan atenuados igual que en la tabla. */
.initiative-rail {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  overflow-x: auto;
  gap: 4px;
  padding: 4px 6px;
  margin-bottom: 8px;
  background: rgba(0, 0, 0, 0.18);
  border: 1px solid rgba(255, 255, 255, 0.35);
  white-space: nowrap;
  scrollbar-width: none;
}

.initiative-rail::-webkit-scrollbar {
  display: none;
}

.initiative-rail-item {
  padding: 1px 6px;
  border: 1px solid transparent;
}

.initiative-rail-item.current {
  background: var(--focus);
  color: var(--focus-text);
  font-weight: bold;
  border-color: var(--focus-text);
}

.initiative-rail-item.inactive {
  opacity: 0.5;
  text-decoration: line-through;
}

.initiative-rail-sep,
.initiative-rail-ellipsis {
  opacity: 0.6;
}

/* Encounter Summary: cabecera clara + campos realmente disponibles. */
.encounter-header {
  font-weight: bold;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
}

.encounter-fields {
  display: grid;
  gap: 2px;
}

.encounter-fields > div {
  display: flex;
  justify-content: space-between;
  gap: 8px;
}

.encounter-field-label {
  opacity: 0.75;
}

.encounter-extra {
  margin-top: 4px;
  opacity: 0.85;
}

/* Lanzador de Dados 2.0 */
.dice-quantity-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.dice-qty-btn {
  min-width: 32px;
  padding: 1px 6px;
}

.dice-qty-value {
  min-width: 24px;
  text-align: center;
  font-weight: bold;
}

.dice-face-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
  margin-bottom: 8px;
}

.dice-face-grid-minor {
  opacity: 0.8;
}

.dice-result {
  line-height: 1.4;
}

.dice-comparison-success {
  color: var(--progress-normal);
  font-weight: bold;
}

.dice-comparison-fail {
  color: var(--warning);
  font-weight: bold;
}

.dice-history-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 8px 0 4px;
  opacity: 0.85;
}

.dice-history-list {
  max-height: 160px;
  overflow-y: auto;
}

.dice-history-item {
  display: grid;
  grid-template-columns: 48px 1fr 56px;
  gap: 8px;
  cursor: pointer;
  padding: 2px 4px;
}

.dice-history-item:hover {
  background: rgba(255, 255, 255, 0.12);
}

.dice-history-time {
  opacity: 0.65;
}

.dice-history-total {
  text-align: right;
  font-weight: bold;
}

.dice-expression-row {
  display: flex;
  gap: 6px;
}

.dice-expression-row input {
  width: auto;
  flex: 1;
}

.dice-expression-row button {
  flex-shrink: 0;
  white-space: nowrap;
}

.dice-history-clear-btn {
  padding: 1px 8px;
}

/* Barra de estado de Combate: nombre de "Actúa" truncado si es muy largo,
   sin ensanchar la barra ni el layout general. */
.combat-actor-name {
  display: inline-block;
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
}

@media (max-width: 640px) {
  .app-shell {
    padding: 12px;
  }

  .grid-two,
  .two-up {
    grid-template-columns: 1fr;
  }

  .dice-face-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  /* "OSR Manager" es redundante en móvil (ya está en el título de la
     pestaña) y es lo que más espacio ocupa de la barra: quitarlo es lo
     que de verdad libera sitio para que los 4 menús quepan sin depender
     del scroll (ver overflow-x:auto en .dos-menu-bar, que se queda como
     red de seguridad, no como mecanismo principal). */
  .dos-app-name {
    display: none;
  }

  .dos-menu-trigger {
    padding: 5px 7px;
  }

  /* Reloj (el móvil ya tiene el suyo) y minimizar/maximizar (Normal vs
     Maximizado no aporta nada en una pantalla ya pequeña) — fuera en
     móvil, liberan sitio en la barra de menú. */
  .dos-clock,
  .dos-window-button {
    display: none;
  }

  /* Turno|Hora|Encuentro|Descanso (y Día|Hora|Terreno|Hex en Exterior)
     no caben en una línea en móvil. .status-strip pasa a permitir wrap;
     .status-row pasa de display:contents a flex real y ocupa toda la
     fila -> el segundo grupo cae debajo; el divisor central ya no hace
     falta con los grupos apilados. */
  .status-strip {
    flex-wrap: wrap;
    overflow-x: visible;
  }

  .status-row {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    width: 100%;
  }

  .status-row-divider {
    display: none;
  }

  /* El "|" suelto en medio del hueco de space-between quedaba flotando
     sin pegarse a ninguno de los dos valores. El propio hueco ya separa
     visualmente Turno/Hora y Encuentro/Descanso, no hace falta carácter. */
  .status-row .strip-divider {
    display: none;
  }
}

/* Layout ancho: activado ÚNICAMENTE por el estado real de maximización
   (.app-window.maximized, ya gestionado por windowSizeBtn en app.js), NUNCA
   por el ancho del viewport. Un monitor grande con la app sin maximizar se
   queda en el layout normal (<=800px); solo maximizar activa esto.
   Reutiliza los paneles ya existentes vía grid-area/grid-template-columns;
   ningún nodo se duplica ni se mueve por JS. El Log nunca es una columna:
   sigue siendo la fila "log" a todo el ancho, tanto normal como maximizado. */
.app-window.maximized .workspace-grid {
  /* Proporciones fluidas (no columnas congeladas): la izquierda crece con
     la ventana en vez de quedarse en un ancho fijo. */
  grid-template-columns: minmax(280px, 24%) minmax(0, 1fr);
}

/* Mazmorra: Acciones (principal) | Encuentro (secundaria). */
.app-window.maximized #dungeonView {
  grid-template-columns: minmax(0, 1fr) minmax(280px, 34%);
}

/* Exterior: Acciones/Estado (principal, ya era .two-col) a la izquierda;
   Encuentro y Hex actual apilados como columna secundaria a la derecha. */
.app-window.maximized #wildernessView {
  grid-template-columns: minmax(0, 1fr) minmax(280px, 34%);
  grid-template-areas:
    "principal top"
    "principal bottom";
}

.app-window.maximized #wildernessView > *:nth-child(1) {
  grid-area: principal;
}

.app-window.maximized #wildernessView > *:nth-child(2) {
  grid-area: top;
}

.app-window.maximized #wildernessView > *:nth-child(3) {
  grid-area: bottom;
}

/* Combate: tabla de combatientes (principal) | Ronda/Acciones (secundaria,
   apiladas verticalmente en vez de lado a lado). */
.app-window.maximized #combatView {
  grid-template-columns: minmax(0, 1fr) minmax(280px, 34%);
  align-items: start;
}

.app-window.maximized #combatView > .two-col {
  grid-template-columns: 1fr;
}

/* --- Temas: overrides de utilidades TuiCss --------------------------- */
/* TuiCss (vendor) sigue siendo la base visual: no se toca tui.css. Estas
   utilidades (.white-168/.white-255/.black-255-text) son las que usan los
   popups y prácticamente todos los botones de la app para su "chrome"
   claro, así que repintarlas aquí es lo que realmente re-tematiza la
   aplicación entera sin reimplementar cada componente. Mismo mecanismo que
   ya usaba custom.css antes de este sistema de temas (sobrescribir
   utilidades vendor), solo que ahora vía variable en vez de color fijo. */
/* Gap preexistente del sistema de temas (no introducido por Fósforo
   Verde): tui.css fija el fondo de .tui-panel (Grupo/Luz/Efectos/
   Acciones/Encuentro/Log...) en rgb(0, 0, 168) sin variable. En EGA Azul
   era invisible porque --app-bg por defecto es ese mismo azul; en
   cualquier otro tema (Fósforo incluido) se veía el azul vendor sin
   re-tematizar. */
.tui-panel {
  background-color: var(--app-bg) !important;
}

.white-168 {
  background-color: var(--panel-bg) !important;
}

.white-255 {
  background-color: var(--button-bg) !important;
}

.black-255-text {
  color: var(--panel-bg-text) !important;
}

/* Marco doble de fieldset (estructura sin cambios: 6px double, solo el
   color). Igual para el sub-marco de inputs con foco propio (amarillo por
   defecto -> color de foco del tema). */
.tui-fieldset,
.tui-input-fieldset {
  border-color: var(--border);
}

.tui-input-fieldset:hover {
  border-color: var(--focus);
}

.tui-input-fieldset:hover legend {
  color: var(--focus);
}

.tui-checkbox input:checked ~ span::after {
  color: var(--focus);
}

.tui-radio input:checked ~ span:after {
  color: var(--focus);
}

.tui-input:focus {
  background-color: var(--focus) !important;
  color: var(--focus-text) !important;
}

/* --- Ajustes: vista previa de tema ------------------------------------ */
.settings-theme-preview {
  display: grid;
  gap: 8px;
  padding: 8px;
  background: rgba(0, 0, 0, 0.18);
  border: 2px solid rgba(255, 255, 255, 0.45);
}

.settings-theme-preview-modes {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.settings-preview-chip {
  padding: 2px 8px;
  font-weight: bold;
}

.settings-preview-dungeon {
  background: var(--mode-dungeon);
  color: var(--mode-dungeon-text);
}

.settings-preview-wilderness {
  background: var(--mode-wilderness);
  color: var(--mode-wilderness-text);
}

.settings-preview-combat {
  background: var(--mode-combat);
  color: var(--mode-combat-text);
}

.settings-preview-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.settings-preview-selected,
.settings-preview-normal {
  padding: 2px 8px;
}

.settings-preview-selected {
  background: var(--focus);
  color: var(--focus-text);
  font-weight: bold;
}

.settings-preview-normal {
  color: var(--text);
  border: 1px solid rgba(255, 255, 255, 0.35);
}
