/* ══════════════════════════════════════════════════════════════
   Integrated Prototype v0.5 — Start → Forge → Deploy → Move → Shoot
   Integration-specific styles only.
   Phase-specific styles imported from phase directories.
══════════════════════════════════════════════════════════════ */

/* ── Screen Router: full-viewport screens with fade transitions ──
   STACKING-CONTEXT WARNING: `.screen` (position:fixed + z-index) and
   `.screen.screen-active` (z-index:10) each establish a stacking
   context. ANY z-index set on a descendant is RELATIVE to the screen,
   not the body. If you need a chrome element to paint above body-root
   siblings (e.g. #global-tooltip at z=200), the element must EITHER
   live at body root OR the screen's effective z-index must beat the
   body-root competitor. Promoting an inner z-index without considering
   this trap is the most common z-index bug in this codebase
   (#roll-overlay → terrain tooltip bleed, #scenario-score-strip →
   phase header overlap). When in doubt, open DevTools → Layers. */
.screen {
  position: fixed;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s ease;
  z-index: 1;
}
.screen.screen-active {
  opacity: 1;
  pointer-events: auto;
  z-index: 10;
}

/* Start screen needs higher z-index for its overlays */
#screen-start { z-index: 1; }
#screen-start.screen-active { z-index: 10; }
#screen-forge { z-index: 1; }
#screen-forge.screen-active { z-index: 15; }
#screen-game { z-index: 1; }
#screen-game.screen-active { z-index: 10; }


/* Fix: v0.7a forge CSS sets .obj-hex-wrap { opacity:0 } globally.
   Game screen objectives must always be visible. */
#screen-game .obj-hex-wrap {
  opacity: 1;
}

/* Fix: start-game/style.css defines .vignette globally as a dark radial gradient.
   Scope it to the start screen so it doesn't bleed into the game screen. */
#screen-game .vignette,
#screen-forge .vignette {
  background: none !important;
}

/* Forge atmospheric overlays live on #screen-forge in the single-board architecture.
   Keep them active during forge preview, then let transition/game rules hide them later. */
body.forge-board-active #screen-forge .bf-vignette,
body.forge-board-active #screen-forge .bf-scanlines,
body.forge-board-active #screen-forge .bf-grain,
body.forge-board-active #screen-forge .scan-line,
body.forge-board-active #screen-forge .bf-edge-fade {
  display: block;
}
body.forge-board-active #screen-forge .bf-vignette { opacity: 1; }
body.forge-board-active #screen-forge .bf-scanlines { opacity: 0.95; }
body.forge-board-active #screen-forge .bf-grain { opacity: 0.03; }
body.forge-board-active #screen-forge .bf-edge-fade { opacity: 1; }

/* Hide clutter from VP bar and deploy badge in integrated */
#screen-game #reset-btn,
#screen-game .vp-round,
#screen-game .deploy-badge {
  display: none !important;
}

/* Settings button — non-primary, non-disabled outline style */
.menu-btn:not(.primary):not(.disabled) {
  border-color: var(--border);
  color: var(--text-sec);
}
/* active-faction: settings button hover themes to active turn */
.menu-btn:not(.primary):not(.disabled):hover {
  border-color: color-mix(in srgb, var(--active-faction) 60%, #000);
  color: var(--text-primary);
  background: color-mix(in srgb, var(--active-faction) 8%, transparent);
}

/* ══════════════════════════════════════════════════════════════
   BATTLE FORGE SCREEN — single-board architecture
   The game board (#battlefield-inner) is shown behind forge chrome
   via body.forge-board-active, which makes #screen-game visible
   with game-specific UI hidden and the board dimmed.
══════════════════════════════════════════════════════════════ */

/* When forge is active, show #screen-game behind forge chrome as a dimmed board backdrop */
body.forge-board-active #screen-game {
  opacity: 1;
  pointer-events: none;
  z-index: 3;
}
/* During forge preview, the live board must occupy the full viewport.
   If the hidden roster column still reserves width, the board appears shifted
   right and the left edge fade becomes a hard cut. Collapse the app grid so
   objective 03 sits on true screen center. */
body.forge-board-active #app {
  /* Use 0px (not 1fr) so the track count matches game layout (220px 1fr).
     CSS can interpolate 0px → 220px within the same 2-track structure,
     enabling smooth grid animation during the forge→game transition. */
  grid-template-columns: 0px 1fr !important;
}
body.forge-board-active #screen-game #battlefield-inner {
  filter: brightness(0.48) saturate(0.88) blur(0.6px);
  transition: filter 1.5s ease;
}
body.forge-board-active.forge-bf-active #screen-game #battlefield-inner {
  filter: brightness(0.6) saturate(0.92) blur(0.35px);
}
body.forge-board-active.forge-bf-full #screen-game #battlefield-inner {
  filter: brightness(0.72) saturate(0.96) blur(0px);
}
/* Hide game UI during forge. Specificity note: `#unit-card.visible`
   (0,2,0) beats `body.forge-board-active #unit-card` (0,1,1), so we
   target `#unit-card.visible` directly to win the cascade without
   `!important`. The base `#unit-card { display: none }` covers the
   non-visible case. */
body.forge-board-active #roster,
body.forge-board-active #vp-bar,
body.forge-board-active #phase-header,
body.forge-board-active #action-bar,
body.forge-board-active .zone-warning,
body.forge-board-active .deploy-badge,
body.forge-board-active #weapon-popup,
body.forge-board-active #roll-overlay,
body.forge-board-active #unit-card.visible {
  display: none;
}

/* Forge screen is transparent chrome — board shows through from #screen-game behind */
#screen-forge {
  background: transparent;
}

/* Navigation chrome */
#screen-forge .forge-nav-back,
#screen-forge .forge-nav-mockups {
  position: fixed; z-index: 50;
  font: 500 11px/1 'Rajdhani', sans-serif;
  color: var(--text-sec); text-decoration: none;
  letter-spacing: 1px; transition: color 0.2s;
  opacity: 0; animation: fade-in 0.4s ease-out 0.8s both;
  background: none; border: none; cursor: pointer;
}
/* faction-a (intentional): forge nav lives BEFORE any active turn is
   set — there's no scenario palette mounted, no activator, no owning
   unit. The forge is themed to the simulator's brand color (cyan in
   default, scenario gold if scenario-mode happens to be active),
   which is exactly what --faction-a resolves to in the cascade. Not
   an oversight; intentional baseline. */
#screen-forge .forge-nav-back:hover,
#screen-forge .forge-nav-mockups:hover { color: var(--faction-a); }
#screen-forge .forge-nav-back    { top: 14px; left: 16px; }
#screen-forge .forge-nav-mockups { top: 14px; right: 16px; }
#screen-forge .forge-version-badge {
  position: fixed; bottom: 12px; left: 16px; z-index: 50;
  font: 500 9px/1 'Rajdhani', sans-serif;
  color: var(--text-muted); letter-spacing: 1px;
  opacity: 0; animation: fade-in 0.4s ease-out 0.8s both;
}

/* ── Start screen debug menu ── */
/* Legacy start-debug removed — unified into #debug-menu */

/* ── Backlink: position below VP bar in game screen ── */
#screen-game .backlink {
  top: 42px;
}

/* ── App layout: standard 2-column (roster | battlefield) ── */
#app {
  display: grid;
  grid-template-columns: 220px 1fr;
  height: 100vh;
}
#roster { grid-column: 1; }
#battlefield { grid-column: 2; overflow: hidden; }
#bf-svg-terrain { overflow: visible; }

/* ── Phase transition animation (pill fade/slide) ── */
.phase-pill.phase-transition {
  animation: pill-transition 0.5s ease;
}
@keyframes pill-transition {
  0%   { opacity: 0.4; transform: translateY(-4px); }
  100% { opacity: 1;   transform: translateY(0); }
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes glow-pulse {
  from { opacity: 0.3; }
  to   { opacity: 0.6; }
}

/* ── Deploy zone + terrain: let clicks pass through to models ── */
.deploy-zone-bg, .deploy-zone-border, .deploy-zone-label,
.deploy-zone-sublabel, .nml-zone-bg, .nml-label,
#deploy-player1, #deploy-player2, #deploy-nml,
#objectiveRings, #objectiveHexes,
.map-sprite-el, #map-sprites-baked { pointer-events: none; }

/* ── Deploy zone visibility + shading ── */
.phase-deploy .deploy-zone-bg.a-zone,
body.forge-board-active .deploy-zone-bg.a-zone {
  fill: rgba(0,80,160,0.11);
  opacity: 1;
}
.phase-deploy .deploy-zone-bg.b-zone,
body.forge-board-active .deploy-zone-bg.b-zone {
  fill: color-mix(in srgb, var(--faction-b) 11%, transparent);
  opacity: 1;
}
.phase-deploy .nml-zone-bg,
body.forge-board-active .nml-zone-bg {
  fill: rgba(0,0,0,0.16);
  opacity: 1;
}
.phase-deploy .deploy-zone-border,
.phase-deploy .deploy-zone-label,
.phase-deploy .deploy-zone-sublabel,
.phase-deploy .nml-label,
body.forge-board-active .deploy-zone-border,
body.forge-board-active .deploy-zone-label,
body.forge-board-active .deploy-zone-sublabel,
body.forge-board-active .nml-label {
  opacity: 1;
}

/* When the game screen is active and no later phase class has been applied yet,
   treat that state as deploy. The forge→game handoff currently lands here before
   move/shoot/etc classes take over, and James expects deploy shading to be visible. */
body.phase-deploy #screen-game.screen-active .deploy-zone-bg,
body.phase-deploy #screen-game.screen-active .deploy-zone-border,
body.phase-deploy #screen-game.screen-active .deploy-zone-label,
body.phase-deploy #screen-game.screen-active .deploy-zone-sublabel,
body.phase-deploy #screen-game.screen-active .nml-label,
body.phase-deploy #screen-game.screen-active .nml-zone-bg,
body.forge-board-active #screen-game.screen-active .deploy-zone-bg,
body.forge-board-active #screen-game.screen-active .deploy-zone-border,
body.forge-board-active #screen-game.screen-active .deploy-zone-label,
body.forge-board-active #screen-game.screen-active .deploy-zone-sublabel,
body.forge-board-active #screen-game.screen-active .nml-label,
body.forge-board-active #screen-game.screen-active .nml-zone-bg {
  opacity: 1;
}

/* ── Hide deploy zones in non-deploy phases (but not during forge preview) ── */
body:not(.phase-deploy):not(.forge-board-active) .deploy-zone-bg,
body:not(.phase-deploy):not(.forge-board-active) .deploy-zone-border,
body:not(.phase-deploy):not(.forge-board-active) .deploy-zone-label,
body:not(.phase-deploy):not(.forge-board-active) .deploy-zone-sublabel,
body:not(.phase-deploy):not(.forge-board-active) .nml-label,
body:not(.phase-deploy):not(.forge-board-active) .nml-zone-bg,
body:not(.phase-deploy):not(.forge-board-active) #deploy-player1 > *,
body:not(.phase-deploy):not(.forge-board-active) #deploy-player2 > * {
  opacity: 0;
  transition: opacity 0.5s ease;
}

/* ── Deploy zone highlight on drag ── */
.deploy-zone-bg.zone-active.a-zone { fill: color-mix(in srgb, var(--faction-a) 14%, transparent); transition: fill 0.2s; }
.deploy-zone-bg.zone-active.b-zone { fill: color-mix(in srgb, var(--faction-b) 14%, transparent); transition: fill 0.2s; }

/* ── Move center lines: hidden during deploy, visible during move ── */
.move-center-line { opacity: 0; transition: opacity 0.5s ease; }
.phase-move .move-center-line { opacity: 1; }

/* ── .phase-command: hide deploy-specific SVGs after deployment handoff ── */
/* Keep DS + Reserves labels visible (same pattern as move/shoot/charge/fight) */
.phase-command .staging-zone-bg,
.phase-command .offboard-zone-label:not(.ds-label):not(.reserves-label),
.phase-command .board-edge-separator,
.phase-command .deploy-zone-bg,
.phase-command .deploy-zone-border,
.phase-command .deploy-zone-label,
.phase-command .deploy-zone-sublabel,
.phase-command .nml-zone-bg,
.phase-command .nml-label,
.phase-command #deploy-player1 > *,
.phase-command #deploy-player2 > * {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s ease;
}
.phase-command .ds-zone-bg,
.phase-command .reserves-zone-bg {
  opacity: 0.3;  transition: opacity 0.5s ease;
}

/* ── .phase-move: hide deploy-specific SVGs ── */
/* Only hide staging zone + deployment zones + NML. Keep DS + Reserves visible. */
.phase-move .staging-zone-bg,
.phase-move .offboard-zone-label:not(.ds-label):not(.reserves-label),
.phase-move .board-edge-separator,
.phase-move .deploy-zone-bg,
.phase-move .deploy-zone-border,
.phase-move .deploy-zone-label,
.phase-move .deploy-zone-sublabel,
.phase-move .nml-zone-bg,
.phase-move .nml-label {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s ease;
}
/* DS + Reserves zones: keep visible but dim slightly, no stroke */
.phase-move .ds-zone-bg,
.phase-move .reserves-zone-bg {
  opacity: 0.3;  transition: opacity 0.5s ease;
}

/* ── Hide zone warning during move phase ── */
.phase-move .zone-warning { display: none !important; }

/* ── .phase-reinforcement: show DS/reserves zones, hide deploy zones ── */
.phase-reinforcement .staging-zone-bg,
.phase-reinforcement .offboard-zone-label:not(.ds-label):not(.reserves-label),
.phase-reinforcement .board-edge-separator,
.phase-reinforcement .deploy-zone-bg,
.phase-reinforcement .deploy-zone-border,
.phase-reinforcement .deploy-zone-label,
.phase-reinforcement .deploy-zone-sublabel,
.phase-reinforcement .nml-zone-bg,
.phase-reinforcement .nml-label {
  opacity: 0; pointer-events: none; transition: opacity 0.5s ease;
}
.phase-reinforcement .ds-zone-bg,
.phase-reinforcement .reserves-zone-bg {
  opacity: 0.6; stroke: none !important; stroke-width: 0 !important; transition: opacity 0.5s ease;
}
.phase-reinforcement .ds-label,
.phase-reinforcement .reserves-label {
  opacity: 0.8;
}

/* ── .phase-shoot: same as .phase-move, keeps deployment zones hidden ── */
.phase-shoot .staging-zone-bg,
.phase-shoot .offboard-zone-label:not(.ds-label):not(.reserves-label),
.phase-shoot .board-edge-separator,
.phase-shoot .deploy-zone-bg,
.phase-shoot .deploy-zone-border,
.phase-shoot .deploy-zone-label,
.phase-shoot .deploy-zone-sublabel,
.phase-shoot .nml-zone-bg,
.phase-shoot .nml-label {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s ease;
}
.phase-shoot .ds-zone-bg,
.phase-shoot .reserves-zone-bg {
  opacity: 0.3;  transition: opacity 0.5s ease;
}
.phase-shoot .zone-warning { display: none !important; }
.phase-shoot .move-center-line { opacity: 1; }

/* ── .phase-charge: same as .phase-shoot ── */
.phase-charge .staging-zone-bg,
.phase-charge .offboard-zone-label:not(.ds-label):not(.reserves-label),
.phase-charge .board-edge-separator,
.phase-charge .deploy-zone-bg,
.phase-charge .deploy-zone-border,
.phase-charge .deploy-zone-label,
.phase-charge .deploy-zone-sublabel,
.phase-charge .nml-zone-bg,
.phase-charge .nml-label {
  opacity: 0; pointer-events: none; transition: opacity 0.5s ease;
}
.phase-charge .ds-zone-bg,
.phase-charge .reserves-zone-bg { opacity: 0.3; stroke: none !important; stroke-width: 0 !important; transition: opacity 0.5s ease; }
.phase-charge .zone-warning { display: none !important; }
.phase-charge .move-center-line { opacity: 1; }

/* ── .phase-fight: same as .phase-charge ── */
.phase-fight .staging-zone-bg,
.phase-fight .offboard-zone-label:not(.ds-label):not(.reserves-label),
.phase-fight .board-edge-separator,
.phase-fight .deploy-zone-bg,
.phase-fight .deploy-zone-border,
.phase-fight .deploy-zone-label,
.phase-fight .deploy-zone-sublabel,
.phase-fight .nml-zone-bg,
.phase-fight .nml-label {
  opacity: 0; pointer-events: none; transition: opacity 0.5s ease;
}
.phase-fight .ds-zone-bg,
.phase-fight .reserves-zone-bg { opacity: 0.3; stroke: none !important; stroke-width: 0 !important; transition: opacity 0.5s ease; }
.phase-fight .zone-warning { display: none !important; }
.phase-fight .move-center-line { opacity: 1; }

/* ── .phase-game-end: same as .phase-fight ── */
.phase-game-end .staging-zone-bg,
.phase-game-end .offboard-zone-label:not(.ds-label):not(.reserves-label),
.phase-game-end .board-edge-separator,
.phase-game-end .deploy-zone-bg,
.phase-game-end .deploy-zone-border,
.phase-game-end .deploy-zone-label,
.phase-game-end .deploy-zone-sublabel,
.phase-game-end .nml-zone-bg,
.phase-game-end .nml-label {
  opacity: 0; pointer-events: none; transition: opacity 0.5s ease;
}
.phase-game-end .ds-zone-bg,
.phase-game-end .reserves-zone-bg { opacity: 0.3; stroke: none !important; stroke-width: 0 !important; transition: opacity 0.5s ease; }
.phase-game-end .zone-warning { display: none !important; }
.phase-game-end .move-center-line { opacity: 1; }

/* ── Hide per-unit CONFIRM/CANCEL during deploy (auto-confirm on drop) ── */
#btn-confirm-unit,
#btn-cancel-unit {
  display: none !important;
}

/* ── Card range toggles: horizontal scroll carousel ── */
/* #unit-card has overflow-x:hidden (shared CSS), so we must scroll
   WITHIN the card. .card-ranges gets explicit max-width = card width
   minus padding, and its own overflow-x:scroll. */
/* owning-faction: scrollbar belongs to the card it lives inside */
.card-ranges {
  display: flex !important;
  flex-wrap: nowrap !important;
  overflow-x: scroll !important;
  overflow-y: hidden !important;
  max-width: 100%;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--owning-faction) 20%, transparent) transparent;
  gap: 4px;
  padding-bottom: 4px;
}
.card-ranges::-webkit-scrollbar { height: 4px; }
.card-ranges::-webkit-scrollbar-track { background: transparent; }
/* owning-faction */
.card-ranges::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--owning-faction) 25%, transparent); border-radius: 2px; }
.card-ranges .range-toggle {
  flex: 0 0 auto !important;
  min-width: 72px !important;
}

/* Weapon range toggle buttons — neutral by default, colored when active */
.range-toggle.weapon {
  background: transparent;
  border: 1px solid var(--text-dis);
  color: var(--text-muted);
  font-size: 8px;
  min-width: 72px !important;
}
.range-toggle.weapon:hover {
  border-color: var(--text-muted);
  color: var(--text-sec);
}
.range-toggle.weapon.active {
  background: rgba(255,100,60,0.15);
  border-color: rgba(255,100,60,0.5);
  color: #ff8855;
}

/* ── CONFIRM DEPLOYMENT disabled state ── */
#btn-end:disabled {
  opacity: 0.35;
  cursor: not-allowed;
  filter: grayscale(0.5);
}

/* Legacy #debug-menu removed — unified into debug-menu.js (.debug-menu class, D key toggle) */

/* ── Debug: ruin footprint overlays ── */
.debug-ruin-footprint {
  fill: rgba(255,100,60,0.12);
  stroke: rgba(255,100,60,0.5);
  stroke-width: 1.5;
  stroke-dasharray: 4 3;
  pointer-events: none;
}
/* ── Debug: enhanced LoS lines ── */
body.debug-los-enhanced .target-line-clear {
  stroke-width: 2 !important;
  stroke-opacity: 0.9 !important;
  stroke: #00d4ff !important;
}
body.debug-los-enhanced .target-line-blocked {
  stroke-width: 2.5 !important;
  stroke-opacity: 0.95 !important;
  stroke: #ff3020 !important;
  stroke-dasharray: 6 4 !important;
}
body.debug-los-enhanced .los-origin-dot {
  fill: #00ff88;
  stroke: #fff;
  stroke-width: 1;
  opacity: 0.95;
}
body.debug-los-enhanced .los-origin-dot-blocked {
  fill: #ff4020;
  stroke: #fff;
  stroke-width: 1;
  opacity: 0.95;
}

/* ── Debug: model-in-ruin highlight ── */
.model-base.debug-in-ruin circle,
.model-base.debug-in-ruin rect {
  stroke: #ff6040 !important;
  stroke-width: 2.5 !important;
  filter: url(#mf-broken) !important;
}

/* ── Map dropdown ── */
.dock-row0 {
  display: flex;
}
.dock-row0 .dock-panel-full {
  flex: 1;
}
.dock-panel-full {
  flex: 1;
}
/* Give deployment type panel more room so 6 cards don't wrap */
.dock-row1 > .dock-panel:first-child {
  flex: 1 1 auto;
}
.dock-row1 > .dock-panel:last-child {
  flex: 0 0 auto;
}
/* Force deploy thumbs to single row */
.deploy-thumbs {
  flex-wrap: nowrap !important;
}
.layout-grid {
  display: flex; gap: 4px; flex-wrap: wrap;
}
.layout-cell {
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(201,163,82,0.15);
  background: rgba(20,24,32,0.6);
  font: 600 12px/1 'Rajdhani', sans-serif;
  color: rgba(201,163,82,0.25);
  cursor: not-allowed; transition: all 0.2s;
}
/* faction-a (intentional): debug-menu layout cell active state, surfaced
   from the dev console pre-game. Same reasoning as forge nav — no
   active turn or owning unit in scope; brand-color baseline. */
.layout-cell.layout-active {
  border-color: color-mix(in srgb, var(--faction-a) 30%, transparent);
  background: color-mix(in srgb, var(--faction-a) 4%, transparent);
  color: #00d4ff;
  cursor: pointer;
}
.dock-select {
  width: 100%;
  padding: 6px 10px;
  background: rgba(20,24,32,0.9);
  color: #c9a352;
  border: 1px solid rgba(201,163,82,0.3);
  border-radius: 3px;
  font: 600 13px/1.4 'Rajdhani', sans-serif;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23c9a352'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 10px 6px;
  padding-right: 28px;
}
.dock-select:hover {
  border-color: rgba(201,163,82,0.5);
}
.dock-select option {
  background: #141820;
  color: #c9a352;
}

/* ── Loading shimmer (on battlefield-inner during map load) ── */
@keyframes shimmer {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

/* Deploy thumb SVG */
.dt-thumb-svg {
  width: 100%;
  height: 100%;
}

/* ── Version badge (overrides both deploy-badge and v23-badge) ── */
/* active-faction: badge is decorative for active turn */
.deploy-badge {
  position: absolute; top: 32px; right: 12px; z-index: 50;
  font: 600 9px/1 'Rajdhani', sans-serif; letter-spacing: 2px; text-transform: uppercase;
  color: var(--text-dis); padding: 3px 8px;
  border: 1px solid color-mix(in srgb, var(--active-faction) 6%, transparent);
}

/* ══════════════════════════════════════════════════════════════
   Forge → Game Cinematic Transition
══════════════════════════════════════════════════════════════ */

/* Disable pointer events during transition */
.forge-transitioning { pointer-events: none; }

/* ── Force forge chrome to a known visible state before animating out ──
   The v0.7a entrance animations use fill:both, so the elements' visible state
   depends on the animation's forward fill. When we set animation:none to begin
   the exit, that removes the fill and the elements snap to opacity:0.
   Fix: override both animation AND explicitly set the "visible" base state,
   THEN the transition rules below animate from visible → hidden. */
#screen-forge.screen-active .os-header {
  animation: none !important;
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
#screen-forge.screen-active #bottomDock {
  animation: none !important;
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* Header + nav: fade up (preserve existing translateX(-50%) centering) */
.forge-transitioning .os-header {
  transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1), opacity 300ms ease !important;
  transform: translateX(-50%) translateY(-40px) !important;
  opacity: 0 !important;
}
.forge-transitioning .forge-nav-mockups,
.forge-transitioning .forge-version-badge {
  transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1), opacity 300ms ease;
  transform: translateY(-40px);
  opacity: 0;
}

/* Left card + panel: slide left */
.forge-transitioning #cardLeft,
.forge-transitioning #panelLeft {
  transition: transform 350ms cubic-bezier(0.4, 0, 0.2, 1) 50ms,
              opacity 300ms ease 50ms;
  transform: translateX(-120%);
  opacity: 0;
}

/* Right card + panel: slide right */
.forge-transitioning #cardRight,
.forge-transitioning #panelRight {
  transition: transform 350ms cubic-bezier(0.4, 0, 0.2, 1) 100ms,
              opacity 300ms ease 100ms;
  transform: translateX(120%);
  opacity: 0;
}

/* VS divider: scale down + fade */
.forge-transitioning #vsDivider {
  transition: transform 300ms ease 150ms, opacity 300ms ease 150ms;
  transform: scale(0);
  opacity: 0;
}

/* Bottom dock: slide down (preserve existing translateX(-50%) centering) */
.forge-transitioning #bottomDock {
  transition: transform 400ms cubic-bezier(0.4, 0, 0.2, 1) 200ms,
              opacity 350ms ease 200ms !important;
  transform: translateX(-50%) translateY(120%) !important;
  opacity: 0 !important;
}

/* Forge FX overlays: fade out during camera lerp (0–1300ms).
   Must finish before forge-board-active is removed at t=1300ms,
   otherwise they vanish instantly when the screen switches. */
.forge-transitioning .bf-vignette,
.forge-transitioning .bf-scanlines,
.forge-transitioning .bf-grain,
.forge-transitioning .scan-line,
.forge-transitioning .bf-edge-fade {
  transition: opacity 1000ms ease 200ms;
  opacity: 0 !important;
}

/* During transition, remove forge-board-active brightness filter
   since transition.js animates it via inline styles */

/* Faction overlay: ensure it's hidden */
.forge-transitioning #factionOverlay {
  opacity: 0;
  pointer-events: none;
}

/* ── Game UI entrance animations ── */
/* Roster slide-in is handled by inline JS transition (translateX) in transition.js.
   The CSS animation was firing invisibly because of display:none timing conflicts. */
.game-entering #action-bar {
  animation: forgeSlideInBottom 400ms cubic-bezier(0.25, 0.1, 0.25, 1) 100ms both;
}
.game-entering #vp-bar {
  animation: forgeFadeIn 400ms ease 100ms both;
}
.game-entering #phase-header {
  animation: forgeFadeIn 400ms ease 200ms both;
}

@keyframes forgeSlideInLeft {
  from { transform: translateX(-100%); opacity: 0; }
  to   { transform: translateX(0);     opacity: 1; }
}
@keyframes forgeSlideInBottom {
  from { transform: translateY(100%); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}
@keyframes forgeFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}


/* ── VP bar auth + menu — absolute inside the full-width bar ── */
.vp-menu-btn {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 28px;
  height: 28px;
  background: none;
  border: none;
  color: var(--text-sec);
  padding: 0;
  border-radius: 3px;
  cursor: pointer;
  transition: color 0.15s;
  display: flex;
  align-items: center;
  justify-content: center;
}
.vp-menu-btn:hover {
  color: var(--text-primary);
}
#auth-container {
  position: absolute;
  right: 48px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
}

/* ══════════════════════════════════════════════════════════════
   Decision Prompt Banner — strategic choice UI
   Gold/amber banner inside #phase-header for target-pick and
   option-select decisions (Oath of Moment, future stance pickers).
══════════════════════════════════════════════════════════════ */
.decision-prompt {
  margin: 6px 0 0;
  padding: 10px 20px 10px;
  background: linear-gradient(180deg, rgba(12,14,20,0.96), rgba(8,12,16,0.92));
  border: 1.5px solid color-mix(in srgb, var(--owning-faction, var(--gold)) 55%, transparent);
  border-radius: 10px;
  box-shadow:
    0 0 14px color-mix(in srgb, var(--owning-faction, var(--gold)) 15%, transparent),
    0 4px 16px rgba(0,0,0,0.5);
  text-align: center;
  pointer-events: auto;
  animation: dp-fade-in 0.35s ease both;
}
@keyframes dp-fade-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.dp-title {
  font: normal 400 14px/1 'Anton', sans-serif;
  letter-spacing: 3px;
  color: var(--owning-faction, var(--gold));
  text-transform: uppercase;
  margin-bottom: 4px;
}
.dp-subtitle {
  font: 600 10px/1.3 'Rajdhani', sans-serif;
  letter-spacing: 1.2px;
  color: var(--text-sec);
  text-transform: uppercase;
}
/* Option tiles — auto-fit so 1 fills the row, 2 split 50/50, 3 pack 3-up,
   4+ wrap. Min track size accounts for the 8px gap × 2 between three
   columns (33% would force a 2+1 collapse on normal modal widths
   because 3×33% + 2×8px > 100%). `min(...100%)` keeps single-tile
   layouts from leaking horizontal scroll on narrow modals. */
.dp-options {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(calc(33.333% - 8px), 100%), 1fr));
  gap: 8px;
  justify-items: stretch;
  margin-top: 8px;
  max-height: 220px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--owning-faction, var(--gold)) 30%, transparent) transparent;
}
.dp-option-tile {
  flex: 0 1 auto;
  min-width: 0;
  padding: 8px 14px;
  background: color-mix(in srgb, var(--owning-faction, var(--gold)) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--owning-faction, var(--gold)) 35%, transparent);
  border-radius: 6px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
.dp-option-tile:hover {
  border-color: color-mix(in srgb, var(--owning-faction, var(--gold)) 70%, transparent);
  background: color-mix(in srgb, var(--owning-faction, var(--gold)) 14%, transparent);
  box-shadow: 0 0 10px color-mix(in srgb, var(--owning-faction, var(--gold)) 18%, transparent);
}
/* Secondary tile (SKIP / DONE) — visually distinguished from unit picks */
.dp-option-secondary {
  border-style: dashed;
  opacity: 0.6;
  grid-column: 1 / -1;   /* span full width as the last row */
}
.dp-option-secondary:hover { opacity: 0.85; }
.dp-option-secondary .dp-opt-label { font-size: 11px; }
.dp-opt-label {
  font: 700 12px/1.2 'Rajdhani', sans-serif;
  letter-spacing: 1.5px;
  color: var(--owning-faction, var(--gold));
  text-transform: uppercase;
}
.dp-opt-desc {
  font: 500 11px/1.3 'Rajdhani', sans-serif;
  color: var(--text-sec);
  letter-spacing: 0.5px;
}
/* Hide during forge preview */
body.forge-board-active #decision-prompt { display: none !important; }
body.forge-board-active #interrupt-banner { display: none !important; }

/* ══════════════════════════════════════════════════════════════
   Interrupt Banner — stratagem reaction prompt with countdown
   Issue #222. Issue #269: `.faction-b` re-points the accent
   channels; faction A matches the (cyan) defaults — no .faction-a
   block so the default IS the source of truth for A.
══════════════════════════════════════════════════════════════ */
.interrupt-banner {
  --ib-border:    color-mix(in srgb, var(--faction-a) 55%, transparent);
  --ib-glow:      color-mix(in srgb, var(--faction-a) 15%, transparent);
  --ib-title:     var(--faction-a);
  --ib-cp:        color-mix(in srgb, var(--faction-a) 60%, transparent);
  --ib-cd-bg:     color-mix(in srgb, var(--faction-a) 15%, transparent);
  --ib-cd-from:   color-mix(in srgb, var(--faction-a) 80%, transparent);
  --ib-cd-to:     color-mix(in srgb, var(--faction-a) 50%, transparent);
  --ib-btn-bg:    color-mix(in srgb, var(--faction-a) 12%, transparent);
  --ib-btn-bd:    color-mix(in srgb, var(--faction-a) 50%, transparent);
  --ib-btn-hbg:   color-mix(in srgb, var(--faction-a) 22%, transparent);
  --ib-btn-hbd:   color-mix(in srgb, var(--faction-a) 70%, transparent);
  --ib-btn-hglow: color-mix(in srgb, var(--faction-a) 20%, transparent);

  margin: 6px 0 0;
  padding: 10px 20px 10px;
  background: linear-gradient(180deg, rgba(8,16,24,0.96), rgba(6,12,18,0.92));
  border: 1.5px solid var(--ib-border);
  border-radius: 10px;
  box-shadow: 0 0 14px var(--ib-glow), 0 4px 16px rgba(0,0,0,0.5);
  text-align: center;
  pointer-events: auto;
  animation: ib-fade-in 0.3s ease both;
}
.interrupt-banner.faction-b {
  --ib-border:    color-mix(in srgb, var(--faction-b) 55%, transparent);
  --ib-glow:      color-mix(in srgb, var(--faction-b) 18%, transparent);
  --ib-title:     var(--faction-b);
  --ib-cp:        color-mix(in srgb, var(--faction-b) 60%, transparent);
  --ib-cd-bg:     color-mix(in srgb, var(--faction-b) 15%, transparent);
  --ib-cd-from:   color-mix(in srgb, var(--faction-b) 80%, transparent);
  --ib-cd-to:     color-mix(in srgb, var(--faction-b) 50%, transparent);
  --ib-btn-bg:    color-mix(in srgb, var(--faction-b) 12%, transparent);
  --ib-btn-bd:    color-mix(in srgb, var(--faction-b) 50%, transparent);
  --ib-btn-hbg:   color-mix(in srgb, var(--faction-b) 22%, transparent);
  --ib-btn-hbd:   color-mix(in srgb, var(--faction-b) 70%, transparent);
  --ib-btn-hglow: color-mix(in srgb, var(--faction-b) 25%, transparent);
}
@keyframes ib-fade-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.ib-header {
  display: flex;
  justify-content: center;
  align-items: baseline;
  gap: 12px;
}
.ib-title {
  font: normal 400 14px/1 'Anton', sans-serif;
  letter-spacing: 3px;
  color: var(--ib-title);
  text-transform: uppercase;
}
.ib-cp {
  font: 600 9px/1 'Rajdhani', sans-serif;
  letter-spacing: 1px;
  color: var(--ib-cp);
  text-transform: uppercase;
}
.ib-subtitle {
  font: 600 10px/1.3 'Rajdhani', sans-serif;
  letter-spacing: 1.2px;
  color: var(--text-sec);
  text-transform: uppercase;
  margin: 4px 0 6px;
}
.ib-countdown {
  height: 3px;
  background: var(--ib-cd-bg);
  border-radius: 2px;
  overflow: hidden;
  margin: 0 0 8px;
}
.ib-countdown-bar {
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, var(--ib-cd-from), var(--ib-cd-to));
  border-radius: 2px;
  transition: none;
}
.ib-actions {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: center;
}
.ib-btn {
  width: 100%;
  max-width: 280px;
  padding: 7px 16px;
  border-radius: 5px;
  cursor: pointer;
  font: 700 10px/1 'Rajdhani', sans-serif;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
.ib-accept {
  background: var(--ib-btn-bg);
  border: 1px solid var(--ib-btn-bd);
  color: var(--ib-title);
}
.ib-accept:hover {
  background: var(--ib-btn-hbg);
  border-color: var(--ib-btn-hbd);
  box-shadow: 0 0 10px var(--ib-btn-hglow);
}
.ib-decline {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.15);
  color: var(--text-muted);
}
.ib-decline:hover {
  background: rgba(255,255,255,0.08);
  border-color: rgba(255,255,255,0.3);
}
.ib-decline-round {
  background: transparent;
  border: 1px solid rgba(255,255,255,0.08);
  color: var(--text-dis, rgba(255,255,255,0.3));
  font-size: 9px;
  padding: 5px 16px;
}
.ib-decline-round:hover {
  background: rgba(255,255,255,0.04);
  border-color: rgba(255,255,255,0.15);
  color: var(--text-muted);
}

/* ── Multi-candidate picker (issue #128 — overwatch against multi-target
   charge declarations). Rendered above the accept/decline row when the
   dispatcher supplies more than one candidate defender. */
.ib-picker-hint {
  font: 600 9px/1 'Rajdhani', sans-serif;
  letter-spacing: 1px;
  color: var(--ib-cp);
  text-transform: uppercase;
  margin: 2px 0 4px;
}
.ib-picker {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 160px;
  overflow-y: auto;
  margin: 0 0 8px;
}
.ib-picker-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 7px 10px;
  border-radius: 4px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.1);
  color: var(--text-sec);
  font: 600 10px/1 'Rajdhani', sans-serif;
  letter-spacing: 1px;
  cursor: pointer;
  text-transform: uppercase;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
.ib-picker-row:hover {
  border-color: var(--ib-btn-hbd);
  background: rgba(255,255,255,0.06);
}
.ib-picker-row.selected {
  border-color: var(--ib-title);
  background: var(--ib-btn-bg);
  box-shadow: 0 0 8px var(--ib-btn-hglow);
  color: var(--ib-title);
}
.ib-picker-name { letter-spacing: 1.2px; }
.ib-picker-sub {
  opacity: 0.6;
  font-weight: 500;
  font-size: 9px;
}
.ib-accept:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  box-shadow: none;
}

/* ── Error / rejection banners ── */
.error-banner {
  position: fixed; top: 8px; left: 8px; right: 8px;
  color: #fff; padding: 8px 12px;
  font: 700 11px/1.5 monospace; z-index: 9999; border-radius: 3px;
}
.error-banner-js { background: #cc2222; }
.error-banner-promise { background: #cc6600; }

/* Keep deployment markers/objectives visible in forge preview.
   James explicitly wants the battleforge board to retain these overlays. */
