@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600;700;800&display=swap');

/* ============================================
   ASHEN THRONE - Dark Steel UI Theme
   ============================================ */

:root {
  /* ---- Backgrounds ---- */
  --bg-dark: #0a0a14;
  --bg-darker: #060610;
  --bg-panel: #111827;
  --bg-panel-hover: #1a2235;
  --bg-slot: #0d1520;
  --bg-slot-hover: #152030;
  --bg-input: #0d0d18;
  --bg-overlay: rgba(6, 6, 14, 0.95);

  /* Chrome-panel texture overlays. Layered over assets/icons/chrome_panel.jpg
     to replace `background-blend-mode: overlay`, which renders inconsistently
     on iOS Safari. The rgba layer darkens the texture consistently everywhere. */
  --chrome-overlay-screen: rgba(10, 10, 20, 0.78);
  --chrome-overlay-panel: rgba(17, 24, 39, 0.82);

  /* ---- Borders ---- */
  --border-steel: #2a3040;
  --border-subtle: #1a2030;
  --border-glow: #4fc3f7;
  --border-gold: #ffd700;

  /* ---- Text ---- */
  /* Greys brightened for readability — old values (#888, #555) were hard to read
     on the dark backgrounds. --text-dim now matches .nav-btn (#b0b0b0). */
  --text-primary: #e0e0e0;
  --text-secondary: #c8c8c8;
  --text-dim: #b0b0b0;
  --text-bright: #fff;

  /* ---- Accent Colors ---- */
  --accent-cyan: #4fc3f7;
  --accent-orange: #ff9800;
  --accent-green: #66bb6a;
  --accent-red: #ef5350;
  --accent-purple: #e040fb;
  --accent-gold: #ffd700;
  --accent-blue: #42a5f5;

  /* ---- Class Colors (Kinetic/Electric/Psionic) ---- */
  --class-kinetic: #ef5350;
  --class-electric: #ff9800;
  --class-psionic: #26c6da;

  /* ---- Tier Colors ---- */
  --tier-1: #888;
  --tier-2: #4fc3f7;
  --tier-3: #ffd700;

  /* ---- Rarity Colors ---- */
  --rarity-common: #888;
  --rarity-rare: #42a5f5;
  --rarity-epic: #e040fb;
  --rarity-legendary: #ffd700;

  /* ---- Skill Type Colors ---- */
  --skill-power: #e040fb;
  --skill-skill: #ffd54f;
  --skill-strike: #ef5350;

  /* ---- Site Type Colors ---- */
  --site-generator: #ffd54f;
  --site-fabrication: #9e9e9e;
  --site-hydroponic: #66bb6a;
  --site-archive: #42a5f5;
  --site-signal: #e040fb;
  --site-catalyst: #ffd700;

  /* ---- Spacing ---- */
  --space-xs: 2px;
  --space-sm: 4px;
  --space-md: 8px;
  --space-lg: 12px;
  --space-xl: 16px;
  --space-2xl: 24px;

  /* ---- Typography ---- */
  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Consolas, Menlo, monospace;
  --font-xs: 9px;
  --font-sm: 10px;
  --font-md: 11px;
  --font-lg: 12px;
  --font-xl: 14px;
  --font-2xl: 16px;
  --font-3xl: 20px;
  --font-heading: 13px;

  /* ---- Border Radius ---- */
  --radius-sm: 3px;
  --radius-md: 4px;
  --radius-lg: 6px;
  --radius-xl: 8px;
  --radius-pill: 12px;
  --radius-full: 50%;
}

/* ============================================
   Panel Components
   ============================================ */
.panel {
  background-color: var(--bg-panel);
  border: 1px solid var(--border-steel);
  border-radius: 6px;
  padding: 16px;
  background-image:
    linear-gradient(var(--chrome-overlay-panel), var(--chrome-overlay-panel)),
    url('assets/icons/chrome_panel.jpg');
  background-size: auto, 256px 256px;
  background-repeat: repeat, repeat;
}

.panel-header {
  font-size: 13px;
  font-family: var(--font-mono);
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border-steel);
}

.panel-glow {
  border-color: var(--border-glow);
  box-shadow: 0 0 8px rgba(79, 195, 247, 0.15);
}

/* ============================================
   Buttons
   ============================================ */
/* Legacy .btn / .btn-primary / .btn-danger / .btn-success / .btn-warning
   /.btn-gold / .btn-ghost / .btn-sm / .btn-lg / .btn-block / .btn-disabled
   live in client/styles/ashen.css with the v2 gradient-fill + cyan-tint
   look. They used to be duplicated here with a flat-cyan legacy style,
   but that shadowed the v2 variants because styles.css loads after
   ashen.css in the cascade. Removed so ashen.css wins.
   Tactical buttons on legacy screens inherit the v2 treatment
   automatically (gradient fill, uppercase, 1.5px tracking). */

/* ============================================
   Cards (items, units, commanders)
   ============================================ */
.ds-card {
  display: flex; align-items: center; gap: var(--space-lg);
  padding: var(--space-lg) var(--space-xl);
  background: var(--bg-dark);
  border: 1px solid var(--border-steel);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: border-color 0.2s;
}
.ds-card:hover { border-color: var(--accent-cyan); }
.ds-card-icon {
  width: 36px; height: 36px; border-radius: var(--radius-lg);
  display: flex; align-items: center; justify-content: center;
  font-size: 18px; flex-shrink: 0;
}
.ds-card-body { flex: 1; min-width: 0; }
.ds-card-title { font-family: var(--font-mono); font-size: var(--font-lg); color: var(--text-primary); font-weight: bold; }
.ds-card-subtitle { font-family: var(--font-mono); font-size: var(--font-sm); color: var(--text-secondary); margin-top: var(--space-xs); }
.ds-card-count {
  font-family: var(--font-mono); font-size: var(--font-2xl); font-weight: bold;
  min-width: 30px; text-align: right; flex-shrink: 0;
}

/* ============================================
   Badges — additional variants only. Base .badge rule lives in
   client/styles/ashen.css (inline-flex, height 16px, gap 4px,
   1.2px letter-spacing — v2). styles.css used to duplicate the
   base with display:inline-block + looser spacing, shadowing the
   v2 flex-with-gap layout.

   Variants below extend the ashen base with app-specific classes
   that ashen doesn't provide (skill types, valence, rarity-common).
   ============================================ */
.badge-common { color: var(--rarity-common); }
.badge-power { background: rgba(255,152,0,0.1); color: var(--skill-power); }
.badge-skill { background: rgba(255,213,79,0.1); color: var(--skill-skill); }
.badge-strike { background: rgba(239,83,80,0.1); color: var(--skill-strike); }
/* Valence badges — green=good (win, gain), red=bad (loss, penalty).
   Sit on top of class-identity colors per the game's two-color-systems
   convention (class = identity, valence = outcome). */
.badge-success { background: rgba(102,187,106,0.15); color: var(--accent-green); border: 1px solid rgba(102,187,106,0.35); }
.badge-danger  { background: rgba(239,83,80,0.15);  color: var(--accent-red);   border: 1px solid rgba(239,83,80,0.35); }

/* ============================================
   Stat Rows
   ============================================ */
.stat-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--space-sm) 0;
  font-family: var(--font-mono); font-size: var(--font-md);
}
.stat-label { color: var(--text-secondary); }
.stat-value { color: var(--text-primary); font-weight: bold; }
.stat-value.positive { color: var(--accent-green); }
.stat-value.negative { color: var(--accent-red); }
.stat-value.gold { color: var(--accent-gold); }
.stat-clickable { cursor: pointer; text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 2px; }
.stat-clickable:hover { color: var(--accent-cyan); }

/* ============================================
   Tab Bar
   ============================================ */
.tab-bar { display: flex; border-bottom: 1px solid var(--border-subtle); }
.tab-item {
  flex: 1; text-align: center; padding: var(--space-md) 0; cursor: pointer;
  font-family: var(--font-mono); font-size: var(--font-sm); letter-spacing: 1px;
  color: var(--text-dim); border-bottom: 2px solid transparent;
  transition: all 0.2s;
}
.tab-item:hover { color: var(--text-secondary); }
.tab-item.active { color: var(--accent-cyan); border-bottom-color: var(--accent-cyan); }

/* Filter pills — canonical styles in client/styles/ashen.css §8 (segmented
   control). Per-screen scoped overrides (e.g. .history-filter below) live
   in this file but the base shape is owned by ashen.css. */

/* ============================================
   Progress Bars
   ============================================ */
.progress-bar { height: 6px; background: var(--bg-slot); border-radius: var(--radius-sm); overflow: hidden; }
.progress-fill { height: 100%; border-radius: var(--radius-sm); transition: width 0.3s; }
.progress-fill.green { background: var(--accent-green); }
.progress-fill.cyan { background: var(--accent-cyan); }
.progress-fill.red { background: var(--accent-red); }
.progress-fill.gold { background: var(--accent-gold); }
.progress-fill.orange { background: var(--accent-orange); }

/* ============================================
   Screen Layout Helpers
   ============================================ */
.screen-header {
  font-family: var(--font-mono); font-size: var(--font-heading);
  color: var(--text-secondary); text-transform: uppercase; letter-spacing: 1px;
  padding: var(--space-lg) var(--space-xl); border-bottom: 1px solid var(--border-subtle);
}
.screen-body { padding: var(--space-md) var(--space-sm); overflow-y: auto; }
.screen-section { margin-bottom: var(--space-xl); }
.section-label {
  font-family: var(--font-mono); font-size: var(--font-sm); color: var(--text-dim);
  text-transform: uppercase; letter-spacing: 1px;
  margin-bottom: var(--space-sm); padding-bottom: var(--space-sm);
  border-bottom: 1px solid var(--border-subtle);
}

/* ============================================
   Dividers
   ============================================ */
.divider { height: 1px; background: linear-gradient(90deg, transparent, var(--border-steel), transparent); margin: var(--space-lg) 0; }
.divider-subtle { height: 1px; background: var(--border-subtle); margin: var(--space-md) 0; }

/* ============================================
   Inputs
   ============================================ */
.ds-input {
  width: 100%; padding: var(--space-md) var(--space-lg);
  background: var(--bg-input); border: 1px solid var(--border-steel);
  border-radius: var(--radius-md); color: var(--text-primary);
  font-family: var(--font-mono); font-size: var(--font-md); outline: none;
}
.ds-input:focus { border-color: var(--accent-cyan); }
.ds-select {
  padding: var(--space-sm); background: var(--bg-input); border: 1px solid var(--border-steel);
  border-radius: var(--radius-sm); color: var(--text-primary);
  font-family: var(--font-mono); font-size: var(--font-md);
}

/* ============================================
   Utility Classes — most duplicates removed. Canonical text-*,
   flex-*, gap-*, mb-*, p-* utilities live in client/styles/ashen.css
   (v2 design system). Keeping only app-specific ones here.
   ============================================ */
.text-mono { font-family: var(--font-mono); }
.text-primary { color: var(--text-primary); }
.hidden { display: none !important; }
.clickable { cursor: pointer; }
.no-select { user-select: none; }

/* ============================================
   Formation Grid
   ============================================ */
.formation-grid {
  display: grid;
  gap: 6px;
}

.formation-grid-3x2 {
  grid-template-columns: repeat(3, 1fr);
}

.formation-slot {
  background: var(--bg-slot);
  border: 1px solid var(--border-steel);
  border-radius: 4px;
  padding: 8px;
  min-height: 70px;
  cursor: pointer;
  transition: all 0.15s;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.formation-slot:hover {
  background: var(--bg-slot-hover);
  border-color: var(--accent-cyan);
}

.formation-slot.has-unit {
  border-color: var(--border-steel);
}


.formation-slot .slot-label {
  font-size: 9px;
  color: var(--text-dim);
  text-transform: uppercase;
  position: absolute;
  top: 3px;
  right: 5px;
}

.formation-slot .unit-img {
  width: 48px;
  height: 64px;
  border-radius: 3px;
  object-fit: cover;
  margin-bottom: 4px;
  background: var(--bg-panel);
}

.formation-slot .unit-name {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-primary);
  font-weight: bold;
}

.formation-slot .unit-class-tag {
  font-size: 9px;
  padding: 1px 4px;
  border-radius: 2px;
  font-family: var(--font-mono);
  margin-bottom: 2px;
}


.formation-slot .unit-count {
  font-family: var(--font-mono);
  font-size: 13px;
  color: #fff;
}

.formation-slot .unit-empty {
  color: var(--text-dim);
  font-size: 11px;
  font-family: var(--font-mono);
}

/* HP Bar inside slots */
.hp-bar {
  width: 100%;
  height: 4px;
  background: #1a1a2a;
  border-radius: 2px;
  margin-top: 4px;
  overflow: hidden;
}

.hp-bar-fill {
  height: 100%;
  border-radius: 2px;
  transition: width 0.3s;
}

.hp-bar-fill.hp-high { background: var(--accent-green); }
.hp-bar-fill.hp-mid { background: var(--accent-gold); }
.hp-bar-fill.hp-low { background: var(--accent-red); }

/* ============================================
   Unit List (Army screen left side)
   ============================================ */
.unit-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 4px;
  transition: background 0.1s;
}

.unit-row:hover { background: var(--bg-panel-hover); }

.unit-row .unit-icon {
  width: 32px;
  height: 32px;
  border-radius: 3px;
  object-fit: cover;
  background: var(--bg-slot);
  border: 1px solid var(--border-steel);
}

.unit-row .unit-info {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.unit-row .unit-info .name {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-primary);
}

.unit-row .unit-info .meta {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
}

.unit-row .unit-count {
  font-family: var(--font-mono);
  font-size: 14px;
  color: #fff;
  min-width: 40px;
  text-align: right;
}

/* ============================================
   Resource Bar (HUD top)
   ============================================ */
.resource-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  /* Left padding mirrors the gap between the avatar and the first
     resource pill so the avatar feels evenly inset from the screen edge. */
  padding: 0 8px 0 12px;
  height: 36px;
  /* 20% upscale of the entire top bar — icons, pills, fonts, gaps. Right-
     side items naturally shift inward because the wider left block pushes
     against them. Anchors below (.screen-overlay top, mobile overrides)
     are bumped from 36/32 → 43/38 to follow the scaled bar height. */
  zoom: 1.2;
  background: linear-gradient(180deg, rgba(17,20,28,0.72) 0%, rgba(10,12,20,0.72) 100%);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(26,31,44,0.9);
  position: relative;
}
.resource-bar::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -1px; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(79,195,247,0.25), transparent);
  pointer-events: none;
}

/* Commander avatar (replaces the dossier logo). Square, full-height,
   class-colored 2px border — matches the dossier-card avatar treatment.
   Border color is applied inline via JS based on the featured commander's
   unitClass (kinetic red / electric orange / psionic cyan). */
.hud-cmd-avatar {
  width: 28px;
  height: 28px;
  /* Adds 6px on top of the 8px flex gap → ~14px visual gap to the first
     resource pill (~175 % of the inter-pill gap, matches the spacing
     between resource values and the next icon). */
  margin-right: 6px;
  cursor: pointer;
  overflow: hidden;
  flex-shrink: 0;
  border: 1px solid var(--border-steel);
  background: #0a0d14;
  box-shadow: 0 2px 6px rgba(0,0,0,0.6);
  box-sizing: border-box;
}
/* The HUD avatar drops the class-coloured border ring (no orange/red
   ring for kinetic commanders, etc) — JS still writes border-color, so
   pin it back to neutral steel here. */
#hud-cmd-avatar-btn {
  border-color: var(--border-steel) !important;
}

/* Profile-screen overrides for the shared top HUD. Only the avatar + an
   identity line (name + "Active since…") show on the left; the rest of
   the bar is suppressed. A BACK button anchors to the right edge.
   We also force the profile overlay back BELOW the HUD (top:36px) — the
   global `.screen-overlay.no-top-bar` rule would otherwise cover the
   whole HUD chrome on non-canvas screens. */
body.on-profile #hud-top-left .resource-item { display: none; }
body.on-profile #hud-haul { display: none !important; }
body.on-profile #hud-profile-identity { display: flex !important; }
body.on-profile #hud-profile-back { display: inline-flex !important; }
body.on-profile #hud-base-alert-preview { display: none; }
body.on-profile #hud-top-map { display: none !important; }
body.on-profile #hud-top-resources { display: flex !important; }
body.on-profile #profile-overlay { top: 43px !important; padding: 16px !important; }

#hud-profile-back {
  margin-left: auto;
  align-self: center;
  padding: 6px 18px;
  background: rgba(79,195,247,0.12);
  border: 1px solid rgba(79,195,247,0.55);
  border-radius: 4px;
  color: var(--accent-cyan);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 2px;
  font-weight: 700;
  cursor: pointer;
}
#hud-profile-back:hover {
  background: rgba(79,195,247,0.22);
  border-color: var(--accent-cyan);
}

.hud-cmd-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.resource-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 8px 3px 2px;
  background: transparent;
  border: none;
  border-radius: 0;
  transition: background 0.15s;
}
.resource-item:hover {
  background: rgba(79,195,247,0.06);
}

.resource-item .res-icon {
  width: 22px;
  height: 22px;
  border-radius: 3px;
  object-fit: contain;
}

.resource-item-compact { gap: 3px; padding: 2px 6px 2px 3px; }
.resource-item-compact .res-icon { width: 18px; height: 18px; }
.resource-item-compact .res-value {
  font-size: 10px;
  line-height: 1.1;
  margin-top: 4px;     /* drop the totals a few px from the top edge */
  /* Nudge totals down+right by 2px without shifting the rate below.
     transform doesn't affect layout flow, so the .res-rate stays put. */
  transform: translate(2px, 2px);
}
.resource-item-compact .res-rate {
  font-size: 9px;
  font-weight: 700;
  line-height: 1;
  color: #8a8a8a;
  font-family: var(--font-mono);
  margin-top: 4px;     /* breathing room between total and per-hour gain */
}

.resource-item .res-icon-placeholder {
  width: 20px;
  height: 20px;
  border-radius: 3px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-family: var(--font-mono);
  font-weight: bold;
}

.resource-item .res-value {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  font-variant-numeric: tabular-nums;
}

.resource-item .res-cap {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  display: none;
}

/* ============================================
   Nav Bar (bottom)
   ============================================ */
.nav-bar {
  display: flex;
  height: 40px;
  background: linear-gradient(180deg, rgba(10,12,20,0.72) 0%, rgba(5,8,16,0.72) 100%);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-top: 1px solid rgba(26,31,44,0.9);
  position: relative;
  /* Matches the .resource-bar zoom:1.2 — scales nav buttons, chat input,
     and chat preview as a single proportional unit. Anchors that sit on
     top of the bar (chat-expanded bottom, .screen-overlay bottom, mobile
     calc heights) are bumped 40/36/32 → 48/43/38 to follow. */
  zoom: 1.2;
}
.nav-bar::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: -1px; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(79,195,247,0.25), transparent);
  pointer-events: none;
}

.nav-group {
  display: flex;
  flex-shrink: 0;
}

/* Brief blue pulse on a nav button to suggest "this is what you just
   pointed at via another shortcut" (currently fired when the crawler
   pill in the top-right HUD is clicked → flashes CRAWLER). */
.nav-btn-flash {
  animation: nav-btn-flash 0.8s ease-out;
}
@keyframes nav-btn-flash {
  0%   { background: rgba(79,195,247,0); box-shadow: none; color: inherit; }
  20%  { background: rgba(79,195,247,0.45); box-shadow: 0 0 14px rgba(79,195,247,0.7); color: #fff; }
  100% { background: rgba(79,195,247,0); box-shadow: none; color: inherit; }
}

.nav-btn {
  width: 80px;
  height: 100%;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  color: var(--text-dim);
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
  text-transform: uppercase;
  letter-spacing: 1.8px;
  border: none;
  background: none;
  padding: 0;
}

.nav-btn:hover { color: var(--text-bright); background: rgba(79,195,247,0.05); }
.nav-btn.active {
  color: var(--accent-cyan);
  background: transparent;
}
/* Top indicator line for active tab (design: 2px cyan bar, cyan glow, inset from edges). */
.nav-btn.active::before {
  content: '';
  position: absolute;
  top: 0;
  left: 20%;
  right: 20%;
  height: 2px;
  background: var(--accent-cyan);
  box-shadow: 0 0 6px var(--accent-cyan);
}
/* SHOP tab — no special styling; sits in line with the other nav
   buttons. */

/* ============================================================
   MEGATOWER (Sunken Arcology) — popup modal
   z-index 35 so chat panel at z 60 stays on top and interactive.
   Backdrop 60% opacity; main box ~85vw × 85vh, centered.
   ============================================================ */
.megatower-overlay {
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(0,0,0,0.6);
  backdrop-filter: blur(1.5px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 35;
}
.megatower-overlay.hidden { display: none; }
.mt-modal {
  width: 90%;
  max-width: 1200px;
  height: 85%;
  max-height: 700px;
  background:
    linear-gradient(180deg, rgba(15,20,35,0.95), rgba(5,8,15,0.98));
  border: 1px solid #1f2738;
  border-radius: 4px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.7), inset 0 1px 0 rgba(255,255,255,0.04);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  color: var(--text-primary);
  font-family: var(--font-mono);
}
.mt-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-bottom: 1px solid #1a2030;
  flex-shrink: 0;
}
.mt-header .mt-title {
  font: 500 14px/1 var(--font-mono);
  letter-spacing: 2.5px;
  text-transform: uppercase;
  color: var(--text-primary);
}
.mt-header .mt-subtitle {
  font: 9px/1 var(--font-mono);
  letter-spacing: 1.4px;
  color: var(--text-dim);
  margin-top: 4px;
}
.mt-header .mt-spacer { flex: 1; }
.mt-timer {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 5px 10px;
  background: rgba(20,30,50,0.65);
  border: 1px solid #253248;
  border-radius: 3px;
}
.mt-timer .dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent-cyan);
  box-shadow: 0 0 6px rgba(79,195,247,0.6);
}
.mt-timer.warn { border-color: #4a3220; }
.mt-timer.warn .dot { background: var(--accent-orange); box-shadow: 0 0 6px rgba(255,152,0,0.6); }
.mt-timer.warn .val { color: var(--accent-orange); }
.mt-timer.danger { border-color: #4a2222; }
.mt-timer.danger .dot { background: var(--accent-red); box-shadow: 0 0 6px rgba(239,83,80,0.6); }
.mt-timer.danger .val { color: var(--accent-red); }
.mt-timer .lbl { font: 8.5px/1 var(--font-mono); letter-spacing: 1.4px; color: var(--text-dim); text-transform: uppercase; }
.mt-timer .val { font: 600 13px/1 var(--font-mono); color: var(--accent-cyan); letter-spacing: 1px; margin-top: 2px; }
.mt-header .mt-floor-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  background: rgba(8,12,22,0.6);
  border: 1px solid #2a3040;
  border-radius: 3px;
  font: 9px/1 var(--font-mono);
  letter-spacing: 1.2px; text-transform: uppercase; color: var(--text-dim);
}
.mt-header .mt-floor-chip .v { color: var(--accent-cyan); margin-left: 4px; }
.mt-btn {
  padding: 6px 12px;
  background: transparent;
  border: 1px solid #2a3040;
  color: var(--text-dim);
  font: 9.5px/1 var(--font-mono);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  cursor: pointer;
  border-radius: 2px;
}
.mt-btn:hover { color: var(--text-primary); border-color: #404a60; }
.mt-btn.danger:hover { color: var(--accent-red); border-color: var(--accent-red); }
.mt-btn.primary {
  background: rgba(79,195,247,0.1);
  border-color: rgba(79,195,247,0.4);
  color: var(--accent-cyan);
}
.mt-btn.primary:hover { background: rgba(79,195,247,0.2); }
.mt-btn.success {
  background: rgba(102,187,106,0.1);
  border-color: rgba(102,187,106,0.4);
  color: var(--accent-green);
}
.mt-btn.success:hover { background: rgba(102,187,106,0.2); }
.mt-btn:disabled { opacity: 0.35; cursor: not-allowed; }

.mt-body {
  flex: 1;
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 8px;
  padding: 8px;
  min-height: 0;
}
.mt-spine {
  background: linear-gradient(180deg, rgba(15,20,35,0.4), rgba(8,10,18,0.6));
  border: 1px solid #151c2a;
  border-radius: 3px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.mt-spine-hdr {
  padding: 8px 10px 6px;
  border-bottom: 1px solid #151c2a;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}
.mt-spine-hdr .title {
  font: 9.5px/1 var(--font-mono); letter-spacing: 1.8px;
  text-transform: uppercase; color: var(--text-dim);
}
.mt-spine-hdr .zone {
  font: 9px/1 var(--font-mono); letter-spacing: 1.3px;
  color: var(--accent-orange); text-transform: uppercase;
}
.mt-spine-body {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column-reverse;   /* floor 1 at the bottom */
  padding: 4px 0;
}
.mt-floor-row {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 10px 5px 28px;
  font: 10px/1 var(--font-mono);
  height: 26px;
  position: relative;
  cursor: default;
}
.mt-floor-row::before {
  content: ''; position: absolute; left: 17px; top: 0; bottom: 0;
  width: 1px; background: #1f2738;
}
.mt-floor-row::after {
  content: ''; position: absolute; left: 13px; top: 50%;
  width: 9px; height: 1px; background: #2a3040; transform: translateY(-0.5px);
}
.mt-floor-row .num {
  font: 600 10px/1 var(--font-mono); letter-spacing: 1px;
  color: var(--text-dim); width: 22px; text-align: right;
}
.mt-floor-row .state {
  flex: 1; font-size: 9px; letter-spacing: 1px;
  text-transform: uppercase; color: var(--text-dim);
}
.mt-floor-row.cleared .num { color: var(--accent-cyan); opacity: 0.55; }
.mt-floor-row.cleared .state { color: var(--text-dim); opacity: 0.55; }
.mt-floor-row.cleared::after { background: var(--accent-cyan); opacity: 0.5; }
.mt-floor-row.milestone-cleared .num { color: var(--accent-gold); }
.mt-floor-row.milestone-cleared .state { color: var(--accent-gold); opacity: 0.8; }
.mt-floor-row.milestone-cleared::after { background: var(--accent-gold); box-shadow: 0 0 4px rgba(255,215,0,0.5); }
.mt-floor-row.current {
  background: linear-gradient(90deg, rgba(79,195,247,0.14), transparent);
}
.mt-floor-row.current .num { color: var(--accent-cyan); font-size: 12px; }
.mt-floor-row.current .state { color: var(--text-primary); font-weight: 500; }
.mt-floor-row.current::after {
  background: var(--accent-cyan);
  width: 13px; height: 3px;
  box-shadow: 0 0 10px rgba(79,195,247,0.9); left: 12px;
}
.mt-floor-row.locked .num, .mt-floor-row.locked .state { color: #2a3040; }
.mt-floor-row.choice::before { background: linear-gradient(180deg, var(--accent-orange), #1f2738 55%); }
.mt-floor-row.milestone .num::after { content: '★'; color: var(--accent-gold); font-size: 7px; margin-left: 2px; }

/* Detail column wraps the fight detail panel + its own footer so the
   footer sits under the detail area only — the spine (left column of
   mt-body) spans from header to modal bottom at full height. */
.mt-detail-column {
  display: flex;
  flex-direction: column;
  gap: 0;
  min-height: 0;
  min-width: 0;
}
.mt-detail {
  background: linear-gradient(180deg, rgba(15,20,35,0.35), rgba(8,10,18,0.5));
  border: 1px solid #151c2a;
  border-radius: 3px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 0;
  flex: 1;            /* eat remaining vertical space; footer hugs the bottom */
}
.mt-detail-body {
  flex: 1;
  overflow-y: auto;
  padding: 10px 12px;
}
/* Title + opponent render on the same line — title left, opponent right.
   Both baseline-aligned, gap collapses cleanly on narrow viewports. */
.mt-detail-title-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 14px;
  margin-bottom: 10px;
}
.mt-detail-title {
  font: 500 14px/1 var(--font-mono);
  letter-spacing: 1.8px;
  color: var(--text-primary);
  text-transform: uppercase;
}
.mt-detail-meta {
  font: 9px/1 var(--font-mono);
  letter-spacing: 1.4px;
  color: var(--text-dim);
  text-transform: uppercase;
  text-align: right;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 55%;
}
.mt-detail-meta .kin { color: #ff9b99; }
.mt-detail-meta .elc { color: #ffbf80; }
.mt-detail-meta .psi { color: #80d5f3; }

.mt-footer {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  margin-top: 8px;
  border: 1px solid #1a2030;
  border-radius: 3px;
  flex-shrink: 0;
  background: rgba(5,8,15,0.55);
}
.mt-cmd-thumbs { display: flex; gap: 8px; }
.mt-cmd-thumb {
  width: 46px; height: 46px;
  border: 1px solid #2a3850;
  border-radius: 2px;
  background: #0c1220;
  display: grid; place-items: center;
  font: 600 14px/1 var(--font-mono);
  color: var(--text-dim);
  cursor: pointer;
  overflow: hidden;
  position: relative;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.mt-cmd-thumb img { width: 100%; height: 100%; object-fit: cover; }
.mt-cmd-thumb:hover { border-color: var(--text-primary); }
.mt-cmd-thumb.active {
  border-color: var(--accent-cyan);
  box-shadow: 0 0 10px rgba(79,195,247,0.45);
}
/* Injured commander thumbs are dimmed but still clickable — the player may
   want to select an injured commander to manage their equipped skill cards.
   ENGAGE is guarded separately so an injured commander can't lead a fight. */
.mt-cmd-thumb.injured {
  opacity: 0.45;
  filter: grayscale(0.6);
}
.mt-cmd-thumb.injured:hover { border-color: rgba(239,83,80,0.55); opacity: 0.6; }
/* Class color band on the left edge of each thumb */
.mt-cmd-thumb::before {
  content: '';
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: 3px;
  background: var(--text-dim);
}
.mt-cmd-thumb.class-kinetic::before  { background: var(--class-kinetic); }
.mt-cmd-thumb.class-electric::before { background: var(--class-electric); }
.mt-cmd-thumb.class-psionic::before  { background: var(--class-psionic); }
/* Level pip in the bottom-right corner */
.mt-cmd-thumb .lvl {
  position: absolute;
  bottom: 0; right: 0;
  padding: 1px 3px;
  background: rgba(8,12,22,0.85);
  font: 600 8px/1 var(--font-mono);
  color: var(--text-primary);
  border-top-left-radius: 2px;
}
.mt-cmd-name {
  font: 9px/1.3 var(--font-mono);
  letter-spacing: 1px;
  color: var(--text-primary);
  text-transform: uppercase;
  margin-left: 2px;
}

/* Side-by-side formation preview pair (used in pre-flight + post-fight) */
.mt-form-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-top: 10px;
}
.mt-form-card {
  position: relative;
  background: rgba(8,12,22,0.55);
  border: 1px solid #1f2738;
  border-radius: 3px;
  padding: 12px;
  display: flex;
  flex-direction: column;
}
.mt-form-card.enemy { border-color: rgba(239,83,80,0.3); }
.mt-form-card.you   { border-color: rgba(79,195,247,0.3); }

/* Corner bracket ornaments — matches the designer's formation card spec */
.mt-form-card::before,
.mt-form-card::after {
  content: '';
  position: absolute;
  width: 10px; height: 10px;
  pointer-events: none;
}
.mt-form-card.you::before,
.mt-form-card.you::after   { border: 1px solid rgba(79,195,247,0.4); }
.mt-form-card.enemy::before,
.mt-form-card.enemy::after { border: 1px solid rgba(239,83,80,0.4); }
.mt-form-card::before { top: -1px; left: -1px; border-right: none; border-bottom: none; }
.mt-form-card::after  { bottom: -1px; right: -1px; border-left: none; border-top: none; }

/* Card header — side label (YOU / ENEMY) + power */
.mt-fc-header {
  /* Stacked: side-label on line 1, power readout on line 2. Keeps the
     header narrow so the fc-header doesn't push the form-col wider than
     the underlying 3×2 grid. */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding-bottom: 5px;
  margin-bottom: 6px;
  border-bottom: 1px dashed #1f2738;
}
.mt-fc-header .side-label {
  font: 600 10px/1 var(--font-mono);
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: var(--text-primary);
}
/* Side-label tint follows the border color — player cyan, enemy red.
   These selectors target both the legacy .mt-form-card host and the
   new .mt-fight-side host so either scope gets the color. */
.mt-form-card.enemy   .mt-fc-header .side-label,
.mt-fight-side.enemy  .mt-fc-header .side-label { color: var(--accent-red); }
.mt-form-card.you     .mt-fc-header .side-label,
.mt-fight-side.you    .mt-fc-header .side-label { color: var(--accent-cyan); }

/* Power: the NUMBER is the hero. Label becomes a tiny caption above it,
   so the eye reads "→ 400" not "power 400". Uses a small inner flex col
   so the label + value stack cleanly. */
.mt-fc-header .power {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  line-height: 1;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  font: 700 14px/1 var(--font-mono);
  letter-spacing: 0.5px;
}
.mt-fc-header .power .pw-lbl {
  font: 600 7px/1 var(--font-mono);
  letter-spacing: 1.4px;
  color: var(--text-dim);
  text-transform: uppercase;
  margin: 0 0 3px 0;
}
.mt-fight-side.enemy  .mt-fc-header .power { color: var(--accent-red); }
.mt-fight-side.you    .mt-fc-header .power { color: var(--accent-cyan); }

/* Static 3×2 formation grid (read-only, used for the enemy side) — mirrors
   the game's formationGrid layout: 3 rows (col 0/1/2) × 2 cols (BACK | FRONT) */
.mt-fg-grid {
  display: grid;
  grid-template-rows: repeat(3, 1fr);
  gap: 5px;
  min-height: 0;
}
.mt-fg-grid-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 5px;
}
.mt-fg-slot {
  background: #0c1220;
  border: 1px solid #1a2538;
  border-radius: 2px;
  padding: 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 52px;
}
.mt-fg-slot.kin { border-left: 2px solid rgba(239,83,80,0.5); }
.mt-fg-slot.elc { border-left: 2px solid rgba(255,152,0,0.5); }
.mt-fg-slot.psi { border-left: 2px solid rgba(79,195,247,0.5); }
.mt-fg-slot.empty {
  background: repeating-linear-gradient(45deg, transparent 0 4px, rgba(255,255,255,0.015) 4px 5px);
  border-style: dashed;
  min-height: 52px;
}
.mt-fg-slot img { width: 28px; height: 28px; object-fit: cover; border-radius: 2px; }
.mt-fg-slot .n { font: 600 11px/1 var(--font-mono); color: var(--text-primary); font-variant-numeric: tabular-nums; }

.mt-fg-grid-hdr {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 5px;
  font: 9px/1 var(--font-mono);
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-dim);
  text-align: center;
  margin-bottom: 4px;
}
.mt-fg-grid-hdr > span:first-child  { color: #80d5f3; }  /* BACK */
.mt-fg-grid-hdr > span:last-child   { color: #ff9b99; }  /* FRONT */

/* Fight-preview layout:  [player-rail | player-form]   [enemy-form | enemy-rail]
   Two equal-width halves, no VS separator. Each half is a 2-column grid:
   player = rail + form, enemy = form + rail. The formation column is
   centered vertically so the shorter grid sits level with the 4-row rail. */
.mt-fight-pair {
  display: grid;
  /* Three columns: player side | VS chip (auto) | enemy side */
  grid-template-columns: 1fr auto 1fr;
  gap: 14px;
  /* Top-align sides so rails + form-cols share a clean baseline — prevents
     the asymmetric "seasick" look you get when the taller player form
     (presets + leadership bar) is center-aligned against the shorter
     enemy form. */
  align-items: start;
  margin-top: 10px;
}
.mt-fight-side { align-items: start !important; }

/* Center VS chip — anchors the eye between the two mirrored halves and
   communicates relative power at a glance. */
.mt-vs-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 6px 10px;
  align-self: center;   /* stay mid-line between the two forms */
}
.mt-vs-label {
  font: 700 12px/1 var(--font-mono);
  letter-spacing: 2px;
  color: var(--text-dim);
}
.mt-vs-delta {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px 7px;
  border-radius: 10px;
  font: 600 9.5px/1 var(--font-mono);
  letter-spacing: 0.8px;
  border: 1px solid currentColor;
  background: rgba(8,12,22,0.5);
}
.mt-vs-delta .sign { font-size: 8px; line-height: 1; }
.mt-vs-delta.ahead  { color: var(--accent-green); }
.mt-vs-delta.behind { color: var(--accent-red); }
.mt-vs-delta.even   { color: var(--text-dim); }

/* Engage row — the CTA is the most-used action on this screen, so it
   earns its own horizontal band with a wider, more saturated button. */
.mt-engage-row {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: center;
  margin-top: 14px;
}
.mt-btn-engage {
  padding: 10px 26px;
  font-size: 12px;
  letter-spacing: 2px;
  min-width: 180px;
  background: linear-gradient(180deg, rgba(79,195,247,0.22), rgba(79,195,247,0.10));
  border: 1px solid rgba(79,195,247,0.55);
  color: var(--accent-cyan);
  box-shadow: 0 2px 14px rgba(79,195,247,0.18), inset 0 1px 0 rgba(255,255,255,0.06);
  transition: background 0.15s, box-shadow 0.15s, transform 0.1s;
}
.mt-btn-engage:hover {
  background: linear-gradient(180deg, rgba(79,195,247,0.30), rgba(79,195,247,0.16));
  box-shadow: 0 2px 18px rgba(79,195,247,0.32), inset 0 1px 0 rgba(255,255,255,0.08);
}
.mt-btn-engage:active { transform: translateY(1px); }
.mt-btn-engage:disabled { opacity: 0.35; box-shadow: none; transform: none; }
.mt-btn-engage .arrow { margin-left: 4px; font-weight: 700; }
/* Header button icon/full label toggle — full label on desktop, single
   glyph on mobile (see @media block below). */
.mt-btn.mt-btn-mini .icon { display: none; }
.mt-btn.mt-btn-mini .full { display: inline; }

/* Hide the long tutorial hint in the engage row at narrow desktop widths
   (< 1100px). The mt-hide-on-mobile rule already drops it at < 960px;
   between 960 and 1100 it's the wrong copy length for the available space
   and breaks the layout — drop it earlier. */
@media (max-width: 1100px) {
  .mt-engage-row .mt-hide-on-mobile { display: none; }
}

.mt-fight-side {
  display: grid;
  gap: 8px;
  align-items: center;
  min-width: 0;     /* permit the 1fr form col to actually shrink */
}
.mt-fight-side.you {
  /* rail (LEFT) | formation (RIGHT) */
  grid-template-columns: 150px minmax(0, 1fr);
}
.mt-fight-side.enemy {
  /* formation (LEFT) | rail (RIGHT) */
  grid-template-columns: minmax(0, 1fr) 150px;
}
.mt-fight-side .mt-form-col {
  min-width: 0;     /* grid-col: minmax(0,1fr) alone doesn't force the child to respect it; fg-grid has intrinsic min of 2×52+gap = 107px which fits after shrink below */
}
.mt-fight-side .mt-form-col {
  /* Wraps the card header + formation grid + power readout together. */
  background: rgba(8,12,22,0.35);
  border: 1px solid #1f2738;
  border-radius: 3px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  position: relative;
  align-items: center;            /* center the 3×2 grid horizontally */
}
/* Scoped formation-grid shrink — only inside Megatower's form-col.
   Default fg-slot is 52×52 (used in Army + Command screens); here we
   need 40×40 so two side-by-side forms + two rails fit a narrow modal.
   Applies to BOTH player (.fg-slot) and enemy (.fg-slot.fg-static) so
   the two grids are pixel-identical. */
.mt-form-col .fg-slot,
.mt-form-col .fg-slot.fg-static {
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
  border-radius: 4px;
  border-width: 1.5px;
}
.mt-form-col .fg-thumb { width: 36px; height: 36px; }
.mt-form-col .fg-count-overlay {
  font-size: 8px;
  min-width: 12px;
  padding: 1px 2px;
  bottom: 1px;
  right: 1px;
}
.mt-form-col .fg-tier-pip {
  font-size: 8px;
  min-width: 12px;
  padding: 1px 2px;
  top: 1px;
  left: 1px;
}
.mt-form-col .fg-plus { font-size: 14px; }
.mt-form-col .fg-grid { gap: 2px; align-items: center; }
.mt-form-col .fg-row { gap: 2px; justify-content: center; }
.mt-form-col .fg-leadership { width: 100%; font-size: 9px; margin-top: 6px; }

/* Enemy metrics strip — symmetric to the player's leadership bar.
   Holds tier tags (CHOICE / MILESTONE / LV N). Thin row so the enemy
   form-col's bottom aligns with the player's bottom. */
.mt-enemy-metrics {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 3px;
  margin-top: 6px;
  width: 100%;
}
.mt-em-tag {
  font: 600 8px/1 var(--font-mono);
  letter-spacing: 1px;
  text-transform: uppercase;
  padding: 3px 6px;
  border-radius: 2px;
  border: 1px solid currentColor;
  background: rgba(8,12,22,0.5);
}
.mt-em-tag.choice    { color: var(--accent-orange); }
.mt-em-tag.milestone { color: var(--accent-gold); }
.mt-em-tag.lvl       { color: var(--accent-red); }
.mt-em-tag.standard  { color: var(--text-dim); }
/* Preset row at the top of the player form-col */
.mt-presets {
  display: flex;
  gap: 4px;
  align-items: center;
  justify-content: flex-end;
  margin-top: 2px;
}
.mt-presets .plbl {
  font: 8px/1 var(--font-mono); letter-spacing: 1.2px;
  color: var(--text-dim); text-transform: uppercase;
  margin-right: 3px;
}
.mt-presets button {
  width: 22px; height: 20px;
  padding: 0;
  background: transparent;
  border: 1px solid #2a3040;
  color: var(--text-dim);
  font: 600 9px/1 var(--font-mono);
  cursor: pointer;
  border-radius: 2px;
  transition: border-color 0.12s, color 0.12s;
}
.mt-presets button:hover { color: var(--accent-cyan); border-color: var(--accent-cyan); }
.mt-presets button.has { color: var(--accent-cyan); border-color: rgba(79,195,247,0.4); }
.mt-presets button:disabled { opacity: 0.3; cursor: not-allowed; }
.mt-fight-side.you   .mt-form-col { border-color: rgba(79,195,247,0.3); }
.mt-fight-side.enemy .mt-form-col { border-color: rgba(239,83,80,0.3); }
.mt-form-col::before,
.mt-form-col::after {
  content: '';
  position: absolute;
  width: 10px; height: 10px;
  pointer-events: none;
}
.mt-fight-side.you   .mt-form-col::before,
.mt-fight-side.you   .mt-form-col::after   { border: 1px solid rgba(79,195,247,0.4); }
.mt-fight-side.enemy .mt-form-col::before,
.mt-fight-side.enemy .mt-form-col::after   { border: 1px solid rgba(239,83,80,0.4); }
.mt-form-col::before { top: -1px; left: -1px; border-right: none; border-bottom: none; }
.mt-form-col::after  { bottom: -1px; right: -1px; border-left: none; border-top: none; }
.mt-form-col .mt-fc-header {
  margin-bottom: 0;
  padding-bottom: 4px;
}

/* Commander rail — vertical stack of 4 rows, each a thumb + optional text. */
.mt-cmd-rail {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 150px;
  flex-shrink: 0;
}
/* Enemy rail: thumb on the RIGHT of the row, text on the LEFT, but text
   itself stays left-aligned so it won't overflow the row (no RTL mirror). */
.mt-cmd-rail-row {
  display: grid;
  grid-template-columns: 38px 1fr;
  gap: 6px;
  align-items: center;
  padding: 4px 6px;
  background: rgba(8,12,22,0.55);
  border: 1px solid #1a2538;
  border-radius: 2px;
  min-height: 44px;
}
.mt-fight-side.enemy .mt-cmd-rail-row {
  grid-template-columns: 1fr 38px;
}
/* Mirror the player rail using the SAME pattern that works on mobile:
   `order` to swap visual position (DOM stays thumb→text for a11y), and
   text-align: right + width: 100% on the rail-text to make text sit
   adjacent to its thumb. Without `order`, thumb auto-flows into col 1
   (1fr wide) and text gets squeezed into col 2 (38px) — text overflows
   the row by ~50px because of its 94px min-width. */
.mt-fight-side.enemy .mt-cmd-rail-row .mt-rail-thumb { order: 2; }
.mt-fight-side.enemy .mt-cmd-rail-row .rail-text     { order: 1; }
.mt-fight-side.enemy .mt-cmd-rail-row .rail-text {
  text-align: right;
  width: 100%;
  min-width: 0;
}
.mt-fight-side.you .mt-cmd-rail-row .rail-text { text-align: left; }
.mt-cmd-rail-row .rail-text {
  /* Don't let the text column collapse below word-width. At 150px rail width
     minus 38px thumb minus 6px gap minus 12px row padding we have ~94px.
     Font 10px × ~7.5px/glyph + 0.3 letter-spacing = room for ~11 chars,
     which covers JUGGERNAUT (10) and CHARGE (6) without char-breaking. */
  min-width: 94px;
}
.mt-cmd-rail-row.clickable { cursor: pointer; transition: border-color 0.12s, background 0.12s; }
.mt-cmd-rail-row.clickable:hover { border-color: rgba(79,195,247,0.55); background: rgba(20,30,50,0.7); }
/* Active-state tint on the player's commander row (only the top thumb row). */
.mt-cmd-rail-row.active {
  border-color: rgba(79,195,247,0.5);
  box-shadow: 0 0 8px rgba(79,195,247,0.15);
}
.mt-cmd-rail-row.row-cmd .cname-line {
  font: 600 10.5px/1.2 var(--font-mono);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-primary);
  /* Up to 2 lines, ellipsis on overflow. Multi-word names like "THE HOLLOW
     ONE" or "JUGGERNAUT CHARGE" wrap at spaces; long single-word names
     like "DEFIBRILLATOR" fit on one line at 94px (~78px wide). overflow-wrap
     stays as `break-word` only as a last-resort safety net for absurd names. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: normal;
  overflow-wrap: break-word;
}
.mt-cmd-rail-row.row-cmd .cmeta-line {
  font: 8.5px/1.3 var(--font-mono);
  letter-spacing: 1.2px;
  color: var(--text-dim);
  text-transform: uppercase;
  margin-top: 3px;
  /* Single-line with ellipsis. "Lv10 · ELECTRIC · Rank 3" otherwise wraps
     to 3 ugly lines at 94px — the L10 pip on the thumb already shows level
     and the class color reinforces class, so a truncated meta is fine. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mt-cmd-rail-row.row-cmd .cmeta-line .class-kinetic  { color: var(--class-kinetic); }
.mt-cmd-rail-row.row-cmd .cmeta-line .class-electric { color: var(--class-electric); }
.mt-cmd-rail-row.row-cmd .cmeta-line .class-psionic  { color: var(--class-psionic); }

/* Skill rows: chip (42×42) + name/meta line */
.mt-cmd-rail-row.row-skill .skill-name {
  font: 600 9.5px/1.2 var(--font-mono);
  letter-spacing: 0.3px;
  color: var(--text-primary);
  text-transform: uppercase;       /* match Commander / Workshop convention */
  /* Up to 2 lines, ellipsis on overflow — same shape as cname-line. Stops
     "PSYCHIC STORM" / "DEFIBRILLATOR" from spilling past the rail. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: normal;
  overflow-wrap: break-word;
}
.mt-cmd-rail-row.row-skill .skill-meta {
  font: 8.5px/1.3 var(--font-mono);
  letter-spacing: 1.1px;
  color: var(--text-dim);
  text-transform: uppercase;
  margin-top: 3px;
  /* Truncate "INNATE · R3 · POWER" cleanly when it doesn't fit. The R3
     rank pip on the thumb already conveys rank, so losing it to ellipsis
     is acceptable. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mt-cmd-rail-row.row-skill .skill-meta .kind-innate { color: var(--accent-gold); }
.mt-cmd-rail-row.row-skill .skill-meta .rank-num { color: var(--accent-cyan); font-weight: 600; }
.mt-cmd-rail-row.row-skill.empty { opacity: 0.4; }
.mt-cmd-rail-row.row-skill.empty .skill-name { font-style: italic; color: var(--text-dim); }

.mt-rail-thumb {
  width: 38px; height: 38px;
  border: 1px solid #2a3850;
  border-radius: 2px;
  background: #0c1220;
  overflow: hidden;
  display: grid;
  place-items: center;
  font: 600 13px/1 var(--font-mono);
  position: relative;
}
.mt-rail-thumb img { width: 100%; height: 100%; object-fit: cover; }
.mt-rail-thumb.skill img { object-fit: contain; padding: 2px; }
.mt-fight-side.you   .mt-rail-thumb.cmd { border-color: var(--accent-cyan); }
.mt-fight-side.enemy .mt-rail-thumb.cmd { border-color: var(--accent-red); }
.mt-rail-thumb.skill.innate   { border-color: rgba(255,215,0,0.45); }
.mt-rail-thumb.skill.kinetic  { border-color: rgba(239,83,80,0.4); }
.mt-rail-thumb.skill.electric { border-color: rgba(255,152,0,0.4); }
.mt-rail-thumb.skill.psionic  { border-color: rgba(79,195,247,0.4); }
.mt-rail-thumb.skill .abbr {
  font: 600 11px/1 var(--font-mono);
  letter-spacing: 0.3px;
}
.mt-rail-thumb.skill.innate   .abbr { color: var(--accent-gold); }
.mt-rail-thumb.skill.kinetic  .abbr { color: var(--class-kinetic); }
.mt-rail-thumb.skill.electric .abbr { color: var(--class-electric); }
.mt-rail-thumb.skill.psionic  .abbr { color: var(--class-psionic); }
.mt-rail-thumb.skill.empty { opacity: 0.35; border-style: dashed; }
.mt-rail-thumb .rank-pip {
  position: absolute;
  bottom: 1px; right: 1px;
  min-width: 12px;
  padding: 0 2px;
  background: rgba(8,12,22,0.9);
  border: 1px solid rgba(255,215,0,0.5);
  font: 600 8px/1 var(--font-mono);
  color: var(--accent-gold);
  text-align: center;
  border-radius: 1px;
}
.mt-rail-thumb .lvl-pip {
  position: absolute;
  bottom: 1px; right: 1px;
  padding: 1px 3px;
  background: rgba(8,12,22,0.85);
  font: 600 8px/1 var(--font-mono);
  color: var(--text-primary);
  border-top-left-radius: 2px;
}

/* Commander strip at the bottom of each formation card — portrait + name +
   level + innate chip + 2 card chips. Same visual per side; colored border
   by side. */
.mt-cmd-strip {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px dashed #1f2738;
  flex-shrink: 0;
}
.mt-cmd-portrait {
  position: relative;
  width: 44px; height: 44px;
  flex-shrink: 0;
  border: 1px solid #2a3850;
  border-radius: 2px;
  background: #0c1220;
  overflow: hidden;
  display: grid;
  place-items: center;
  font: 600 15px/1 var(--font-mono);
}
.mt-cmd-portrait img { width: 100%; height: 100%; object-fit: cover; }
.mt-form-card.you   .mt-cmd-portrait { border-color: var(--accent-cyan); }
.mt-form-card.enemy .mt-cmd-portrait { border-color: var(--accent-red); }
.mt-cmd-meta {
  flex: 1;
  min-width: 0;
}
.mt-cmd-meta .cname {
  font: 600 11px/1 var(--font-mono);
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mt-cmd-meta .cmeta {
  font: 8.5px/1.4 var(--font-mono);
  letter-spacing: 1.3px;
  color: var(--text-dim);
  text-transform: uppercase;
  margin-top: 4px;
}
.mt-cmd-meta .cmeta .class-kinetic  { color: var(--class-kinetic); }
.mt-cmd-meta .cmeta .class-electric { color: var(--class-electric); }
.mt-cmd-meta .cmeta .class-psionic  { color: var(--class-psionic); }

.mt-cmd-skills {
  display: flex;
  gap: 5px;
  flex-shrink: 0;
}
.mt-skill-chip {
  width: 32px; height: 32px;
  border: 1px solid #2a3850;
  border-radius: 2px;
  background: #0c1220;
  display: grid;
  place-items: center;
  font: 600 11px/1 var(--font-mono);
  color: var(--text-secondary);
  cursor: help;
  overflow: hidden;
  text-align: center;
  padding: 2px;
  position: relative;
}
.mt-skill-chip .rankdot {
  position: absolute;
  bottom: 1px; right: 1px;
  font-size: 8px;
  color: var(--accent-gold);
  line-height: 1;
  letter-spacing: 0;
}
.mt-skill-chip.empty { opacity: 0.35; border-style: dashed; }
.mt-skill-chip.innate { border-color: rgba(255,215,0,0.45); color: var(--accent-gold); }
.mt-skill-chip.kinetic  { border-color: rgba(239,83,80,0.4);  color: var(--class-kinetic); }
.mt-skill-chip.electric { border-color: rgba(255,152,0,0.4);  color: var(--class-electric); }
.mt-skill-chip.psionic  { border-color: rgba(79,195,247,0.4); color: var(--class-psionic); }
.mt-skill-chip .abbr {
  font-size: 9px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  width: 100%;
}

.mt-post-fight-banner {
  padding: 10px 12px;
  margin-bottom: 10px;
  border-radius: 3px;
  font: 500 13px/1 var(--font-mono);
  letter-spacing: 2px;
  text-transform: uppercase;
}
.mt-post-fight-banner.win  { background: rgba(102,187,106,0.12); color: var(--accent-green); border: 1px solid rgba(102,187,106,0.4); }
.mt-post-fight-banner.loss { background: rgba(239,83,80,0.12);  color: var(--accent-red);   border: 1px solid rgba(239,83,80,0.4);  }

/* Post-fight title uses the same mt-detail-title slot as preflight, but
   colored by outcome. Matches preflight/lane-picker typography exactly. */
.mt-post-fight-title.win  { color: var(--accent-green); }
.mt-post-fight-title.loss { color: var(--accent-red); }

.mt-losses {
  margin-top: 8px;
  padding: 6px 8px;
  background: rgba(8,12,22,0.5);
  border: 1px solid #1a2538;
  border-radius: 2px;
  font: 10px/1.5 var(--font-mono);
  color: var(--text-dim);
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.mt-losses .hdr { color: var(--text-primary); letter-spacing: 1.4px; text-transform: uppercase; font-size: 9px; margin-bottom: 4px; }

/* Post-fight loss rows — one unit type per line with thumb + name + count.
   Mirrors the compact rail row density used in commander rails. */
.mt-loss-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 0;
}
.mt-loss-thumb {
  width: 20px;
  height: 20px;
  object-fit: cover;
  border-radius: 2px;
  border: 1px solid rgba(255,255,255,0.12);
  flex: 0 0 20px;
}
.mt-loss-thumb.placeholder { background: rgba(255,255,255,0.04); }
.mt-loss-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-primary);
  letter-spacing: 0.3px;
}
.mt-loss-count {
  font-weight: 700;
  color: #ef5350;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.mt-loss-empty { color: var(--accent-green); font-style: italic; text-align: center; padding: 4px 0; }

/* Post-fight injury notice — shows which commander was benched by the loss.
   Red-orange accent matches the loss column header. */
.mt-injury-notice {
  margin-top: 10px;
  padding: 6px 10px;
  display: flex;
  align-items: center;
  gap: 8px;
  background: rgba(239,83,80,0.08);
  border: 1px solid rgba(239,83,80,0.35);
  border-radius: 2px;
  font: 10px/1.4 var(--font-mono);
}
.mt-injury-chip {
  padding: 2px 6px;
  background: rgba(239,83,80,0.2);
  color: var(--accent-red);
  border: 1px solid rgba(239,83,80,0.5);
  border-radius: 2px;
  font: 700 8px/1 var(--font-mono);
  letter-spacing: 1.5px;
}
.mt-injury-name { font-weight: 700; color: var(--text-primary); letter-spacing: 0.5px; }
.mt-injury-detail { color: var(--text-dim); font-size: 9px; letter-spacing: 0.2px; }

/* Inline "DAMAGED" tag shown on the enemy header when the player's prior
   retry-loss left damage persisting to this fight. */
/* Ghost (Captain of the Hold) UI — spine icon, preflight badge, owner byline.
   Purple/magenta pallette distinguishes from orange (DAMAGED) + red (LOSS). */
.mt-ghost-badge {
  color: #ba68c8;
  font-size: 11px;
  letter-spacing: 1.4px;
  margin-left: 8px;
  padding: 1px 5px;
  border: 1px solid rgba(186,104,200,0.45);
  background: rgba(186,104,200,0.12);
  border-radius: 2px;
  font-weight: 700;
}
.mt-ghost-owner {
  color: #ce93d8;
  font-size: 10px;
  margin-left: 6px;
  letter-spacing: 0.3px;
}
.mt-floor-row.has-ghost .num {
  color: #ce93d8;
}
.mt-floor-ghost {
  color: #ba68c8;
  font-size: 10px;
  margin-left: 4px;
  cursor: help;
}
.mt-rail-owner {
  font: 9px/1.3 var(--font-mono);
  color: #ce93d8;
  letter-spacing: 0.3px;
  margin-top: 2px;
}
.mt-rail-thumb.cmd .ghost-pip {
  position: absolute;
  top: 1px; right: 1px;
  padding: 0 3px;
  background: rgba(8,12,22,0.9);
  border: 1px solid rgba(186,104,200,0.6);
  color: #ba68c8;
  font: 700 9px/1 var(--font-mono);
  border-radius: 2px;
}

.mt-damaged-tag {
  padding: 1px 5px;
  margin-left: 6px;
  background: rgba(255,152,0,0.15);
  color: var(--accent-orange);
  border: 1px solid rgba(255,152,0,0.45);
  border-radius: 2px;
  font: 700 8px/1 var(--font-mono);
  letter-spacing: 1.3px;
}

/* Injured commander rail row — dimmed but still clickable (player may want
   to view/unequip the injured commander's card slots). The ENGAGE button
   is guarded separately so an injured commander can't actually fight. */
.mt-cmd-rail-row.injured { opacity: 0.55; }
.mt-cmd-rail-row.injured:hover { opacity: 0.75; }
.mt-cmd-rail-row.injured .cname-line::after {
  content: ' · INJURED';
  color: var(--accent-red);
  font-weight: 700;
  letter-spacing: 1px;
}

/* Run-modifier chip rail (header) — shows stolen modifiers active for
   the rest of the run. Each chip has a cyan tint to match the accent
   scheme, with a dimmed label on the left. */
.mt-run-mods {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 8px;
  background: rgba(8,12,22,0.6);
  border: 1px solid #181f2e;
  border-radius: 3px;
  max-width: 420px;
  overflow-x: auto;
  overflow-y: hidden;
}
.mt-run-mods:empty { display: none; }
.mt-run-mods-label {
  font: 8.5px/1 var(--font-mono); letter-spacing: 1.4px;
  text-transform: uppercase; color: var(--text-dim);
  padding-right: 6px; border-right: 1px solid #1f2738;
  white-space: nowrap;
}
.mt-mod-chip {
  display: inline-flex; align-items: center;
  padding: 3px 7px;
  background: rgba(79,195,247,0.08);
  border: 1px solid rgba(79,195,247,0.25);
  border-radius: 2px;
  font: 9.5px/1 var(--font-mono); letter-spacing: 0.6px;
  color: var(--accent-cyan);
  white-space: nowrap;
  cursor: help;
}

/* Choice-floor lane picker — two cards side-by-side, mobile-landscape
   optimized. Normal lane LEFT, modifier lane RIGHT. Tight layout so the
   enemy formation + CTA fit without scrolling at 844×390. */
.mt-lane-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-top: 6px;
}
.mt-lane {
  background: rgba(8,12,22,0.55);
  border: 1px solid #1a2538;
  border-radius: 3px;
  padding: 8px 10px;
  transition: border-color 0.15s, background 0.15s;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.mt-lane.normal { border-color: rgba(79,195,247,0.3); }
.mt-lane.normal:hover { border-color: rgba(79,195,247,0.6); background: rgba(12,18,32,0.7); }
.mt-lane.modifier {
  border-color: rgba(255,152,0,0.35);
  background: linear-gradient(180deg, rgba(90,55,15,0.25), rgba(8,12,22,0.55));
}
.mt-lane.modifier:hover {
  border-color: var(--accent-orange);
  box-shadow: 0 0 10px rgba(255,152,0,0.15);
}

/* Compact header row: tag · title · power chip all inline */
.mt-lane-header {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.mt-lane-tag {
  padding: 2px 6px;
  font: 8px/1 var(--font-mono);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  border-radius: 2px;
  background: rgba(102,187,106,0.12);
  color: var(--accent-green);
  border: 1px solid rgba(102,187,106,0.35);
}
.mt-lane-tag.risk {
  background: rgba(255,152,0,0.12);
  color: var(--accent-orange);
  border-color: rgba(255,152,0,0.4);
}
.mt-lane-title {
  font: 500 11px/1 var(--font-mono);
  letter-spacing: 1.2px;
  text-transform: uppercase;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mt-lane-power {
  font: 10px/1 var(--font-mono);
  color: var(--accent-red);
  letter-spacing: 0.5px;
  white-space: nowrap;
}
.mt-lane-power .pw-lbl {
  font-size: 8px;
  color: var(--text-dim);
  margin-right: 3px;
}

/* Choice-floor lane formation grid — thumb fills the slot tighter than
   the default 28px, leaving just enough border space for the T/R pips. */
.mt-lane .fg-slot,
.mt-lane .fg-slot.fg-static { padding: 2px; }
.mt-lane .fg-thumb { width: 44px; height: 44px; }
.mt-lane .fg-count-overlay { font-size: 8px; min-width: 11px; padding: 1px 2px; bottom: 1px; right: 1px; }
.mt-lane .fg-tier-pip { font-size: 8px; min-width: 11px; padding: 1px 2px; top: 1px; left: 1px; }
.mt-lane .fg-grid { gap: 2px; }
.mt-lane .fg-row  { gap: 2px; }

.mt-lane-reward {
  padding: 5px 7px;
  background: rgba(8,12,22,0.4);
  border: 1px solid #1a2538;
  border-radius: 2px;
  font: 9px/1.35 var(--font-mono);
  color: var(--text-dim);
  letter-spacing: 0.2px;
}
.mt-lane.modifier .mt-lane-reward {
  border-style: dashed;
  border-color: rgba(255,152,0,0.35);
  background: rgba(255,152,0,0.06);
  color: #ffb74d;
}
.mt-lane.modifier .mt-lane-reward strong { color: var(--accent-orange); }

.mt-lane-choose {
  width: 100%;
  padding: 7px 0;
  font-size: 10px;
  letter-spacing: 1.3px;
}
.mt-lane-choose.modifier-btn {
  border-color: rgba(255,152,0,0.5);
  color: var(--accent-orange);
}

/* Minimized Megatower HUD chip — floats top-right when the player
   temporarily hides the modal to check the map / base. */
.mt-minimized-chip {
  position: fixed;
  top: 48px;
  right: 10px;
  z-index: 34;   /* below modal (35), above HUD (30) */
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 12px;
  background: linear-gradient(180deg, rgba(15,20,35,0.95), rgba(5,8,15,0.98));
  border: 1px solid rgba(79,195,247,0.4);
  border-radius: 3px;
  cursor: pointer;
  font-family: var(--font-mono);
  color: var(--text-primary);
  box-shadow: 0 2px 10px rgba(0,0,0,0.5), 0 0 8px rgba(79,195,247,0.15);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.mt-minimized-chip:hover {
  border-color: var(--accent-cyan);
  box-shadow: 0 2px 10px rgba(0,0,0,0.6), 0 0 12px rgba(79,195,247,0.35);
}
.mt-minimized-chip .mt-chip-icon {
  font-size: 18px;
  color: var(--accent-cyan);
}
.mt-minimized-chip .mt-chip-label {
  font: 600 10px/1 var(--font-mono);
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--text-primary);
}
.mt-minimized-chip .mt-chip-timer {
  font: 11px/1 var(--font-mono);
  letter-spacing: 0.8px;
  color: var(--accent-cyan);
  margin-top: 3px;
}
.mt-minimized-chip.warn { border-color: rgba(255,152,0,0.45); }
.mt-minimized-chip.warn .mt-chip-icon,
.mt-minimized-chip.warn .mt-chip-timer { color: var(--accent-orange); }
.mt-minimized-chip.danger { border-color: rgba(239,83,80,0.55); box-shadow: 0 2px 10px rgba(0,0,0,0.6), 0 0 12px rgba(239,83,80,0.35); }
.mt-minimized-chip.danger .mt-chip-icon,
.mt-minimized-chip.danger .mt-chip-timer { color: var(--accent-red); }

/* Inline lane chip in the preflight title row. Replaces the old full-width
   mt-lane-banner — the banner overflowed mobile landscape (~844w) once the
   description + CHANGE LANE button were on it. Compact pill stays inline
   next to the milestone/ghost badges and never wraps. */
.mt-lane-chip {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 7px;
  border-radius: 2px;
  font: 600 9px/1 var(--font-mono);
  letter-spacing: 1.4px;
  text-transform: uppercase;
  vertical-align: 1px;
}
.mt-lane-chip.normal {
  background: rgba(79,195,247,0.10);
  border: 1px solid rgba(79,195,247,0.35);
  color: var(--accent-cyan);
}
.mt-lane-chip.modifier {
  background: rgba(255,152,0,0.10);
  border: 1px solid rgba(255,152,0,0.4);
  color: var(--accent-orange);
}

/* Hold Oath confirm modal — 2-panel layout for mobile landscape. The old
   modal listed every troop type vertically and overflowed at 844x390. This
   one splits text-content (flavor + hint) on the LEFT and the visual
   commitment (Captain card + formation grid) on the RIGHT, so the player
   sees exactly what the Captain takes with them at a glance. */
.mt-guard-confirm { font: 11px/1.5 var(--font-mono); color: #ccc; }
.mt-guard-cols {
  display: flex;
  gap: 14px;
  align-items: stretch;
}
.mt-guard-left {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 10px;
}
.mt-guard-right {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  background: rgba(8,12,22,0.5);
  border: 1px solid rgba(255,152,0,0.25);
  border-radius: 3px;
}
.mt-guard-flavor {
  color: var(--accent-orange);
  font-size: 11px;
  line-height: 1.5;
}
.mt-guard-cmd-host { flex: 0 0 auto; }
.mt-guard-grid-host { flex: 1 1 auto; min-width: 0; display: flex; justify-content: center; }
/* Tighten the embedded formation grid so it fits in landscape modal width
   without horizontal scroll. The fight-pair host uses defaults; here we
   shrink slightly. */
.mt-guard-grid-host .fg-grid { gap: 3px; }
.mt-guard-grid-host .fg-slot { width: 42px; height: 42px; }
.mt-guard-hint {
  font-size: 10px;
  color: var(--text-dim);
  line-height: 1.5;
}

/* Captain card for the Hold Oath modal — explicitly the GHOST representation,
   not the commander (commander goes home; only an imprint stays). Uses the
   universal ghost thumb so the player can't misread it as "the commander
   stays here." Compact: ~70px tall, ~88px wide. */
.mt-guard-cmd-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: 88px;
}
.mt-guard-cmd-portrait {
  position: relative;
  width: 56px;
  height: 56px;
  border-radius: 4px;
  overflow: hidden;
  background: rgba(20,28,44,0.6);
  border: 1px solid rgba(79,195,247,0.35);
}
.mt-guard-cmd-portrait.ghost {
  /* Cyan-tinted border for the Signal-imprint visual. Matches the ghost
     pip color used elsewhere (mt-rail-thumb.cmd .ghost-pip). */
  border-color: rgba(79,195,247,0.55);
  box-shadow: 0 0 8px rgba(79,195,247,0.18) inset;
}
.mt-guard-cmd-portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.mt-guard-ghost-pip {
  position: absolute;
  top: 2px;
  right: 2px;
  background: rgba(8,16,32,0.85);
  color: var(--accent-cyan);
  font: 700 11px var(--font-mono);
  width: 16px;
  height: 16px;
  border-radius: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.mt-guard-cmd-meta {
  text-align: center;
  font: 600 10px var(--font-mono);
  letter-spacing: 0.6px;
  line-height: 1.3;
}
.mt-guard-cmd-name {
  color: var(--accent-cyan);
  text-transform: uppercase;
  letter-spacing: 1.2px;
}
.mt-guard-cmd-class {
  color: var(--text-dim);
  margin-top: 2px;
  font-size: 9px;
  letter-spacing: 1px;
}

/* Narrow-viewport (mobile landscape ~960w or smaller). Placed AFTER all the
   desktop megatower rules so the cascade resolves these as overrides — not
   earlier, where the later desktop rules would re-override the mobile ones
   (media queries don't add specificity; source order wins at equal
   specificity). Mobile behavior:
     1. Stack the two fight sides vertically so rails don't clip off-screen.
     2. Collapse rail rows to icon thumbs only (hide .rail-text). Commander
        thumb click → commander picker; skill thumb click → skill detail modal.
     3. Hide the footer — commander switching lives on the rail thumb now.
     4. Compact header: tiny icon buttons (no labels), drop subtitle, shrink
        spine heading. Reclaims ~2 rows of vertical space for short viewports. */
@media (max-width: 960px) {
  .mt-modal { height: 94%; max-height: 94vh; }
  .mt-header { padding: 6px 10px; gap: 8px; }
  .mt-header .mt-title { font-size: 12px; letter-spacing: 1.8px; }
  .mt-header .mt-subtitle { display: none; }
  .mt-timer { padding: 3px 7px; }
  .mt-timer .lbl { display: none; }
  .mt-timer .val { font-size: 11px; }
  .mt-btn.mt-btn-mini {
    padding: 5px 8px;
    min-width: 26px;
    font-size: 13px;
    line-height: 1;
  }
  .mt-btn.mt-btn-mini .full { display: none; }
  .mt-btn.mt-btn-mini .icon { display: inline; font-weight: 600; }

  .mt-body { grid-template-columns: 92px 1fr; gap: 6px; padding: 6px; }
  .mt-spine-hdr { padding: 5px 7px 3px; }
  .mt-spine-hdr .title { font-size: 8px; letter-spacing: 1.2px; }
  .mt-spine-hdr .zone { display: none; }
  .mt-floor-row { height: 18px; padding: 3px 6px 3px 22px; font-size: 9px; }
  .mt-floor-row .num { font-size: 9px; width: 16px; }
  .mt-floor-row .state { font-size: 8.5px; }
  .mt-floor-row.current .num { font-size: 11px; color: var(--accent-cyan); }
  .mt-floor-row.current::after { width: 11px; height: 2.5px; }

  /* Horizontal side-by-side at mobile landscape — NO stacking. Both halves
     hug their content width (auto/auto), and the pair is centered in the
     detail panel. That keeps the whole fight in one scroll-free row. */
  .mt-fight-pair {
    /* player | VS chip | enemy — all content-sized, centered as a group */
    grid-template-columns: auto auto auto;
    justify-content: center;
    align-items: start;
    gap: 8px;
    margin-top: 3px;
  }
  .mt-vs-chip { padding: 4px 2px; gap: 3px; align-self: center; }
  .mt-vs-label { font-size: 11px; letter-spacing: 1.6px; }
  .mt-vs-delta { padding: 2px 6px; font-size: 9px; }

  /* Engage row tighter on mobile — smaller button, no helper text.
     The preset buttons now live here alongside Engage, so the row reads
     left-to-right: [Presets 1 2 3] [        ENGAGE →        ] */
  .mt-engage-row { margin-top: 6px; gap: 10px; }
  .mt-btn-engage {
    padding: 7px 20px;
    font-size: 11px;
    letter-spacing: 1.6px;
    min-width: 140px;
  }
  .mt-engage-row .mt-presets { margin-top: 0; }
  .mt-engage-row .mt-presets button { width: 22px; height: 20px; font-size: 10px; }
  .mt-engage-row .mt-presets .plbl { font-size: 8px; }

  /* Title row collapses if opponent runs long — ellipsis instead of
     pushing the title off the edge. */
  .mt-detail-title-row { margin-bottom: 3px; gap: 10px; }
  .mt-detail-title { font-size: 10.5px; letter-spacing: 1.2px; }
  .mt-detail-meta { font-size: 8px; }
  .mt-fight-side.you {
    /* rail (LEFT) | form (RIGHT) — rail widened to 118px so it can show
       commander + skill names alongside the thumb, not just icons. */
    grid-template-columns: 118px auto;
    gap: 4px;
  }
  .mt-fight-side.enemy {
    /* form (LEFT) | rail (RIGHT) — preserves the player-vs-enemy mirror */
    grid-template-columns: auto 118px;
    gap: 4px;
  }

  /* Form-col shrink-wraps around the 3×2 formation grid. Compact padding,
     smaller fc-header text, tighter presets row. */
  .mt-fight-side .mt-form-col {
    padding: 5px 6px;
    gap: 3px;
    align-self: center;
  }
  .mt-fc-header { padding-bottom: 2px; margin-bottom: 3px; gap: 0px; }
  .mt-fc-header .side-label { font-size: 8px; letter-spacing: 0.9px; }
  .mt-fc-header .power { font-size: 12px; }
  .mt-fc-header .power .pw-lbl { font-size: 6.5px; margin: 0 0 1px 0; }
  .mt-form-col .fg-leadership { font-size: 8px; margin-top: 3px; }
  .mt-enemy-metrics { margin-top: 3px; gap: 2px; }
  .mt-em-tag { font-size: 7px; padding: 2px 4px; letter-spacing: 0.8px; }

  /* Corner brackets are thin desktop polish; at 40px grid they just
     render as stray 10px L-marks. Drop on mobile. */
  .mt-form-col::before,
  .mt-form-col::after { display: none; }

  /* Rail: thumb + compact text. 118px = 40 thumb + 4 gap + 68 text + 6 padding.
     Keeps commander names + rank info readable at mobile landscape. */
  .mt-cmd-rail { width: 118px; gap: 3px; }
  .mt-cmd-rail-row {
    grid-template-columns: 40px 1fr;
    gap: 4px;
    padding: 3px 5px;
    min-height: 40px;
  }
  .mt-fight-side.enemy .mt-cmd-rail-row {
    /* Mirror: text on left, thumb on right. DOM order is always
       [thumb, rail-text], so `order` swaps them so rail-text lands
       in the 1fr column and thumb in the 40px column — otherwise the
       thumb eats the 1fr and the text gets squeezed into the 40px. */
    grid-template-columns: 1fr 40px;
  }
  .mt-fight-side.enemy .mt-cmd-rail-row .mt-rail-thumb { order: 2; }
  .mt-fight-side.enemy .mt-cmd-rail-row .rail-text     { order: 1; }
  .mt-rail-thumb { width: 40px; height: 40px; }

  /* Compact text — commander name wraps up to 2 lines; meta truncates with
     ellipsis. Text column is the grid's 1fr remainder; min-width: 0 so
     long meta strings stay contained inside the column (no overflow past
     the rail border). Enemy side text-align: right mirrors the player
     side so text sits adjacent to its thumb on both sides. */
  .mt-cmd-rail-row .rail-text {
    display: block;
    /* Without an explicit stretch, Chrome resolves a grid-item with
       overflow:hidden + text-align:right to its min-content width (it
       shrink-wraps around the wrapped text) — which on the enemy side
       collapses the text column from the 62px the grid reserved down
       to ~40px. Forcing width:100% keeps the box filling its track so
       player and enemy text columns are exactly mirrored. */
    width: 100%;
    min-width: 0;
    overflow: hidden;
  }
  .mt-fight-side.enemy .mt-cmd-rail-row .rail-text { text-align: right; }
  .mt-fight-side.you    .mt-cmd-rail-row .rail-text { text-align: left; }
  .mt-cmd-rail-row.row-cmd .cname-line {
    font: 600 8.5px/1.15 var(--font-mono);
    letter-spacing: 0.4px;
  }
  .mt-cmd-rail-row.row-cmd .cmeta-line {
    font-size: 7px;
    letter-spacing: 0.6px;
    margin-top: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .mt-cmd-rail-row.row-skill .skill-name {
    font: 600 8px/1.15 var(--font-mono);
    letter-spacing: 0.3px;
  }
  .mt-cmd-rail-row.row-skill .skill-meta {
    font-size: 6.5px;
    letter-spacing: 0.5px;
    margin-top: 1px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* Hide footer — commander picker lives on the commander-row click. */
  .mt-footer { display: none; }

  /* "pick a commander in the footer" helper text no longer applies. */
  .mt-hide-on-mobile { display: none; }

  /* No scrollbars in the detail area — the layout now fits horizontally.
     Engage row wraps below the fight pair; tiny bottom padding to keep
     it off the modal's inner border. */
  .mt-detail-body { padding: 4px 8px; overflow: hidden; }
  .mt-detail-title { font-size: 10.5px; letter-spacing: 1.2px; margin-bottom: 1px; }
  .mt-detail-meta { font-size: 8.5px; margin-bottom: 2px; }
}

/* Unread indicator on nav buttons (Mail count on REPORTS). Red pill in the
   top-right of the button. Injected/removed by hud._renderMailBadge. */
.nav-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 14px;
  height: 14px;
  padding: 0 3px;
  border-radius: 7px;
  background: var(--accent-red, #ef5350);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  line-height: 14px;
  text-align: center;
  box-shadow: 0 0 4px rgba(239, 83, 80, 0.8);
  pointer-events: none;
}

/* ============================================
   Map HUD — Top bar (coords, zone, shield)
   ============================================ */
.hud-top-content {
  display: flex;
  align-items: center;
  gap: 24px;
  width: 100%;
  height: 100%;
}

#hud-top-map {
  /* Pre-restructure this used space-between to push the (then-present)
     avatar+resources block left and the crawler pill right. After the
     avatar+resources moved into the always-visible #hud-top-left sibling
     (and the alert preview was retired into the SYS chat tab), only the
     inline rail + crawler-wrap live here — they should hug the right
     edge as a contiguous group so the deployed pills sit beside the
     crawler pill, not at the opposite end of the bar. */
  justify-content: flex-end;
  padding: 0 12px;
  gap: 8px;
}

.map-hud-group {
  display: flex;
  align-items: center;
  gap: 8px;
}

.map-hud-crawler-icon {
  width: 22px;
  height: 22px;
  border-radius: 3px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(79,195,247,0.35);
  object-fit: cover;
}

#map-hud-crawler-pill:hover .map-hud-crawler-icon {
  border-color: var(--accent-cyan);
}

#map-hud-crawler-pill:hover .map-hud-label,
#map-hud-crawler-pill:hover .map-hud-value {
  color: var(--accent-cyan);
}

/* Top-HUD inline squad rail — replaces the left-aside rail on the world
   map. Sits inside #hud-top-map to the left of the crawler pill. */
.top-hud-rail {
  display: flex;
  align-items: center;
  gap: 6px;
}
.top-hud-rail__pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(6,6,14,0.72);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 4px;
  padding: 2px 8px 2px 2px;
  cursor: pointer;
  color: var(--text-secondary);
  font-family: var(--font-mono);
}
.top-hud-rail__pill:hover {
  border-color: var(--accent-cyan);
  color: var(--accent-cyan);
}
.top-hud-rail__icon,
.top-hud-rail__icon-btn {
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 3px;
  overflow: hidden;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.12);
  cursor: pointer;
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: 10px;
  padding: 0;
}
.top-hud-rail__icon img,
.top-hud-rail__icon-btn img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.top-hud-rail__icon-btn:hover {
  border-color: var(--accent-cyan);
  color: var(--accent-cyan);
}
.top-hud-rail__icon-btn.is-empty {
  color: var(--text-dim);
  background: rgba(255,255,255,0.02);
}
.top-hud-rail__coords {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1;
  gap: 1px;
}
.top-hud-rail__place {
  font-size: 9px;
  text-transform: uppercase;
  color: var(--text-dim);
  max-width: 100px;
  overflow: hidden;
  white-space: nowrap;
}
/* Only fade the right edge when the text actually overflows — toggled
   via JS (.is-truncated) so short names don't get a phantom fade. */
.top-hud-rail__place.is-truncated {
  -webkit-mask-image: linear-gradient(to right, #000 70%, transparent 100%);
  mask-image: linear-gradient(to right, #000 70%, transparent 100%);
}
.top-hud-rail__pill:hover .top-hud-rail__place,
.top-hud-rail__pill:hover .top-hud-rail__xy {
  color: var(--accent-cyan);
}
.top-hud-rail__xy {
  font-size: 11px;
}
.top-hud-rail__div {
  display: inline-block;
  width: 1px;
  height: 18px;
  background: rgba(255,255,255,0.15);
}

/* Task rows in the objectives popover are whole-row clickable. */
.objectives-modal-row[data-row] {
  border-radius: 3px;
}
.objectives-modal-row[data-row]:hover {
  background: rgba(40, 30, 6, 0.35);
}

/* Heat-band tints on the deployed-pill dark box. Colors mirror the legacy
   squad-rail bands: cold (cyan) → warm (yellow) → hot (orange) → critical (red).
   Background gets a faint wash so it reads at a glance, border lifts for hot+. */
.top-hud-rail__pill.is-heat-cold     { background: rgba(79,195,247,0.10); border-color: rgba(79,195,247,0.35); }
.top-hud-rail__pill.is-heat-warm     { background: rgba(255,213,79,0.12); border-color: rgba(255,213,79,0.45); }
.top-hud-rail__pill.is-heat-hot      { background: rgba(255,152,0,0.16);  border-color: rgba(255,152,0,0.65); }
.top-hud-rail__pill.is-heat-critical { background: rgba(239,83,80,0.20);  border-color: rgba(239,83,80,0.80);
  animation: top-hud-rail-pulse 1s ease-in-out infinite; }
@keyframes top-hud-rail-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(239,83,80,0.45); }
  50%      { box-shadow: 0 0 0 3px rgba(239,83,80,0.18); }
}

/* Event decision badge — hangs below the pill, clickable to open modal. */
.top-hud-rail__pill-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.top-hud-rail__event {
  /* "Background" tier — always visible, even when a modal/scrim is open.
     position:fixed + high z-index so we escape the HUD's stacking context.
     Top/left are written by JS each render (see topHudRail._positionPopdowns
     and objectivesPanel._positionButton). */
  position: fixed;
  box-sizing: border-box;
  /* Flex centering so the [?] DECIDE / [!] TASKS text always sits in the
     middle of the popup, regardless of whether JS sets a wider min-width
     than the text needs. text-align is the fallback. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  line-height: 1.2;
  /* 5px vertical (was 3px) — popup is ~20 % taller so the text doesn't
     feel cramped against the cyan border. Horizontal 10 px (was 6 px)
     leaves breathing room around "DECIDE" / "TASKS (N)". */
  padding: 5px 10px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  /* Translucent dark with cyan glow — matches the resource-bar / info
     panel chrome. */
  background: rgba(6, 12, 24, 0.78);
  color: var(--accent-cyan);
  border: 1px solid rgba(79, 195, 247, 0.6);
  border-radius: 4px;
  cursor: pointer;
  white-space: nowrap;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.55),
    0 3px 10px rgba(0,0,0,0.55),
    0 0 12px rgba(79, 195, 247, 0.35);
  /* Above modal-backdrop (z-index 1000) so the badge stays visible as
     persistent "background-tier" UI even while a menuground is open. */
  z-index: 1100;
  pointer-events: auto;
}
.top-hud-rail__event::before {
  content: '';
  position: absolute;
  top: -6px;
  left: 50%;
  transform: translateX(-50%);
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 6px solid rgba(79, 195, 247, 0.6);
  filter: drop-shadow(0 -1px 0 rgba(0,0,0,0.7));
}
/* Urgent decisions keep the translucent base, glow red. */
.top-hud-rail__event.is-urgent {
  color: #ff8a80;
  border-color: rgba(239, 83, 80, 0.75);
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.55),
    0 3px 10px rgba(0,0,0,0.55),
    0 0 14px rgba(239,83,80,0.6);
  animation: top-hud-rail-pulse 0.8s ease-in-out infinite;
}
.top-hud-rail__event.is-urgent::before {
  border-bottom-color: rgba(239, 83, 80, 0.75);
}
.top-hud-rail__event:hover {
  background: rgba(12, 24, 40, 0.92);
  border-color: var(--accent-cyan);
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.55),
    0 3px 10px rgba(0,0,0,0.55),
    0 0 18px rgba(79, 195, 247, 0.65);
}
/* Objectives variant — same translucent chrome, gold accent. */
.top-hud-rail__event--objectives {
  color: var(--accent-gold, #ffd54f);
  border-color: rgba(255, 213, 79, 0.65);
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.55),
    0 3px 10px rgba(0,0,0,0.55),
    0 0 12px rgba(255,213,79,0.45);
}
.top-hud-rail__event--objectives::before {
  border-bottom-color: rgba(255, 213, 79, 0.65);
}
.top-hud-rail__event--objectives:hover {
  border-color: var(--accent-gold, #ffd54f);
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.55),
    0 3px 10px rgba(0,0,0,0.55),
    0 0 18px rgba(255,213,79,0.7);
}

/* Idle-commander icons rendered inside the crawler pill — same dark block
   as the crawler icon, with a thin divider on the right when present. */
.top-hud-rail__inline-icons {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
/* Idle icons are inside the crawler pill — they share the dark block
   with the crawler icon and should sit flush against it (just the pill's
   built-in gap, no extra spacing). */

/* Hide the legacy left-aside rail — top-hud rail replaces it. */
.squad-rail { display: none !important; }

.map-hud-label {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--text-dim);
  text-transform: uppercase;
}

.map-hud-value {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-secondary);
}

.map-hud-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 10px;
  border-radius: 9px;
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.map-hud-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
}

/* HAUL chip popover — floats below #map-hud-haul, shows banked-haul
   resource breakdown by icon. Position is set inline (anchored to the
   chip's bounding rect) by worldMapScreen._toggleHaulPopover. */
.haul-popover {
  background: var(--bg-elevated, #16181c);
  border: 1px solid rgba(255, 152, 0, 0.45);
  border-radius: 4px;
  padding: 8px 10px 6px 10px;
  min-width: 160px;
  max-width: 220px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6);
  font-family: var(--font-mono);
  pointer-events: auto;
}
.haul-popover__title {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: #ff9800;
  margin-bottom: 6px;
}
.haul-popover__row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 0;
  font-size: 11px;
}
.haul-popover__icon {
  width: 14px;
  height: 14px;
  object-fit: contain;
  flex-shrink: 0;
}
.haul-popover__label {
  flex: 1;
  color: var(--text-secondary, #aaa);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}
.haul-popover__value {
  color: var(--text-primary, #fff);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}
.haul-popover__hint {
  margin-top: 6px;
  padding-top: 5px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  font-size: 8px;
  color: var(--text-tertiary, #666);
  letter-spacing: 0.3px;
  line-height: 1.3;
}

/* Alert preview chips (top-bar) — RETIRED. The same data is mirrored
   into the SYS chat tab via chatPanel.addSystemMessage, so the dedicated
   HUD chip is hidden everywhere. */
#hud-alert-preview,
#hud-base-alert-preview {
  display: none !important;
}
#hud-alert-lines {
  display: flex;
  flex-direction: column;
  gap: 1px;
  position: relative;
  margin-left: 10px;
}
.hud-alert-line {
  display: flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-mono);
  font-size: 9px;
  color: #ccc;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.4;
}
.hud-alert-icon {
  flex: 0 0 14px;
  width: 14px;
  height: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid currentColor;
  border-radius: 3px;
  font-size: 9px;
  font-weight: 800;
  line-height: 1;
  color: var(--accent-cyan);
  background: rgba(255,255,255,0.035);
}
.hud-alert-icon--action { color: var(--accent-gold); }
.hud-alert-icon--status { color: var(--accent-cyan); }
.hud-alert-icon--success { color: var(--accent-green); }
.hud-alert-icon--blocked { color: var(--accent-purple); }
.hud-alert-icon--warning { color: var(--accent-orange); }
.hud-alert-icon--error { color: var(--accent-red); }
.hud-alert-icon--combat { color: var(--accent-orange); }
.hud-alert-icon--raid { color: var(--accent-red); }
.hud-alert-message {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hud-alert-line--empty { color: var(--text-dim); }
.hud-alert-dot {
  position: absolute;
  left: -12px;
  top: 50%;
  transform: translateY(-50%);
  width: 6px; height: 6px;
  border-radius: 50%;
  animation: alertPulse 0.8s ease-in-out infinite;
  pointer-events: none;
}
@keyframes alertPulse {
  0%, 100% { opacity: 1; box-shadow: 0 0 4px 1px currentColor; }
  50% { opacity: 0.3; box-shadow: 0 0 8px 3px currentColor; }
}

/* ==============================================================
   ALERTS — v2 design system (mirrors .dedit-modal aesthetic)
   --------------------------------------------------------------
   Two layers in the same family:
     .alert-panel  — dropdown-from-HUD list of recent alerts (low pri)
     .alert-toast  — top-center floating notice (high pri, auto-dismiss)
   Both use design tokens; no hard-coded hex / inline font-family.
   ============================================================== */

/* Dropdown panel — shown by notifications.toggleAlertPanel() */
.alert-panel {
  position: fixed;
  top: 44px;
  left: 50%;
  width: 400px;
  max-width: 90vw;
  max-height: 50vh;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, rgba(17, 24, 39, 0.92) 0%, rgba(8, 10, 22, 0.95) 100%);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid var(--border-subtle);
  border-top: none;
  border-radius: 0 0 5px 5px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.7),
              0 0 30px rgba(79, 195, 247, 0.08),
              inset 0 1px 0 rgba(255, 255, 255, 0.04);
  z-index: 55;
  font-family: var(--font-mono);
  transform-origin: top center;
  transform: translateX(-50%) scaleY(0);
  opacity: 0;
  transition: transform 0.15s cubic-bezier(0.33, 1, 0.68, 1),
              opacity 0.15s ease-out;
  overflow: hidden;
}
.alert-panel.is-open {
  transform: translateX(-50%) scaleY(1);
  opacity: 1;
}

.alert-panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 6px 12px;
  min-height: 28px;
  background: linear-gradient(180deg, rgba(79, 195, 247, 0.08) 0%, transparent 100%);
  border-bottom: 1px solid var(--border-subtle);
  position: relative;
  flex-shrink: 0;
}
.alert-panel-header::after {
  content: '';
  position: absolute;
  left: 12px; right: 12px;
  bottom: -1px;
  height: 1px;
  background: linear-gradient(90deg, var(--accent-cyan), transparent 60%);
}
.alert-panel-kicker {
  font-size: 9px;
  letter-spacing: 1.5px;
  color: var(--text-dim);
  text-transform: uppercase;
  font-weight: 600;
}
.alert-panel-count {
  font-size: 9px;
  letter-spacing: 1px;
  color: var(--text-secondary);
  font-weight: 600;
}

.alert-panel-body {
  flex: 1;
  overflow-y: auto;
  padding: 4px 0;
}
.alert-panel-empty {
  padding: 20px 12px;
  text-align: center;
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: 1px;
  text-transform: uppercase;
}

.alert-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 5px 12px;
  border-bottom: 1px solid var(--border-subtle);
  font-size: 10px;
  line-height: 1.4;
  transition: background 0.12s;
}
.alert-row:last-child { border-bottom: none; }
.alert-row:hover { background: rgba(79, 195, 247, 0.04); }
.alert-row-time {
  min-width: 28px;
  text-align: right;
  color: var(--text-dim);
  font-size: 9px;
  flex-shrink: 0;
}
.alert-row-icon {
  flex: 0 0 18px;
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid currentColor;
  border-radius: 3px;
  font-size: 10px;
  font-weight: 800;
  line-height: 1;
  color: var(--accent-cyan);
  background: rgba(255,255,255,0.035);
}
.alert-row-icon--action { color: var(--accent-gold); }
.alert-row-icon--status { color: var(--accent-cyan); }
.alert-row-icon--success { color: var(--accent-green); }
.alert-row-icon--blocked { color: var(--accent-purple); }
.alert-row-icon--warning { color: var(--accent-orange); }
.alert-row-icon--error { color: var(--accent-red); }
.alert-row-icon--combat { color: var(--accent-orange); }
.alert-row-icon--raid { color: var(--accent-red); }
.alert-row-message {
  flex: 1;
  min-width: 0;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Toast container + toasts — high-priority floating notices.
   RETIRED in favour of the chat SYS tab. Hidden everywhere; the alert()
   call still adds to the alert log + SYS chat but no top-center toast
   renders any more. */
#alert-container {
  display: none !important;
  position: fixed;
  top: 48px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  flex-direction: column;
  gap: 6px;
  pointer-events: auto;
  width: 480px;
  max-width: 90vw;
}
.alert-toast {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: linear-gradient(180deg, rgba(17, 24, 39, 0.94) 0%, rgba(8, 10, 22, 0.96) 100%);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border: 1px solid var(--border-subtle);
  border-left-width: 3px;
  border-radius: 5px;
  font-family: var(--font-mono);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.55),
              0 0 18px rgba(79, 195, 247, 0.06),
              inset 0 1px 0 rgba(255, 255, 255, 0.04);
  animation: alert-slide-down 0.25s ease-out;
}
/* Per-type left-border accent. Default is error/red. */
.alert-toast--action   { border-left-color: var(--accent-gold); }
.alert-toast--status,
.alert-toast--info     { border-left-color: var(--accent-cyan); }
.alert-toast--success  { border-left-color: var(--accent-green); }
.alert-toast--blocked  { border-left-color: var(--accent-purple); }
.alert-toast--warning  { border-left-color: var(--accent-orange); }
.alert-toast--error    { border-left-color: var(--accent-red); }
.alert-toast--battle   { border-left-color: var(--accent-orange); }
.alert-toast--combat   { border-left-color: var(--accent-orange); }
.alert-toast--raid     { border-left-color: var(--accent-red); }
.alert-toast--victory  { border-left-color: var(--accent-green); }
.alert-toast--defeat   { border-left-color: var(--accent-red); }

.alert-toast-icon {
  font-size: 14px;
  flex-shrink: 0;
  line-height: 1;
}
.alert-toast-icon--action   { color: var(--accent-gold); }
.alert-toast-icon--status,
.alert-toast-icon--info     { color: var(--accent-cyan); }
.alert-toast-icon--success  { color: var(--accent-green); }
.alert-toast-icon--blocked  { color: var(--accent-purple); }
.alert-toast-icon--warning  { color: var(--accent-orange); }
.alert-toast-icon--error    { color: var(--accent-red); }
.alert-toast-icon--battle,
.alert-toast-icon--combat   { color: var(--accent-orange); }
.alert-toast-icon--raid     { color: var(--accent-red); }
.alert-toast-icon--victory  { color: var(--accent-green); }
.alert-toast-icon--defeat   { color: var(--accent-red); }

.alert-toast-message {
  flex: 1;
  min-width: 0;
  font-size: 12px;
  color: var(--text-primary);
  font-weight: 700;
  letter-spacing: 0.3px;
  overflow: hidden;
}
.alert-toast-message--obs {
  font-weight: 500;
  font-size: 11px;
}

.alert-toast-btn {
  flex-shrink: 0;
  padding: 4px 10px;
  background: rgba(13, 21, 32, 0.6);
  border: 1px solid var(--border-steel);
  border-radius: 3px;
  color: var(--text-primary);
  font-family: inherit;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s, box-shadow 0.15s;
  line-height: 1;
}
.alert-toast-btn:hover {
  border-color: var(--accent-cyan);
  background: rgba(26, 34, 53, 0.8);
}
.alert-toast-btn--primary {
  background: linear-gradient(180deg, rgba(79, 195, 247, 0.25), rgba(79, 195, 247, 0.08));
  border-color: var(--accent-cyan);
  color: var(--accent-cyan);
  box-shadow: 0 0 10px rgba(79, 195, 247, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.alert-toast-btn--primary:hover {
  background: linear-gradient(180deg, rgba(79, 195, 247, 0.4), rgba(79, 195, 247, 0.15));
  color: #fff;
  box-shadow: 0 0 16px rgba(79, 195, 247, 0.35);
}

.alert-toast-close {
  flex-shrink: 0;
  width: 18px; height: 18px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  color: var(--text-dim);
  font-size: 12px;
  line-height: 1;
  border-radius: 3px;
  transition: color 0.15s, background 0.15s;
}
.alert-toast-close:hover {
  color: var(--accent-red);
  background: rgba(239, 83, 80, 0.08);
}

/* Win pill inside observer-battle toasts (replaces inline #66bb6a chip). */
.alert-toast-winpill {
  display: inline-block;
  background: var(--accent-green);
  color: #000;
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  margin: 0 3px;
  vertical-align: baseline;
}
.alert-toast-vs { color: var(--text-dim); }
.alert-toast-meta { color: var(--text-dim); }

/* ============================================
   Bottom Bar — Chat preview (left) + nav buttons (right)
   ============================================ */
#map-chat-preview {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 12px;
  cursor: pointer;
  border-right: 1px solid var(--border-subtle);
  overflow: hidden;
  position: relative;
  background: transparent;
  transition: background 0.15s;
}
/* Green dot: indicates live alliance chat. Matches design's nav-chat-dot. */
#map-chat-preview::before {
  content: '';
  flex-shrink: 0;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-green);
  box-shadow: 0 0 6px var(--accent-green);
}
#map-chat-preview:hover { background: rgba(255,255,255,0.02); }

#map-chat-lines {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1;
}

.map-chat-line {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.4;
}

.map-chat-sender {
  color: var(--accent-cyan);
  font-weight: 700;
  margin-right: 4px;
}



/* ============================================
   Settings Modal
   ============================================ */
.settings-section {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 1px;
  padding: 6px 0 2px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  margin-bottom: 2px;
}
/* First section in a column shouldn't push down — column padding already
   gives breathing room. */
.settings-col > .settings-section:first-child { padding-top: 0; }

.settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 3px 0;
  border-bottom: 1px solid rgba(255,255,255,0.03);
  min-width: 0;
}

/* Audio slider rows: track sits on the right, label on the left. The track
   holds the range input + the % readout; the readout has its own min-width
   so it never gets squeezed off the column's right edge. The track flexes
   to consume whatever the label leaves behind. */
.settings-audio-track {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 auto;
  min-width: 0;
}
.settings-audio-range {
  flex: 1 1 auto;
  min-width: 0;
  accent-color: var(--accent-cyan);
}
.settings-audio-pct {
  font-size: 10px;
  color: #888;
  min-width: 30px;
  text-align: right;
  font-family: var(--font-mono);
  flex-shrink: 0;
}

/* ── Settings modal: 2-column landscape layout ──────────────────────
   The settings modal stacks ~10 rows + 5 audio sliders. On mobile-
   landscape (~375 vh) that overflows the dedit-modal's 360px max-height
   and the bottom buttons get clipped. Splitting GAMEPLAY into a left
   column and AUDIO+ACCOUNT into a right column halves the vertical
   demand and uses the wide horizontal space the landscape phone offers.
   On portrait viewports the grid collapses to a single column.            */
.dedit-modal--settings {
  max-width: 760px;
  max-height: min(420px, 92vh);
}
.settings-body {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px 24px;
  align-content: start;
}
.settings-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
@media (max-width: 600px), (orientation: portrait) and (max-width: 720px) {
  .settings-body { grid-template-columns: 1fr; gap: 0; }
}

.settings-label {
  font-family: var(--font-mono);
  font-size: 11px;
  color: #ccc;
}

.settings-desc {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--text-dim);
  margin-top: 1px;
}

.settings-toggle {
  position: relative;
  width: 36px;
  height: 20px;
  flex-shrink: 0;
}

.settings-toggle input {
  opacity: 0;
  width: 0;
  height: 0;
}

.settings-toggle-slider {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  cursor: pointer;
  background: #2a2a3a;
  border-radius: 10px;
  transition: background 0.2s;
}

.settings-toggle-slider::before {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  left: 2px;
  bottom: 2px;
  background: #888;
  border-radius: 50%;
  transition: transform 0.2s, background 0.2s;
}

.settings-toggle input:checked + .settings-toggle-slider {
  background: rgba(79,195,247,0.3);
}

.settings-toggle input:checked + .settings-toggle-slider::before {
  transform: translateX(16px);
  background: var(--accent-cyan);
}

.settings-slider {
  width: 120px;
  height: 4px;
  -webkit-appearance: none;
  appearance: none;
  background: #2a2a3a;
  border-radius: 2px;
  outline: none;
  flex-shrink: 0;
}

.settings-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent-cyan);
  cursor: pointer;
}

.settings-select {
  background: #1a1a2a;
  border: 1px solid #2a3a50;
  border-radius: 4px;
  color: #ccc;
  font-family: var(--font-mono);
  font-size: 11px;
  padding: 4px 8px;
  outline: none;
  cursor: pointer;
}

.settings-select:focus {
  border-color: var(--accent-cyan);
}

/* ============================================
   Battle History List
   ============================================ */
.battle-list-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border: 1px solid var(--border-steel);
  border-radius: 4px;
  margin-bottom: 6px;
  cursor: pointer;
  transition: all 0.15s;
}

.battle-list-item:hover { background: var(--bg-panel-hover); }
.battle-list-item.selected { border-color: var(--accent-cyan); background: rgba(79, 195, 247, 0.05); }

.battle-result-badge {
  width: 28px;
  height: 28px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-weight: bold;
  font-size: 14px;
}

.battle-result-badge.win { background: rgba(102, 187, 106, 0.2); color: var(--accent-green); }
.battle-result-badge.loss { background: rgba(239, 83, 80, 0.2); color: var(--accent-red); }

/* ============================================
   Commander Card
   ============================================ */
.commander-card {
  display: flex;
  gap: 12px;
  padding: 12px;
  background: var(--bg-slot);
  border: 1px solid var(--accent-purple);
  border-radius: 6px;
}

.commander-card .cmd-portrait {
  width: 100px;
  height: 125px;
  border-radius: 4px;
  object-fit: cover;
  background: var(--bg-panel);
  border: 2px solid var(--accent-purple);
  box-shadow: 0 0 10px rgba(171, 71, 188, 0.3);
}

.commander-card .cmd-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.commander-card .cmd-name {
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--accent-purple);
  text-transform: uppercase;
}

.commander-card .cmd-level {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-secondary);
}

.commander-card .cmd-skill {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  padding: 2px 6px;
  background: rgba(171, 71, 188, 0.1);
  border-radius: 3px;
  display: inline-block;
}

/* ============================================
   Modal sizing — chrome (gradient, cyan border, blur, shadow, mono font)
   comes from .modal + .modal-tactical in ashen.css. This rule only
   provides the default #modal-box dimensions and padding for plain
   modal.show() callers. The .modal-box--dedit and .modal-box--boost
   modifiers below strip these so their inner shells own sizing.
   ============================================ */
.modal-box {
  padding: 16px;
  min-width: 300px;
  max-width: 560px;
  max-height: 80vh;
  overflow-y: auto;
}

/* Direct-child scope: the tactical h2 treatment is ONLY for plain
   modal.show() callers (title at the top of the box). The custom shells
   (.dedit-modal, .boost-modal) have their own header markup with their
   own title/divider — letting the generic rule leak into those nested
   h2 elements doubles the divider line and pushes the kicker off-screen. */
.modal-box > h2 {
  color: #fff !important;
  font-family: var(--font-mono);
  font-size: var(--font-heading) !important;
  font-weight: 700;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  text-shadow: 0 0 10px rgba(79, 195, 247, 0.2);
  padding-bottom: 8px;
  margin-bottom: 10px;
  border-bottom: 1px solid var(--border-subtle);
  position: relative;
}
.modal-box > h2::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -1px; height: 1px;
  background: linear-gradient(90deg, var(--accent-cyan), transparent 60%);
  pointer-events: none;
}

.modal-box input, .modal-box select {
  background: var(--bg-slot) !important;
  border: 1px solid var(--border-steel) !important;
  color: var(--text-primary) !important;
  font-family: var(--font-mono);
}

.modal-box input:focus, .modal-box select:focus {
  border-color: var(--accent-cyan) !important;
  outline: none;
}

/* ============================================
   Screen Layouts
   ============================================ */
.screen-overlay {
  position: fixed;
  top: 43px;
  left: 0;
  right: 0;
  bottom: 48px;
  overflow-y: auto;
  padding: 16px;
  background-color: var(--bg-dark);
  background-image:
    linear-gradient(var(--chrome-overlay-screen), var(--chrome-overlay-screen)),
    url('assets/icons/chrome_panel.jpg');
  background-size: auto, 512px 512px;
  background-repeat: repeat, repeat;
  z-index: 10;
}

.screen-overlay.hidden { display: none; }
/* no-top-bar overlay variant — used for non-canvas screens that hide the
   top resource bar (alliance/army/profile/etc). The HUD-bottom nav is still
   visible (z=30 over us at z=10), so we MUST leave bottom-room for it or
   tall scrollable content (e.g. alliance Settings tab) overflows behind
   the nav and becomes inaccessible on mobile landscape. Match base height
   (40px desktop nav). The mobile media query overrides to 32px to match
   the smaller nav. */
.screen-overlay.no-top-bar { top: 0 !important; bottom: 40px !important; padding: 8px !important; }

/* ============================================
   Alliance screen — 2-column landscape layout
   ============================================
   The alliance screen mixes "header info" + "scrolling list" patterns. On
   landscape we split horizontally (auto-fit grid) so we don't waste the
   wide aspect ratio AND the inner scrollers can be removed — the OUTER
   .screen-overlay handles the only scroll.
*/
.alliance-grid-2col {
  display: grid;
  grid-template-columns: minmax(280px, 1fr) minmax(280px, 1.2fr);
  gap: 10px;
  align-items: start;
}
@media (max-width: 640px) {
  .alliance-grid-2col { grid-template-columns: 1fr; }
}
.alliance-section { display: flex; flex-direction: column; gap: 10px; }

.alliance-requests-layout {
  display: grid;
  grid-template-columns: minmax(340px, 1.45fr) minmax(260px, 0.9fr);
  gap: 10px;
  align-items: start;
}
.alliance-requests-main,
.alliance-requests-side {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
@media (max-width: 760px) {
  .alliance-requests-layout { grid-template-columns: 1fr; }
}

/* Discover screen: founder banner. Lights up gold to reinforce the value
   prop ("you get something for joining"). Suppressed once founderPackEligible
   flips false on the server. */
.alliance-founder-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  border-color: var(--accent-gold);
  background: linear-gradient(90deg, rgba(255,215,0,0.18), rgba(255,215,0,0.05));
}
.alliance-founder-banner-icon { font-size: 22px; color: var(--accent-gold); }
.alliance-founder-banner-title {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--accent-gold);
  font-weight: bold;
  letter-spacing: 0.5px;
}

/* Discover row: alliance card. Stacked text + JOIN/APPLY action on the right.
   Truncate long names + charters with ellipsis to keep rows single-height. */
.alliance-discover-row {
  padding: 8px 4px;
  border-bottom: 1px solid rgba(255,255,255,0.05);
  display: flex;
  align-items: center;
  gap: 8px;
}
.alliance-row-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
/* Two-line clamp for ad bodies on the discover row — keeps tile heights
   bounded on narrow viewports without truncating to a single line. */
.alliance-row-clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
}
.alliance-policy-badge {
  font-size: 9px;
  padding: 2px 6px;
  border-radius: 3px;
  border: 1px solid currentColor;
  letter-spacing: 0.5px;
}
.alliance-policy-badge-open  { color: var(--accent-green); background: rgba(102,187,106,0.1); }
.alliance-policy-badge-apply { color: var(--accent-gold);  background: rgba(255,215,0,0.1); }
.alliance-row-meta { margin-top: 2px; }
.alliance-relation-status { margin-right: 8px; }

/* Members tab — header + member rows. Treasury sits as a pill in the panel
   header. Member rows are tappable when the caller can manage them. */
.alliance-treasury-pill {
  color: var(--accent-gold);
  font-size: 11px;
  font-family: var(--font-mono);
}
.alliance-level-panel {
  border: 1px solid rgba(79,195,247,0.18);
  background: rgba(79,195,247,0.06);
  border-radius: 6px;
  padding: 8px;
  margin-bottom: 8px;
}
.alliance-level-top {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 7px;
  align-items: center;
  margin-bottom: 5px;
}
.alliance-level-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  height: 22px;
  border: 1px solid var(--accent-cyan);
  border-radius: 4px;
  color: var(--accent-cyan);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: bold;
  background: rgba(79,195,247,0.12);
}
.alliance-level-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 5px;
  margin-top: 6px;
}
.alliance-level-stats span {
  min-width: 0;
  padding: 4px 5px;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 4px;
  color: var(--text-secondary);
  font-family: var(--font-mono);
  font-size: 10px;
  text-align: center;
  overflow-wrap: anywhere;
}
.alliance-member-row {
  padding: 6px 0;
  border-bottom: 1px solid rgba(255,255,255,0.04);
  cursor: default;
}
.alliance-member-row.clickable { cursor: pointer; }
.alliance-member-name    { color: var(--text-primary); }
.alliance-member-name-me { color: var(--accent-cyan); }
.alliance-member-presence { min-width: 55px; text-align: right; margin-right: 6px; }
.alliance-member-power    { min-width: 45px; text-align: right; margin-right: 8px; }
.alliance-member-menu     { margin-left: 6px; cursor: pointer; }

.alliance-charter-text {
  white-space: pre-wrap;
  font-style: italic;
  line-height: 1.4;
}
.alliance-leave-row { text-align: center; }

/* ── Alliance Help Board (REQUESTS tab) ─────────────────────────────────────
   Single panel: action bar on top → sectioned list below.
   The old four-box layout (request form + 3 list panels) is gone — see
   SPEC.md and the spec-driven redesign that replaced it. The form lives in
   a tile-picker modal launched from a single REQUEST HELP button. */

/* Action bar: button on the left, meta chip (caps + cooldown) on the right.
   Cooldown ticker patches #alliance-help-meta and #alliance-help-button-slot
   in place every second — no full re-render of the alliance overlay. */
.alliance-help-actionbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 10px;
  margin-bottom: 8px;
  border-bottom: 1px solid var(--border-subtle);
}
.alliance-help-actionbar-btn { flex-shrink: 0; }
.alliance-help-actionbar-btn .btn {
  min-height: 36px;
  font-weight: bold;
  letter-spacing: 0.4px;
}
.alliance-help-actionbar-meta {
  flex: 1;
  min-width: 0;
  color: var(--text-secondary);
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Section divider: 18 px line with an active-section header, 22 px line
   when the section has zero rows (empty text inline after the rule). */
.alliance-help-divider {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 2px;
  margin: 10px 0 4px 0;
  height: 18px;
}
.alliance-help-divider-empty {
  height: 22px;
  margin-bottom: 0;
}
.alliance-help-divider-title {
  font-family: var(--font-mono);
  font-size: var(--font-md);
  font-weight: bold;
  letter-spacing: 0.5px;
  color: var(--text-primary);
  text-transform: uppercase;
  flex-shrink: 0;
}
.alliance-help-divider-count {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-dim);
  flex-shrink: 0;
}
.alliance-help-divider-rule {
  flex: 1;
  height: 1px;
  background: var(--border-subtle);
  min-width: 8px;
}
.alliance-help-divider-empty-text {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex-shrink: 1;
  min-width: 0;
}

/* Help request row: 3-column grid — leading icon, body, action area. */
.alliance-help-row {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 8px 2px;
  border-bottom: 1px solid var(--border-subtle);
  min-height: 52px;
}
.alliance-help-row:last-child { border-bottom: none; }
.alliance-help-row.is-awaiting-thanks {
  background: linear-gradient(90deg, rgba(255,215,0,0.08), transparent 65%);
  margin: 0 -6px;
  padding-left: 6px;
  padding-right: 6px;
}
.alliance-help-row-icon {
  font-size: var(--font-xl);
  color: var(--text-secondary);
  text-align: center;
}
.alliance-help-class-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  display: inline-block;
  margin: 0 auto;
  box-shadow: 0 0 6px currentColor;
}
.alliance-help-class-dot-kinetic  { background: var(--class-kinetic);  color: var(--class-kinetic); }
.alliance-help-class-dot-electric { background: var(--class-electric); color: var(--class-electric); }
.alliance-help-class-dot-psionic  { background: var(--class-psionic);  color: var(--class-psionic); }
.alliance-help-row-main { min-width: 0; }
.alliance-help-title {
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: var(--font-lg);
  line-height: 1.25;
  overflow-wrap: anywhere;
}
.alliance-help-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 10px;
  margin-top: 3px;
  color: var(--text-dim);
  font-size: var(--font-sm);
}
.alliance-help-actions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  min-width: 70px;
}
/* Bump sm-buttons to the 32px touch-target floor inside row actions. */
.alliance-help-actions .btn-sm { min-height: 32px; padding: 6px 12px; }
.alliance-help-tier-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* ── Request Help modal — visual picker ──────────────────────────────────
   4 resource tiles + 3 troop class tiles. Tap fires the request at the
   CC-scaled cap; no amount input. */
.alliance-help-modal {
  width: min(92vw, 480px);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.alliance-help-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border-subtle);
}
.alliance-help-modal-title {
  font-family: var(--font-mono);
  font-size: var(--font-xl);
  font-weight: bold;
  letter-spacing: 0.5px;
  color: var(--text-primary);
  text-transform: uppercase;
}
.alliance-help-modal-close {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  line-height: 1;
  border: 1px solid var(--border-steel);
  border-radius: 4px;
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--font-mono);
  font-size: var(--font-xl);
  cursor: pointer;
}
.alliance-help-modal-close:hover {
  color: var(--accent-cyan);
  border-color: var(--accent-cyan);
}
.alliance-help-modal-hint {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-dim);
  text-align: center;
  padding-top: 6px;
  border-top: 1px solid var(--border-subtle);
}

.alliance-help-tile-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}
.alliance-help-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 4px;
  width: 100%;
  height: 104px;
  padding: 8px 4px;
  background: var(--bg-panel);
  border: 1px solid var(--border-steel);
  border-radius: 6px;
  cursor: pointer;
  font-family: var(--font-mono);
  transition: transform 0.06s ease-out, border-color 0.12s ease-out;
}
.alliance-help-tile:hover { border-color: var(--accent-cyan); }
.alliance-help-tile:active { transform: scale(0.97); }
.alliance-help-tile:focus-visible {
  outline: 2px solid var(--accent-cyan);
  outline-offset: 2px;
  border-color: var(--accent-cyan);
}
.alliance-help-tile-img {
  width: 56px;
  height: 56px;
  object-fit: cover;
  border-radius: 4px;
  background: rgba(0,0,0,0.3);
}
.alliance-help-tile-label {
  color: var(--text-primary);
  font-size: var(--font-md);
  font-weight: bold;
  letter-spacing: 0.3px;
  text-align: center;
}
.alliance-help-tile-amount {
  color: var(--text-secondary);
  font-size: var(--font-sm);
  text-align: center;
}
/* Class-tinted backgrounds for troop tiles — subtle, just enough to
   group them visually without a header. color-mix is already widely used
   in this stylesheet (~30 occurrences); modern target browsers only. */
.alliance-help-tile-kinetic  { background: color-mix(in srgb, var(--class-kinetic)  10%, var(--bg-panel)); }
.alliance-help-tile-electric { background: color-mix(in srgb, var(--class-electric) 10%, var(--bg-panel)); }
.alliance-help-tile-psionic  { background: color-mix(in srgb, var(--class-psionic)  10%, var(--bg-panel)); }

/* ── Fulfill modal — slider-based partial-fulfill UI ──────────────────── */
.alliance-help-fulfill-modal {
  width: min(92vw, 460px);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.alliance-help-fulfill-modal-troops { width: min(92vw, 540px); }
.alliance-help-fulfill-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border-subtle);
}
.alliance-help-fulfill-title {
  font-family: var(--font-mono);
  font-size: var(--font-xl);
  font-weight: bold;
  letter-spacing: 0.5px;
  color: var(--text-primary);
  text-transform: uppercase;
}
.alliance-help-fulfill-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.alliance-help-fulfill-line {
  font-family: var(--font-mono);
  font-size: var(--font-md);
  color: var(--text-primary);
  line-height: 1.35;
}
.alliance-help-fulfill-line.text-dim { color: var(--text-dim); font-size: var(--font-sm); }
.alliance-help-slider-row {
  display: flex;
  align-items: center;
  gap: 12px;
}
.alliance-help-slider {
  flex: 1;
  min-width: 0;
  height: 4px;
  accent-color: var(--accent-cyan);
}
.alliance-help-slider-readout {
  flex-shrink: 0;
  min-width: 90px;
  text-align: right;
  font-family: var(--font-mono);
  font-size: var(--font-lg);
  color: var(--text-primary);
}
.alliance-help-fulfill-subsidy {
  padding: 8px 10px;
  border: 1px solid var(--border-subtle);
  border-radius: 4px;
  background: color-mix(in srgb, var(--accent-cyan) 6%, var(--bg-panel));
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-secondary);
}
.alliance-help-fulfill-subsidy span {
  color: var(--accent-gold);
  font-weight: bold;
}
/* Clamped subsidy: payout was reduced by the daily $ato cap. Show the
   reduced number in red and the theoretical in dim text. */
.alliance-help-fulfill-subsidy .alliance-help-subsidy-clamped {
  color: var(--accent-red);
}
.alliance-help-fulfill-subsidy .text-xs {
  color: var(--text-dim);
  font-weight: normal;
}
.alliance-help-fulfill-usage {
  margin-top: 4px;
  padding-top: 4px;
  border-top: 1px solid var(--border-subtle);
  color: var(--text-dim);
  font-size: var(--font-xs);
  letter-spacing: 0.3px;
}
.alliance-help-fulfill-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  padding-top: 6px;
  border-top: 1px solid var(--border-subtle);
}

/* Troop tier picker: row of 3 tiles, active one outlined in cyan. */
.alliance-help-tier-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.alliance-help-tier-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 8px 4px;
  background: var(--bg-panel);
  border: 1px solid var(--border-steel);
  border-radius: 6px;
  cursor: pointer;
  font-family: var(--font-mono);
  transition: transform 0.06s ease-out, border-color 0.12s ease-out;
}
.alliance-help-tier-tile:hover:not(.is-disabled) { border-color: var(--accent-cyan); }
.alliance-help-tier-tile.is-active {
  border-color: var(--accent-cyan);
  background: color-mix(in srgb, var(--accent-cyan) 10%, var(--bg-panel));
}
.alliance-help-tier-tile.is-disabled,
.alliance-help-tier-tile[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}
.alliance-help-tier-tile-img {
  width: 56px;
  height: 56px;
  object-fit: cover;
  border-radius: 4px;
  background: rgba(0,0,0,0.3);
}
.alliance-help-tier-tile-label {
  color: var(--text-primary);
  font-size: var(--font-md);
  font-weight: bold;
  text-align: center;
}
.alliance-help-tier-tile-have {
  color: var(--text-secondary);
  font-size: var(--font-sm);
  text-align: center;
}

@media (max-width: 640px) {
  .alliance-level-top,
  .alliance-level-stats { grid-template-columns: 1fr; }
  .alliance-help-actionbar { gap: 8px; }
  .alliance-help-actionbar-btn .btn { min-height: 32px; padding: 6px 10px; font-size: var(--font-md); }
  /* Floor the mobile cap-chip at 10px — readability rule, not 9px which is
     reserved for decorative badges. Vertical space comes from elsewhere. */
  .alliance-help-actionbar-meta { font-size: var(--font-sm); }
  .alliance-help-row { min-height: 48px; padding: 6px 2px; }
  .alliance-help-tile { height: 96px; padding: 6px 4px; }
  .alliance-help-tile-img { width: 48px; height: 48px; }
}
/* Below 460 px tile-grid drops to 3 columns so the 7th tile wraps cleanly. */
@media (max-width: 460px) {
  .alliance-help-tile-grid { grid-template-columns: repeat(3, 1fr); }
}

/* Settings tab — form fields. .ds-input handles input chrome; we just need
   layout + label spacing. */
.alliance-form-field { margin-bottom: 8px; }
.alliance-form-label {
  display: block;
  margin-bottom: 3px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: 0.5px;
}
.alliance-form-textarea { resize: vertical; }
.alliance-form-uppercase { text-transform: uppercase; }
.alliance-form-amount { width: 70px; flex-shrink: 0; }
.alliance-form-select { width: 100%; }

.alliance-danger-panel  { border-color: var(--accent-red); }
.alliance-danger-header { color: var(--accent-red); }

/* Diplomacy tab — relation rows. */
.alliance-relation-row {
  padding: 6px 0;
  border-bottom: 1px solid rgba(255,255,255,0.04);
}
.alliance-relation-tag-friendly { color: var(--accent-green); }
.alliance-relation-tag-hostile  { color: var(--accent-red); }

/* Applications tab — pending request cards. The applicant message is the
   key social signal; emphasize with a left accent bar. */
.alliance-application-row {
  padding: 10px;
  border-bottom: 1px solid rgba(255,255,255,0.05);
}
.alliance-application-message {
  font-style: italic;
  margin: 6px 0 8px;
  padding: 6px 8px;
  background: rgba(0,0,0,0.25);
  border-left: 2px solid var(--accent-cyan);
  border-radius: 2px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-secondary);
}

/* History tab — audit log row. Compact one-liner with right-aligned timestamp. */
.alliance-history-row {
  padding: 6px 8px;
  border-bottom: 1px solid rgba(255,255,255,0.04);
  font-size: 12px;
}
.alliance-history-time { margin-left: 8px; flex-shrink: 0; }

/* Phase 2: invite banner on the discover (no-alliance) screen — sticky-feel
   panel with cyan glow so it stands out as actionable. */
.alliance-invite-banner {
  border-color: var(--accent-cyan);
  margin-bottom: 10px;
}
.alliance-invite-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 4px;
  border-bottom: 1px solid rgba(255,255,255,0.05);
}
.alliance-invite-row:last-child { border-bottom: none; }
#command-overlay.no-top-bar { padding: 4px !important; }

/* Building interior backgrounds — replace tiling chrome panel */
#command-overlay {
  background-color: var(--bg-dark);
  background-image:
    linear-gradient(rgba(6, 6, 14, 0.55), rgba(6, 6, 14, 0.55)),
    url('assets/interiors/command_center_bg.jpg');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
/* Army overlay bg set dynamically by armyScreen._switchTab — army=bg_2, commanders=bg */
#army-overlay {
  background-color: var(--bg-dark);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
#hospital-overlay {
  background-color: var(--bg-dark);
  background-image:
    linear-gradient(rgba(6, 6, 14, 0.55), rgba(6, 6, 14, 0.55)),
    url('assets/interiors/hospital_bg.jpg');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
#workshop-overlay {
  background-color: var(--bg-dark);
  background-image:
    linear-gradient(rgba(6, 6, 14, 0.55), rgba(6, 6, 14, 0.55)),
    url('assets/interiors/workshop_bg.jpg');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
#research-overlay {
  background-color: var(--bg-dark);
  background-image:
    linear-gradient(rgba(6, 6, 14, 0.82), rgba(6, 6, 14, 0.82)),
    url('assets/interiors/research_bg.jpg');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

.screen-overlay.fullscreen { top: 0 !important; bottom: 0 !important; height: 100vh !important; padding: 0 !important; }
#army-overlay.fullscreen { overflow: hidden; }

.screen-header {
  font-family: var(--font-mono);
  font-size: 18px;
  color: var(--accent-cyan);
  text-align: center;
  margin-bottom: 16px;
  text-transform: uppercase;
  letter-spacing: 2px;
}

.two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.two-col-wide-right {
  display: grid;
  grid-template-columns: 300px 1fr;
  gap: 16px;
}

/* ============================================
   Counter Triangle Indicator
   ============================================ */
.counter-badge {
  font-size: 9px;
  font-family: var(--font-mono);
  padding: 1px 4px;
  border-radius: 2px;
  font-weight: bold;
}

.counter-badge.strong { background: rgba(102, 187, 106, 0.2); color: var(--accent-green); }
.counter-badge.weak { background: rgba(239, 83, 80, 0.2); color: var(--accent-red); }
.counter-badge.neutral { background: rgba(136, 136, 136, 0.1); color: var(--text-dim); }

/* ============================================
   Crawler Base Layout - Full Bleed
   ============================================ */
/* ============================================
   Base Screen — Full-bleed hull + floating panels
   ============================================ */

.base-fullbleed {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #04040c;
}

/* Hull image fills the screen, object-position biased toward center-top
   so the crawler body is always visible */
.base-hull-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 30%;
  pointer-events: none;
  user-select: none;
}

/* Dark vignette — bottom and top edges fade to bg so chrome bars read cleanly */
.base-hull-vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(4,4,12,0.55) 0%, transparent 18%),
    linear-gradient(to top,    rgba(4,4,12,0.65) 0%, transparent 20%);
}

/* ---- Building rails (left / bottom / right) ---- */
.base-rail {
  position: absolute;
  display: flex;
  z-index: 10;
  gap: 6px;
  pointer-events: none;
}
.base-rail > * { pointer-events: auto; }

.base-rail--left {
  left: 8px;
  top: 50%;
  transform: translateY(-50%);
  flex-direction: column;
}

.base-rail--right {
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  flex-direction: column;
}

.base-rail--bottom {
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  flex-direction: row;
}

/* ---- Building panels ----
   Two variants, both on the same `.bpanel` class:
   - Nav variant (left/right rails): horizontal grid icon | body | chev
   - Production variant (bottom rail): vertical layout icon+name / rate / storage-bar
   CSS distinguishes via parent `.base-rail--left/right/bottom`. */
.bpanel {
  position: relative;
  display: grid;
  grid-template-columns: 32px 1fr 10px;
  gap: 8px;
  align-items: center;
  padding: 6px 4px 6px 6px;
  min-width: 148px;
  background: linear-gradient(180deg, rgba(17,24,39,0.55) 0%, rgba(8,10,22,0.55) 100%);
  border: 1px solid rgba(42,48,64,0.7);
  border-radius: 5px;
  cursor: pointer;
  font-family: var(--font-mono);
  transition: background 0.15s, border-color 0.15s, transform 0.15s, box-shadow 0.15s;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: 0 2px 8px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.05);
}
.bpanel:hover {
  background: linear-gradient(180deg, rgba(17,24,39,0.70) 0%, rgba(8,10,22,0.70) 100%);
  border-color: var(--accent-cyan);
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(0,0,0,0.5), 0 0 10px rgba(79,195,247,0.2), inset 0 1px 0 rgba(255,255,255,0.08);
}
.bpanel:active {
  transform: translateY(1px);
}
.bpanel--selected {
  border-color: var(--accent-cyan);
  box-shadow: 0 4px 14px rgba(0,0,0,0.5), 0 0 12px rgba(79,195,247,0.3), inset 0 1px 0 rgba(255,255,255,0.08);
}

/* Right-rail: mirror (chev | body | icon). Grid items are placed in source
   order by default, so we re-order via CSS `order` instead of swapping HTML. */
.base-rail--right .bpanel {
  grid-template-columns: 10px 1fr 32px;
}
.base-rail--right .bpanel .bpanel-chev { order: 1; }
.base-rail--right .bpanel .bpanel-body { order: 2; text-align: right; }
.base-rail--right .bpanel .bpanel-glyph-box { order: 3; }
.base-rail--right .bpanel .bpanel-body .bpanel-meta { justify-content: flex-end; }

/* Upgrading: gold animated top line + gold progress bar (see @keyframes glow-top). */
.bpanel--upgrading {
  border-color: rgba(255,215,0,0.5);
}
.bpanel--upgrading::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: var(--accent-gold);
  animation: glow-top 1.6s ease-in-out infinite;
  pointer-events: none;
}

/* Working: barracks/hospital/workshop/research has an active job running.
   Same shape as upgrading but cyan (not gold) to distinguish "building is
   busy" from "building is levelling up". */
.bpanel--working {
  border-color: rgba(79,195,247,0.5);
}
.bpanel--working::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: var(--accent-cyan);
  animation: glow-top-cyan 1.6s ease-in-out infinite;
  pointer-events: none;
}
.bpanel--working .bpanel-glyph-box { color: var(--accent-cyan); }

@keyframes glow-top-cyan {
  0%, 100% { opacity: 0.3; box-shadow: 0 0 4px var(--accent-cyan); }
  50%      { opacity: 1;   box-shadow: 0 0 12px var(--accent-cyan); }
}

.bpanel--maxed {
  border-color: rgba(255,215,0,0.4);
  opacity: 0.85;
}

/* Icon box — 32x32, dark-gradient background, 1px subtle border */
.bpanel-glyph-box {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(180deg, #0d1520 0%, #05090f 100%);
  border: 1px solid var(--border-subtle);
  border-radius: 4px;
  color: var(--accent-cyan);
  flex-shrink: 0;
}
.bpanel--upgrading .bpanel-glyph-box { color: var(--accent-gold); }
.bpanel--maxed .bpanel-glyph-box { color: var(--accent-gold); }
/* Legacy emoji icon (still used inside modals / binfo tab) */
.bpanel-icon {
  font-size: 17px;
  line-height: 1;
  filter: drop-shadow(0 1px 4px color-mix(in srgb, var(--bpc,#4fc3f7) 50%, transparent));
}

.bpanel-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.bpanel-label {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-bright);
  white-space: nowrap;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  line-height: 1;
  overflow: hidden;
  text-overflow: ellipsis;
}

.bpanel-meta {
  display: flex;
  gap: 6px;
  align-items: center;
  font-size: 9px;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  white-space: nowrap;
}
.bpanel-lv { color: var(--text-dim); }
.bpanel-status-idle { color: var(--text-dim); opacity: 0.5; }
.bpanel-status-timer { color: var(--accent-gold); font-weight: 700; }
/* Work-state ETA (barracks/hospital/workshop/research_lab) — cyan to read
   as "in progress" and to differentiate from the gold .bpanel-status-timer
   used for upgrades. Same weight + size as siblings inside .bpanel-meta. */
.bpanel-work-timer { color: var(--accent-cyan); font-weight: 700; }

/* Upgrade progress bar — gold fill, cyan-glow shadow, 2px tall */
.bpanel-progress {
  height: 2px;
  background: #050a12;
  margin-top: 1px;
  overflow: hidden;
}
.bpanel-progress-fill {
  height: 100%;
  background: var(--accent-gold);
  box-shadow: 0 0 4px rgba(255,215,0,0.6);
  transition: width 0.3s;
}

/* Legacy sub (still rendered by info panel + binfo tab) */
.bpanel-sub {
  font-size: 9px;
  color: var(--text-dim);
  white-space: nowrap;
}

.bpanel-timer {
  color: var(--accent-gold);
  font-weight: 700;
  font-style: normal;
}

.bpanel-chev {
  font-size: 14px;
  color: var(--text-dim);
  opacity: 0.5;
  line-height: 1;
  transition: color 0.15s, opacity 0.15s, transform 0.15s;
}
.bpanel:hover .bpanel-chev {
  color: var(--accent-cyan);
  opacity: 1;
}
.base-rail--left .bpanel:hover .bpanel-chev { transform: translateX(2px); }
.base-rail--right .bpanel:hover .bpanel-chev { transform: translateX(-2px); }

/* Legacy arrow (kept for non-redesigned subscreens that reuse bpanel). */
.bpanel-arrow {
  position: absolute;
  top: 3px;
  right: 5px;
  font-size: 12px;
  opacity: 0.6;
  line-height: 1;
}

/* ---- Production tiles (bottom-rail variant) ---- */
.base-rail--bottom .bpanel {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  min-width: 0;
  width: 112px;
  padding: 6px 8px 7px;
  gap: 3px;
}
.bpanel-prod-top {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.bpanel-prod-icon {
  width: 14px;
  height: 14px;
  object-fit: contain;
  flex-shrink: 0;
  color: var(--accent-cyan);
}
.bpanel-prod-name {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.bpanel-prod-rate {
  display: flex;
  align-items: baseline;
  gap: 2px;
  line-height: 1;
}
.bpanel-prod-num {
  font-size: 14px;
  font-weight: 800;
  color: var(--text-bright);
  font-variant-numeric: tabular-nums;
}
.bpanel-prod-unit {
  font-size: 9px;
  color: var(--text-dim);
}
.bpanel-storage-bar {
  height: 2px;
  background: #050a12;
  overflow: hidden;
}
.bpanel-storage-fill {
  height: 100%;
  background: var(--accent-cyan);
  transition: width 0.3s, background-color 0.15s;
}
.bpanel-storage-fill.full { background: var(--accent-orange); }

/* ---- Animations (new for polish pass) ---- */
@keyframes glow-top {
  0%, 100% { opacity: 0.3; box-shadow: 0 0 4px var(--accent-gold); }
  50%      { opacity: 1;   box-shadow: 0 0 12px var(--accent-gold); }
}
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 6px currentColor; }
  50%      { box-shadow: 0 0 14px currentColor, 0 0 20px currentColor; }
}

/* Commander Talk bubble — positioned outside bpanel to the side */
.bpanel-commander-bubble {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 2px solid var(--bpc, #4fc3f7);
  object-fit: cover;
  cursor: pointer;
  z-index: 5;
  background: var(--bg-dark);
  box-shadow: 0 0 8px rgba(0,0,0,0.7), 0 0 6px color-mix(in srgb, var(--bpc, #4fc3f7) 20%, transparent);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.bpanel-commander-bubble:hover {
  transform: translateY(-50%) scale(1.15);
  box-shadow: 0 0 12px rgba(0,0,0,0.7), 0 0 10px color-mix(in srgb, var(--bpc, #4fc3f7) 40%, transparent);
}
.bpanel-commander-bubble:active {
  transform: translateY(-50%) scale(0.95);
}
.bpanel-commander-bubble--right {
  right: -38px;
}
.bpanel-commander-bubble--left {
  left: -38px;
}

/* ---- Interior peek overlay ---- */
.interior-peek {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(0, 0, 0, 0.75);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: fade-in 0.2s ease-out;
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

.interior-peek-scene {
  position: relative;
  width: 90vw;
  max-width: 900px;
  aspect-ratio: 2 / 1;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid #2a3a50;
  box-shadow: 0 8px 40px rgba(0,0,0,0.8);
}

.interior-peek-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Contact shadow — ellipse at commander's feet for grounded 2.5D look */
.interior-peek-shadow {
  position: absolute;
  z-index: 1;
  height: 6%;
  transform: translateX(-50%);
  background: radial-gradient(ellipse, rgba(0,0,0,0.45) 0%, transparent 65%);
  border-radius: 50%;
  pointer-events: none;
}

.interior-peek-commander {
  position: absolute;
  cursor: pointer;
  z-index: 2;
  filter: drop-shadow(0 2px 8px rgba(0,0,0,0.6));
  transition: filter 0.15s ease;
}
.interior-peek-commander:hover {
  filter: drop-shadow(0 2px 8px rgba(0,0,0,0.6)) brightness(1.15);
}

.interior-peek-fg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  z-index: 3;
}

.interior-peek-speech {
  position: absolute;
  top: 10%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  background: rgba(6, 6, 14, 0.88);
  border: 1px solid var(--accent-cyan);
  border-radius: 6px;
  padding: 10px 16px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: #ddd;
  width: 70%;
  min-height: 2.4em;
  text-align: left;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
  backdrop-filter: blur(4px);
}
.interior-peek-speech.visible {
  opacity: 1;
}
/* Invisible sizing ghost — keeps box at full-line width during typewriter */
.interior-peek-speech::after {
  content: attr(data-full);
  display: block;
  height: 0;
  overflow: hidden;
  visibility: hidden;
}

.interior-peek-actions {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 10;
  display: flex;
  gap: 8px;
  justify-content: center;
  padding: 10px;
  background: linear-gradient(transparent, rgba(6, 6, 14, 0.9));
}

/* Commander name label — pinned to the TOP of the scene so the action
   buttons at the bottom never overlap it. Was bottom:44px but the v2
   .btn variants are taller than the original flat buttons, pushing them
   up over the name. Top placement is also closer to "above the
   character's head" which is what the label is meant to identify. */
.interior-peek-name {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  font-weight: 700;
  color: var(--accent-cyan);
  text-transform: uppercase;
  letter-spacing: 1.5px;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.9);
  padding: 4px 10px;
  background: rgba(8, 10, 22, 0.55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(79, 195, 247, 0.3);
  border-radius: var(--radius-sm);
}

/* Elevated container — escapes screen-overlay stacking context during tutorial */
#base-info-elevated {
  position: fixed;
  inset: 0;
  z-index: 102;
  pointer-events: none;
}
#base-info-elevated .base-info-panel {
  position: fixed;
  pointer-events: auto;
}

/* ---- Inline info panel (center) ---- */
.base-info-panel {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 240px;
  background: rgba(8, 10, 22, 0.92);
  border: 1px solid color-mix(in srgb, var(--bpc, #4fc3f7) 40%, transparent);
  border-top: 2px solid var(--bpc, #4fc3f7);
  border-radius: 6px;
  padding: 10px 12px;
  z-index: 20;
  font-family: var(--font-mono);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 4px 24px rgba(0,0,0,0.7), 0 0 20px color-mix(in srgb, var(--bpc,#4fc3f7) 12%, transparent);
  animation: base-info-in 0.15s ease-out;
}

@keyframes base-info-in {
  from { opacity: 0; transform: translate(-50%, -48%) scale(0.96); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

.base-info-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.base-info-icon { font-size: 22px; line-height: 1; }

.base-info-title {
  font-size: 12px;
  font-weight: bold;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.base-info-level {
  font-size: 9px;
  color: var(--text-dim, #666);
  text-transform: uppercase;
}

.base-info-close {
  margin-left: auto;
  cursor: pointer;
  color: var(--text-dim, #666);
  font-size: 14px;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 3px;
  transition: color 0.12s, background 0.12s;
}

.base-info-close:hover {
  color: var(--text-primary, #e0e0e0);
  background: rgba(255,255,255,0.08);
}

.base-info-stats {
  border-top: 1px solid rgba(255,255,255,0.06);
  padding-top: 6px;
  margin-bottom: 8px;
}

.base-info-stats .stat-row { padding: 2px 0; font-size: 10px; }

.base-info-divider {
  height: 1px;
  background: rgba(255,255,255,0.06);
  margin: 4px 0;
}

.base-info-cost {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 6px;
}

.base-cost-chip {
  font-size: 10px;
  padding: 3px 6px;
  border-radius: 3px;
  background: rgba(255,255,255,0.05);
  color: var(--text-secondary, #aaa);
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.base-cost-chip .base-cost-icon {
  width: 12px;
  height: 12px;
  vertical-align: middle;
  flex-shrink: 0;
}

.base-cost-chip--short {
  color: var(--accent-red, #ef5350);
  background: rgba(239, 83, 80, 0.18);
  border: 1px solid rgba(239, 83, 80, 0.5);
  padding: 2px 5px;
}

.base-cost-chip--short .base-cost-have {
  color: var(--accent-red, #ef5350);
  opacity: 0.85;
  font-size: 9px;
}

.base-info-actions {
  display: flex;
  gap: 6px;
  align-items: center;
}

.base-info-upgrade { flex: 1; }

.base-info-progress-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.base-info-timer {
  font-size: 10px;
  color: var(--accent-cyan, #4fc3f7);
  font-weight: bold;
  text-align: center;
}

.base-info-boost {
  white-space: nowrap;
  font-size: 10px;
  padding: 4px 8px;
}

/* ---- Boost modal ---- */
.base-boost-progress {
  margin-bottom: 10px;
}

.base-boost-modal-timer {
  font-size: 11px;
  color: var(--accent-cyan, #4fc3f7);
  font-weight: bold;
  text-align: center;
  margin-top: 3px;
  font-family: var(--font-mono);
}

.base-boost-grades {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.base-boost-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  border-radius: 5px;
  background: rgba(255,255,255,0.03);
  border: 1px solid color-mix(in srgb, var(--gc, #888) 25%, transparent);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
  font-family: var(--font-mono);
}

.base-boost-row:hover {
  background: rgba(255,255,255,0.07);
  border-color: color-mix(in srgb, var(--gc, #888) 55%, transparent);
}

.base-boost-row--dim {
  opacity: 0.45;
  cursor: default;
}

.base-boost-row-icon {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.base-boost-row-count {
  font-size: 10px;
  font-weight: bold;
  min-width: 28px;
}

.base-boost-row-pct {
  font-size: 10px;
  color: var(--text-dim, #666);
  min-width: 30px;
}

.base-boost-row-time {
  font-size: 9px;
  font-weight: bold;
  flex: 1;
  min-width: 0;
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.base-boost-row-btn {
  font-size: 9px;
  padding: 3px 8px;
  white-space: nowrap;
  flex-shrink: 0;
}

.base-boost-free-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-radius: 5px;
  background: rgba(102,187,106,0.08);
  border: 1px solid rgba(102,187,106,0.3);
  cursor: pointer;
  transition: background 0.12s;
  font-family: var(--font-mono);
}

.base-boost-free-row:hover {
  background: rgba(102,187,106,0.15);
}

/* ============================================
   BOOST MODAL SHELL — shared tactical shell used by every boost
   surface (building upgrade, training, research, hospital heal,
   extraction). Mirrors the dossier-modal aesthetic.
   Opens via modal.show() with `.modal-box--boost` set on #modal-box
   to strip the default chrome so the inner shell owns the look.
   ============================================ */
.modal-box.modal-box--boost {
  background: transparent !important;
  background-image: none !important;
  border: none !important;
  border-image: none !important;
  border-radius: 5px !important;
  padding: 0 !important;
  min-width: 280px !important;
  max-width: 440px !important;
  max-height: none;
  overflow: visible !important;
  box-shadow: none !important;
}

.boost-modal {
  position: relative;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, rgba(17, 24, 39, 0.92) 0%, rgba(8, 10, 22, 0.95) 100%);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid rgba(79, 195, 247, 0.4);
  border-radius: 5px;
  color: var(--text-primary);
  font-family: var(--font-mono);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.8), 0 0 40px rgba(79, 195, 247, 0.2);
  overflow: hidden;
}

.boost-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 6px 12px;
  min-height: 44px;
  background: linear-gradient(180deg, rgba(79, 195, 247, 0.08) 0%, transparent 100%);
  border-bottom: 1px solid var(--border-subtle);
  position: relative;
  flex-shrink: 0;
}
.boost-header::after {
  content: '';
  position: absolute;
  left: 12px; right: 12px; bottom: -1px; height: 1px;
  background: linear-gradient(90deg, var(--accent-cyan), transparent 60%);
}
.boost-header-inner {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.boost-kicker {
  font-size: var(--font-xs);
  letter-spacing: 1.5px;
  color: var(--text-dim);
  text-transform: uppercase;
  font-weight: 600;
}
.boost-title {
  font-size: var(--font-heading);
  letter-spacing: 1.5px;
  color: #fff;
  text-transform: uppercase;
  font-weight: 700;
  margin: 0;
  text-shadow: 0 0 10px rgba(79, 195, 247, 0.2);
  white-space: nowrap;
  line-height: 1;
}
.boost-close {
  width: 22px;
  height: 22px;
  background: transparent;
  border: 1px solid var(--border-subtle);
  border-radius: 3px;
  color: var(--text-dim);
  font-family: inherit;
  font-size: var(--font-md);
  cursor: pointer;
  transition: all 0.15s;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  padding: 0;
  line-height: 1;
}
.boost-close:hover {
  border-color: var(--accent-red);
  color: var(--accent-red);
  background: rgba(239, 83, 80, 0.08);
}

.boost-body {
  padding: 10px 12px;
  overflow: auto;
}
.boost-meta {
  font-size: var(--font-sm);
  letter-spacing: 0.5px;
  color: var(--text-secondary);
  text-align: center;
  margin-bottom: 8px;
  font-variant-numeric: tabular-nums;
}
.boost-progress {
  margin-bottom: 10px;
}
.boost-progress-timer {
  font-size: var(--font-md);
  color: var(--accent-cyan);
  font-weight: 700;
  text-align: center;
  margin-top: 3px;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
.boost-rows {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.boost-footer {
  padding: 6px 12px;
  border-top: 1px solid var(--border-subtle);
  background: rgba(6, 6, 16, 0.4);
  flex-shrink: 0;
}

/* ============================================
   BUILDING INFO TAB (v2)
   --------------------------------------------------------------
   Shared chrome for the INFO tab in all 6 nav-screen buildings.
   Driven entirely by buildingInfoTab.js — no per-screen CSS.

   Layout:
     • Desktop / portrait: stacked single column (~400px max-width).
     • Has-detail / has-bonuses: a narrow center column flanks meta.
     • Landscape (handled below): 3-col grid (meta | center | upgrade)
       sized to fit 812×375 with zero scrolling.

   Section primitive (.binfo-section + .binfo-section-kicker) mirrors
   .dedit-header — kicker uppercase 9px + cyan thin-line under it. The
   header itself uses the same kicker rhythm so the page reads as a
   sequence of named blocks.
   ============================================ */
.binfo-tab {
  max-width: 420px;
  margin: 12px auto;
  padding: 14px 16px;
  font-family: var(--font-mono);
  color: var(--text-primary);
  /* Dark panel chrome so text reads cleanly over the busy interior art.
     Mirrors the .dedit-modal gradient + blur recipe so the INFO tab feels
     like a v2 surface (no need to compete with maps, screens, lights). */
  background: linear-gradient(180deg, rgba(17, 24, 39, 0.92) 0%, rgba(8, 10, 22, 0.94) 100%);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border: 1px solid var(--border-subtle);
  border-radius: 5px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.55),
              0 0 18px rgba(79, 195, 247, 0.06),
              inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.binfo-main {
  display: flex;
  flex-direction: column;
}
.binfo-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* ── v2 Section primitive ──────────────────────────────────── */
.binfo-section {
  position: relative;
  padding: 8px 0 10px;
  border-top: 1px solid var(--border-subtle);
}
.binfo-col > .binfo-section:first-child,
.binfo-section:first-child {
  border-top: none;
  padding-top: 0;
}
.binfo-section--lore { border-top: none; padding-top: 0; }
.binfo-section-kicker {
  font-size: 9px;
  letter-spacing: 1.5px;
  color: var(--text-dim);
  text-transform: uppercase;
  font-weight: 600;
  margin-bottom: 5px;
  position: relative;
  padding-bottom: 3px;
}
.binfo-section-kicker::after {
  content: '';
  position: absolute;
  left: 0;
  right: 60%;
  bottom: 0;
  height: 1px;
  background: linear-gradient(90deg, var(--accent-cyan), transparent);
}
.binfo-section-kicker--sub {
  margin-top: 8px;
  font-size: 8px;
}
.binfo-section-body {
  font-size: var(--font-md);
  color: var(--text-primary);
}

/* ── Header (mirrors .dedit-header — kicker + title + badges) ── */
.binfo-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 0 8px;
  position: relative;
}
.binfo-header::after {
  content: '';
  position: absolute;
  left: 0;
  right: 50%;
  bottom: 0;
  height: 1px;
  background: linear-gradient(90deg, var(--accent-cyan), transparent);
}
.binfo-icon { font-size: 28px; line-height: 1; flex-shrink: 0; }
.binfo-header-inner {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1;
}
.binfo-header-kicker {
  font-size: 8px;
  letter-spacing: 1.5px;
  color: var(--text-dim);
  text-transform: uppercase;
  font-weight: 600;
}
.binfo-title {
  font-size: 14px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  margin: 0;
  line-height: 1;
  text-shadow: 0 0 10px rgba(79, 195, 247, 0.15);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.binfo-header-badges {
  display: flex;
  flex-direction: column;
  gap: 2px;
  align-items: flex-end;
  flex-shrink: 0;
}

/* ── Lore (subtle quote block, kept on landscape with 2-line clamp) ── */
.binfo-lore {
  font-size: 10px;
  color: var(--text-secondary);
  line-height: 1.5;
  padding: 7px 10px;
  background: linear-gradient(180deg, rgba(79, 195, 247, 0.04), rgba(79, 195, 247, 0));
  border-left: 2px solid rgba(79, 195, 247, 0.25);
  border-radius: 0 4px 4px 0;
}

/* ── Effects (Current / Next preview) ──────────────────────────── */
.binfo-effect {
  font-size: 10px;
  padding: 4px 8px;
  border-radius: 3px;
  background: rgba(79, 195, 247, 0.08);
  border: 1px solid rgba(79, 195, 247, 0.20);
  color: var(--accent-cyan);
  margin-bottom: 4px;
  line-height: 1.4;
}
.binfo-effect:last-child { margin-bottom: 0; }
.binfo-effect--next {
  background: rgba(255, 255, 255, 0.03);
  border-color: var(--border-subtle);
  color: var(--text-dim);
}
.binfo-effect-label {
  font-weight: 700;
  margin-right: 4px;
  text-transform: uppercase;
  font-size: 9px;
  letter-spacing: 1px;
}

/* ── Active Bonuses pill grid ────────────────────────────────── */
.binfo-bonus-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
}
.binfo-bonus-pill {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 4px 7px;
  background: rgba(13, 21, 32, 0.6);
  border: 1px solid var(--border-subtle);
  border-left: 2px solid var(--accent-cyan);
  border-radius: 3px;
  min-width: 0;
}
.binfo-bonus-pill-label {
  font-size: 8px;
  letter-spacing: 1px;
  color: var(--text-dim);
  text-transform: uppercase;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.binfo-bonus-pill-value {
  font-size: 10px;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.binfo-bonus-pill--alliance { border-left-color: var(--accent-cyan); }
.binfo-bonus-pill--zone     { border-left-color: var(--accent-green); }
.binfo-bonus-pill--district { border-left-color: var(--accent-gold); }
.binfo-bonus-pill--research { border-left-color: var(--accent-purple); }
/* Event-granted buffs (player_buffs rows). Green border for positive
   buffs, red for debuffs — matches the chip-color convention used on
   event result cards so the same visual language carries across the UI. */
.binfo-bonus-pill--event-buff   { border-left-color: var(--accent-green); }
.binfo-bonus-pill--event-debuff { border-left-color: var(--accent-red); }
.binfo-empty {
  font-size: 10px;
  color: var(--text-dim);
  text-align: center;
  padding: 6px;
}

/* ── Upgrade column ────────────────────────────────────────── */
.binfo-section--upgrade .binfo-section-body { display: flex; flex-direction: column; gap: 4px; }
.binfo-upgrade-label {
  font-size: 11px;
  color: var(--text-primary);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.binfo-upgrade-label--blocked { color: var(--accent-red); }
.binfo-upgrade-progress {
  display: flex;
  align-items: center;
  gap: 8px;
}
.binfo-upgrade-progress .progress-bar { flex: 1; }
.binfo-upgrade-timer {
  font-size: 11px;
  font-weight: 700;
  color: var(--accent-cyan);
  white-space: nowrap;
}
.binfo-upgrade-maxed { display: flex; justify-content: center; padding: 4px 0; }
.binfo-costs { display: flex; flex-direction: column; gap: 2px; }
.binfo-costs .stat-row { padding: 2px 0; font-size: 10px; }
.binfo-cost-icon {
  width: 14px;
  height: 14px;
  vertical-align: middle;
  margin-right: 4px;
}
.binfo-cost-have {
  opacity: 0.85;
  font-size: 9px;
}

/* ── Detail panel (barracks Commander Leveling, etc.) ──────── */
.binfo-detail-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-secondary);
}
.binfo-detail-table td:first-child { color: var(--text-dim); }
.binfo-detail-table td:last-child { text-align: right; }
.binfo-detail-row--lead td:last-child { color: var(--accent-cyan); }
.binfo-detail-row--skill td:last-child { color: var(--accent-purple); }
.binfo-detail-rarity { text-transform: capitalize; }

/* ── Side-column flanking (desktop / portrait) ─────────────── */
/* When the building has a center column (bonuses or detail), the layout
   becomes a 2-col flex on wider portrait/desktop so the upgrade panel
   stays visible without scrolling. Landscape grid below overrides. */
@media (min-width: 600px) {
  .binfo-tab--has-detail,
  .binfo-tab--has-bonuses {
    max-width: 720px;
  }
  .binfo-tab--has-detail .binfo-main,
  .binfo-tab--has-bonuses .binfo-main {
    display: grid;
    grid-template-columns: 1fr 200px;
    gap: 16px;
  }
  .binfo-tab--has-detail .binfo-col-meta,
  .binfo-tab--has-bonuses .binfo-col-meta {
    grid-row: span 2;
  }
  .binfo-tab--has-detail .binfo-col-detail,
  .binfo-tab--has-bonuses .binfo-col-bonuses {
    border-left: 1px solid var(--border-subtle);
    padding-left: 12px;
  }
  .binfo-tab--has-detail .binfo-col-upgrade,
  .binfo-tab--has-bonuses .binfo-col-upgrade {
    border-left: 1px solid var(--border-subtle);
    padding-left: 12px;
  }
}

/* ============================================
   Profile Screen
   ============================================ */

/* Stats panel (Panel 3) — ROK-style power breakdown + battle counters.
   Built on the v2 .binfo-section primitive so it visually matches the
   building INFO tabs and the rest of the dedit/v2 surfaces. */
.profile-stats { display: flex; flex-direction: column; gap: 4px; }
.profile-stats-section { padding: 6px 0 8px; }
.profile-stats-section:first-child { border-top: none; padding-top: 0; }

/* Kicker for the Power section gets a right-aligned total badge alongside
   the label so the rolled-up number stays visible without a 5th pill. */
.profile-stats-kicker {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding-right: 0;
}
.profile-stats-total {
  color: var(--accent-gold);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: none;
}

.profile-stat-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
}

/* Individual stat pill — same skeleton as .binfo-bonus-pill, source/tone
   conveyed by the left-border accent color so 8 pills can sit close
   together and still read as 4 distinct categories. */
.profile-stat-pill {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 4px 8px;
  background: rgba(13, 21, 32, 0.6);
  border: 1px solid var(--border-subtle);
  border-left: 2px solid var(--accent-cyan);
  border-radius: 3px;
  min-width: 0;
}
.profile-stat-pill-label {
  font-size: 8px;
  letter-spacing: 1px;
  color: var(--text-dim);
  text-transform: uppercase;
  font-weight: 600;
}
.profile-stat-pill-value {
  font-size: 11px;
  color: var(--text-primary);
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Power-source colors (cyan/orange/red/purple — match the design
   tokens already used for class colors). */
.profile-stat-pill--buildings  { border-left-color: var(--accent-cyan); }
.profile-stat-pill--tech       { border-left-color: var(--accent-purple); }
.profile-stat-pill--troops     { border-left-color: var(--accent-red); }
.profile-stat-pill--commanders { border-left-color: var(--accent-gold); }

/* Battle stat tones — green wins, red losses, gold kills, dim losses. */
.profile-stat-pill--win  { border-left-color: var(--accent-green); }
.profile-stat-pill--loss { border-left-color: var(--accent-red); }
.profile-stat-pill--kill { border-left-color: var(--accent-gold); }
.profile-stat-pill--lost { border-left-color: var(--text-dim); }

/* Legacy stat tile kept for any caller still using it. */
.profile-stat {
  padding: 8px;
  background: rgba(10, 10, 20, 0.5);
  border-radius: 4px;
  text-align: center;
}

.profile-stat-label {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.profile-stat-value {
  font-family: var(--font-mono);
  font-size: 16px;
  color: #fff;
  font-weight: bold;
  margin: 2px 0;
}

.profile-stat-sub {
  font-family: var(--font-mono);
  font-size: 10px;
  color: #666;
}

/* ============================================
   Research Screen — 2-panel layout
   ============================================ */

/* Layout */
.res-layout {
  display: flex;
  gap: 8px;
  height: calc(100vh - 116px);
  padding: 6px 8px 0;
}
.res-grid-panel { width: 48%; flex-shrink: 0; }
.res-detail-panel { flex: 1; }

/* Left: category labels + cell grid.
   T3-010: bumped font-size from 8px to 11px and added weight/tint
   so MILITARY / ECONOMY / UTILITY headers actually read against
   the busy lab background art. */
.res-cat-label {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: bold;
  letter-spacing: 1.5px;
  margin: 8px 0 3px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
}
.res-cat-row {
  display: flex;
  gap: 4px;
  margin-bottom: 4px;
}

/* Grid cells */
.res-cell {
  flex: 1;
  aspect-ratio: 1;
  min-width: 68px;
  padding: 3px 2px;
  text-align: center;
  cursor: pointer;
  border-radius: 5px;
  border: 2px solid var(--border-subtle);
  background: rgba(10,10,20,0.7);
  transition: border-color 0.15s, background 0.15s, transform 0.12s;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
}
.res-cell:hover {
  background: rgba(14, 18, 36, 0.9);
  border-color: color-mix(in srgb, var(--cat-color, var(--accent-cyan)) 50%, transparent);
  transform: translateY(-1px);
}
.res-cell--selected {
  border-color: var(--cat-color, var(--accent-cyan));
  background: color-mix(in srgb, var(--cat-color, var(--accent-cyan)) 12%, transparent);
  box-shadow: 0 0 8px color-mix(in srgb, var(--cat-color, var(--accent-cyan)) 20%, transparent);
}
.res-cell-icon { font-size: 14px; line-height: 1; }
.res-cell-name {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-secondary);
  line-height: 1.15;
  word-break: break-word;
}
.res-cell-level {
  font-family: var(--font-mono);
  font-size: var(--font-md);
  font-weight: bold;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.res-cell--max .res-cell-level { color: var(--accent-green); }
.res-cell--active .res-cell-level { color: var(--accent-gold); }

/* Short-viewport tightening: on mobile landscape (height ≤ 500px) the 1:1
   cells + label spacing overflow the panel. Flatten cells, trim padding
   and margins so all three category rows fit without scroll. */
@media (max-height: 500px) {
  .res-cat-label { font-size: 10px; margin: 3px 0 2px; letter-spacing: 1px; }
  .res-cat-row { gap: 3px; margin-bottom: 2px; }
  .res-cell {
    aspect-ratio: auto;
    height: clamp(54px, 14vh, 72px);
    min-width: 56px;
    padding: 2px 2px;
    gap: 1px;
  }
  .res-cell-icon { font-size: 12px; }
  .res-cell-name { font-size: 10px; line-height: 1.1; }
  .res-cell-level { font-size: 10px; }
}

/* Right: empty state */
.res-empty-detail {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}

/* Right: detail panel */
.res-detail-inner {
  display: flex;
  flex-direction: column;
  height: 100%;
  gap: 6px;
}
.res-detail-icon { font-size: 24px; text-align: center; }
.res-detail-name {
  font-family: var(--font-mono);
  font-size: 14px;
  text-align: center;
  font-weight: bold;
}
.res-detail-desc {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-secondary);
  text-align: center;
}
.res-detail-level {
  font-family: var(--font-mono);
  font-size: var(--font-2xl);
  color: var(--text-primary);
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.res-detail-level--max { color: var(--accent-green); }
.res-detail-action { margin-top: auto; }

/* Cost box */
.res-cost-box {
  padding: 8px;
  background: rgba(0,0,0,0.3);
  border-radius: 4px;
  border: 1px solid var(--border-subtle);
}
.res-cost-header {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-secondary);
  margin-bottom: 4px;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.res-cost-line {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.res-cost-line--short { color: var(--accent-red); }
.res-cost-time {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-secondary);
  margin-top: 4px;
  font-variant-numeric: tabular-nums;
}

/* Lore block */
.res-lore {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-dim);
  font-style: italic;
  border-left: 2px solid var(--text-dim);
  padding-left: 6px;
  line-height: 1.4;
}

/* Research detail effect breakdown (current vs next level bonuses) */
.res-effect-box {
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 6px 8px;
  margin-top: 4px;
}
.res-effect-row {
  display: flex;
  justify-content: space-between;
  font-size: var(--font-sm);
  padding: 1px 0;
  font-variant-numeric: tabular-nums;
}
.res-effect-label { color: var(--text-dim); }

/* One-time grant preview (Signal Integration unit bundles, etc.) */
.res-grant-box {
  background: rgba(102, 187, 106, 0.08);
  border: 1px solid color-mix(in srgb, var(--accent-green) 30%, transparent);
  border-radius: var(--radius-md);
  padding: 6px 8px;
  margin-top: 4px;
  font-size: var(--font-sm);
}
.res-grant-header {
  color: var(--accent-green);
  font-size: var(--font-sm);
  margin-bottom: 3px;
  letter-spacing: 1px;
  text-transform: uppercase;
  font-weight: 600;
}
.res-grant-name { color: var(--text-secondary); }

/* Endgame-sink note (weapons/armor have no level cap) */
.res-sink-note {
  font-size: var(--font-sm);
  color: var(--accent-gold);
  text-align: center;
  margin-top: 4px;
  font-style: italic;
}

/* Boost modal CTA text (free-complete row) */
.res-boost-cta {
  color: var(--accent-green);
  font-weight: bold;
}

/* Boost modal catalyst-row USE button — colored via --gc custom prop
   set on the row (see researchScreen._renderBoostModalContent). */
.base-boost-row-btn {
  background: color-mix(in srgb, var(--gc, var(--accent-cyan)) 13%, transparent);
  color: var(--gc, var(--accent-cyan));
  border: 1px solid color-mix(in srgb, var(--gc, var(--accent-cyan)) 27%, transparent);
}
.base-boost-row-count { color: var(--gc, var(--text-primary)); font-variant-numeric: tabular-nums; }
.base-boost-row-time { color: var(--gc, var(--accent-cyan)); font-variant-numeric: tabular-nums; }

/* Timer row */
.res-timer-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 4px;
}

/* Timer text (used by both detail panel and grid) */
.research-timer-text {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--accent-cyan);
}

/* Boost buttons */
.research-boost-btn {
  flex-shrink: 0;
  background: color-mix(in srgb, var(--accent-gold) 13%, transparent);
  color: var(--accent-gold);
  border: 1px solid color-mix(in srgb, var(--accent-gold) 27%, transparent);
  font-size: 11px;
  white-space: nowrap;
}
.research-free-btn {
  background: color-mix(in srgb, var(--accent-green) 13%, transparent);
  color: var(--accent-green);
  border: 1px solid color-mix(in srgb, var(--accent-green) 27%, transparent);
  font-weight: bold;
}

/* Gated / already-researching messages */
.res-gated-msg {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-secondary);
  text-align: center;
  padding: 8px;
}

/* Boost modal title */
.res-boost-title {
  font-size: 13px;
  color: var(--accent-cyan);
  font-weight: bold;
}

/* ============================================
   Hospital - Cryostasis Cards
   ============================================ */
.hosp-cryo-card {
  background: var(--bg-slot);
  border: 1px solid var(--border-steel);
  border-radius: 6px;
  padding: 12px;
  margin-bottom: 8px;
}

.hosp-cryo-top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 10px;
}

.hosp-cryo-actions {
  display: flex;
  gap: 8px;
}

.hosp-cryo-actions .btn {
  flex: 1;
  font-size: 11px;
  padding: 8px;
}

/* ============================================
   Command Center - Formation & Commander
   ============================================ */
.cmd-formation-grid {
  display: flex;
  gap: 12px;
  justify-content: center;
}

.cmd-formation-col {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 120px;
}

.cmd-formation-label {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  text-align: center;
  letter-spacing: 1px;
}

.cmd-slot {
  padding: 10px;
  background: var(--bg-slot);
  border: 1px solid var(--border-steel);
  border-radius: 4px;
  cursor: pointer;
  text-align: center;
  min-height: 56px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  transition: all 0.15s;
}

.cmd-slot:hover {
  border-color: var(--accent-cyan);
  background: var(--bg-slot-hover);
}

.cmd-slot.has-unit {
  border-left-width: 3px;
}

.cmd-slot-name {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: bold;
}

.cmd-slot-count {
  font-family: var(--font-mono);
  font-size: 16px;
  color: #fff;
}

.cmd-slot-class {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--text-dim);
}

.cmd-unit-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 1px solid var(--border-steel);
  border-radius: 4px;
  margin-bottom: 4px;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 12px;
  transition: all 0.15s;
}

.cmd-unit-option:hover {
  background: var(--bg-panel-hover);
  border-color: var(--accent-cyan);
}

.cmd-unit-option.selected {
  border-color: var(--accent-cyan);
  background: rgba(79, 195, 247, 0.1);
}

/* ============================================
   Army Screen - Accordion List
   ============================================ */
/* ============================================
   Army Screen
   ============================================ */

.army-list {
  max-width: 480px;
  margin: 0 auto;
  padding-bottom: 16px;
}

/* Training queue banner */
.army-queue-bar {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--accent-cyan);
  padding: 8px 12px;
  background: rgba(79, 195, 247, 0.06);
  border: 1px solid rgba(79, 195, 247, 0.18);
  border-radius: 6px;
  margin-bottom: 12px;
  text-align: center;
  max-width: 480px;
  margin-left: auto;
  margin-right: auto;
}

/* Tier header */
.army-tier-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 2px 6px;
  border-bottom: 1px solid var(--border-subtle);
  margin-bottom: 6px;
}

.army-tier-title {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 1.5px;
  font-weight: bold;
}

.army-tier-meta {
  display: flex;
  align-items: center;
  gap: 5px;
}

.army-tier-chip {
  font-family: var(--font-mono);
  font-size: 9px;
  padding: 2px 5px;
  border-radius: 3px;
  font-weight: bold;
  letter-spacing: 0.3px;
}

.army-tier-lock {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--accent-red);
  margin-left: 4px;
}

.army-tier-ready {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--accent-green);
  margin-left: 4px;
}

/* Unit row */
.army-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 10px 0 0;
  background: var(--bg-panel);
  border: 1px solid var(--border-steel);
  border-left: 3px solid var(--row-color, var(--border-steel));
  border-radius: 6px;
  margin-bottom: 4px;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, transform 0.1s;
  min-height: 52px;
  overflow: hidden;
}

.army-row:hover { background: var(--bg-panel-hover); }
.army-row:active { transform: scale(0.99); }
.army-row.expanded {
  border-color: var(--row-color, var(--accent-cyan));
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
  margin-bottom: 0;
}
.army-row.locked {
  opacity: 0.28;
  cursor: default;
  border-left-color: var(--border-steel);
}
.army-row.locked:hover { background: var(--bg-panel); }

/* Thumbnail */
.army-row-thumb {
  width: 52px;
  height: 52px;
  flex-shrink: 0;
  border-right: 1px solid var(--border-subtle);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-darker);
}

.army-row-thumb img {
  width: 52px;
  height: 52px;
  object-fit: cover;
  display: block;
}

.army-row-thumb--missing {
  background: var(--bg-slot);
}

.army-row-thumb--missing img {
  opacity: 0;
}

/* Row body */
.army-row-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 10px 0;
}

.army-row-name {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: bold;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.army-row-meta {
  display: flex;
  align-items: center;
  gap: 5px;
}

.army-row-carry {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--text-dim);
}

.army-row-count {
  font-family: var(--font-mono);
  font-size: 18px;
  font-weight: bold;
  min-width: 40px;
  text-align: right;
  flex-shrink: 0;
}

.army-row-count--locked {
  color: var(--text-dim);
  font-size: 16px;
}

.army-row-arrow {
  font-size: 13px;
  color: var(--text-dim);
  flex-shrink: 0;
  width: 18px;
  text-align: center;
}

/* ---- Expanded detail panel ---- */
.army-detail {
  background: rgba(8, 12, 24, 0.97);
  border: 1px solid var(--border-steel);
  border-top: none;
  border-radius: 0 0 6px 6px;
  padding: 14px;
  margin-bottom: 4px;
}

.army-detail-top {
  display: flex;
  gap: 14px;
  margin-bottom: 14px;
}

/* Portrait container — shows colored fallback letter if art missing */
.army-detail-portrait-wrap {
  width: 90px;
  height: 120px;
  border-radius: 6px;
  border: 2px solid var(--border-steel);
  flex-shrink: 0;
  background: var(--bg-slot);
  overflow: hidden;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

.army-detail-portrait {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  position: relative;
  z-index: 1;
}

.army-portrait-fallback {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 40px;
  font-weight: bold;
  color: var(--border-steel);
  pointer-events: none;
}

.army-portrait--missing .army-detail-portrait {
  opacity: 0;
}

.army-detail-stats {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.army-detail-name {
  font-family: var(--font-mono);
  font-size: 16px;
  font-weight: bold;
}

.army-detail-stat-row {
  display: flex;
  gap: 14px;
  margin-top: 2px;
}

.army-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 40px;
}

.army-stat-num {
  font-family: var(--font-mono);
  font-size: 18px;
  font-weight: bold;
}

.army-stat-label {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--text-dim);
  text-transform: uppercase;
}

.army-detail-counters {
  display: flex;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 11px;
  flex-wrap: wrap;
}

.army-lore-btn {
  color: var(--text-dim);
  cursor: pointer;
  font-size: 11px;
  margin-left: 4px;
}

.army-lore-btn:hover { color: var(--accent-cyan); }

/* Training section */
.army-train-section {
  border-top: 1px solid var(--border-subtle);
  padding-top: 12px;
}

.army-train-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin-bottom: 10px;
}

.army-train-qty {
  font-family: var(--font-mono);
  font-size: 18px;
  color: #fff;
  font-weight: bold;
  min-width: 36px;
  text-align: center;
}

.army-train-costs {
  border: 1px solid var(--border-subtle);
  border-radius: 4px;
  padding: 6px 8px;
  background: rgba(10,10,20,0.4);
}

.army-train-time {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

/* Army > unit detail/training sweep (v2 migration) — one-class-per-concern
   to replace the inline-style jungle in armyScreen._render() */

.army-detail-wrap {
  display: flex;
  gap: 8px;
  height: 100%;
  overflow: hidden;
}
.army-portrait-col {
  flex: 1;
  min-width: 0;
  display: flex;
  justify-content: center;
  overflow: hidden;
}
.army-detail-col {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.army-cmd-detail-layout {
  display: flex;
  gap: 8px;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  padding: 4px;
  overflow: hidden;
  contain: layout paint;
}

/* Override the base portrait-flip to include the self-bounding frame that
   used to live inline. --army-portrait-clr drives the class-color border
   (set inline because it's per-unit dynamic). */
.army-detail-wrap .army-portrait-flip {
  aspect-ratio: 1;
  max-height: 90%;
  max-width: 90%;
  border: 2px solid color-mix(in srgb, var(--army-portrait-clr, var(--border-steel)) 27%, transparent);
  border-radius: var(--radius-lg);
}
.army-portrait-flip.is-locked-visual .army-portrait-front img {
  filter: grayscale(0.6) brightness(0.5);
}

.army-portrait-caption {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 8px 8px 6px;
  background: linear-gradient(transparent 0%, rgba(0, 0, 0, 0.7) 30%, rgba(0, 0, 0, 0.95) 100%);
}
.army-portrait-name {
  font-family: var(--font-mono);
  font-size: var(--font-2xl);
  font-weight: bold;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.9);
}
.army-portrait-back .army-portrait-name {
  margin-bottom: 2px;
}
.army-portrait-meta {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  opacity: 0.7;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
  font-variant-numeric: tabular-nums;
}

/* Unit stat stack: ATK/DEF/HP over Carry/Units */
.army-stats-stack {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex-shrink: 0;
}
.army-stats-row {
  display: flex;
  gap: 4px;
  text-align: center;
}
.army-stats-row--logistics { padding: 0 12%; }
.army-stats-row .army-stat {
  flex: 1;
  padding: 4px;
  background: rgba(10, 10, 20, 0.6);
  border-radius: var(--radius-md);
  min-width: 0;
}
.army-stats-row .army-stat-num {
  font-family: var(--font-mono);
  font-size: var(--font-xl);
  font-weight: bold;
  color: var(--text-bright);
  font-variant-numeric: tabular-nums;
}
.army-stats-row .army-stat-label {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 1px;
}

.army-detail-action-area {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Locked empty state (when unit's tier isn't unlocked yet) */
.army-locked-empty {
  text-align: center;
  padding: 8px;
}
.army-locked-icon {
  font-size: var(--font-3xl);
  margin-bottom: 6px;
}
.army-locked-title {
  font-family: var(--font-mono);
  font-size: var(--font-md);
  color: var(--text-dim);
  margin-bottom: 4px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  font-weight: 700;
}
.army-locked-req {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.army-locked-current {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-dim);
  opacity: 0.6;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}

/* Training section — slider, qty, time preview */
.army-train-controls {
  flex-direction: column;
  gap: 6px;
  margin-bottom: 6px;
}
.army-train-slider {
  width: 100%;
  cursor: pointer;
}
.army-train-qty-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.army-train-step {
  padding: 4px 10px;
  font-size: var(--font-xl);
  min-width: 0;
}
.army-train-qty-row .army-train-qty {
  flex: 1;
  text-align: center;
}

/* Timer preview above TRAIN button — readable (was grey-on-dark before) */
.army-train-time-row {
  text-align: center;
  margin: 4px 0;
}

.army-queue-display {
  font-family: var(--font-mono);
  font-size: var(--font-xs);
  color: var(--text-secondary);
  text-align: center;
  margin-top: 3px;
  font-variant-numeric: tabular-nums;
}

.army-queue-display.is-over {
  color: var(--accent-red);
}

/* Active training label — "TRAINING Militia x10" */
.army-train-progress-label {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-secondary);
  margin-bottom: 4px;
  letter-spacing: 1px;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

/* Back-face counters: strong/weak rows */
.army-back-strong { color: var(--accent-green); }
.army-back-weak   { color: var(--accent-red); }

/* Portrait flip card */
.army-portrait-flip {
  perspective: 800px;
  cursor: pointer;
  flex: 1;
  min-height: 0;
  overflow: visible;
}

/* Full-screen detail/locked portrait variant: defaults to height-driven 2:3
   (works on mobile's tall viewport). On landscape viewports the 2/3-of-height
   width hogs the row, so cap width with min() and drop to width-driven while
   keeping the aspect ratio. */
.army-portrait-flip.army-portrait-detail {
  flex: 0 0 auto;
  aspect-ratio: 2 / 3;
  height: 100%;
  overflow: hidden;
  contain: layout paint;
}
@media (min-aspect-ratio: 4 / 3) {
  .army-portrait-flip.army-portrait-detail {
    height: auto;
    width: min(35vw, 450px);
    max-height: 100%;
    align-self: center;
  }
}

.army-portrait-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.45s ease;
}

.army-portrait-inner.flipped {
  transform: rotateY(180deg);
}

.army-portrait-front,
.army-portrait-back {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: 6px;
  overflow: hidden;
}
.army-portrait-back {
  transform: rotateY(180deg);
}

.army-portrait-front img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  display: block;
}

.army-portrait-back {
  transform: rotateY(180deg);
  background: rgba(8, 10, 22, 0.95);
  border: 1px solid var(--border-subtle);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 12px;
  gap: 8px;
  font-family: var(--font-mono);
}

.army-portrait-back .army-back-desc {
  font-size: 11px;
  color: #aaa;
  line-height: 1.5;
}

.army-portrait-back .army-back-lore {
  font-size: 10px;
  color: #aaa;
  line-height: 1.4;
  font-style: italic;
  border-left: 2px solid #444;
  padding-left: 8px;
}

.army-portrait-back .army-back-counters {
  display: flex;
  gap: 10px;
  font-size: 11px;
}

.army-flip-hint {
  position: absolute;
  bottom: 4px;
  right: 6px;
  font-family: var(--font-mono);
  font-size: 8px;
  color: var(--text-dim);
  pointer-events: none;
}

/* Locked/unowned commander card */
.army-cmd-locked {
  filter: grayscale(85%) brightness(0.6);
  transition: filter 0.2s ease;
}
.army-cmd-locked:hover {
  filter: grayscale(60%) brightness(0.75);
}

/* Lock overlay on unowned portrait detail */
.army-lock-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.35);
  z-index: 2;
  pointer-events: none;
}
.army-lock-overlay::after {
  content: '🔒';
  font-size: 28px;
  opacity: 0.7;
}

/* LOCKED badge on roster cards */
.army-locked-badge {
  position: absolute;
  top: 4px;
  right: 4px;
  background: rgba(0, 0, 0, 0.7);
  color: #666;
  font-size: 7px;
  padding: 1px 4px;
  border-radius: 2px;
  font-family: var(--font-mono);
  letter-spacing: 0.5px;
}

/* "How to obtain" hint */
.army-obtain-hint {
  padding: 8px 10px;
  background: rgba(79, 195, 247, 0.08);
  border: 1px solid rgba(79, 195, 247, 0.2);
  border-radius: 4px;
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--accent-cyan, #4fc3f7);
  text-align: center;
}

/* Training progress (active queue) */
.army-train-progress-wrap {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.army-train-timer {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: bold;
  text-align: center;
}

.army-train-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}

/* Grid tile training overlay */
.army-tile-training {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  padding: 2px 3px;
  background: rgba(0,0,0,0.75);
  font-family: var(--font-mono);
  font-size: 8px;
  color: var(--accent-cyan);
  font-weight: bold;
  text-align: center;
  pointer-events: none;
}

/* ============================================
   Scrollbar Styling
   ============================================ */
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: var(--bg-dark); }
::-webkit-scrollbar-thumb { background: var(--border-steel); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-dim); }

/* ============================================
   Battle Replay
   ============================================ */
.br-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  -webkit-user-select: none;
  user-select: none;
  background: #0a0a14;
}

.br-battlefield {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px;
  perspective: 500px;
  perspective-origin: 50% 35%;
  background-color: #0a0a14;
  background-size: cover;
  background-position: center;
  position: relative;
  overflow: hidden;
  min-height: 0;
}

.br-side {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  max-width: 200px;
}

.br-side-label {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: bold;
  letter-spacing: 1px;
}

.br-formation {
  display: flex;
  gap: 4px;
  transform-style: preserve-3d;
}

/* 3D perspective — formations angle toward each other */
.br-side.br-attacker .br-formation {
  transform: rotateY(25deg) rotateX(8deg);
}
.br-side.br-defender .br-formation {
  transform: rotateY(-25deg) rotateX(8deg);
}

.br-col {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.br-col-label {
  font-family: var(--font-mono);
  font-size: 8px;
  color: var(--text-dim);
  text-align: center;
  letter-spacing: 1px;
}

.br-vs {
  font-family: var(--font-mono);
  font-size: 20px;
  color: #333;
  padding: 0 8px;
  align-self: center;
}

/* Portrait-oriented slot cards (80×120, 2:3 ratio) */
.br-slot {
  position: relative;
  width: 80px;
  height: 120px;
  border: 1px solid #2a3040;
  border-radius: 6px;
  background: rgba(10, 10, 20, 0.85);
  overflow: hidden;
  transition: all 0.2s;
}

.br-slot.empty {
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.3;
}

.br-slot.destroyed {
  border-color: #3a1a1a;
}
.br-slot.destroyed .br-slot-hud {
  display: none;
}

/* Buff — green pulsing border */
.br-buff-1 { animation: br-buff-border 1.5s ease-in-out infinite; }
.br-buff-2 { animation: br-buff-border 1.0s ease-in-out infinite; border-width: 3px; }
.br-buff-3 { animation: br-buff-border 0.7s ease-in-out infinite; border-width: 4px; }

@keyframes br-buff-border {
  0%, 100% { border-color: rgba(102,187,106,0.5); }
  50% { border-color: rgba(102,187,106,1.0); }
}

/* Debuff — red pulsing border */
.br-debuff-1 { animation: br-debuff-border 1.5s ease-in-out infinite; }
.br-debuff-2 { animation: br-debuff-border 1.0s ease-in-out infinite; border-width: 3px; }
.br-debuff-3 { animation: br-debuff-border 0.7s ease-in-out infinite; border-width: 4px; }

@keyframes br-debuff-border {
  0%, 100% { border-color: rgba(239,83,80,0.5); }
  50% { border-color: rgba(239,83,80,1.0); }
}

/* Both buff + debuff: split green/red border — overrides individual animations */
.br-buff-debuff {
  animation: br-split-border 1.2s ease-in-out infinite !important;
  border-width: 3px !important;
}
@keyframes br-split-border {
  0%, 100% { border-color: rgba(102,187,106,0.5); border-bottom-color: rgba(239,83,80,0.5); border-right-color: rgba(239,83,80,0.5); }
  50% { border-color: rgba(102,187,106,1.0); border-bottom-color: rgba(239,83,80,1.0); border-right-color: rgba(239,83,80,1.0); }
}

.br-destroyed-overlay {
  position: absolute;
  inset: 0;
  background: rgba(30, 10, 10, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 3;
}

.br-destroyed-text {
  font-family: var(--font-mono);
  font-size: 9px;
  color: #5a2a2a;
  letter-spacing: 1px;
  text-align: center;
}

.br-slot-portrait {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.br-slot-video {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 1;
}

.br-slot-video.hidden {
  visibility: hidden;
  pointer-events: none;
}

/* Mirror right-side (attacker) troop portraits to face left */
.br-side.br-defender .br-slot-portrait,
.br-side.br-defender .br-slot-video {
  transform: scaleX(-1);
}

/* Commander portrait wrapper — applies same rotation as .br-formation */
.br-cmd-wrap {
  flex-shrink: 0;
  align-self: center;
  transform-style: preserve-3d;
}
/* Left wrapper — skew angles vertical edges, top/bottom stay equal length */
#br-cmd-left-wrap {
  transform: skewX(3deg);
}
/* Right wrapper — mirrored */
#br-cmd-right-wrap {
  transform: skewX(-3deg);
}

/* Commander portrait — flat rectangle inside skewed wrapper */
.br-cmd-portrait {
  position: relative;
  width: 244px;
  height: 366px;
  border: 2px solid #4fc3f755;
  border-radius: 6px;
  overflow: hidden;
  background: rgba(10, 10, 20, 0.85);
}

.br-cmd-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.br-cmd-video,
.br-cmd-video-b {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 1;
}
.br-cmd-video.hidden,
.br-cmd-video-b.hidden { display: none; }

/* Mirror right-side commander to face left */
#br-cmd-right .br-cmd-img,
#br-cmd-right .br-cmd-video,
#br-cmd-right .br-cmd-video-b {
  transform: scaleX(-1);
}

/* Per-commander orientation fix. Cipher's base PNG and commander_cipher_short.mp4
   are rendered facing the wrong direction in the source assets, so we flip them
   horizontally in every context. The alt proc video (commander_cipher_short_b.mp4)
   is authored in the correct orientation and is exempt. Stacking overrides:
   on the right side, this overrides the global scaleX(-1) to scaleX(1), which
   together with the fact the source was mirror-wrong ends up facing the correct
   direction; on the left, it applies the flip directly. */
.br-cmd-portrait[data-cmd="cipher"] .br-cmd-img,
.br-cmd-portrait[data-cmd="cipher"] .br-cmd-video {
  transform: scaleX(-1);
}
#br-cmd-right[data-cmd="cipher"] .br-cmd-img,
#br-cmd-right[data-cmd="cipher"] .br-cmd-video {
  transform: scaleX(1);
}

.br-cmd-name {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  padding: 3px 5px;
  background: linear-gradient(transparent, rgba(0,0,0,0.85));
  font: bold 8px monospace;
  color: #aaa;
  text-align: center;
  z-index: 2;
}

/* HUD overlay at bottom of slot card */
.br-slot-hud {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  z-index: 2;
  padding: 3px 5px;
  background: linear-gradient(transparent, rgba(0,0,0,0.85));
  display: flex;
  align-items: center;
  gap: 4px;
}

.br-slot-count {
  font-family: var(--font-mono);
  font-size: 10px;
  color: #fff;
  text-shadow: 0 1px 2px rgba(0,0,0,0.8);
  flex-shrink: 0;
  min-width: 28px;
  text-align: right;
}

.br-slot-empty {
  font-family: var(--font-mono);
  font-size: 10px;
  color: #333;
}

/* Base HP bars */
.br-base-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 4px 0;
}

.br-base-label {
  font-family: var(--font-mono);
  font-size: 9px;
  color: #666;
  min-width: 30px;
}

.br-base-track {
  flex: 1;
  height: 8px;
  background: #1a1a2a;
  border-radius: 4px;
  overflow: hidden;
}

.br-base-fill {
  height: 100%;
  background: var(--accent-cyan);
  border-radius: 4px;
  transition: width 0.4s;
}

.br-base-hp {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-secondary);
  min-width: 40px;
  text-align: right;
}

/* Controls */
.br-controls {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  background: rgba(6, 6, 14, 0.95);
  border-top: 1px solid #2a3040;
  flex-wrap: nowrap;
  position: relative;
}

.br-controls .btn {
  padding: 3px 8px;
  font-size: 9px;
  min-height: 0;
}

.br-log-inline {
  flex: 1;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-secondary);
  padding: 0 8px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  position: relative;
  min-width: 0;
}

.br-log-inline .br-log-full {
  display: none;
}

.br-log-inline.expanded {
  position: absolute;
  bottom: 100%;
  left: 0;
  right: 0;
  white-space: normal;
  overflow-y: auto;
  max-height: 120px;
  background: rgba(4, 4, 10, 0.95);
  border: 1px solid #2a3040;
  border-radius: 6px 6px 0 0;
  padding: 6px 8px;
  z-index: 5;
}

.br-log-inline.expanded > #br-log-latest {
  display: none;
}

.br-log-inline.expanded .br-log-full {
  display: block;
  font-size: 9px;
  color: #666;
  line-height: 1.5;
}

.br-round-indicator {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-secondary);
  margin-left: auto;
}

.br-speed-btns {
  display: flex;
  gap: 4px;
}

.br-speed-btns .btn.active {
  background: var(--accent-cyan);
  color: #000;
  border-color: var(--accent-cyan);
}

/* Battle log */
.br-log {
  height: 80px;
  overflow-y: auto;
  padding: 6px 10px;
  background: rgba(4, 4, 10, 0.95);
  border-top: 1px solid #1a2030;
}

/* Projectile streak */
.br-streak {
  position: absolute;
  height: 2px;
  background: linear-gradient(90deg, transparent 0%, #ffd54f 30%, #ff6d00 70%, transparent 100%);
  pointer-events: none;
  animation: br-streak-anim 0.35s ease-out forwards;
  z-index: 10;
}

@keyframes br-streak-anim {
  0% { opacity: 0; transform-origin: 0 50%; }
  20% { opacity: 1; }
  100% { opacity: 0; }
}
.br-streak-orange { background: linear-gradient(90deg, transparent 0%, #ff9800 30%, #ef5350 70%, transparent 100%); }
.br-streak-purple { background: linear-gradient(90deg, transparent 0%, #4fc3f7 30%, #e040fb 70%, transparent 100%); }
.br-streak-gold { background: linear-gradient(90deg, transparent 0%, #ffd700 30%, #fff 60%, #ffd700 80%, transparent 100%); }

/* Damage popup */
.br-damage-popup {
  position: absolute;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-weight: bold;
  font-size: 13px;
  color: #ef5350;
  pointer-events: none;
  z-index: 30;
  animation: br-dmg-float 1s ease-out forwards;
  white-space: nowrap;
  text-shadow: 0 1px 3px rgba(0,0,0,0.9), 0 0 6px rgba(0,0,0,0.6);
}

@keyframes br-dmg-float {
  0% { opacity: 0; transform: translateX(-50%) translateY(0) scale(0.92); }
  10% { opacity: 1; transform: translateX(-50%) translateY(0) scale(1.06); }
  50% { opacity: 1; transform: translateX(-50%) translateY(0) scale(1.04); }
  78% { opacity: 1; transform: translateX(-50%) translateY(-16px) scale(1); }
  100% { opacity: 0; transform: translateX(-50%) translateY(-26px) scale(0.96); }
}

/* Attack shake */
.br-attack-shake {
  animation: br-shake 0.25s ease-in-out;
}

@keyframes br-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(4px); }
  75% { transform: translateX(-4px); }
}

/* Buff-scaled shake variants */
.br-attack-shake-1 { animation: br-shake-1 0.25s ease-in-out; }
.br-attack-shake-2 { animation: br-shake-2 0.25s ease-in-out; }
.br-attack-shake-3 { animation: br-shake-3 0.2s ease-in-out; }

@keyframes br-shake-1 {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(6px); }
  75% { transform: translateX(-6px); }
}
@keyframes br-shake-2 {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(8px) scale(1.02); }
  75% { transform: translateX(-8px) scale(1.02); }
}
@keyframes br-shake-3 {
  0%, 100% { transform: translateX(0) scale(1); }
  20% { transform: translateX(10px) scale(1.04); }
  40% { transform: translateX(-10px) scale(1.04); }
  60% { transform: translateX(6px) scale(1.02); }
  80% { transform: translateX(-6px) scale(1.02); }
}

/* Screen shake for 3+ buff attacks */
.br-screen-shake { animation: br-screen-rumble 0.3s ease-in-out; }
@keyframes br-screen-rumble {
  0%, 100% { transform: translate(0); }
  20% { transform: translate(-3px, 2px); }
  40% { transform: translate(3px, -2px); }
  60% { transform: translate(-2px, 1px); }
  80% { transform: translate(2px, -1px); }
}

/* Hit flash */
.br-hit-flash {
  animation: br-hit 0.35s ease-out;
}

@keyframes br-hit {
  0% { box-shadow: 0 0 0 rgba(239, 83, 80, 0); background: rgba(10,10,20,0.85); }
  30% { box-shadow: 0 0 15px rgba(239, 83, 80, 0.6); background: rgba(60,20,20,0.9); }
  100% { box-shadow: 0 0 0 rgba(239, 83, 80, 0); background: rgba(10,10,20,0.85); }
}

/* Buff-scaled hit flash variants */
.br-hit-flash-orange { animation: br-hit-orange 0.35s ease-out; }
.br-hit-flash-purple { animation: br-hit-purple 0.35s ease-out; }
.br-hit-flash-gold { animation: br-hit-gold 0.4s ease-out; }

@keyframes br-hit-orange {
  0% { box-shadow: 0 0 0 rgba(255,152,0,0); }
  30% { box-shadow: 0 0 18px rgba(255,152,0,0.7); background: rgba(40,25,10,0.9); }
  100% { box-shadow: 0 0 0 rgba(255,152,0,0); background: rgba(10,10,20,0.85); }
}
@keyframes br-hit-purple {
  0% { box-shadow: 0 0 0 rgba(224,64,251,0); }
  30% { box-shadow: 0 0 20px rgba(224,64,251,0.7); background: rgba(30,10,40,0.9); }
  100% { box-shadow: 0 0 0 rgba(224,64,251,0); background: rgba(10,10,20,0.85); }
}
@keyframes br-hit-gold {
  0% { box-shadow: 0 0 0 rgba(255,215,0,0); }
  25% { box-shadow: 0 0 25px rgba(255,215,0,0.8); background: rgba(40,35,10,0.9); }
  50% { box-shadow: 0 0 15px rgba(255,215,0,0.5); }
  100% { box-shadow: 0 0 0 rgba(255,215,0,0); background: rgba(10,10,20,0.85); }
}

/* Base flash */
.br-flash {
  animation: br-base-flash 0.4s ease-out;
}

@keyframes br-base-flash {
  0% { box-shadow: none; }
  30% { box-shadow: 0 0 10px rgba(239, 83, 80, 0.5); }
  100% { box-shadow: none; }
}

/* Commander skill flash */
.br-commander-flash {
  animation: br-cmd-flash 0.5s ease-out;
}

@keyframes br-cmd-flash {
  0% { box-shadow: inset 0 0 0 rgba(171, 71, 188, 0); }
  30% { box-shadow: inset 0 0 40px rgba(171, 71, 188, 0.4); }
  100% { box-shadow: inset 0 0 0 rgba(171, 71, 188, 0); }
}

/* Panel scale-in animation (chat, alerts) */
@keyframes panel-scale-in {
  0% { transform: scale(0.9); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}

/* Conduit +100 float-up celebration */
@keyframes conduit-float {
  0% { transform: translateY(0); opacity: 1; }
  100% { transform: translateY(-30px); opacity: 0; }
}

/* Alert toast slide-down */
@keyframes alert-slide-down {
  0% { transform: translateY(-20px); opacity: 0; }
  100% { transform: translateY(0); opacity: 1; }
}


.notif-loc-btn:hover {
  background: rgba(255, 255, 255, 0.1) !important;
}

/* Location title card (Dark Souls style) */
@keyframes lore-location-fade {
  0% { opacity: 0; transform: translateX(-50%) translateY(10px); }
  15% { opacity: 1; transform: translateX(-50%) translateY(0); }
  75% { opacity: 1; transform: translateX(-50%) translateY(0); }
  100% { opacity: 0; transform: translateX(-50%) translateY(-5px); }
}

/* ============================================
   Lore Popup (Elden Ring style)
   ============================================ */
.lore-popup {
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(0, 0, 0, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  animation: lore-fade-in 0.2s ease-out;
}

.lore-popup.hidden { display: none; }

@keyframes lore-fade-in {
  0% { opacity: 0; }
  100% { opacity: 1; }
}

.lore-popup-inner {
  background: #0d0d18;
  border: 1px solid #2a3a50;
  border-radius: 8px;
  max-width: 400px;
  width: 90%;
  max-height: 85vh;
  padding: 0;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.8);
  animation: lore-slide-up 0.25s ease-out;
  display: flex;
  flex-direction: column;
}
/* Wider when two-panel detail is present */
.lore-popup-inner.has-detail { max-width: 600px; }

@keyframes lore-slide-up {
  0% { transform: translateY(20px); opacity: 0; }
  100% { transform: translateY(0); opacity: 1; }
}

.lore-popup-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px 10px;
  border-bottom: 1px solid #1a2030;
  flex-shrink: 0;
}

.lore-popup-title {
  font-family: var(--font-mono);
  font-size: 16px;
  font-weight: bold;
  color: #e0e0e0;
  text-transform: uppercase;
  letter-spacing: 1px;
}

.lore-popup-subtitle {
  font-family: var(--font-mono);
  font-size: 11px;
  color: #888;
  margin-left: 10px;
  margin-right: auto;
  letter-spacing: 0.5px;
  padding: 1px 6px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 3px;
}
.lore-popup-subtitle:empty { display: none; }

.lore-popup-close {
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 18px;
  cursor: pointer;
  padding: 4px 8px;
}

.lore-popup-close:hover { color: #fff; }

/* Body — single column by default, flex row when detail present */
.lore-popup-body {
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}
.lore-popup-body.has-detail {
  display: flex;
  flex-direction: row;
}
.lore-popup-body.has-detail .lore-popup-text {
  flex: 1;
  min-width: 0;
  border-right: 1px solid #1a2030;
  overflow-y: auto;
}
.lore-popup-body.has-detail .lore-popup-detail {
  flex: 0 0 200px;
  overflow-y: auto;
}

.lore-popup-desc {
  font-family: var(--font-mono);
  font-size: 12px;
  color: #ccc;
  padding: 12px 16px;
  line-height: 1.5;
}

.lore-popup-divider {
  height: 1px;
  background: linear-gradient(90deg, transparent, #2a3a50, transparent);
  margin: 0 16px;
}

.lore-popup-lore {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-secondary);
  font-style: italic;
  padding: 12px 16px 16px;
  line-height: 1.6;
}

/* Detail panel (right column in two-panel mode) */
.lore-popup-detail {
  display: none;
  font-family: var(--font-mono);
  font-size: 10px;
  color: #aaa;
  padding: 12px 14px;
  line-height: 1.5;
}

/* ============================================
   Enhanced Battle Replay — Trailing Health Bars + Commander Pop-ins
   ============================================ */

/* Trailing red health bar (green drops instantly, red bleeds down) */
.br-slot-hp-bar {
  height: 3px;
  flex: 1;
  background: #1a1a2a;
  border-radius: 2px;
  overflow: hidden;
  position: relative;
}

.br-slot-hp-trail {
  position: absolute;
  top: 0; left: 0; bottom: 0;
  background: #ef535088;
  border-radius: 3px;
  transition: width 0.8s ease-out;
  z-index: 1;
}

.br-slot-hp-fill {
  position: relative;
  height: 100%;
  border-radius: 3px;
  transition: width 0.15s ease-out;
  z-index: 2;
}

/* Commander skill pop-in */
.br-commander-popin {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  background: rgba(10, 10, 20, 0.95);
  border-radius: 8px;
  z-index: 30;
  pointer-events: none;
  box-shadow: 0 0 20px rgba(0,0,0,0.6);
}

.br-commander-popin.from-left {
  left: -200px;
  animation: br-popin-left 1.5s ease-out forwards;
  border: 1px solid #66bb6a;
}

.br-commander-popin.from-right {
  right: -200px;
  animation: br-popin-right 1.5s ease-out forwards;
  border: 1px solid #ef5350;
}

@keyframes br-popin-left {
  0% { left: -200px; opacity: 0; }
  15% { left: 10px; opacity: 1; }
  75% { left: 10px; opacity: 1; }
  100% { left: -200px; opacity: 0; }
}

@keyframes br-popin-right {
  0% { right: -200px; opacity: 0; }
  15% { right: 10px; opacity: 1; }
  75% { right: 10px; opacity: 1; }
  100% { right: -200px; opacity: 0; }
}

.br-commander-portrait {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  font-weight: bold;
  flex-shrink: 0;
}

.br-commander-text {
  font-family: var(--font-mono);
}

.br-commander-name {
  font-size: 11px;
  font-weight: bold;
  color: #fff;
}

.br-commander-skill {
  font-size: 10px;
  color: #ffd54f;
  margin-top: 2px;
}

/* Targeting line */
.br-target-line {
  position: absolute;
  height: 2px;
  pointer-events: none;
  z-index: 5;
  animation: br-target-fade 0.5s ease-out forwards;
}

@keyframes br-target-fade {
  0% { opacity: 0.8; }
  100% { opacity: 0; }
}

/* Collapsed battle log */
.br-log-collapsed {
  height: 24px;
  overflow: hidden;
  padding: 4px 10px;
  background: rgba(4, 4, 10, 0.95);
  border-top: 1px solid #1a2030;
  cursor: pointer;
  transition: height 0.3s;
}

.br-log-collapsed.expanded {
  height: 120px;
  overflow-y: auto;
}

.br-log-toggle {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--text-dim);
  text-align: right;
  cursor: pointer;
  user-select: none;
}

/* Round summary */
.br-round-summary {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(6, 6, 14, 0.92);
  border: 1px solid #ffd700;
  border-radius: 8px;
  padding: 12px 24px;
  z-index: 30;
  font-family: var(--font-mono);
  text-align: center;
  pointer-events: none;
  animation: br-round-fade 1.5s ease-out forwards;
}

@keyframes br-round-fade {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.8); }
  15% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  75% { opacity: 1; }
  100% { opacity: 0; }
}

/* ====================================================================
   Battle replay history — v2 design system upgrade.

   Two-column flex grid: HISTORY list (left) + DETAIL card (right),
   equal width on wide screens, stacked on narrow. List items use
   v2 chrome (.history-item with selected-state border tint),
   detail card uses neutral steel border (was gold accent — too
   loud against the gold meta chips inside). XP shard chip lives
   inline with the meta row.
   ==================================================================== */
/* #battle-overlay needs to be a flex column so the tab-bar sits at the
   top and #reports-tab-body fills the remaining height. Without this,
   the body collapses to its content height and the history grid can't
   reach the bottom HUD chrome (calc-math approaches drift across the
   different nav-bar heights at desktop / mobile-landscape / portrait
   breakpoints; flex auto-fills regardless).
   overflow: hidden suppresses the .screen-overlay's default overflow-y:auto
   so the flex children own the scrolling — without this, when the grid
   height doesn't EXACTLY match the overlay, the overlay scrolls 1-2px
   spuriously and a phantom scrollbar appears. */
#battle-overlay {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
#reports-tab-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.history-grid {
  display: grid;
  grid-template-columns: 300px 1fr;
  gap: 12px;
  align-items: stretch;
  flex: 1;
  min-height: 0;
}
.history-panel,
.history-detail {
  min-width: 0;
  max-height: 100%;
  overflow-y: auto;
}
.history-panel {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 14px;
  border: 1px solid var(--border-steel, #2a3a50);
  border-radius: 6px;
  background: linear-gradient(180deg, rgba(13, 21, 32, 0.7), rgba(8, 10, 22, 0.92));
}
.history-header {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1.5px;
  color: var(--text-dim);
  text-transform: uppercase;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border-steel, #2a3a50);
  margin-bottom: 4px;
}
.history-topline {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border-steel, #2a3a50);
  margin-bottom: 4px;
}
.history-topline .history-header {
  padding-bottom: 0;
  border-bottom: 0;
  margin-bottom: 0;
}
.history-filter .filter-bar {
  gap: 4px;
  margin-bottom: 0;
  flex-wrap: nowrap;
}
.history-filter .filter-pill {
  padding: 3px 7px;
  font-size: 9px;
  white-space: nowrap;
}
.history-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.history-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 1px solid #1a2030;
  border-radius: 4px;
  background: rgba(13, 21, 32, 0.55);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-secondary);
  transition: border-color 120ms ease-out, background 120ms ease-out;
}
.history-item:hover {
  border-color: rgba(79, 195, 247, 0.35);
  background: rgba(79, 195, 247, 0.05);
}
.history-item--selected {
  border-color: var(--accent-cyan, #4fc3f7);
  background: rgba(79, 195, 247, 0.10);
  color: #fff;
}
.history-empty {
  text-align: center;
  color: var(--text-dim);
  padding: 20px;
  font-family: var(--font-mono);
  font-size: 11px;
  border: 1px solid var(--border-steel, #2a3a50);
  border-radius: 6px;
  background: rgba(13, 21, 32, 0.5);
}

/* Narrow viewport — collapse to single column, stack history above detail.
   Lets the body itself scroll instead of each pane scrolling internally. */
@media (max-width: 720px) {
  .history-grid {
    grid-template-columns: 1fr;
    flex: 0 0 auto;
  }
  .history-topline {
    align-items: flex-start;
    flex-direction: column;
  }
  #reports-tab-body { overflow-y: auto; }
  .history-panel,
  .history-detail {
    width: 100%;
    max-height: none;
    overflow-y: visible;
  }
}

/* Mail-specific row dressing inside the shared .history-list / .history-item
   chrome. Battle replay items use WIN/LOSS badges; mail uses an unread dot
   on the left, attachment icon on the right, timestamp at the far right.
   Subject text fills the available space and truncates with ellipsis. */
.history-item .mail-unread-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent-cyan);
  flex-shrink: 0;
}
.history-item .mail-subject {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-primary);
}
.history-item.mail-item--read .mail-subject { color: var(--text-secondary); }
.history-item .mail-attach-icon {
  flex-shrink: 0;
  font-size: 12px;
  line-height: 1;
}
.history-item .mail-attach-icon--claimed { color: var(--text-dim); }
.history-item .mail-attach-icon--pending { color: var(--accent-gold); font-size: 13px; }
.history-item .mail-when {
  flex-shrink: 0;
  color: var(--text-dim);
  font-size: 10px;
}

/* Mail-detail v2 — replaces the inline-hex render in mailTab._renderDetail.
   Mirrors the .br-detail-* battle-replay pattern but tuned for mail content
   (longer body prose, attachment chip, delete button). All colors via
   tokens so the dark-steel theme stays consistent across screens. */
.mail-detail-header {
  display: flex;
  align-items: flex-start;
  gap: var(--space-md);
  margin-bottom: var(--space-sm);
}
.mail-detail-titlewrap { flex: 1; min-width: 0; }
.mail-detail-subject {
  font-family: var(--font-mono);
  font-size: 15px;
  color: var(--text-primary);
  margin-bottom: var(--space-xs);
  word-break: break-word;
}
.mail-detail-meta {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-dim);
}
.mail-detail-delete {
  padding: var(--space-sm) var(--space-md);
  font-size: var(--font-md);
  background: rgba(239, 83, 80, 0.12);
  color: var(--accent-red);
  border: 1px solid rgba(239, 83, 80, 0.3);
}
.mail-detail-body {
  margin-top: var(--space-md);
  padding: var(--space-md);
  background: var(--bg-slot);
  border-radius: 3px;
  font-family: var(--font-mono);
  font-size: var(--font-lg);
  color: var(--text-secondary);
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
}
.mail-attachment {
  margin-top: var(--space-md);
  padding: var(--space-md);
  border-radius: 3px;
  border: 1px solid var(--border-steel);
  background: var(--bg-slot);
}
.mail-attachment--claimed {
  background: rgba(102, 187, 106, 0.06);
  border-color: rgba(102, 187, 106, 0.35);
}
.mail-attachment--unclaimed {
  background: rgba(255, 213, 79, 0.06);
  border-color: rgba(255, 213, 79, 0.35);
}
.mail-attachment-label {
  font-family: var(--font-mono);
  font-size: var(--font-md);
  margin-bottom: var(--space-sm);
}
.mail-attachment--claimed .mail-attachment-label { color: var(--accent-green); }
.mail-attachment--unclaimed .mail-attachment-label { color: var(--accent-gold); }
.mail-attachment-summary {
  font-family: var(--font-mono);
  font-size: var(--font-lg);
  color: var(--text-secondary);
  margin-bottom: var(--space-md);
}
.mail-attachment-claim {
  width: 100%;
  padding: var(--space-md);
  font-size: var(--font-lg);
}

/* ====================================================================
   Battle replay history detail panel — v2 design system upgrade.

   Replaces the bare inline-styled .panel render with a bordered card +
   gold-accent header, prominent XP shard chip, and side sub-panels
   tinted by class (cyan defender / red attacker). Uses v2 tokens so
   re-theming doesn't require touching battleReplayScreen.js.
   ==================================================================== */
.br-detail-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 14px;
  border: 1px solid var(--border-steel, #2a3a50);
  border-radius: 6px;
  background: linear-gradient(180deg, rgba(13, 21, 32, 0.7), rgba(8, 10, 22, 0.92));
}

.br-detail-header {
  display: flex;
  flex-direction: column;
  gap: 2px;
  align-items: flex-start;
}
/* Inline VICTORY chip + winner name on a single row to save vertical
   space — used to be a stacked column, now reads as one headline. */
.br-detail-headline {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.br-detail-tag {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 1.5px;
  color: var(--accent-gold, #ffd700);
  border: 1px solid rgba(255, 215, 0, 0.55);
  background: rgba(255, 215, 0, 0.12);
  padding: 2px 8px;
  border-radius: 3px;
  flex-shrink: 0;
}
/* Perspective-tinted variant for battles the viewer participated in.
   Red DEFEAT badge when viewer's side lost; gold .br-detail-tag carries
   the VICTORY case + alliance-spectator (no perspective) battles. */
.br-detail-tag--defeat {
  color: var(--accent-red, #ef5350);
  border-color: rgba(239, 83, 80, 0.55);
  background: rgba(239, 83, 80, 0.12);
}
.br-detail-name {
  font-family: var(--font-mono);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 1px;
  color: #fff;
  text-transform: uppercase;
}
.br-detail-meta {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: 0.5px;
}
/* XP chip lives inline with the meta row now — same baseline as
   timestamp / site / rounds, accent-cyan for the reward emphasis. */
.br-detail-xp {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.8px;
  color: var(--accent-cyan, #4fc3f7);
  border: 1px solid rgba(79, 195, 247, 0.45);
  background: rgba(79, 195, 247, 0.10);
  padding: 1px 6px;
  border-radius: 3px;
}

.br-detail-side {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 10px;
  border: 1px solid #2a3a50;
  border-radius: 4px;
  background: rgba(13, 21, 32, 0.55);
}
.br-detail-side--def { border-color: rgba(79, 195, 247, 0.40); }
.br-detail-side--atk { border-color: rgba(239, 83, 80, 0.40); }

.br-detail-side-head {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 2px;
}
.br-detail-side-thumb {
  width: 20px; height: 20px;
  object-fit: cover;
  border-radius: 3px;
  border: 1px solid #2a3a50;
  flex-shrink: 0;
}
.br-detail-side--def .br-detail-side-thumb { border-color: rgba(79, 195, 247, 0.45); }
.br-detail-side--atk .br-detail-side-thumb { border-color: rgba(239, 83, 80, 0.45); }
.br-detail-side-name {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.5px;
}

.br-detail-row {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-secondary);
  line-height: 1.5;
}
.br-detail-row-label {
  color: var(--text-dim);
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  font-size: 9px;
  flex-shrink: 0;
  min-width: 60px;
}
.br-detail-row-list {
  flex: 1 1 auto;
}

.br-detail-actions {
  display: flex;
  gap: 6px;
  margin-top: 4px;
}
.br-detail-cta {
  flex: 1 1 auto;
  padding: 9px 12px;
  font-size: 13px;
  letter-spacing: 1px;
}
.br-detail-share,
.br-detail-buffs {
  padding: 9px 14px;
  font-size: 13px;
}

/* BUFFS modal — shows research bonuses + active event buffs both sides
   went into the battle with. Read from `buffSnapshot` field on the
   battle report (added at battle resolution time by combat callsites). */
.br-buffs-modal {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 320px;
  max-width: 480px;
  padding: 4px;
}
.br-buffs-header {
  font-family: ui-monospace, "JetBrains Mono", monospace;
  font-size: 13px;
  letter-spacing: 2px;
  color: var(--text-secondary, #b0b0b0);
  border-bottom: 1px solid #2a3040;
  padding-bottom: 6px;
}
.br-buffs-side {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 10px;
  background: rgba(13, 21, 32, 0.5);
  border: 1px solid #2a3040;
  border-radius: 4px;
}
.br-buffs-side-name {
  font-family: ui-monospace, "JetBrains Mono", monospace;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 1.5px;
}
.br-buffs-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-family: ui-monospace, "JetBrains Mono", monospace;
  font-size: 11px;
}
.br-buffs-row-label {
  color: var(--text-secondary, #b0b0b0);
  font-weight: 700;
  letter-spacing: 1px;
  min-width: 64px;
  padding-top: 3px;
}
.br-buffs-row-list {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.br-buffs-chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  background: rgba(13, 21, 32, 0.7);
  border: 1px solid #2a3040;
  border-radius: 3px;
  color: var(--accent-cyan, #4fc3f7);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  font-family: ui-monospace, "JetBrains Mono", monospace;
  font-variant-numeric: tabular-nums;
}
.br-buffs-chip--event {
  color: var(--accent-gold, #ffd700);
  border-color: rgba(255, 215, 0, 0.35);
}
.br-buffs-chip--source {
  color: var(--accent-green, #4caf50);
  border-color: rgba(76, 175, 80, 0.35);
}
.br-buffs-chip-source {
  color: var(--text-secondary, #b0b0b0);
  margin-right: 4px;
}
.br-buffs-empty {
  color: var(--text-tertiary, #888);
  font-size: 11px;
  font-style: italic;
  padding: 4px 0;
}
.br-buffs-footer {
  display: flex;
  justify-content: flex-end;
  margin-top: 4px;
}

/* ====================================================================
   Battle replay result splash — v2 design system upgrade.

   Old layout was a bare monospace "{winner} — Victory" headline with
   comma-listed losses on transparent backdrop; new layout uses a
   bordered card panel (gold accent), side-by-side DEF/ATK loss
   columns (cyan/red), stat-rows for base HP, and the v2 .btn-primary
   CTA. Sticks to the v2 token + class vocabulary (--accent-gold,
   --border-steel, .stat-row/.stat-label/.stat-value, .btn).
   ==================================================================== */
.br-result-splash {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: rgba(6, 6, 14, 0.88);
  z-index: 40;
  animation: br-splash-in 0.5s ease-out;
  padding: 16px;
}

@keyframes br-splash-in {
  0% { opacity: 0; transform: scale(0.96); }
  100% { opacity: 1; transform: scale(1); }
}

.br-result-card {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  width: min(460px, 100%);
  padding: 14px 16px 12px;
  border: 1px solid rgba(255, 215, 0, 0.55);
  border-radius: 6px;
  background: linear-gradient(180deg, rgba(255, 215, 0, 0.10), rgba(8, 10, 22, 0.92));
  box-shadow: 0 0 18px rgba(255, 215, 0, 0.25), inset 0 0 30px rgba(255, 215, 0, 0.04);
}

.br-result-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.br-result-tag {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 2px;
  color: var(--accent-gold, #ffd700);
  border: 1px solid rgba(255, 215, 0, 0.55);
  background: rgba(255, 215, 0, 0.12);
  padding: 2px 10px;
  border-radius: 3px;
}
.br-result-name {
  font-family: var(--font-mono);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 2px;
  color: #fff;
  text-transform: uppercase;
}
.br-result-meta {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: 1px;
  text-transform: uppercase;
}

.br-result-losses {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.br-result-loss-col {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 10px;
  border: 1px solid #2a3a50;
  border-radius: 4px;
  background: rgba(13, 21, 32, 0.55);
  min-width: 0;
}
.br-result-loss-col--def { border-color: rgba(79, 195, 247, 0.45); }
.br-result-loss-col--atk { border-color: rgba(239, 83, 80, 0.45); }
.br-result-loss-label {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.br-result-loss-col--def .br-result-loss-label { color: var(--accent-cyan, #4fc3f7); }
.br-result-loss-col--atk .br-result-loss-label { color: var(--accent-red, #ef5350); }
.br-result-loss-rows {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.br-result-loss-row {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-secondary);
  gap: 8px;
}
.br-result-loss-row--none { color: var(--text-dim); justify-content: center; }
.br-result-loss-count {
  font-weight: 700;
  color: #fff;
}
.br-result-loss-name {
  text-transform: capitalize;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.br-result-base {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 10px;
  border-top: 1px solid #1a2030;
  border-bottom: 1px solid #1a2030;
}

.br-result-cta {
  width: 100%;
  margin-top: 2px;
  padding: 8px 24px;
  font-size: 12px;
  letter-spacing: 1.5px;
}
/* Two-button row — REPLAY (secondary) + EXIT (primary). REPLAY restarts
   the battle from round 0; EXIT routes through _backToHistory which
   returns the player to wherever they came from (squad-detail modal,
   megatower run, history list, etc). Tutorial flow renders a single
   CONTINUE button instead — see eventResultCard branching. */
.br-result-actions {
  display: flex;
  gap: 8px;
  margin-top: 2px;
}
.br-result-actions .br-result-cta {
  margin-top: 0;
  flex: 1 1 0;
}

@media (max-width: 480px), (max-height: 400px) {
  .br-result-card { padding: 10px 12px 10px; gap: 8px; width: min(420px, 100%); }
  .br-result-name { font-size: 18px; letter-spacing: 1.5px; }
  .br-result-tag { font-size: 9px; padding: 1px 8px; }
  .br-result-loss-col { padding: 6px 8px; }
  .br-result-loss-row { font-size: 10px; }
  .br-result-cta { padding: 6px 18px; font-size: 11px; }
  /* Base HP rows hide on mobile — at 2+ unit-loss rows the loss columns
     already push the card near the viewport edge; the HP detail is a
     nice-to-have flavor stat that the desktop layout has room for. */
  .br-result-base { display: none; }
}

/* Counter color targeting lines */
.br-target-line.strong { background: linear-gradient(90deg, transparent, #66bb6a88, transparent); }
.br-target-line.weak { background: linear-gradient(90deg, transparent, #ef535088, transparent); }
.br-target-line.neutral { background: linear-gradient(90deg, transparent, #ffffff44, transparent); }

@keyframes flash-red {
  0% { box-shadow: 0 0 0 rgba(239, 83, 80, 0); }
  50% { box-shadow: 0 0 12px rgba(239, 83, 80, 0.6); }
  100% { box-shadow: 0 0 0 rgba(239, 83, 80, 0); }
}

@keyframes flash-green {
  0% { box-shadow: 0 0 0 rgba(102, 187, 106, 0); }
  50% { box-shadow: 0 0 12px rgba(102, 187, 106, 0.6); }
  100% { box-shadow: 0 0 0 rgba(102, 187, 106, 0); }
}

@keyframes damage-float {
  0% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-30px); }
}

.slot-flash-hit { animation: flash-red 0.4s ease-out; }
.slot-flash-heal { animation: flash-green 0.4s ease-out; }

.damage-popup {
  position: absolute;
  font-family: var(--font-mono);
  font-weight: bold;
  font-size: 14px;
  color: var(--accent-red);
  animation: damage-float 0.8s ease-out forwards;
  pointer-events: none;
  z-index: 20;
}

/* ============================================
   TUTORIAL OVERLAY
   ============================================ */

/* ── Formation Grid ── */
.fg-grid { display:flex; flex-direction:column; gap:3px; }
.fg-header { display:flex; gap:3px; }
.fg-col-label { flex:1; text-align:center; color: var(--text-dim); font-size:9px; font-family:monospace; letter-spacing:1px; }
.fg-row { display:flex; gap:3px; }
.fg-slot { position:relative; width:52px; height:52px; flex:0 0 52px; border:2px solid #2a3040; border-radius:6px; display:flex; align-items:center; justify-content:center; cursor:pointer; background:rgba(10,10,20,0.6); overflow:hidden; }
.fg-slot:hover { background:rgba(20,20,40,0.8); }
.fg-filled { }
.fg-empty { border-style:dashed; border-color:#333; }
/* Static variant (read-only) — disables click affordances + allows callers
   to tint for enemy side. Produced by formationGrid.renderStatic(). */
.fg-slot.fg-static { cursor: default; }
.fg-slot.fg-static:hover { background: rgba(10,10,20,0.6); }
.fg-slot.fg-static.enemy { border-color: rgba(239,83,80,0.55); }
.fg-thumb { width:48px; height:48px; object-fit:contain; border-radius:4px; }
/* Count pill + tier pill on formation slots. Mirrors the .rank-pip style
   used on skill-card thumbs (black bg, thin border, tabular mono digits).
   Frame provides legibility regardless of the slot's class-tinted border. */
.fg-count-overlay {
  position: absolute;
  bottom: 2px;
  right: 2px;
  min-width: 14px;
  padding: 1px 3px;
  background: rgba(8,12,22,0.9);
  border: 1px solid rgba(255,255,255,0.35);
  border-radius: 2px;
  font: 700 10px/1 var(--font-mono);
  color: #fff;
  text-align: center;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
.fg-tier-pip {
  position: absolute;
  top: 2px;
  left: 2px;
  min-width: 14px;
  padding: 1px 3px;
  background: rgba(8,12,22,0.9);
  border: 1px solid rgba(255,255,255,0.35);
  border-radius: 2px;
  font: 700 9px/1 var(--font-mono);
  color: #cfd8dc;
  text-align: center;
  letter-spacing: 0.3px;
  pointer-events: none;
}
.fg-abbr { font-family:monospace; font-weight:bold; font-size:12px; }
.fg-count { font-family:monospace; font-size:10px; color:#aaa; }
.fg-cost { font-family:monospace; font-size:8px; color:#ff9800; opacity:0.7; }
.fg-plus { color: var(--text-dim); font-size:18px; }
.fg-leadership { margin-top:8px; font-family:monospace; font-size:10px; }
.fg-bar { height:4px; background:#1a1a2a; border-radius:2px; margin-top:4px; overflow:hidden; }
.fg-bar-fill { height:100%; border-radius:2px; transition:width 0.2s; }
.fg-picker-grid { display:grid; grid-template-columns:1fr 1fr 1fr; gap:6px; }
.fg-picker-cell { padding:10px 6px; border:1px solid #333; border-radius:6px; text-align:center; cursor:pointer; background:rgba(10,10,20,0.8); display:flex; flex-direction:column; align-items:center; gap:2px; }
.fg-picker-cell:hover:not(.fg-disabled) { background:rgba(30,30,60,0.9); }
.fg-disabled { opacity:0.3; cursor:not-allowed; }

.tutorial-locked {
  opacity: 0.3 !important;
  pointer-events: none !important;
  filter: grayscale(1);
}
.tutorial-locked::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(239, 83, 80, 0.15);
  border-radius: inherit;
}

.tutorial-panel {
  position: fixed;
  top: 48px; /* below top HUD */
  right: 0;
  max-height: 50vh;
  width: 260px;
  background: linear-gradient(to left, #0a0e14 0%, #0a0e14ee 80%, #0a0e1400 100%);
  padding: 16px 12px 8px;
  z-index: 105;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}
.tutorial-panel::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -32px;
  height: 40px;
  background: linear-gradient(to bottom, #0a0e14cc 0%, transparent 100%);
  pointer-events: none;
}
.tutorial-panel.hidden { display: none; }

/* OBJECTIVE / DO X — sits at the top so player reads it first */
.tutorial-top {
  margin-bottom: 10px;
  padding: 8px 10px;
  background: rgba(79, 195, 247, 0.10);
  border-left: 3px solid #4fc3f7;
  border-radius: 4px;
}
.tutorial-top-label {
  display: block;
  color: #ff9800;
  font-size: 10px;
  font-weight: bold;
  letter-spacing: 1.5px;
  margin-bottom: 2px;
  text-transform: uppercase;
}
.tutorial-top-text {
  display: block;
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.25;
  text-shadow: 0 0 8px rgba(79, 195, 247, 0.35);
}

/* Two-column body — cloud art on the left, speech/buttons on the right */
.tutorial-body {
  display: flex;
  gap: 10px;
  align-items: stretch;
}
.tutorial-cloud {
  flex: 0 0 78px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.tutorial-cloud-name {
  color: #4fc3f7;
  font-size: 10px;
  font-weight: bold;
  letter-spacing: 1px;
  text-align: center;
}
.tutorial-cloud-img {
  width: 78px;
  height: 156px;           /* 1:2 ratio of 256x512 source */
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid rgba(79, 195, 247, 0.25);
  box-shadow: 0 0 12px rgba(79, 195, 247, 0.15);
  flex-shrink: 0;
}
.tutorial-right {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.tutorial-ada-speech {
  color: #ccc;
  font-size: 14px;
  line-height: 1.5;
  margin-bottom: 10px;
  padding: 8px 10px;
  background: #111;
  border: 1px solid #333;
  border-radius: 6px;
}
.tutorial-ada-speech[data-typing="true"]::after {
  content: '▋';
  color: #4fc3f7;
  margin-left: 1px;
  animation: tutorial-caret 0.8s steps(1) infinite;
}
@keyframes tutorial-caret {
  50% { opacity: 0; }
}
.tutorial-action-btn {
  width: 100%;
  padding: 12px;
  border: none;
  border-radius: 6px;
  font-size: 14px;
  font-weight: bold;
  color: #000;
  cursor: pointer;
  letter-spacing: 1px;
  margin-bottom: 8px;
}
.tutorial-action-btn:active {
  opacity: 0.8;
}

.tutorial-progress {
  display: flex;
  justify-content: center;
  gap: 6px;
}
.tutorial-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #1a1a2a;
}
.tutorial-dot.done { background: #4fc3f7; }
.tutorial-dot.active { background: #4fc3f744; box-shadow: 0 0 6px #4fc3f7; }

.tutorial-result-box {
  border: 1px solid;
  border-radius: 6px;
  padding: 8px 10px;
  margin-bottom: 8px;
  text-align: center;
}
.tutorial-result-label {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-bottom: 2px;
}
.tutorial-result-lore {
  border-left: 3px solid #777;
  padding: 6px 10px;
  margin-bottom: 8px;
}

/* Highlight animation for interactive tutorial steps */
@keyframes tutorial-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(79, 195, 247, 0.7); }
  50% { box-shadow: 0 0 0 8px rgba(79, 195, 247, 0); }
}
.tutorial-highlight {
  animation: tutorial-pulse 1.5s infinite !important;
  outline: 2px solid #4fc3f7 !important;
  outline-offset: 2px;
  position: relative;
  z-index: 10;
}

/* Floating arrow that points at a UI element — used for post-tutorial nudges.
   Position is set by JS via getBoundingClientRect; the arrow itself is a CSS
   triangle bouncing vertically to draw the eye. */
@keyframes floating-arrow-bounce {
  0%, 100% { transform: translate(-50%, 0); }
  50%      { transform: translate(-50%, 10px); }
}
.floating-arrow {
  position: fixed;
  pointer-events: none;
  z-index: 9999;
  width: 0;
  height: 0;
  border-left: 14px solid transparent;
  border-right: 14px solid transparent;
  border-top: 20px solid #4fc3f7;
  filter: drop-shadow(0 0 6px rgba(79, 195, 247, 0.8)) drop-shadow(0 0 12px rgba(79, 195, 247, 0.4));
  animation: floating-arrow-bounce 1s ease-in-out infinite;
  transform: translate(-50%, 0);
}

/* ---- Emergency Power Overlay (Tutorial Step 0) ---- */
.emergency-power-overlay {
  position: fixed;
  border-radius: 8px;
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.82);
  border: 2px solid rgba(239, 83, 80, 0.4);
  z-index: 100;
  pointer-events: none;
  transition: opacity 1.2s ease-out;
}
.emergency-power-overlay.fade-out { opacity: 0; }

.emergency-power-label {
  position: fixed;
  top: 28%;
  left: 50%;
  transform: translateX(-50%);
  text-align: center;
  z-index: 101;
  pointer-events: none;
  transition: opacity 1.2s ease-out;
}
.emergency-power-label.fade-out { opacity: 0; }

.emergency-power-icon {
  font-size: 48px;
  color: #ef5350;
  margin-bottom: 8px;
  animation: emergency-blink 2s infinite;
}
.emergency-power-text {
  color: #ef5350;
  font-size: 22px;
  font-weight: bold;
  letter-spacing: 4px;
  text-transform: uppercase;
  animation: emergency-blink 2s infinite;
}
.emergency-power-sub {
  color: rgba(239, 83, 80, 0.4);
  font-size: 11px;
  letter-spacing: 3px;
  text-transform: uppercase;
  margin-top: 4px;
}

@keyframes emergency-blink {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 1; }
}

/* ============================================
   CONNECTION STATUS BANNER
   ============================================ */
.connection-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-xl);
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--accent-orange);
  background: rgba(255, 152, 0, 0.12);
  border-bottom: 1px solid rgba(255, 152, 0, 0.3);
  transition: transform 0.3s ease-out, opacity 0.3s ease-out;
}
.connection-banner.hidden {
  transform: translateY(-100%);
  opacity: 0;
  pointer-events: none;
}
.connection-banner.failed {
  color: var(--accent-red);
  background: rgba(239, 83, 80, 0.12);
  border-bottom-color: rgba(239, 83, 80, 0.3);
}
.connection-banner .pulse-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent-orange);
  animation: connection-pulse 1.5s ease-in-out infinite;
  margin-right: var(--space-sm);
}
.connection-banner.failed .pulse-dot {
  background: var(--accent-red);
  animation: none;
}
@keyframes connection-pulse {
  0%, 100% { opacity: 0.3; transform: scale(0.8); }
  50% { opacity: 1; transform: scale(1.2); }
}

/* ============================================
   CLIENT UPDATE BLOCKER
   ============================================ */
.client-update-overlay {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-xl);
  background: rgba(5, 5, 18, 0.92);
  backdrop-filter: blur(8px);
}
.client-update-overlay.hidden {
  display: none;
}
.client-update-card {
  width: min(420px, 92vw);
  padding: var(--space-xl);
  border: 1px solid rgba(79, 195, 247, 0.38);
  border-radius: 8px;
  background: rgba(10, 14, 26, 0.96);
  box-shadow: 0 0 36px rgba(79, 195, 247, 0.18), inset 0 0 0 1px rgba(255,255,255,0.04);
  text-align: center;
}
.client-update-kicker {
  margin-bottom: var(--space-sm);
  font-family: var(--font-mono);
  font-size: var(--font-xs);
  color: var(--accent-cyan);
  letter-spacing: 2px;
  text-transform: uppercase;
}
.client-update-title {
  margin: 0 0 var(--space-md);
  font-size: 24px;
  line-height: 1.1;
  color: var(--text-primary);
  letter-spacing: 0;
}
.client-update-body {
  margin: 0 0 var(--space-lg);
  color: var(--text-secondary);
  font-size: var(--font-sm);
  line-height: 1.5;
}

/* ============================================
   ROTATE DEVICE OVERLAY (portrait blocker)
   ============================================ */
#rotate-overlay {
  display: none;
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  background: #0a0a1a;
  z-index: 9999;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}
@media (orientation: portrait) {
  #rotate-overlay { display: flex; }
}
@media (orientation: landscape) {
  #rotate-overlay { display: none !important; }
}

/* ============================================
   MOBILE RESPONSIVE
   ============================================ */
@media (max-width: 768px) {
  /* Resource bar: compact */
  .resource-bar { gap: 8px; padding: 0 8px; height: 36px; }
  .resource-item .res-icon, .resource-item .res-icon-placeholder { width: 24px; height: 24px; }
  .resource-item .res-value { font-size: 10px; }
  .resource-item .res-cap { display: none; }

  /* Nav bar: smaller */
  .nav-bar { height: 36px; }
  .nav-btn { font-size: 8px; gap: 1px; min-height: 36px; }
  .nav-btn img { width: 16px; height: 16px; }

  /* Game area adjusted for smaller chrome */
  .screen-overlay {
    top: 43px !important;
    height: calc(100vh - 86px) !important;
  }

  /* Login box: fit mobile (panel chrome from ashen.css; only reflow padding) */
  .login-box { width: 90vw; max-width: 360px; padding: 16px 18px 18px; }

  /* Modal: full width on mobile */
  .modal-box { max-width: 95vw !important; min-width: unset !important; padding: 16px; }

  /* Panels: reduce padding */
  .panel { padding: 8px; }

  /* Two-column layouts: stack on mobile */
  .two-col-wide-right { grid-template-columns: 1fr !important; }

  /* Buttons: bigger touch targets */
  .btn { min-height: 36px; padding: 8px 12px; font-size: 11px; }

  /* Battle replay: scale down */
  .br-slot { width: 60px !important; height: 90px !important; }
  .br-slot-count { font-size: 9px !important; min-width: 20px !important; }
  .br-slot-hud { padding: 1px 2px !important; gap: 2px !important; }
  .br-slot-hp-bar { height: 2px !important; }
  .br-cmd-wrap { width: 100px !important; }
  .br-cmd-portrait { width: 100px !important; height: 150px !important; }

  /* Army screen: adjust grid */
  .army-roster-grid { grid-template-columns: repeat(auto-fill, minmax(60px, 1fr)) !important; }

  /* Tabs: scrollable */
  .tabs { overflow-x: auto; flex-wrap: nowrap; }
  .tabs .tab { white-space: nowrap; font-size: 10px; padding: 6px 10px; }

  /* Filter pills: scrollable */
  .filter-pills { overflow-x: auto; flex-wrap: nowrap; gap: 4px; }
  .filter-pill { font-size: 9px; padding: 3px 8px; white-space: nowrap; }
}

@media (max-width: 480px) {
  /* Extra small: hide resource labels, icon-only nav */
  .resource-bar { gap: 4px; }
  .resource-item .res-value { font-size: 9px; }
  .nav-btn span { display: none; }
  .nav-btn img { width: 20px; height: 20px; }
  .nav-bar { height: 32px; }

  .login-box { padding: 14px 16px 16px; }

  .br-slot { width: 50px !important; height: 75px !important; }
  .br-cmd-wrap { width: 80px !important; }
  .br-cmd-portrait { width: 80px !important; height: 120px !important; }
}

/* Landscape mobile (short height = phone sideways) */
@media (max-height: 450px) {
  .resource-bar { gap: 8px; padding: 0 8px; height: 32px; }
  .resource-item .res-icon { width: 22px !important; height: 22px !important; }
  .resource-item .res-value { font-size: 10px; }
  .resource-item .res-cap { display: none; }
  .nav-bar { height: 32px; }
  .nav-btn { font-size: 8px; min-height: 32px; }
  .screen-overlay { top: 38px !important; height: calc(100vh - 76px) !important; }
  /* Leave bottom-room for the 32px-tall HUD nav so tall content
     (alliance Settings, etc) doesn't slide behind it on landscape. */
  .screen-overlay.no-top-bar { top: 0 !important; bottom: 32px !important; height: auto !important; padding: 6px !important; }
  .screen-overlay.fullscreen { top: 0 !important; bottom: 0 !important; height: 100vh !important; padding: 0 !important; }

  /* Bigger touch targets for all buttons */
  .btn, button { min-height: 32px; }
  .login-box {
    width: min(34vw, 300px);
    min-width: 280px;
    padding: 9px 14px 10px;
    gap: 5px;
    overflow: visible;
  }
  .login-box .form-head { gap: 8px; }
  .login-box .wordmark { font-size: 13px; letter-spacing: 2.4px; }
  .login-box .field { gap: 2px; }
  .login-box .field-label { font-size: 8px; letter-spacing: 1.4px; }
  .login-box .input { height: 22px; font-size: 10px; }
  .login-box .btn-lg { height: 30px; min-height: 30px; font-size: 10px; letter-spacing: 2px; }
  .login-box .or-rule { margin: 0; gap: 8px; }
  .login-box .login-error { min-height: 10px; line-height: 10px; }
  .login-box #g_id_signin { max-height: 34px; overflow: hidden; }

  @media (max-height: 360px) {
    .login-box {
      width: min(45vw, 280px);
      min-width: 250px;
      padding: 7px 10px 8px;
      gap: 3px;
    }
    .login-box .form-head { gap: 6px; }
    .login-box .wordmark { font-size: 11px; letter-spacing: 2px; }
    .login-box .pill { padding: 1px 6px; font-size: 8px; letter-spacing: 1px; }
    .login-box .field-label { font-size: 7px; letter-spacing: 1.2px; }
    .login-box .input { height: 20px; padding: 0 6px; font-size: 9px; }
    .login-box .btn-lg { height: 25px; min-height: 25px; padding: 0 10px; font-size: 9px; letter-spacing: 1.6px; }
    .login-box .or-rule { gap: 6px; height: 8px; }
    .login-box .or-rule span { font-size: 7px; letter-spacing: 1.2px; }
    .login-box .login-error { min-height: 8px; line-height: 8px; }
    .login-box #g_id_signin { max-height: 30px; }
  }
  /* Landscape modals are usually taller than 80vh (375h × 0.8 = 300px,
     and the deploy/extract modal alone needs ~310px). Bump to 96vh so
     the modal claims the full short-axis without scrolling, leaving a
     thin gutter to read as a panel rather than a full takeover. */
  .modal-box { max-width: 96vw !important; max-height: 96vh !important; }
  .modal-box button { min-height: 36px; padding: 8px 16px; }

  /* Notification dismiss buttons */
  .notif-action { min-width: 32px; min-height: 32px; font-size: 14px; }

  /* Battle replay — scale to fill mobile landscape viewport */
  /* Battle replay — maximize vertical space on mobile landscape.
     overflow-x: hidden (was auto) — at narrow widths the formation
     grids extend past the viewport edges; we'd rather clip the
     extreme edges than render a horizontal scrollbar that only
     scrolls a few pixels. The center of action stays centered. */
  .br-battlefield { overflow-x: hidden; overflow-y: hidden; padding: 0 4px !important; align-items: stretch !important; }
  .br-side { max-width: none !important; flex: 1 !important; display: flex !important; flex-direction: column !important; }
  .br-side-label { font-size: 8px !important; flex-shrink: 0 !important; padding-top: 2px !important; }
  .br-formation { flex: 1 !important; display: flex !important; }
  .br-col { flex: 1 !important; display: flex !important; flex-direction: column !important; }
  .br-col-label { display: none !important; }
  .br-slot { width: 65px !important; height: 98px !important; }
  .br-base-bar { padding: 1px 0 !important; }
  .br-base-track { height: 4px !important; }
  .br-base-hp { font-size: 8px !important; }
  .br-base-label { font-size: 8px !important; }
  .br-slot-count { font-size: 8px !important; }
  .br-cmd-portrait { width: auto !important; height: 70vh !important; aspect-ratio: 2/3 !important; }
  .br-cmd-wrap { width: auto !important; }
  .br-cmd-name { font-size: 7px !important; }

  /* Tutorial panel — compact for mobile landscape */
  .tutorial-panel {
    top: 34px;
    width: 260px;
    max-height: calc(100vh - 68px);
    padding: 8px 10px 6px;
    overflow-y: auto;
  }
  .tutorial-panel.narrow { width: 184px; padding: 6px 8px 5px; }
  .tutorial-panel.narrow .tutorial-body { gap: 6px; }
  .tutorial-panel.narrow .tutorial-cloud { flex: 0 0 56px; }
  .tutorial-panel.narrow .tutorial-cloud-img { width: 56px; height: 112px; }
  .tutorial-panel.narrow .tutorial-ada-speech { font-size: 11px; padding: 5px 7px; }
  .tutorial-panel.narrow .tutorial-top-text { font-size: 12px; }
  .tutorial-panel::after { display: none; }
  .tutorial-top { margin-bottom: 6px; padding: 5px 7px; }
  .tutorial-top-label { font-size: 9px; letter-spacing: 1.2px; }
  .tutorial-top-text { font-size: 13px; line-height: 1.2; }
  .tutorial-body { gap: 8px; }
  .tutorial-cloud { flex: 0 0 64px; gap: 3px; }
  .tutorial-cloud-name { font-size: 9px; letter-spacing: 0.8px; }
  .tutorial-cloud-img { width: 64px; height: 128px; }
  .tutorial-ada-speech { font-size: 12px; line-height: 1.35; padding: 6px 8px; margin-bottom: 6px; }
  .tutorial-action-btn { padding: 8px; font-size: 12px; margin-bottom: 4px; }
  .tutorial-progress { gap: 4px; }
  .tutorial-dot { width: 6px; height: 6px; }
  .tutorial-result-box { padding: 6px 8px; margin-bottom: 6px; }
  .tutorial-result-box div { font-size: 10px !important; }
  .tutorial-result-label { font-size: 8px !important; }

  /* Emergency overlay label — move up on mobile */
  .emergency-power-label { top: 22%; }
  .emergency-power-icon { font-size: 32px; margin-bottom: 4px; }
  .emergency-power-text { font-size: 16px; letter-spacing: 3px; }
  .emergency-power-sub { font-size: 9px; }

  /* Lore popup — compact for mobile landscape */
  .lore-popup-inner { max-height: calc(100vh - 16px); max-width: 92vw; }
  .lore-popup-inner.has-detail { max-width: 92vw; }
  .lore-popup-header { padding: 8px 12px 6px; }
  .lore-popup-title { font-size: 13px; }
  .lore-popup-desc { font-size: 11px; padding: 8px 12px; }
  .lore-popup-lore { font-size: 10px; padding: 8px 12px 10px; }
  .lore-popup-detail { font-size: 9px; padding: 8px 10px; }
  .lore-popup-body.has-detail .lore-popup-detail { flex: 0 0 180px; }

  /* ── BUILDING INFO TAB — landscape (zero-scroll target) ──
     3-column grid (meta | center | upgrade), or 2-col when no
     center column. Hard target: 812×375 fits all 6 buildings
     without any scroll. */
  .binfo-tab {
    max-width: calc(100% - 16px);
    margin: 6px auto;
    padding: 8px 12px;
  }
  .binfo-main {
    display: grid;
    grid-template-columns: 1fr 200px;
    gap: 10px;
    align-items: start;
  }
  .binfo-tab--has-detail .binfo-main,
  .binfo-tab--has-bonuses .binfo-main {
    grid-template-columns: 1fr 1fr 200px;
  }
  /* Specificity-match the desktop `.binfo-tab--has-bonuses .binfo-col-meta`
     rule (which sets grid-row: span 2 for the 2-col desktop layout). On
     landscape we always have 3 cols side-by-side, so meta should be 1 row.
     Without these matched-specificity overrides, auto-flow shoves meta to
     col 3. */
  .binfo-tab--has-detail .binfo-col-meta,
  .binfo-tab--has-bonuses .binfo-col-meta,
  .binfo-col-meta,
  .binfo-col-bonuses,
  .binfo-col-detail,
  .binfo-col-upgrade {
    overflow: hidden;
    grid-row: 1;
  }
  .binfo-col-bonuses,
  .binfo-col-detail,
  .binfo-col-upgrade {
    border-left: 1px solid var(--border-subtle);
    padding-left: 10px;
  }

  /* Compact section padding on landscape — vertical density is the
     scarcest resource here. */
  .binfo-section {
    padding: 5px 0 6px;
  }
  .binfo-section-kicker {
    font-size: 8px;
    margin-bottom: 3px;
    padding-bottom: 2px;
  }

  /* Header: smaller icon, single-line, less padding */
  .binfo-header {
    gap: 8px;
    padding: 2px 0 6px;
  }
  .binfo-icon { font-size: 22px; }
  .binfo-header-kicker { font-size: 7px; }
  .binfo-title { font-size: 12px; }

  /* Lore: keep visible on landscape (was display:none in v1). The meta
     column has ~210px of vertical headroom after header + current effect +
     requirements, so a 6-line clamp is generous and never causes scroll
     even at 9px font. */
  .binfo-lore {
    font-size: 9px;
    line-height: 1.4;
    padding: 5px 8px;
    display: -webkit-box;
    -webkit-line-clamp: 6;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  /* Effects compacter */
  .binfo-effect {
    font-size: 9px;
    padding: 3px 6px;
  }

  /* Pill grid stays 2-col but tighter */
  .binfo-bonus-grid { gap: 3px; }
  .binfo-bonus-pill { padding: 3px 6px; }
  .binfo-bonus-pill-label { font-size: 7px; }
  .binfo-bonus-pill-value { font-size: 9px; }

  /* Upgrade column compact */
  .binfo-upgrade-label { font-size: 9px; }
  .binfo-upgrade-timer { font-size: 9px; }
  .binfo-costs .stat-row { font-size: 9px; padding: 1px 0; }

  /* Detail panel table tighter */
  .binfo-detail-table { font-size: 9px; }
  .binfo-detail-table td { padding: 1px 0; }
}

/* ============================================
   TUTORIAL PANEL — DESKTOP OVERRIDE
   Only applies when NOT in mobile landscape
   ============================================ */
@media (min-height: 451px) {
  .tutorial-panel {
    width: 320px;
    max-height: 60vh;
    overflow-y: auto;
    background: rgba(8, 12, 20, 0.94);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-left: 2px solid rgba(79, 195, 247, 0.15);
    border-bottom: 1px solid rgba(79, 195, 247, 0.08);
    border-radius: 0 0 0 8px;
  }
  .tutorial-panel.narrow { width: 220px; }
  .tutorial-panel.narrow .tutorial-cloud { flex: 0 0 64px; }
  .tutorial-panel.narrow .tutorial-cloud-img { width: 64px; height: 128px; }
  .tutorial-panel.narrow .tutorial-ada-speech { font-size: 12px; }
  .tutorial-panel::after { display: none; }
  .tutorial-ada-speech {
    background: rgba(15, 20, 30, 0.8);
    border-color: #2a3a50;
  }
}

/* ============================================
   WORKSHOP
   ============================================ */

.ws-recipe {
  width: 100%;
  padding: 10px;
  margin-bottom: 4px;
  border-radius: 4px;
  cursor: pointer;
  border: 2px solid #1a2030;
  background: rgba(10, 10, 20, 0.8);
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: 8px;
  text-align: left;
  transition: border-color 0.15s, background 0.15s;
}

.ws-recipe:hover {
  border-color: var(--recipe-color, #4a5060) !important;
}

.ws-recipe.is-selected {
  border-color: var(--recipe-color, var(--accent-cyan));
  background: color-mix(in srgb, var(--recipe-color, var(--accent-cyan)) 11%, rgba(10, 10, 20, 0.8));
}

.ws-recipe.is-locked {
  cursor: default;
  opacity: 0.52;
  filter: grayscale(0.85);
}

.ws-recipe-icon,
.ws-result-icon {
  flex: 0 0 auto;
}

.ws-recipe-copy {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.ws-recipe-name {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--recipe-color, var(--accent-cyan));
  line-height: 1.1;
}

.ws-recipe-desc {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-secondary);
  line-height: 1.2;
}

.ws-craft-layout {
  display: flex;
  gap: 8px;
  height: calc(100vh - 116px);
  padding-top: 6px;
}

.ws-recipe-list {
  width: 30%;
  min-width: 180px;
  flex-shrink: 0;
  overflow-y: auto;
}

.ws-detail-pane {
  flex: 1;
  min-width: 0;
}

.ws-detail,
.ws-detail-empty {
  display: flex;
  flex-direction: column;
  height: 100%;
  gap: 8px;
  font-family: var(--font-mono);
}

.ws-detail-empty {
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  font-size: 10px;
}

.ws-detail-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--recipe-color, var(--accent-cyan));
  text-transform: uppercase;
}

.ws-detail-desc {
  margin-top: 5px;
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.35;
}

.ws-icon-label,
.ws-inline-icon {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
}

.ws-icon-label {
  gap: 5px;
  min-width: 0;
}

.ws-icon-label > span:last-child {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ws-inline-icon {
  width: var(--ws-icon-size, 16px);
  height: var(--ws-icon-size, 16px);
  justify-content: center;
  flex: 0 0 auto;
}

.ws-inline-icon img {
  border-radius: 3px;
}

.ws-cost-panel,
.ws-progress-panel {
  padding: 10px;
  background: rgba(0, 0, 0, 0.6);
  border: 1px solid #1a2030;
  border-radius: 4px;
}

.ws-cost-title,
.ws-action-label {
  margin-bottom: 6px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-secondary);
  letter-spacing: 0;
}

.ws-cost-list {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.ws-cost-row,
.ws-owned-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-secondary);
}

.ws-cost-row.is-short {
  color: var(--accent-red);
}

.ws-cost-need,
.ws-cost-have,
.ws-owned-row span {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
}

.ws-cost-have {
  flex-shrink: 0;
  color: currentColor;
}

.ws-owned-row {
  color: var(--recipe-color, var(--accent-cyan));
  font-size: 10px;
}

.ws-action-wrap {
  position: relative;
}

.ws-class-actions {
  display: flex;
  gap: 4px;
}

.ws-detail-footer {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-secondary);
}

.ws-detail-lore {
  margin-top: auto;
  padding-left: 6px;
  border-left: 2px solid #777;
  font-family: var(--font-mono);
  font-size: 11px;
  font-style: italic;
  line-height: 1.4;
  color: var(--text-secondary);
}

.ws-craft-btn {
  width: 100%;
  padding: 10px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: bold;
  border: 1px solid var(--craft-color, #4fc3f7);
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.15s;
  letter-spacing: 0;
}

.ws-craft-btn.ws-craft-class {
  flex: 1;
  padding: 7px;
  font-size: 10px;
  font-weight: normal;
}

.ws-craft-ready {
  background: var(--craft-color, #4fc3f7);
  color: #000;
}

.ws-craft-ready:hover {
  filter: brightness(1.2);
  box-shadow: 0 0 12px color-mix(in srgb, var(--craft-color) 50%, transparent);
}

.ws-craft-ready:active {
  transform: scale(0.96);
  filter: brightness(0.9);
}

.ws-craft-disabled {
  background: #1a2030;
  color: #777;
  border-color: #333;
  cursor: not-allowed;
  opacity: 0.5;
}

/* Craft result cards — stack above the craft button */
#ws-craft-results {
  position: absolute;
  bottom: 100%;
  left: 0;
  right: 0;
  pointer-events: none;
  z-index: 10;
}

.ws-craft-result {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  background: rgba(10, 12, 20, 0.92);
  border: 1px solid var(--result-color, #e040fb);
  border-radius: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: bold;
  color: var(--result-color, #e040fb);
  white-space: nowrap;
  box-shadow: 0 0 8px color-mix(in srgb, var(--result-color) 30%, transparent);
  animation: ws-result-enter 0.3s ease-out;
  transition: bottom 0.3s ease;
}

@media (max-width: 760px) and (orientation: landscape) {
  .ws-craft-layout {
    gap: 6px;
  }

  .ws-recipe-list {
    width: 32%;
    min-width: 150px;
  }

  .ws-recipe {
    padding: 7px;
    gap: 6px;
  }

  .ws-recipe-desc {
    font-size: 10px;
  }

  .ws-detail {
    gap: 6px;
  }

  .ws-detail-title {
    font-size: 12px;
  }

  .ws-detail-desc,
  .ws-detail-lore {
    font-size: 10px;
  }

  .ws-cost-panel,
  .ws-progress-panel {
    padding: 8px;
  }
}

.ws-craft-result-exit {
  animation: ws-result-exit 0.7s ease-in forwards;
}

@keyframes ws-result-enter {
  from { opacity: 0; transform: translateX(-50%) translateY(8px) scale(0.9); }
  to { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
}

@keyframes ws-result-exit {
  from { opacity: 1; transform: translateX(-50%) translateY(0); }
  to { opacity: 0; transform: translateX(-50%) translateY(-20px); }
}

/* ============================================
   PREMIUM SHOP
   ============================================ */

#shop-overlay {
  display: flex;
  flex-direction: column;
}

#shop-overlay .shop-content {
  flex: 1;
  min-height: 0;
  max-height: none;
  overflow-y: auto;
}

.shop-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 6px 16px;
  background: rgba(10, 10, 20, 0.9);
  border-top: 1px solid var(--border-steel);
  flex-shrink: 0;
}

.shop-ash-display {
  display: flex;
  align-items: center;
  gap: 8px;
}

.shop-ash-amount {
  font-family: var(--font-mono);
  font-size: 22px;
  font-weight: bold;
  color: var(--accent-gold);
  font-variant-numeric: tabular-nums;
}

.shop-ash-label {
  font-family: var(--font-mono);
  font-size: var(--font-lg);
  color: var(--text-dim);
  letter-spacing: 1px;
}

.shop-content {
  padding: 12px 16px;
  max-width: 960px;
  margin: 0 auto;
  overflow-y: auto;
  max-height: calc(100vh - 80px);
}

/* Pack grid — horizontal row, fill height */
.shop-pack-grid {
  display: flex;
  gap: 12px;
  overflow-x: hidden;
  padding-bottom: 8px;
  height: 100%;
}

.shop-pack-card {
  flex: 1 1 0;
  min-width: 0;
  background: rgba(10, 12, 20, 0.9);
  border: 1px solid var(--border-steel);
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: border-color 0.2s;
}

.shop-pack-card:hover {
  border-color: var(--border-glow);
}

/* Pack art — 2:1 aspect ratio images */
.shop-pack-art {
  width: 100%;
  aspect-ratio: 2 / 1;
  overflow: hidden;
  border-bottom: 1px solid rgba(42, 48, 64, 0.4);
  flex-shrink: 0;
}

.shop-pack-art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Pack info */
.shop-pack-info {
  padding: 12px;
  display: flex;
  flex-direction: column;
  flex: 1;
}

.shop-pack-name {
  font-family: var(--font-mono);
  font-size: var(--font-xl);
  font-weight: bold;
  letter-spacing: 1px;
  margin-bottom: 4px;
}

.shop-pack-desc {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-dim);
  margin-bottom: 10px;
  line-height: 1.4;
}

.shop-pack-contents {
  flex: 1;
  margin-bottom: 10px;
}

.shop-pack-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: var(--font-md);
  color: var(--text-secondary);
  margin-bottom: 3px;
}

.shop-res-summary {
  font-size: var(--font-sm);
  color: var(--text-dim);
}

/* Upgrade chances */
.shop-upgrade-section {
  border-top: 1px solid var(--border-subtle);
  padding-top: 8px;
  margin-bottom: 10px;
}

.shop-upgrade-header {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-dim);
  letter-spacing: 1px;
  margin-bottom: 4px;
  text-transform: uppercase;
}

.shop-upgrade-chance {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--accent-gold);
  margin-bottom: 2px;
}

/* One-time badge */
.shop-onetime-badge {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--accent-cyan);
  letter-spacing: 1px;
  text-align: center;
  margin-bottom: 6px;
  padding: 3px 0;
  border: 1px solid rgba(79, 195, 247, 0.27);
  border-radius: 3px;
  background: rgba(79, 195, 247, 0.06);
}

.shop-purchased-badge {
  font-family: var(--font-mono);
  font-size: var(--font-md);
  color: var(--accent-green);
  letter-spacing: 1px;
  text-align: center;
  padding: 8px 0;
  border: 1px solid rgba(102, 187, 106, 0.27);
  border-radius: 4px;
  background: rgba(102, 187, 106, 0.06);
}

/* Gold buy button */
.btn-gold {
  background: linear-gradient(135deg, #ffd70033, #ff980022);
  border: 1px solid #ffd70066;
  color: #ffd700;
  font-family: var(--font-mono);
  font-weight: bold;
  letter-spacing: 1px;
  cursor: pointer;
  transition: all 0.2s;
}

.btn-gold:hover {
  background: linear-gradient(135deg, #ffd70055, #ff980044);
  border-color: #ffd700;
  box-shadow: 0 0 12px #ffd70033;
}

.btn-block { width: 100%; }

.shop-confirm-btn {
  background: linear-gradient(135deg, rgba(239, 83, 80, 0.27), rgba(255, 87, 34, 0.2));
  border: 1px solid var(--accent-red);
  color: var(--accent-red);
  font-family: var(--font-mono);
  font-weight: bold;
  letter-spacing: 2px;
  animation: shop-confirm-pulse 0.6s ease-in-out infinite alternate;
}

@keyframes shop-confirm-pulse {
  from { box-shadow: 0 0 4px rgba(239, 83, 80, 0.2); }
  to   { box-shadow: 0 0 12px rgba(239, 83, 80, 0.4); }
}

/* ASH purchase grid — fill available space */
.shop-ash-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 10px;
  height: 100%;
}

.shop-ash-card {
  background: rgba(10, 12, 20, 0.9);
  border: 1px solid var(--border-steel);
  border-radius: 8px;
  padding: 0;
  text-align: center;
  overflow: hidden;
  transition: border-color 0.2s;
  display: flex;
  flex-direction: column;
}

.shop-ash-icon {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px;
  background: rgba(15, 18, 28, 0.5);
  border-bottom: 1px solid var(--border-steel);
}

.shop-ash-card:hover {
  border-color: rgba(255, 215, 0, 0.27);
}

.shop-ash-amount-display {
  font-family: var(--font-mono);
  font-size: var(--font-3xl);
  font-weight: bold;
  color: var(--accent-gold);
  padding: 4px 0;
  font-variant-numeric: tabular-nums;
}

.shop-ash-bonus {
  font-family: var(--font-mono);
  font-size: var(--font-md);
  color: var(--accent-green);
  font-weight: bold;
  margin-bottom: 4px;
}

.shop-ash-price {
  font-family: var(--font-mono);
  font-size: var(--font-xl);
  color: var(--text-primary);
  margin-bottom: 8px;
  font-variant-numeric: tabular-nums;
}

.shop-ash-card .btn {
  margin: 0 12px 12px;
  width: calc(100% - 24px);
}

.shop-alpha-notice {
  text-align: center;
  font-family: var(--font-mono);
  font-size: var(--font-lg);
  color: var(--text-dim);
  margin-top: 24px;
  padding: 12px;
  border: 1px dashed var(--border-steel);
  border-radius: 6px;
}

/* Vault */
.shop-vault-section {
  margin-bottom: 16px;
}

.shop-vault-wallet {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 12px;
}

.shop-vault-status {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: var(--font-heading);
  color: var(--text-secondary);
}

.shop-vault-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
}
.shop-vault-dot--offline { background: var(--accent-red); }

.shop-vault-hint {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--text-dim);
  text-align: center;
}
.shop-vault-hint--spaced { margin-top: var(--space-lg); }

.shop-vault-disclaimer {
  font-family: var(--font-mono);
  font-size: var(--font-md);
  color: var(--text-dim);
  text-align: center;
  padding: var(--space-lg);
  margin-top: var(--space-md);
  border-top: 1px solid var(--border-subtle);
  line-height: 1.5;
}

/* Shop sweep (v2 migration) — new classes for JS-side class-over-inline refactor. */
.shop-btn-icon {
  width: 16px;
  height: 16px;
  vertical-align: middle;
}
.shop-ash-icon-sm { width: 22px; height: 22px; }
.shop-ash-icon-img { width: 100%; height: 100%; object-fit: contain; }

.shop-reward-cmd-icon { font-size: var(--font-2xl); line-height: 1; }
.shop-reward-cmd-name { font-weight: 700; }
.shop-reward-cmd-meta { font-size: var(--font-xs); color: var(--text-dim); }

.shop-reward-title {
  margin: 0 0 var(--space-md);
  font-family: var(--font-mono);
  font-size: var(--font-xl);
  font-weight: 700;
  color: var(--accent-gold);
  text-shadow: 0 1px 4px #000;
}
.shop-reward-remaining {
  text-align: center;
  margin-top: var(--space-md);
  font-family: var(--font-mono);
  font-size: var(--font-md);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
.shop-reward-collect { margin-top: var(--space-md); }

.shop-confirm-body {
  text-align: center;
  font-family: var(--font-mono);
  color: var(--accent-gold);
  margin: var(--space-xl) 0;
}
.shop-confirm-kicker {
  font-size: var(--font-md);
  color: var(--accent-cyan);
  margin-bottom: var(--space-md);
}
.shop-confirm-note {
  margin-top: var(--space-md);
  color: var(--text-dim);
  font-size: var(--font-md);
}

/* Reward modal — widened with pack image background */
.shop-reward-modal-box {
  max-width: 600px !important;
  min-width: 500px !important;
  padding: 0 !important;
  overflow: hidden;
  background: rgba(8, 10, 18, 0.85) !important;
}

.shop-reward-modal {
  position: relative;
  display: flex;
  min-height: 200px;
  max-height: 70vh;
}

.shop-reward-bg {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  background-size: cover;
  background-position: center;
  opacity: 0.35;
  pointer-events: none;
}

.shop-reward-body {
  position: relative;
  z-index: 1;
  flex: 1;
  padding: 16px 20px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.shop-reward-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 4px 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px 16px;
  align-content: start;
}

.shop-reward-line {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: var(--font-heading);
  color: var(--text-primary);
  padding: 4px 0;
  font-variant-numeric: tabular-nums;
}

.shop-reward-upgrade {
  font-family: var(--font-mono);
  font-size: var(--font-lg);
  padding: 4px 8px;
  margin: 4px 0;
  background: rgba(255, 215, 0, 0.06);
  border-left: 2px solid var(--accent-gold);
  border-radius: 0 4px 4px 0;
}

.shop-reward-tag {
  font-family: var(--font-mono);
  font-size: var(--font-xs);
  font-weight: bold;
  letter-spacing: 1px;
  padding: 1px 5px;
  border-radius: 3px;
  margin-left: auto;
  flex-shrink: 0;
}

.shop-reward-tag-upgrade {
  background: rgba(255, 215, 0, 0.13);
  color: var(--accent-gold);
  border: 1px solid rgba(255, 215, 0, 0.27);
}

.shop-reward-tag-bonus {
  background: rgba(102, 187, 106, 0.13);
  color: var(--accent-green);
  border: 1px solid rgba(102, 187, 106, 0.27);
}

.shop-reward-commander {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px;
  margin-top: 8px;
  border: 1px solid;
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.3);
  font-family: var(--font-mono);
  font-size: var(--font-heading);
}

/* Responsive: stack pack cards vertically on narrow portrait screens */
@media (max-width: 600px) and (orientation: portrait) {
  .shop-pack-grid {
    flex-direction: column;
  }
  .shop-pack-card {
    flex: 0 0 auto;
    min-width: auto;
  }
  .shop-ash-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Mobile landscape: compact layout to minimize scrolling */
@media (max-height: 500px) {
  .shop-footer {
    padding: 3px 10px;
  }
  .shop-ash-amount {
    font-size: 14px;
  }
  .shop-content {
    padding: 4px 10px;
    max-height: calc(100vh - 68px);
  }

  /* Pack cards: same as desktop (image top, items bottom) but compact */
  .shop-pack-grid {
    flex-direction: row;
    gap: 6px;
    height: 100%;
  }
  .shop-pack-card {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    height: 100%;
  }
  .shop-pack-art {
    aspect-ratio: 2 / 1;
    flex-shrink: 0;
  }
  .shop-pack-info {
    padding: 4px 6px;
    flex: 1;
    display: flex;
    flex-direction: column;
  }
  .shop-pack-name {
    font-size: 11px;
    margin-bottom: 3px;
    text-align: center;
  }
  .shop-pack-desc {
    display: none;
  }
  .shop-pack-item {
    font-size: 10px;
    margin-bottom: 2px;
    gap: 4px;
  }
  .shop-pack-item img {
    width: 14px !important;
    height: 14px !important;
  }
  .shop-pack-contents {
    margin-bottom: 2px;
    flex: 1;
  }
  .shop-res-summary {
    display: none;
  }
  .shop-upgrade-section {
    display: none;
  }
  .shop-onetime-badge {
    font-size: 7px;
    padding: 1px 0;
    margin-bottom: 2px;
  }
  .shop-purchased-badge {
    font-size: 8px;
    padding: 3px 0;
  }
  .shop-pack-card .btn-gold {
    padding: 3px 4px;
    font-size: 9px;
    margin-top: auto;
  }

  /* Ashes: compact for landscape */
  .shop-ash-grid {
    gap: 6px;
  }
  .shop-ash-amount-display {
    font-size: 14px;
    padding: 2px 0;
  }
  .shop-ash-price {
    font-size: 11px;
    margin-bottom: 4px;
  }
  .shop-ash-card .btn {
    margin: 0 6px 6px;
    width: calc(100% - 12px);
    padding: 3px 4px;
    font-size: 9px;
  }
  .shop-alpha-notice {
    display: none;
  }
  .shop-reward-modal-box {
    min-width: unset !important;
    max-width: 95vw !important;
    max-height: 85vh !important;
  }
  .shop-reward-modal {
    max-height: 80vh;
  }
  .shop-reward-body {
    padding: 10px 14px;
  }
  .shop-reward-body h2 {
    font-size: 12px !important;
    margin-bottom: 4px !important;
  }
  .shop-reward-list {
    grid-template-columns: 1fr 1fr;
    gap: 1px 12px;
  }
  .shop-reward-line {
    font-size: 11px;
    padding: 2px 0;
    gap: 4px;
  }
  .shop-reward-line img {
    width: 16px !important;
    height: 16px !important;
  }
}

/* ============================================
   Packing Hourglass — extraction-site "preparing to leave" indicator
   ============================================ */

/* Hand-driven animation for the static hourglass image. Uses rotateX
   (rotation around the horizontal axis) instead of plain rotate — so the
   hourglass tips forward like flipping a card, going through "edge-on"
   at the 90° midpoint instead of sideways. The animation is 2 s so two
   flips happen per cycle (down, then back up); the 180°→360° wrap loops
   invisibly back to 0°.

   0.00–0.30 s : rotateX   0° → 180°  (tip down, sand pours)
   0.30–1.00 s : hold     180°
   1.00–1.30 s : rotateX 180° → 360°  (tip back up, sand pours)
   1.30–2.00 s : hold     360° (= 0° visually) */
@keyframes packing-hourglass-cycle {
  0%   { transform: rotateX(0deg);   }
  15%  { transform: rotateX(180deg); }
  50%  { transform: rotateX(180deg); }
  65%  { transform: rotateX(360deg); }
  100% { transform: rotateX(360deg); }
}
.packing-hourglass {
  image-rendering: pixelated;
  transform-origin: center;
  /* rotateX in 2D collapses the element to a horizontal line at the
     90° midpoint — but the symmetric pixel-art hourglass reads cleanly
     through this "flip" motion, never sideways. */
  animation: packing-hourglass-cycle 2s linear infinite;
}

/* ============================================
   Chat Panel
   ============================================ */

.chat-expanded {
  position: fixed;
  /* Flush against the top of the nav-bar (zoom:1.2 of 40px = 48 viewport px).
     Because this element ALSO has zoom:1.2, its own `bottom` value is
     multiplied by 1.2 too — so we set 40 CSS px to land at exactly 48
     viewport px. Mirror of the way it hugs the left wall via `left: 0`. */
  bottom: 40px;
  /* Flush to the left edge of the screen (chat lives on the left, no
     gutter). More translucent than the resource bars so the canvas
     reads clearly behind it. */
  left: 0;
  z-index: 55;
  /* Width tuned so the chat panel's right edge lands at the right edge of
     the SEND button. Math (slot width 380 CSS, inner row padding 0 8px,
     gap 4, SEND ≈ 46 CSS px → SEND ends at slot_left + 372 CSS
     px = 446 viewport px after zoom 1.2). Chat is zoomed 1.2 too, so its
     CSS width = 446 / 1.2 ≈ 372 CSS px to match. */
  width: 372px;
  /* Trimmed off the top — the red-marked region in the screenshot was
     roughly 5 chat lines. At 13 px / 1.15 line-height × zoom:1.2 each
     line is ~16 viewport px, so ~80 viewport ≈ 67 CSS px less. Box
     shrinks from the TOP because it's anchored to `bottom`. */
  height: 240px;
  /* Match the bottom-bar zoom so chat text + tabs + input slot live at
     the same visual scale. */
  zoom: 1.2;
  background: rgba(6, 10, 18, 0.45);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border-top: 1px solid rgba(255,255,255,0.08);
  border-right: 1px solid rgba(255,255,255,0.08);
  border-bottom: 1px solid rgba(255,255,255,0.08);
  border-left: none;
  /* Top-right corner only — bottom-right is flush against the nav-bar so
     a rounded bottom corner would look like a chip cut out of the chrome. */
  border-radius: 0 8px 0 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transform-origin: bottom left;
  animation: panel-scale-in 0.15s cubic-bezier(0.33, 1, 0.68, 1) both;
}
/* When the chat is open, the bottom chat preview row is REPLACED by the
   panel's input slot (which lives in #chat-input-slot inside #hud-bottom).
   Mutually exclusive — preview hides outright so the input takes its space.
   The slot is capped at the chat panel's own width (380 px) so the input
   doesn't stretch all the way to the nav buttons. */
body.chat-open #map-chat-preview { display: none; }
#chat-input-slot {
  display: none;
  width: 380px;
  flex: 0 0 380px;
  max-width: 380px;
  align-items: center;
}
body.chat-open #chat-input-slot { display: flex; }
/* When the chat is open, the flex:1 #map-chat-preview is gone — without
   a flex-grow child to absorb the slack, the nav-group slides left to
   the closest sibling. Pin it back to the right edge via auto margin
   ONLY in chat-open state so the closed-state layout is unchanged. */
body.chat-open .nav-group { margin-left: auto; }

/* Idle-fade: 4 s after expand (or after any chat interaction), the chrome
   layer (tabs row + background + borders) fades to 0. Messages stay
   readable thanks to per-row shading below. Click anywhere on the panel
   to un-fade. Hover also keeps it visible. */
.chat-expanded.chat-faded {
  background: transparent !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
  border-color: transparent !important;
}
.chat-expanded.chat-faded .chat-chrome {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.6s ease-out;
}
.chat-expanded .chat-chrome { transition: opacity 0.25s ease-in; }
.chat-expanded { transition: background 0.6s ease-out, border-color 0.6s ease-out; }
/* Hover does NOT un-fade — only a real click on the panel re-arms the
   fade timer via the listener in init(). Mouse-over behaviour was
   triggering accidental un-fades while the player was just moving the
   cursor across the screen. */

/* Soft outline around each chat word so the text stays legible against
   the bare map once the panel chrome fades. No bar / no background —
   just a thin dark stroke from layered text-shadows. Applied to chat
   rows AND the bottom-bar preview rows. */
#chat-messages > div,
#map-chat-lines .map-chat-line {
  text-shadow:
    -1px -1px 0 rgba(0,0,0,0.85),
     1px -1px 0 rgba(0,0,0,0.85),
    -1px  1px 0 rgba(0,0,0,0.85),
     1px  1px 0 rgba(0,0,0,0.85),
     0   0   3px rgba(0,0,0,0.6);
}
/* First message anchors to the bottom of the message area; later messages
   stack upward as they arrive. Achieved with flex-direction: column-reverse
   on the natural order? — no, we'd lose chronological ordering. Instead,
   keep column order but push the FIRST row down via auto top margin so an
   empty list has its single row at the bottom of the panel. */
#chat-messages {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
  /* Tighter bottom padding so the lowest message sits closer to the
     input row instead of floating with a wide gap above the divider. */
  padding-bottom: 2px !important;
}
#chat-messages > :first-child { margin-top: auto; }
#chat-messages > :last-child { margin-bottom: 0 !important; }

/* While the panel is faded the scrollbar should also disappear (the user
   wants ONLY the message text visible after 4 s idle). */
.chat-expanded.chat-faded #chat-messages {
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* IE/Edge legacy */
}
.chat-expanded.chat-faded #chat-messages::-webkit-scrollbar { width: 0; height: 0; display: none; }

@media (max-height: 500px) and (orientation: landscape) {
  .chat-expanded {
    bottom: 0;
    left: 0;
    top: 0;
    width: 300px;
    height: 100vh;
    height: 100dvh;
    border-radius: 0 10px 10px 0;
  }
}

/* Chat help-request card: one-line strip with a state-tag on the left,
   request title, and optional meta. When `is-clickable`, the whole card
   is the action target (the tag chip telegraphs the action) — no separate
   action button. State tints (border/tag) come from `.is-help` / `.is-thank`
   / `.is-mine` / `.is-waiting` / `.is-done` / `.is-expired` modifiers
   applied to both `.chat-help-card` and `.chat-help-tag`. */
.chat-help-card {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  max-width: 248px;
  margin-top: 2px;
  padding: 4px 6px;
  border: 1px solid var(--border-subtle);
  border-radius: 6px;
  background: rgba(22,18,10,0.78);
  text-align: left;
  vertical-align: top;
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  line-height: 1.25;
}
.chat-help-card.is-clickable {
  cursor: pointer;
  transition: border-color 0.12s ease-out, background 0.12s ease-out;
}
.chat-help-card.is-clickable:hover {
  border-color: var(--accent-cyan);
  background: color-mix(in srgb, var(--accent-cyan) 8%, rgba(22,18,10,0.78));
}
.chat-help-card.is-clickable.is-thank:hover {
  border-color: var(--accent-gold);
  background: color-mix(in srgb, var(--accent-gold) 8%, rgba(22,18,10,0.78));
}
.chat-help-card.is-help    { border-color: color-mix(in srgb, var(--accent-green) 40%, transparent); }
.chat-help-card.is-thank   { border-color: color-mix(in srgb, var(--accent-gold)  40%, transparent); }
.chat-help-card.is-mine    { border-color: color-mix(in srgb, var(--accent-cyan)  30%, transparent); }
.chat-help-card.is-waiting { border-color: color-mix(in srgb, var(--accent-gold)  30%, transparent); }
.chat-help-card.is-done    { border-color: color-mix(in srgb, var(--accent-green) 30%, transparent); }
.chat-help-card.is-expired { border-color: var(--border-subtle); opacity: 0.6; }

.chat-help-tag {
  flex-shrink: 0;
  padding: 1px 5px;
  border: 1px solid currentColor;
  border-radius: 3px;
  font-size: var(--font-xs);
  font-weight: bold;
  letter-spacing: 0.5px;
  color: var(--text-dim);
}
.chat-help-tag.is-help    { color: var(--accent-green); }
.chat-help-tag.is-thank   { color: var(--accent-gold); }
.chat-help-tag.is-mine    { color: var(--accent-cyan); }
.chat-help-tag.is-waiting { color: var(--accent-gold); }
.chat-help-tag.is-done    { color: var(--accent-green); }
.chat-help-tag.is-expired { color: var(--text-dim); }

.chat-help-body {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chat-help-meta {
  flex-shrink: 0;
  color: var(--text-dim);
  font-size: var(--font-xs);
}

/* ============================================
   Cloud AI Advisor Panel
   ============================================ */

/* Thumbnail button — bottom-right of Crawler screen */
.cloud-thumb-btn {
  position: absolute;
  bottom: 12px;
  right: 12px;
  width: 48px;
  height: 48px;
  cursor: pointer;
  z-index: 15;
  border-radius: 8px;
  border: 2px solid var(--class-psionic, #4fc3f7);
  background: rgba(6, 6, 14, 0.85);
  padding: 3px;
  box-shadow: 0 0 12px rgba(79, 195, 247, 0.3);
  transition: box-shadow 0.2s, transform 0.15s;
}
.cloud-thumb-btn:hover {
  box-shadow: 0 0 20px rgba(79, 195, 247, 0.5);
  transform: scale(1.08);
}
.cloud-thumb-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 5px;
}

/* Floating panel overlay — desktop uses same row layout as mobile landscape */
.cloud-panel {
  position: fixed;
  bottom: 52px;
  right: 12px;
  z-index: 60;
  width: 460px;
  height: 420px;
  background: rgba(6, 6, 14, 0.96);
  border: 1px solid #2a3a50;
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transform-origin: bottom right;
  animation: panel-scale-in 0.15s cubic-bezier(0.33, 1, 0.68, 1) both;
}

/* Body wrapper — row layout (portrait sidebar + chat column) */
.cloud-panel-body {
  display: flex;
  flex-direction: row;
  flex: 1;
  min-height: 0;
  padding-top: 36px; /* space for absolute header */
}
/* Header overlays the top so portrait can extend full-height */
.cloud-panel-header {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 2;
}
/* Hide per-message avatars & header img — portrait sidebar is single source */
.cloud-header-img { display: none; }
.cloud-msg-avatar { display: none; }

/* Portrait sidebar — shows the 1:2 Cloud image on the left */
.cloud-portrait-sidebar {
  width: 140px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px;
  border-right: 1px solid #1a2030;
}
.cloud-portrait-sidebar img {
  width: 124px;
  height: 248px;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid rgba(79, 195, 247, 0.3);
}
/* Chat column fills remaining body width */
.cloud-chat-column {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}
.cloud-msg-bubble--cloud {
  word-break: break-word;
  overflow-wrap: break-word;
}

/* Mobile landscape: full-height right panel with Cloud portrait sidebar */
@media (max-height: 500px) and (orientation: landscape) {
  .cloud-panel {
    bottom: 0;
    right: 0;
    top: 0;
    width: 420px;
    height: 100vh;
    height: 100dvh;
    border-radius: 10px 0 0 10px;
    flex-direction: row;
  }
  /* Cloud portrait sidebar — shows the 1:2 image properly */
  .cloud-panel::before {
    display: none; /* portrait handled by inner layout */
  }
  .cloud-panel-header {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 2;
    padding: 4px 8px;
  }
  /* Hide header Cloud image on mobile — portrait sidebar is the single source */
  .cloud-header-img {
    display: none;
  }
  .cloud-header-name {
    font-size: 10px;
    letter-spacing: 1px;
  }
  .cloud-header-count {
    font-size: 9px;
  }
  .cloud-panel-body {
    display: flex;
    flex-direction: row;
    flex: 1;
    min-height: 0;
    padding-top: 28px; /* space for header */
  }
  .cloud-portrait-sidebar {
    width: 90px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 6px;
    border-right: 1px solid #1a2030;
  }
  .cloud-portrait-sidebar img {
    width: 78px;
    height: 156px;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid rgba(79, 195, 247, 0.3);
  }
  .cloud-chat-column {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
  }
  .cloud-messages {
    flex: 1;
    padding: 6px 8px;
    gap: 6px;
  }
  /* Hide per-message avatars on mobile — portrait sidebar is enough */
  .cloud-msg-avatar {
    display: none;
  }
  .cloud-msg-bubble {
    font-size: 10px;
    padding: 4px 8px;
    line-height: 1.4;
    max-width: 100%;
  }
  /* Prevent text overflow */
  .cloud-chat-column {
    overflow: hidden;
  }
  .cloud-messages {
    overflow-x: hidden;
  }
  .cloud-msg-bubble--cloud {
    word-break: break-word;
    overflow-wrap: break-word;
  }
  .cloud-suggestions {
    padding: 4px 8px;
    gap: 4px;
  }
  .cloud-suggestion {
    font-size: 9px;
    padding: 3px 8px;
  }
  .cloud-input-row {
    padding: 4px 6px;
  }
  .cloud-input-row input {
    font-size: 10px;
    padding: 5px 8px;
  }
  .cloud-send-btn {
    font-size: 9px;
    padding: 5px 8px;
  }
  /* Welcome state — hide image (sidebar shows it), just show text */
  .cloud-welcome {
    padding: 8px;
  }
  .cloud-welcome-img {
    display: none;
  }
  .cloud-welcome-text {
    font-size: 10px;
    max-width: 220px;
    text-align: left;
  }
  /* Thumb button — square 1:1, bottom-right of viewport above nav bar */
  .cloud-thumb-btn {
    position: fixed;
    width: 36px;
    height: 36px;
    bottom: 32px;
    right: 8px;
    border-radius: 6px;
    padding: 2px;
  }
}

/* ============================================
   Continuing Tutorial Tips
   ============================================ */
.continuing-tip-root {
  position: fixed;
  inset: 0;
  z-index: 72;
  pointer-events: none;
}
.continuing-tip-root.hidden { display: none; }
.continuing-tip-panel {
  position: fixed;
  width: min(360px, calc(100vw - 16px));
  max-height: calc(100dvh - 16px);
  pointer-events: auto;
  background: linear-gradient(180deg, rgba(8, 12, 24, 0.98), rgba(5, 7, 16, 0.98));
  border: 1px solid rgba(79, 195, 247, 0.42);
  border-radius: 6px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.72), 0 0 18px rgba(79, 195, 247, 0.18);
  padding: 10px 12px 9px;
  font-family: var(--font-mono);
  color: var(--text-primary);
  overflow: visible;
}
.continuing-tip-kicker {
  color: var(--accent-cyan);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 1.5px;
  margin-bottom: 6px;
}
.continuing-tip-body {
  display: grid;
  grid-template-columns: 58px 1fr;
  gap: 10px;
  align-items: start;
}
.continuing-tip-cloud {
  width: 58px;
  height: 116px;
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid rgba(79, 195, 247, 0.28);
  box-shadow: 0 0 12px rgba(79, 195, 247, 0.16);
}
.continuing-tip-copy {
  min-width: 0;
  padding-right: 14px;
}
.continuing-tip-title {
  color: #fff;
  font-size: 13px;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  margin-bottom: 5px;
}
.continuing-tip-text {
  color: var(--text-secondary);
  font-size: 11px;
  line-height: 1.45;
  overflow-wrap: anywhere;
}
.continuing-tip-close {
  position: absolute;
  top: 7px;
  right: 7px;
  width: 20px;
  height: 20px;
  border: 1px solid rgba(255,255,255,0.16);
  border-radius: 3px;
  background: rgba(255,255,255,0.04);
  color: var(--text-dim);
  cursor: pointer;
  font: 700 12px/1 var(--font-mono);
  text-transform: uppercase;
}
.continuing-tip-close:hover {
  color: #fff;
  border-color: rgba(79,195,247,0.55);
}
.continuing-tip-disable {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  color: var(--text-dim);
  font-size: 10px;
  letter-spacing: 0.4px;
}
.continuing-tip-disable input {
  width: 13px;
  height: 13px;
  accent-color: var(--accent-cyan);
}
.continuing-tip-arrow {
  position: absolute;
  width: 0;
  height: 0;
}
.continuing-tip-panel[data-placement="right"] .continuing-tip-arrow {
  left: -10px;
  top: var(--tip-arrow-y, 50%);
  transform: translateY(-50%);
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
  border-right: 10px solid rgba(79, 195, 247, 0.72);
}
.continuing-tip-panel[data-placement="left"] .continuing-tip-arrow {
  right: -10px;
  top: var(--tip-arrow-y, 50%);
  transform: translateY(-50%);
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
  border-left: 10px solid rgba(79, 195, 247, 0.72);
}
.continuing-tip-panel[data-placement="bottom"] .continuing-tip-arrow {
  top: -10px;
  left: var(--tip-arrow-x, 50%);
  transform: translateX(-50%);
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
  border-bottom: 10px solid rgba(79, 195, 247, 0.72);
}
.continuing-tip-panel[data-placement="top"] .continuing-tip-arrow {
  bottom: -10px;
  left: var(--tip-arrow-x, 50%);
  transform: translateX(-50%);
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
  border-top: 10px solid rgba(79, 195, 247, 0.72);
}
@keyframes continuing-tip-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(79, 195, 247, 0.64); }
  50% { box-shadow: 0 0 0 8px rgba(79, 195, 247, 0); }
}
.continuing-tip-highlight {
  outline: 2px solid var(--accent-cyan) !important;
  outline-offset: 3px;
  animation: continuing-tip-pulse 1.4s ease-in-out infinite !important;
  position: relative;
  z-index: 65;
}

@media (max-height: 500px) and (orientation: landscape) {
  .continuing-tip-panel {
    width: min(320px, calc(100vw - 16px));
    padding: 8px 10px;
  }
  .continuing-tip-body {
    grid-template-columns: 44px 1fr;
    gap: 8px;
  }
  .continuing-tip-cloud {
    width: 44px;
    height: 88px;
  }
  .continuing-tip-title {
    font-size: 11px;
    line-height: 1.15;
    margin-bottom: 4px;
  }
  .continuing-tip-text {
    font-size: 10px;
    line-height: 1.35;
  }
  .continuing-tip-kicker,
  .continuing-tip-disable {
    font-size: 9px;
  }
}

/* Header */
.cloud-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  border-bottom: 1px solid #1a2030;
  background: rgba(79, 195, 247, 0.05);
}
.cloud-panel-title {
  display: flex;
  align-items: center;
  gap: 8px;
}
.cloud-header-img {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  border: 1px solid rgba(79, 195, 247, 0.4);
}
.cloud-header-name {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--class-psionic, #4fc3f7);
  letter-spacing: 2px;
  font-weight: bold;
}
.cloud-header-right {
  display: flex;
  align-items: center;
  gap: 10px;
}
.cloud-header-count {
  font-family: var(--font-mono);
  font-size: 10px;
  color: #666;
}
.cloud-header-close {
  cursor: pointer;
  color: #666;
  font-size: 14px;
  transition: color 0.15s;
}
.cloud-header-close:hover {
  color: #ccc;
}

/* Messages area */
.cloud-messages {
  flex: 1;
  overflow-y: auto;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Welcome state */
.cloud-welcome {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  height: 100%;
  text-align: center;
}
.cloud-welcome-img {
  width: 56px;
  height: 56px;
  border-radius: 10px;
  border: 1px solid rgba(79, 195, 247, 0.3);
  opacity: 0.8;
}
.cloud-welcome-text {
  font-family: var(--font-mono);
  font-size: 11px;
  color: #888;
  max-width: 240px;
  line-height: 1.5;
}

/* Message bubbles */
.cloud-msg {
  display: flex;
  gap: 8px;
}
.cloud-msg--user {
  justify-content: flex-end;
}
.cloud-msg--cloud {
  align-items: flex-start;
}
.cloud-msg-avatar {
  width: 24px;
  height: 24px;
  border-radius: 5px;
  border: 1px solid rgba(79, 195, 247, 0.3);
  flex-shrink: 0;
  margin-top: 2px;
}
.cloud-msg-bubble {
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.5;
  padding: 6px 10px;
  border-radius: 8px;
  max-width: 260px;
  word-wrap: break-word;
  white-space: pre-wrap;
}
.cloud-msg-bubble--user {
  background: rgba(79, 195, 247, 0.12);
  border: 1px solid rgba(79, 195, 247, 0.2);
  color: #c0d8e8;
  border-bottom-right-radius: 2px;
}
.cloud-msg-bubble--cloud {
  background: rgba(224, 64, 251, 0.08);
  border: 1px solid rgba(224, 64, 251, 0.15);
  color: #d0d0d0;
  border-bottom-left-radius: 2px;
}

/* Streaming cursor */
.cloud-cursor {
  color: var(--class-psionic, #4fc3f7);
  animation: cloud-blink 0.6s step-end infinite;
}
@keyframes cloud-blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0; }
}

/* Suggestions */
.cloud-suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 6px 12px;
  border-top: 1px solid #1a2030;
}
.cloud-suggestion {
  background: rgba(79, 195, 247, 0.08);
  border: 1px solid rgba(79, 195, 247, 0.2);
  border-radius: 12px;
  color: var(--class-psionic, #4fc3f7);
  font-family: var(--font-mono);
  font-size: 10px;
  padding: 4px 10px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.cloud-suggestion:hover {
  background: rgba(79, 195, 247, 0.18);
  border-color: rgba(79, 195, 247, 0.4);
}

/* Input row */
.cloud-input-row {
  display: flex;
  border-top: 1px solid #1a2030;
  padding: 6px 8px;
  gap: 4px;
}
.cloud-input-row input {
  flex: 1;
  background: #0d0d18;
  border: 1px solid #2a3040;
  border-radius: 6px;
  padding: 7px 10px;
  color: #e0e0e0;
  font-family: var(--font-mono);
  font-size: 11px;
  outline: none;
}
.cloud-input-row input:focus {
  border-color: rgba(79, 195, 247, 0.4);
}
.cloud-input-row input:disabled {
  opacity: 0.5;
}
.cloud-send-btn {
  padding: 7px 12px;
  background: rgba(79, 195, 247, 0.12);
  border: 1px solid rgba(79, 195, 247, 0.3);
  border-radius: 6px;
  color: var(--class-psionic, #4fc3f7);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1px;
  transition: background 0.15s;
}
.cloud-send-btn:hover {
  background: rgba(79, 195, 247, 0.22);
}
.cloud-send-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

/* Scrollbar styling for cloud messages */
.cloud-messages::-webkit-scrollbar {
  width: 4px;
}
.cloud-messages::-webkit-scrollbar-track {
  background: transparent;
}
.cloud-messages::-webkit-scrollbar-thumb {
  background: #2a3a50;
  border-radius: 2px;
}

/* ============================================
   SHARED: Back button inline with the tab bar.
   Rendered by ui.tabs() as the first child of every .tab-bar so every
   building/sub-screen (army, research, workshop, hospital, market,
   command) surfaces a consistent left-edge return affordance.
   ============================================ */
.tab-bar .tab-back {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  padding: 0 10px;
  font-family: var(--font-mono);
  font-size: 18px;
  line-height: 1;
  color: var(--text-dim);
  border-bottom: 2px solid transparent;
  border-right: 1px solid var(--border-subtle);
  cursor: pointer;
  transition: color 0.12s, background 0.12s, transform 0.12s;
  user-select: none;
}
.tab-bar .tab-back:hover {
  color: var(--accent-cyan);
  background: rgba(79, 195, 247, 0.08);
}
.tab-bar .tab-back:active { transform: translateX(-1px); }

/* ============================================
   EVENTS SYSTEM — banner, drawer, detail screen
   Uses canonical tokens (--border-steel, --text-secondary, etc.), reuses
   .tab-bar/.tab-item + .progress-bar utilities so the surface reads like
   part of the rest of the UI. --events-accent is set inline from JS based
   on event.key; falls back to cyan.
   ============================================ */

/* Banner — compact event chip pinned top-center on the Crawler screen.
   Mirrors the design handoff's "objectives strip" event-chip visual (purple
   pulsing dot + uppercase label + timer + optional gold reward badge). */
.events-banner {
  --events-accent: var(--accent-purple);
  position: fixed;
  top: 44px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 10px 5px 8px;
  background: rgba(8, 10, 22, 0.55);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(42, 48, 64, 0.7);
  border-radius: 4px;
  font-family: var(--font-mono);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, transform 0.15s;
  white-space: nowrap;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
.events-banner::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--events-accent);
  color: var(--events-accent);
  box-shadow: 0 0 6px currentColor;
  animation: pulse 1.6s ease-in-out infinite;
  flex-shrink: 0;
}
.events-banner:hover {
  background: rgba(26, 34, 53, 0.7);
  border-color: var(--accent-cyan);
  transform: translateX(-50%) translateY(-1px);
}
.events-banner--urgent::before {
  background: var(--accent-red);
  color: var(--accent-red);
}
/* Legacy icon span — superseded by ::before dot. */
.events-banner-icon { display: none; }

.events-banner-label {
  color: var(--text-dim);
  font-weight: 600;
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
}
.events-banner-timer {
  color: var(--text-bright);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.5px;
  font-variant-numeric: tabular-nums;
}
.events-banner-badge {
  color: var(--accent-gold);
  font-size: 10px;
  font-weight: 700;
  padding-left: 8px;
  border-left: 1px solid var(--border-subtle);
  background: transparent;
  box-shadow: none;
  min-width: 0;
  height: auto;
  line-height: 1;
  border-radius: 0;
}

/* Scrim — dims the base behind the open drawer so the drawer doesn't
   compete with the crawler hero / building rail. Click to dismiss. */
.events-drawer-scrim {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 49;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease-out;
}
.events-drawer-scrim.events-drawer-scrim--open {
  opacity: 1;
  pointer-events: auto;
}

/* Drawer — sits at top:8px (was 44px) so it covers the entire chip + claims
   the extra ~36px of vertical room for an additional event tile in landscape.
   z=50 over chip z=40. Chrome matches the .bpanel building-card glass
   treatment so the drawer reads as the same UI family. */
.events-drawer {
  position: fixed;
  top: 8px;
  left: 50%;
  width: 380px;
  max-width: 95vw;
  max-height: calc(100vh - 16px);
  overflow-y: auto;
  background: linear-gradient(180deg, rgba(17,24,39,0.55) 0%, rgba(8,10,22,0.55) 100%);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(42,48,64,0.7);
  border-radius: 5px;
  z-index: 50;
  font-family: var(--font-mono);
  transform-origin: top center;
  transform: translateX(-50%) scaleY(0);
  opacity: 0;
  transition: transform 0.18s cubic-bezier(0.33, 1, 0.68, 1), opacity 0.18s ease-out;
}
.events-drawer.events-drawer--open {
  transform: translateX(-50%) scaleY(1);
  opacity: 1;
}
.events-drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border-subtle);
}
.events-drawer-title {
  font-size: 10px;
  font-weight: bold;
  letter-spacing: 2px;
  color: var(--text-secondary);
}
.events-drawer-close {
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-size: 18px;
  cursor: pointer;
  line-height: 1;
  padding: 0 4px;
}
.events-drawer-close:hover { color: var(--text-primary); }
.events-drawer-tabs {
  display: flex;
  border-bottom: 1px solid var(--border-subtle);
}
.events-drawer-tab {
  flex: 1;
  padding: 8px 4px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1px;
  color: var(--text-dim);
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  transition: color 0.12s, border-color 0.12s;
}
.events-drawer-tab:hover { color: var(--text-secondary); }
.events-drawer-tab--active {
  color: var(--accent-cyan);
  border-bottom-color: var(--accent-cyan);
}
.events-drawer-body {
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.events-drawer-empty {
  padding: 20px;
  text-align: center;
  font-size: 10px;
  color: var(--text-dim);
}

/* Event tile — drawer list item, modeled on .shop-pack-card. */
.events-tile {
  --events-accent: var(--accent-cyan);
  display: flex;
  background: rgba(10, 10, 20, 0.7);
  border: 1px solid var(--border-steel);
  border-radius: 5px;
  overflow: hidden;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s, transform 0.12s;
}
.events-tile:hover {
  background: rgba(16, 20, 38, 0.9);
  border-color: var(--events-accent);
  transform: translateY(-1px);
}
.events-tile-accent {
  width: 3px;
  background: var(--events-accent);
  flex-shrink: 0;
}
/* Right-side action column — timer above GO, both right-aligned and vertically
   centered against the body. Prevents the body from sprawling vertically and
   uses the previously-empty right side of the tile. */
.events-tile-action {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 4px;
  padding: 5px 8px 5px 4px;
  flex-shrink: 0;
}
/* GO action — compact button beneath the timer in the right action column.
   Always green, regardless of event accent. Stops bubble-clicks from also
   opening the detail page (handled by onclick handler). */
.events-tile-go {
  padding: 4px 12px;
  background: color-mix(in srgb, var(--accent-green) 18%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent-green) 60%, transparent);
  border-radius: 4px;
  color: var(--accent-green);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: bold;
  letter-spacing: 1.2px;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.events-tile-go:hover {
  background: color-mix(in srgb, var(--accent-green) 32%, transparent);
  border-color: var(--accent-green);
}
.events-tile-go:active { transform: translateY(1px); }
.events-tile-body {
  flex: 1;
  padding: 5px 4px 5px 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.events-tile-name {
  font-size: 12px;
  color: var(--text-primary);
  font-weight: bold;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  letter-spacing: 0.5px;
}
.events-tile-timer {
  display: block;
  font-size: 11px;
  color: var(--accent-cyan);
  font-weight: bold;
  text-align: right;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.events-tile-row2 {
  font-size: 9px;
  color: var(--text-dim);
  letter-spacing: 0.5px;
  line-height: 1.1;
}
.events-tile-progress {
  height: 3px;
  margin-top: 1px;
}
.events-tile-row3 {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-top: 1px;
}
.events-tile-score {
  font-size: 9px;
  color: var(--text-secondary);
  line-height: 1.1;
}
.events-tile-claim {
  font-size: 9px;
  color: var(--accent-gold);
  font-weight: bold;
  letter-spacing: 0.5px;
  white-space: nowrap;
}

/* Detail screen — full-screen overlay. */
.events-detail {
  display: flex;
  flex-direction: column;
  height: 100%;
  font-family: var(--font-mono);
  color: var(--text-secondary);
}
.events-detail-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 14px;
  background: rgba(10, 10, 20, 0.75);
  border-bottom: 1px solid var(--border-subtle);
  min-height: 44px;
}
.events-detail-back {
  background: transparent;
  color: var(--text-dim);
  border: 1px solid var(--border-steel);
  padding: 4px 10px;
  border-radius: 4px;
  font-family: var(--font-mono);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  transition: color 0.12s, border-color 0.12s;
}
.events-detail-back:hover { color: var(--text-primary); border-color: var(--accent-cyan); }
.events-detail-hdr-text { flex: 1; min-width: 0; }
.events-detail-name {
  font-size: 13px;
  color: var(--text-primary);
  font-weight: bold;
  letter-spacing: 1px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.events-detail-meta {
  font-size: 9px;
  color: var(--text-dim);
  margin-top: 1px;
  letter-spacing: 0.5px;
}
.events-detail-hdr-timer {
  display: flex;
  align-items: center;
  gap: 5px;
  flex-shrink: 0;
}
.events-detail-hdr-timer-icon {
  color: var(--accent-cyan);
  font-size: 12px;
}
.events-detail-hdr-timer-val {
  color: var(--accent-cyan);
  font-weight: bold;
  font-size: 12px;
  letter-spacing: 0.5px;
}

/* Canonical .tab-item doesn't reset <button> default background/border, so
   when we use <button class="tab-item"> the browser injects grey chrome.
   Reset it here — scoped to events so we don't disturb other tab users. */
.events-detail-tabs { padding: 0; background: rgba(10, 10, 20, 0.7); }
.events-detail-tabs .tab-item {
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--text-dim);
  font-family: var(--font-mono);
  padding: 10px 4px;
  font-size: 11px;
  letter-spacing: 1.5px;
  cursor: pointer;
  transition: color 0.12s, border-color 0.12s, background 0.12s;
}
.events-detail-tabs .tab-item:hover {
  color: var(--text-secondary);
  background: rgba(16, 20, 38, 0.5);
}
.events-detail-tabs .tab-item.active {
  color: var(--accent-cyan);
  border-bottom-color: var(--accent-cyan);
  background: transparent;
}

.events-detail-body {
  flex: 1;
  overflow-y: auto;
  padding: 12px 16px;
}

/* Overview tab */
.events-detail-overview {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 720px;
  margin: 0 auto;
}
.events-detail-blurb {
  font-size: 11px;
  color: var(--text-secondary);
  line-height: 1.5;
  padding: 10px 12px;
  background: rgba(10, 10, 20, 0.5);
  border: 1px solid var(--border-subtle);
  border-radius: 5px;
}
.events-detail-score-card {
  position: relative;
  padding: 14px;
  background: rgba(10, 10, 20, 0.7);
  border: 1px solid var(--border-steel);
  border-radius: 6px;
  box-shadow: inset 0 0 40px rgba(79, 195, 247, 0.05);
}
.events-detail-score-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 12px;
}
.events-detail-score-label {
  font-size: 9px;
  color: var(--text-dim);
  letter-spacing: 1.5px;
}
.events-detail-score-val {
  font-size: 22px;
  color: var(--accent-cyan);
  font-weight: bold;
  margin-top: 4px;
  letter-spacing: 0.5px;
}
.events-detail-score-unit {
  font-size: 11px;
  color: var(--text-dim);
  font-weight: normal;
  letter-spacing: 0;
}
.events-detail-rank-block { text-align: right; }
.events-detail-rank-val {
  font-size: 22px;
  color: var(--accent-gold);
  font-weight: bold;
  margin-top: 4px;
}
.events-detail-progress {
  height: 8px;
  margin-top: 4px;
}
.events-detail-progress-label {
  font-size: 10px;
  color: var(--text-dim);
  margin-top: 6px;
  text-align: center;
}
.events-detail-card {
  padding: 10px 12px;
  background: rgba(10, 10, 20, 0.5);
  border: 1px solid var(--border-subtle);
  border-radius: 5px;
}
.events-detail-card-title {
  font-size: 9px;
  color: var(--text-dim);
  letter-spacing: 1.5px;
  margin-bottom: 6px;
}
.events-detail-card-body {
  font-size: 11px;
  color: var(--text-secondary);
  line-height: 1.5;
}
.events-detail-card-body > div { margin-top: 2px; }

/* Community Channels reward rail */
.social-rewards-panel {
  max-width: 860px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-family: var(--font-mono);
}
.social-rewards-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 12px;
  padding: 12px 14px;
  background: rgba(10, 10, 20, 0.62);
  border: 1px solid var(--border-subtle);
  border-radius: 6px;
}
.social-rewards-kicker {
  color: var(--accent-cyan);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 1.6px;
  font-weight: 700;
}
.social-rewards-title {
  color: var(--text-secondary);
  font-size: 11px;
  margin-top: 4px;
}
.social-rewards-progress {
  color: var(--accent-gold);
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
  letter-spacing: 1px;
}
.social-rewards-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 8px;
}
.social-reward-card {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: stretch;
  gap: 10px;
  min-height: 112px;
  padding: 10px 12px 10px 10px;
  background: rgba(10, 10, 20, 0.52);
  border: 1px solid var(--border-subtle);
  border-radius: 6px;
}
.social-reward-card--ready {
  border-color: rgba(255, 215, 0, 0.42);
  background: rgba(24, 20, 10, 0.5);
}
.social-reward-card--mail {
  border-color: rgba(79, 195, 247, 0.38);
  background: rgba(10, 18, 28, 0.58);
}
.social-reward-card--done {
  border-color: rgba(102, 187, 106, 0.34);
  background: rgba(12, 22, 14, 0.54);
}
.social-reward-card--blocked { opacity: 0.58; }
.social-reward-main {
  flex: 1;
  min-width: 0;
  padding-right: 34px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.social-reward-platform {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.social-reward-platform-name {
  color: var(--text-primary);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.5px;
}
.social-reward-status {
  flex-shrink: 0;
  padding: 2px 6px;
  border-radius: 4px;
  border: 1px solid var(--border-subtle);
  color: var(--text-dim);
  font-size: 8px;
  letter-spacing: 0.8px;
}
.social-reward-status--ready { color: var(--accent-gold); border-color: rgba(255, 215, 0, 0.35); }
.social-reward-status--mail { color: var(--accent-cyan); border-color: rgba(79, 195, 247, 0.35); }
.social-reward-status--done { color: var(--accent-green); border-color: rgba(102, 187, 106, 0.35); }
.social-reward-status--blocked { color: var(--accent-red); border-color: rgba(239, 83, 80, 0.35); }
.social-reward-copy {
  color: var(--text-secondary);
  font-size: 10px;
  line-height: 1.45;
}
.social-reward-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: auto;
}
.social-reward-mode,
.social-reward-ash {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 20px;
  padding: 2px 6px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border-subtle);
  color: var(--text-dim);
  font-size: 9px;
}
.social-reward-ash { color: var(--accent-gold); }
.social-reward-ash-icon {
  display: inline-flex;
  width: 18px;
  height: 18px;
  align-items: center;
  justify-content: center;
}
.social-reward-logo {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 1;
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.06);
  color: #fff;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
  pointer-events: none;
}
.social-reward-logo-img {
  width: 20px;
  height: 20px;
  display: block;
  object-fit: contain;
  filter: brightness(0) invert(1);
}
.social-reward-logo--instagram {
  background: radial-gradient(circle at 30% 110%, #feda75 0 16%, #fa7e1e 28%, #d62976 54%, #962fbf 76%, #4f5bd5 100%);
}
.social-reward-logo--tiktok {
  background: #050505;
}
.social-reward-logo--x { background: #050505; }
.social-reward-logo--reddit { background: #ff4500; }
.social-reward-logo--youtube { background: #ff0000; }
.social-reward-logo--facebook { background: #1877f2; }
.social-reward-logo--discord { background: #5865f2; }
.social-reward-action {
  width: 88px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding-top: 28px;
  flex-shrink: 0;
}
.social-reward-action .btn {
  width: 100%;
}
.social-reward-done {
  color: var(--accent-green);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1px;
}
.social-rewards-empty {
  max-width: 520px;
  margin: 20px auto;
  padding: 20px;
  border: 1px solid var(--border-subtle);
  border-radius: 6px;
  background: rgba(10, 10, 20, 0.52);
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: 11px;
  text-align: center;
}
.social-rewards-compact .dedit-btn {
  flex-shrink: 0;
}
@media (max-width: 640px) {
  .social-rewards-head { align-items: flex-start; flex-direction: column; }
  .social-reward-card { min-height: 128px; }
  .social-reward-main { padding-right: 30px; }
}

/* Rewards tab */
.events-detail-rewards {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: 720px;
  margin: 0 auto;
}
.events-detail-section-title {
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: 2px;
  font-weight: bold;
  margin-top: 8px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--border-subtle);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}
.events-detail-section-sub {
  font-size: 9px;
  color: #666;
  font-weight: normal;
  letter-spacing: 0.5px;
  text-transform: none;
}
.events-detail-tier-list,
.events-detail-bracket-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.events-detail-tier-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: rgba(10, 10, 20, 0.5);
  border: 1px solid var(--border-subtle);
  border-radius: 5px;
}
.events-detail-tier-card--claimed {
  border-color: rgba(102, 187, 106, 0.3);
  background: rgba(14, 24, 16, 0.5);
}
.events-detail-tier-card--claim {
  border-color: var(--accent-gold);
  background: rgba(24, 20, 10, 0.5);
  box-shadow: 0 0 8px rgba(255, 215, 0, 0.12);
}
.events-detail-tier-card--locked { opacity: 0.55; }
.events-detail-tier-threshold {
  font-size: 12px;
  font-weight: bold;
  color: var(--text-primary);
  min-width: 88px;
  letter-spacing: 0.5px;
}
.events-detail-tier-rewards {
  flex: 1;
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}
.events-detail-tier-action {
  min-width: 88px;
  text-align: right;
}
.events-detail-tier-claimed {
  font-size: 10px;
  color: var(--accent-green);
  letter-spacing: 1px;
  font-weight: bold;
}
.events-detail-tier-locked {
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: 1px;
}
.events-detail-bracket-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: rgba(10, 10, 20, 0.5);
  border: 1px solid var(--border-subtle);
  border-radius: 5px;
}
.events-detail-bracket-card--you {
  border-color: var(--accent-cyan);
  background: rgba(10, 18, 28, 0.7);
  box-shadow: 0 0 10px rgba(79, 195, 247, 0.18);
}
.events-detail-bracket-rank {
  font-size: 13px;
  font-weight: bold;
  color: var(--accent-gold);
  min-width: 100px;
  letter-spacing: 1px;
}
.events-detail-bracket-rewards {
  flex: 1;
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}
.events-detail-empty {
  padding: 16px;
  text-align: center;
  font-size: 10px;
  color: var(--text-dim);
  border: 1px dashed var(--border-subtle);
  border-radius: 4px;
}

/* Reward chip — compact, icon-first pill. Mirrors .shop-pack-item cadence. */
.events-reward-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 7px 3px 3px;
  background: rgba(10, 10, 20, 0.65);
  border: 1px solid var(--border-steel);
  border-radius: 12px;
  font-size: 10px;
  white-space: nowrap;
}
.events-reward-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
}
.events-reward-icon--emoji {
  font-size: 12px;
  color: var(--accent-gold);
}
.events-reward-text {
  color: var(--text-secondary);
  letter-spacing: 0.3px;
}
.events-reward-text b {
  color: var(--accent-gold);
  font-weight: bold;
  margin-right: 2px;
}

/* Leaderboard tab */
.events-detail-lb {
  max-width: 780px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
}
.events-detail-lb-header {
  display: flex;
  align-items: center;
  padding: 6px 12px;
  font-size: 9px;
  color: var(--text-dim);
  letter-spacing: 2px;
  border-bottom: 1px solid var(--border-subtle);
}
.events-detail-lb-rank-col   { width: 56px; }
.events-detail-lb-name-col   { flex: 1; min-width: 0; }
.events-detail-lb-reward-col { width: 210px; }
.events-detail-lb-score-col  { width: 90px; text-align: right; }

.events-detail-lb-rows { display: flex; flex-direction: column; }
.events-detail-lb-row {
  display: flex;
  align-items: center;
  padding: 7px 12px;
  border-bottom: 1px solid #101828;
  font-size: 11px;
}
.events-detail-lb-row:hover { background: rgba(16, 20, 38, 0.5); }
.events-detail-lb-row--self {
  background: rgba(10, 18, 28, 0.75);
  border-left: 2px solid var(--accent-cyan);
}
.events-detail-lb-rank {
  width: 56px;
  font-weight: bold;
  color: var(--text-dim);
  letter-spacing: 0.5px;
}
.events-detail-lb-rank--gold   { color: #ffd700; }
.events-detail-lb-rank--silver { color: #c0c0c0; }
.events-detail-lb-rank--bronze { color: #cd7f32; }
.events-detail-lb-name {
  flex: 1;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.events-detail-lb-tag {
  color: var(--text-dim);
  font-size: 10px;
  margin-left: 4px;
}
.events-detail-lb-reward {
  width: 210px;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  overflow: hidden;
}
.events-detail-lb-no-reward {
  color: var(--text-dim);
  opacity: 0.4;
  font-size: 12px;
  padding: 0 4px;
}
.events-detail-lb-score {
  width: 90px;
  text-align: right;
  color: var(--accent-cyan);
  font-weight: bold;
  letter-spacing: 0.5px;
}
.events-detail-lb-sticky {
  position: sticky;
  bottom: 0;
  background: rgba(6, 6, 14, 0.95);
  border-top: 2px solid var(--accent-cyan);
  box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.4);
}

/* ── Mobile landscape (max-height: 500px) ── */
@media (max-height: 500px) {
  .events-banner {
    min-width: 180px;
    max-width: 220px;
    font-size: 10px;
    padding: 3px 10px;
  }
  .events-drawer {
    top: 8px;
    max-height: calc(100vh - 16px);
  }
  .events-detail-header {
    min-height: 36px;
    padding: 4px 10px;
  }
  .events-detail-meta { display: none; }
  .events-detail-hdr-timer-val { font-size: 11px; }
  .events-detail-body { padding: 8px 10px; }
  .events-detail-score-val,
  .events-detail-rank-val { font-size: 18px; }
  .events-detail-tier-threshold { min-width: 70px; font-size: 11px; }
  .events-detail-bracket-rank { min-width: 80px; font-size: 12px; }
}

/* ── Narrow width: stack leaderboard rewards under player name, compress
     reward chips to icon-only, stack score-card columns. ── */
@media (max-width: 560px) {
  .events-detail-lb-header .events-detail-lb-reward-col { display: none; }
  .events-detail-lb-row { flex-wrap: wrap; padding: 7px 10px; }
  .events-detail-lb-reward {
    width: auto;
    flex: 1 0 100%;
    order: 4;
    padding: 3px 0 0 58px;
    border: none;
  }
  .events-detail-lb-reward:empty,
  .events-detail-lb-reward:has(.events-detail-lb-no-reward) { display: none; }
  .events-detail-lb-name-col { flex: 1; }
  .events-reward-chip .events-reward-text { display: none; }
  .events-reward-chip { padding: 2px; }
}
@media (max-width: 480px) {
  .events-detail-score-row { flex-direction: column; gap: 6px; }
  .events-detail-rank-block { text-align: left; }
  .events-detail-tier-card { flex-wrap: wrap; gap: 6px; padding: 8px 10px; }
  .events-detail-tier-rewards { flex-basis: 100%; }
  .events-detail-tier-action { min-width: 0; }
  .events-detail-bracket-card { flex-wrap: wrap; gap: 6px; padding: 8px 10px; }
  .events-detail-bracket-rewards { flex-basis: 100%; }
}

/* ============================================
   DOSSIER EDITOR MODAL (dedit-*)
   Scoped to the game viewport (position:fixed on body in this app).
   Own modal shell rather than reusing modal.js so the layout and
   animations can match the spec exactly without affecting other modals.
   ============================================ */

/* Modifier: strip all chrome/padding from the generic .modal-box when it
   hosts a dedit-style inner shell (e.g. modal.confirm). The inner
   .dedit-modal owns the visuals; the outer box is just a passthrough. */
.modal-box.modal-box--dedit {
  background: transparent !important;
  background-image: none !important;
  border: none !important;
  border-image: none !important;
  border-radius: 5px !important;
  padding: 0 !important;
  min-width: 0 !important;
  max-width: 420px !important;
  max-height: none;
  overflow: visible !important;
  box-shadow: none !important;
}
.modal-box.modal-box--dedit > .dedit-modal {
  /* Auto-size to content since confirm dialogs aren't the full 740x360 shell. */
  width: auto;
  height: auto;
  max-width: 420px;
  max-height: none;
}
/* Settings modal opts out of the 420px confirm-dialog cap — it needs the
   horizontal real estate for its 2-column grid (especially on landscape
   phones where vertical space is tight). Gives the modal a *real* height
   (not just max-height) so the flex column inside actually has room to
   distribute — without this the body's flex:1 collapses to 0 because
   `height: auto` on the parent gives the children no growth target.
   The :has() rule lifts the parent .modal-box's 420px cap so the 760px
   shell isn't asymmetrically clipped (without this the box stayed 420
   wide and the child overflowed off the right edge of the centered box,
   pushing the footer below the viewport on short landscape screens). */
.modal-box.modal-box--dedit:has(> .dedit-modal--settings) {
  max-width: min(760px, 96vw) !important;
  width: min(760px, 96vw);
  height: min(420px, 92vh);
  max-height: min(420px, 92vh);
}
.modal-box.modal-box--dedit > .dedit-modal--settings {
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
}
/* Override the confirm-dialog `display: block` rule with equal specificity
   so the 2-column grid wins. The .dedit-body confirm-style block layout
   only applies to confirm dialogs (single message), not the settings grid.
   `min-height: 0` is the standard flex-overflow fix — without it the body
   refuses to shrink and pushes the footer (RESET/DONE buttons) past the
   viewport bottom. `flex: 1 1 0` makes the body the consumer of any
   leftover modal height after the header + footer. */
.modal-box.modal-box--dedit .dedit-body.settings-body {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px 24px;
  align-content: start;
  overflow-y: auto;
  flex: 1 1 0;
  min-height: 0;
  padding-right: 4px;
}
@media (max-width: 600px), (orientation: portrait) and (max-width: 720px) {
  .modal-box.modal-box--dedit .dedit-body.settings-body {
    grid-template-columns: 1fr;
    gap: 0;
  }
}
.modal-box.modal-box--dedit .dedit-body {
  /* Confirm body is a single message block, not a grid. Apply the text
     style here (not to a child <p>) because callers pass free-form HTML
     which may or may not wrap in <p>. */
  display: block;
  overflow: visible;
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-primary);
  letter-spacing: 0.3px;
}
.modal-box.modal-box--dedit .dedit-body p {
  margin: 0;
}

.dedit-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(3, 5, 10, 0.72);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Lower than modal.js's #modal-overlay (z-index:50) so the discard-confirm
     dialog surfaces above this editor. Still higher than HUD + screen
     overlays so the editor sits on top of the base screen. */
  z-index: 40;
  padding: 12px;
  animation: dedit-backdrop-in 0.18s ease-out both;
}

@keyframes dedit-backdrop-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.dedit-modal {
  position: relative;
  width: 100%;
  height: 100%;
  max-width: 880px;
  max-height: 560px;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, rgba(17, 24, 39, 0.92) 0%, rgba(8, 10, 22, 0.95) 100%);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid var(--border-subtle);
  border-radius: 5px;
  color: var(--text-primary);
  font-family: var(--font-mono);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.7), 0 0 30px rgba(79, 195, 247, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.04);
  overflow: hidden;
  animation: dedit-modal-in 0.2s cubic-bezier(0.2, 0.8, 0.2, 1) both;
}
@keyframes dedit-modal-in {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

/* Header — min 44px with cyan underlay + thin cyan line. min-height
   (not fixed height) so the kicker + title stack can't get clipped. */
.dedit-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 6px 12px;
  min-height: 44px;
  background: linear-gradient(180deg, rgba(79, 195, 247, 0.08) 0%, transparent 100%);
  border-bottom: 1px solid var(--border-subtle);
  position: relative;
  flex-shrink: 0;
}
.dedit-header::after {
  content: '';
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: -1px;
  height: 1px;
  background: linear-gradient(90deg, var(--accent-cyan), transparent 60%);
}
.dedit-header-inner {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.dedit-kicker {
  font-size: 8px;
  letter-spacing: 1.5px;
  color: var(--text-dim);
  text-transform: uppercase;
  font-weight: 600;
}
.dedit-title {
  font-size: 13px;
  letter-spacing: 1.5px;
  color: #fff;
  text-transform: uppercase;
  font-weight: 700;
  margin: 0;
  text-shadow: 0 0 10px rgba(79, 195, 247, 0.2);
  white-space: nowrap;
  line-height: 1;
}
.dedit-close {
  width: 22px;
  height: 22px;
  background: transparent;
  border: 1px solid var(--border-subtle);
  border-radius: 3px;
  color: var(--text-dim);
  font-family: inherit;
  font-size: 11px;
  cursor: pointer;
  transition: all 0.15s;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  padding: 0;
  line-height: 1;
}
.dedit-close:hover {
  border-color: var(--accent-red);
  color: var(--accent-red);
  background: rgba(239, 83, 80, 0.08);
}

/* Body — 2-col grid: 260px preview / 1fr fields */
.dedit-body {
  padding: 10px 12px;
  /* Modal itself never scrolls — long inventories (titles) handle their
     own internal scroll in the right column. */
  overflow: hidden;
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: 12px;
}

/* Left column — preview + motto input */
.dedit-preview-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px;
  background: radial-gradient(ellipse at center, rgba(79, 195, 247, 0.06) 0%, transparent 70%);
  border: 1px solid var(--border-subtle);
  border-radius: 4px;
  align-self: start;
}
.dedit-preview-kicker {
  font-size: 8px;
  letter-spacing: 1.5px;
  color: var(--text-dim);
  text-transform: uppercase;
  font-weight: 600;
}
.dedit-preview-canvas {
  display: block;
  border-radius: 4px;
  width: 240px;
  height: 60px;
}

/* Right column — galleries + field row */
.dedit-fields {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.dedit-fld {
  width: 100%;
  min-width: 0;
}
.dedit-fld-label {
  font-size: 8px;
  letter-spacing: 1.5px;
  color: var(--text-dim);
  text-transform: uppercase;
  font-weight: 600;
  margin-bottom: 3px;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}
.dedit-fld-count {
  font-size: 8px;
  color: #7a8494;
  letter-spacing: 0.5px;
  font-variant-numeric: tabular-nums;
  text-transform: none;
}
.dedit-fld-select,
.dedit-fld-text {
  width: 100%;
  padding: 5px 8px;
  height: 24px;
  box-sizing: border-box;
  background: var(--bg-slot);
  border: 1px solid var(--border-subtle);
  border-radius: 3px;
  font-family: inherit;
  font-size: 10px;
  color: var(--text-primary);
  transition: border-color 0.15s, box-shadow 0.15s;
  -webkit-appearance: none;
  appearance: none;
}
.dedit-fld-select:focus,
.dedit-fld-text:focus {
  outline: none;
  border-color: var(--accent-cyan);
  box-shadow: 0 0 6px rgba(79, 195, 247, 0.2);
}
.dedit-fld-select option:disabled { color: #666; }
.dedit-fld-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

/* Achieved Titles picker — custom listbox so each row can render its
   unlock condition as grey italic text next to the title label. Locked
   rows render dimmed with a 🔒 and are unclickable. */
.dedit-titlepick {
  border: 1px solid var(--border-steel);
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.25);
  /* Fills the right column and scrolls internally — modal stays fixed
     while a long list of unlocked titles stays reachable here. */
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--border-steel) transparent;
}
.dedit-titlepick::-webkit-scrollbar { width: 6px; }
.dedit-titlepick::-webkit-scrollbar-track { background: transparent; }
.dedit-titlepick::-webkit-scrollbar-thumb {
  background: var(--border-steel);
  border-radius: 3px;
}
/* Right column fills its grid cell so the .dedit-fld--fill child can
   stretch and the picker inside it can use flex:1 + overflow:auto. */
.dedit-fields {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.dedit-fld--fill {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
/* Left column needs its own scroll-fallback since the modal body no
   longer scrolls — if the preview + motto + cmd + banner + frame stack
   ever exceeds the available height, this column scrolls instead of
   spilling outside the modal. */
.dedit-preview-wrap {
  overflow-y: auto;
  min-height: 0;
  scrollbar-width: thin;
  scrollbar-color: var(--border-steel) transparent;
}
.dedit-preview-wrap::-webkit-scrollbar { width: 6px; }
.dedit-preview-wrap::-webkit-scrollbar-track { background: transparent; }
.dedit-preview-wrap::-webkit-scrollbar-thumb {
  background: var(--border-steel);
  border-radius: 3px;
}
.dedit-titlepick-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 5px 10px;
  font-family: var(--font-mono);
  font-size: 12px;
  cursor: pointer;
  border-top: 1px solid rgba(255, 255, 255, 0.04);
}
.dedit-titlepick-row:first-child { border-top: 0; }
.dedit-titlepick-row:hover:not(.locked) { background: rgba(79, 195, 247, 0.08); }
.dedit-titlepick-row.selected {
  background: rgba(79, 195, 247, 0.18);
  color: var(--accent-cyan);
}
.dedit-titlepick-row.locked {
  cursor: not-allowed;
  opacity: 0.55;
}
.dedit-titlepick-label {
  color: #e6e8ee;
  white-space: nowrap;
  flex-shrink: 0;
}
.dedit-titlepick-row.selected .dedit-titlepick-label {
  color: var(--accent-cyan);
  font-weight: 700;
}
.dedit-titlepick-row.locked .dedit-titlepick-label { color: #aaa; }
.dedit-titlepick-hint {
  color: #888;
  font-style: italic;
  font-size: 11px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dedit-titlepick-lock { margin-left: 2px; }

/* Horizontal scroll galleries — banner + frame pickers */
.dedit-gal {
  display: flex;
  gap: 5px;
  overflow-x: auto;
  overflow-y: hidden;
  padding-bottom: 3px;
  scrollbar-width: thin;
  scrollbar-color: var(--border-steel) transparent;
}
.dedit-gal::-webkit-scrollbar { height: 4px; }
.dedit-gal::-webkit-scrollbar-track { background: transparent; }
.dedit-gal::-webkit-scrollbar-thumb {
  background: var(--border-steel);
  border-radius: 2px;
}
.dedit-gal-it {
  position: relative;
  background: var(--bg-slot);
  border: 1px solid var(--border-subtle);
  border-radius: 3px;
  padding: 2px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-family: inherit;
  transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s;
  overflow: hidden;
  width: 54px;
  flex-shrink: 0;
  color: inherit;
}
.dedit-gal-it:hover:not(.locked) {
  border-color: var(--border-steel);
  transform: translateY(-1px);
}
.dedit-gal-it.on {
  border-color: var(--accent-cyan);
  box-shadow: 0 0 0 1px var(--accent-cyan), 0 0 10px rgba(79, 195, 247, 0.3);
}
.dedit-gal-it.locked {
  opacity: 0.4;
  cursor: not-allowed;
}
.dedit-gal-it.tier-rare { border-color: rgba(66, 165, 245, 0.3); }
.dedit-gal-it.tier-epic { border-color: rgba(224, 64, 251, 0.3); }
.dedit-gal-it.tier-legendary { border-color: rgba(255, 215, 0, 0.3); }
.dedit-gal-banner {
  display: block;
  height: 26px;
  background-size: cover;
  background-position: center;
  border-radius: 2px;
  background-color: #0a0c14;
}
.dedit-gal-frame {
  display: block;
  height: 26px;
  border-radius: 2px;
  border: 2px solid;
  background: #0a0c14;
  box-sizing: border-box;
}
.dedit-gal-name {
  font-size: 8px;
  letter-spacing: 0.3px;
  color: var(--text-dim);
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 1.2;
}
.dedit-gal-it.on .dedit-gal-name {
  color: var(--accent-cyan);
  font-weight: 700;
}
.dedit-gal-check {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--accent-cyan);
  color: #050810;
  font-size: 8px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 6px rgba(79, 195, 247, 0.5);
}
.dedit-gal-lock {
  position: absolute;
  top: 4px;
  right: 4px;
  font-size: 9px;
}

/* Footer — 34px with dirty indicator + action buttons */
.dedit-footer {
  padding: 6px 12px;
  height: 34px;
  border-top: 1px solid var(--border-subtle);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  background: rgba(6, 6, 16, 0.4);
  flex-shrink: 0;
}
.dedit-foot-hint {
  font-size: 9px;
  letter-spacing: 1px;
  color: var(--text-dim);
  text-transform: uppercase;
  display: flex;
  align-items: center;
  gap: 5px;
}
.dedit-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  flex-shrink: 0;
}
.dedit-dot.amber {
  background: var(--accent-gold);
  box-shadow: 0 0 5px var(--accent-gold);
  animation: pulse 1.6s ease-in-out infinite;
}
.dedit-dot.dim {
  background: var(--text-dim);
  opacity: 0.4;
}
.dedit-foot-btns {
  display: flex;
  gap: 6px;
}
.dedit-btn {
  padding: 5px 12px;
  height: 24px;
  font-family: inherit;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  cursor: pointer;
  border-radius: 3px;
  transition: border-color 0.15s, background 0.15s, color 0.15s, box-shadow 0.15s;
  border: 1px solid var(--border-steel);
  background: rgba(13, 21, 32, 0.6);
  color: var(--text-primary);
  line-height: 1;
}
.dedit-btn:hover:not(:disabled) {
  border-color: var(--accent-cyan);
  background: rgba(26, 34, 53, 0.8);
}
.dedit-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.dedit-btn-primary {
  background: linear-gradient(180deg, rgba(79, 195, 247, 0.25), rgba(79, 195, 247, 0.08));
  border-color: var(--accent-cyan);
  color: var(--accent-cyan);
  box-shadow: 0 0 12px rgba(79, 195, 247, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.dedit-btn-primary:hover:not(:disabled) {
  background: linear-gradient(180deg, rgba(79, 195, 247, 0.4), rgba(79, 195, 247, 0.15));
  color: #fff;
  box-shadow: 0 0 18px rgba(79, 195, 247, 0.35);
}

/* ============================================
   ARMY > COMMANDERS ROSTER FILTERS (v2 migration)
   Extends ashen.css .filter-pill with per-class color tint when active.
   'all' keeps the default cyan active-state.
   ============================================ */
.army-roster-filters {
  display: flex;
  gap: 6px;
  padding: 4px 4px 8px;
}
.army-roster-filter--kinetic.is-active  { color: var(--class-kinetic);  background: color-mix(in srgb, var(--class-kinetic) 13%, transparent); }
.army-roster-filter--electric.is-active { color: var(--class-electric); background: color-mix(in srgb, var(--class-electric) 13%, transparent); }
.army-roster-filter--psionic.is-active  { color: var(--class-psionic);  background: color-mix(in srgb, var(--class-psionic) 13%, transparent); }

/* Conduit install button — narrow padding + margin-left:auto to push to
   right within its row. Extends .btn .btn-sm, so color/border follow
   the variant (btn-primary when conduits available, btn-ghost otherwise). */
.army-conduit-btn {
  margin-left: auto;
  padding: 0 6px;
  font-size: var(--font-sm);
  letter-spacing: 0.5px;
  white-space: nowrap;
}

/* ============================================
   WORKSHOP > INVENTORY TAB (v2 migration)
   --ws-inv-color is a per-cell dynamic accent set inline.
   ============================================ */
.ws-inv-loading {
  text-align: center;
  padding: 20px;
  font-family: var(--font-mono);
  color: var(--text-dim);
  font-size: var(--font-md);
}
.ws-inv-filters {
  display: flex;
  gap: 4px;
  margin: 6px 0;
}
.ws-inv-layout {
  display: flex;
  gap: 8px;
  height: calc(100vh - 140px);
}
.ws-inv-grid-pane {
  width: 50%;
  flex-shrink: 0;
  overflow-y: auto;
}
.ws-inv-detail-pane { flex: 1; }
.ws-inv-empty {
  text-align: center;
  padding: 30px;
  font-family: var(--font-mono);
  color: var(--text-dim);
  font-size: var(--font-sm);
}
.ws-inv-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(70px, 1fr));
  gap: 4px;
}

/* Item cell — accent color via --ws-inv-color. Count pinned top-right
   as "Nx" frees the bottom row for 2-line item names without ellipsis. */
.ws-inv-cell {
  position: relative;
  padding: 6px 6px 4px;
  text-align: center;
  border-radius: var(--radius-md);
  cursor: pointer;
  border: 2px solid color-mix(in srgb, var(--ws-inv-color, var(--border-subtle)) 20%, transparent);
  background: rgba(10, 10, 20, 0.8);
  transition: border-color .15s, background .15s;
}
.ws-inv-cell:hover {
  border-color: color-mix(in srgb, var(--ws-inv-color, var(--accent-cyan)) 60%, transparent);
}
.ws-inv-cell.is-selected {
  border-color: var(--ws-inv-color, var(--accent-cyan));
  background: color-mix(in srgb, var(--ws-inv-color, var(--accent-cyan)) 8%, rgba(10, 10, 20, 0.8));
}
.ws-inv-cell-img {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto;
}
.ws-inv-cell-glyph {
  font-size: var(--font-2xl);
  line-height: 1;
}
.ws-inv-cell-name {
  display: flex;
  justify-content: center;
  min-height: calc(var(--font-sm) * 1.15 * 2);
  min-width: 0;
  margin-top: 3px;
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--ws-inv-color, var(--text-secondary));
  line-height: 1.15;
  overflow: hidden;
}
.ws-inv-cell-name .ws-icon-label {
  justify-content: center;
  max-width: 100%;
}
.ws-inv-cell-name .ws-icon-label > span:last-child {
  white-space: normal;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
/* Count pinned top-right, rendered as "7x". Compact tabular-nums. */
.ws-inv-cell-count {
  position: absolute;
  top: 2px;
  right: 4px;
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  font-weight: 700;
  color: var(--text-bright);
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9);
}
.ws-inv-cell-level {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--ws-inv-color, var(--text-dim));
  font-variant-numeric: tabular-nums;
}
.ws-inv-cell-eqp {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--accent-green);
}

/* Detail panel */
.ws-inv-detail-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-family: var(--font-mono);
  color: var(--text-dim);
  font-size: var(--font-sm);
}
.ws-inv-detail {
  display: flex;
  flex-direction: column;
  height: 100%;
  gap: 8px;
}
.ws-inv-detail-head {
  text-align: center;
}
.ws-inv-detail-img {
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto;
}
.ws-inv-detail-glyph {
  font-size: 32px;
  line-height: 1;
  text-align: center;
}
.ws-inv-detail-name {
  font-family: var(--font-mono);
  font-size: var(--font-xl);
  font-weight: bold;
  margin-top: 4px;
}
.ws-inv-detail-name .ws-icon-label {
  justify-content: center;
}
.ws-inv-detail-count {
  font-family: var(--font-mono);
  font-size: var(--font-3xl);
  color: var(--text-bright);
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
.ws-inv-detail-desc {
  font-family: var(--font-mono);
  font-size: var(--font-lg);
  color: var(--text-secondary);
  text-align: center;
}
.ws-inv-detail-eqp {
  font-family: var(--font-mono);
  font-size: var(--font-sm);
  color: var(--accent-green);
  text-align: center;
}
.ws-inv-detail-level {
  font-family: var(--font-mono);
  font-size: var(--font-md);
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.ws-inv-detail-lore {
  font-family: var(--font-mono);
  font-size: var(--font-md);
  color: var(--text-dim);
  font-style: italic;
  border-left: 2px solid var(--text-dim);
  padding-left: 6px;
  line-height: 1.4;
}

/* ── Crawler Death Screen ─────────────────────────────────────────────
   Fired from crawlerDeathScreen.show() via modal.show(). Headline is
   red + uppercase to match the loss gravitas; loss rows mirror the
   extraction haul list layout. Respawn button uses the primary cyan
   accent so it's the unambiguous CTA.
*/
.crawler-death-modal {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 28px 32px;
  min-width: 360px;
  max-width: 480px;
  background: linear-gradient(180deg, #1a1a22 0%, #12121a 100%);
  border: 1px solid rgba(239, 83, 80, 0.3);
  border-radius: 6px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.7), 0 0 40px rgba(239, 83, 80, 0.12);
  font-family: var(--font-mono);
  color: var(--text-primary);
}
.cd-headline {
  font-size: 20px;
  font-weight: 700;
  color: var(--accent-red);
  text-transform: uppercase;
  letter-spacing: 2px;
  text-align: center;
  text-shadow: 0 0 12px rgba(239, 83, 80, 0.4);
}
.cd-losses {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 240px;
  overflow-y: auto;
  padding: 12px 14px;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 4px;
}
.cd-loss-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
}
.cd-loss-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
}
.cd-loss-label {
  flex: 1;
  color: var(--text-primary);
}
.cd-loss-amt {
  color: var(--accent-red);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.cd-loss-empty {
  color: var(--text-dim);
  font-style: italic;
  text-align: center;
  padding: 4px 0;
  font-size: 12px;
}
.cd-subtitle {
  font-size: 12px;
  color: var(--text-dim);
  font-style: italic;
  text-align: center;
  letter-spacing: 1px;
}
.cd-btn-row {
  display: flex;
  gap: 10px;
}
.cd-btn {
  flex: 1;
  padding: 11px 16px;
  border: none;
  border-radius: 4px;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 2px;
  cursor: pointer;
  transition: background 0.15s, box-shadow 0.15s, transform 0.05s, border-color 0.15s;
}
.cd-btn:active { transform: translateY(1px); }
.cd-btn-primary {
  background: var(--accent-cyan);
  color: #0a0a14;
  box-shadow: 0 0 16px rgba(79, 195, 247, 0.25);
}
.cd-btn-primary:hover {
  background: #6fcef8;
  box-shadow: 0 0 20px rgba(79, 195, 247, 0.45);
}
.cd-btn-secondary {
  background: transparent;
  color: var(--text-primary);
  border: 1px solid rgba(255, 255, 255, 0.18);
}
.cd-btn-secondary:hover {
  border-color: var(--accent-cyan);
  color: var(--accent-cyan);
}

/* =============================================
   AMM Marketplace (Signal Exchange) — landscape-first split pane
   ============================================= */

.amm-muted { color: #788; }
.amm-label { color: #9aa; }

/* INFO tab — pair the shared building card with marketplace economics so the
   desktop surface reads as one composed panel instead of a floating card plus
   a detached full-width strip. */
.amm-info-page {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  min-height: calc(100vh - 112px);
  padding-top: 12px;
  overflow: hidden;
}
.amm-info-shell {
  width: min(920px, 100%);
  display: grid;
  grid-template-columns: minmax(400px, 1fr) minmax(300px, 0.9fr);
  gap: 12px;
  align-items: stretch;
}
.amm-info-building,
.amm-info-economy {
  min-width: 0;
}
.amm-info-building .binfo-tab {
  max-width: none;
  margin: 0;
  height: 100%;
  box-sizing: border-box;
}

/* INFO tab fee schedule — companion panel to buildingInfoTab. */
.amm-fee-schedule {
  height: 100%;
  box-sizing: border-box;
  background: linear-gradient(180deg, rgba(17, 24, 39, 0.86) 0%, rgba(8, 10, 22, 0.9) 100%);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border: 1px solid var(--border-subtle);
  border-radius: 5px;
  padding: 14px 16px;
  margin: 0;
  font-family: monospace;
  font-size: 11px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45),
              inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.amm-fee-header {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border-subtle);
}
.amm-fee-header-kicker {
  color: var(--text-dim);
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
}
.amm-fee-header-title {
  color: var(--accent-gold);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  line-height: 1.1;
}
.amm-fee-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.amm-fee-label {
  color: #9aa;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.amm-fee-chips {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
}
.amm-fee-chip {
  padding: 3px 8px;
  background: rgba(15, 20, 30, 0.6);
  border: 1px solid #2a3040;
  border-radius: 3px;
  color: #bcd;
  font-size: 11px;
  white-space: nowrap;
}
.amm-fee-chip-lvl {
  color: #788;
  font-size: 9px;
  margin-right: 4px;
}
.amm-fee-chip.current {
  background: #4fc3f7;
  color: #0a0a1a;
  border-color: #4fc3f7;
  font-weight: bold;
}
.amm-fee-chip.current .amm-fee-chip-lvl { color: rgba(10, 10, 26, 0.7); }
.amm-fee-vault-note {
  font-size: 10px;
  color: #bcd;
  padding-top: 8px;
  border-top: 1px dashed #223;
}
.amm-fee-vault-note strong { color: #ffca28; }

@media (max-height: 500px) {
  .amm-info-page {
    min-height: auto;
    padding-top: 4px;
    overflow: visible;
  }
  .amm-info-shell {
    width: 100%;
    grid-template-columns: minmax(0, 1.25fr) minmax(260px, 0.85fr);
    gap: 8px;
  }
  .amm-info-building .binfo-tab {
    padding: 8px 10px;
  }
  .amm-info-building .binfo-main {
    display: flex;
    flex-direction: column;
    gap: 0;
  }
  .amm-info-building .binfo-col-meta,
  .amm-info-building .binfo-col-upgrade {
    overflow: visible;
    grid-row: auto;
  }
  .amm-info-building .binfo-col-upgrade {
    border-left: 0;
    padding-left: 0;
  }
  .amm-info-building .binfo-lore {
    display: block;
    -webkit-line-clamp: unset;
    overflow: visible;
    line-height: 1.35;
  }
  .amm-info-economy .amm-fee-schedule {
    padding: 8px 10px;
    gap: 6px;
  }
  .amm-fee-header {
    padding-bottom: 5px;
  }
  .amm-fee-header-title {
    font-size: 12px;
  }
  .amm-fee-row {
    gap: 5px;
  }
  .amm-fee-label {
    font-size: 8px;
  }
  .amm-fee-chip {
    padding: 2px 6px;
    font-size: 10px;
  }
  .amm-fee-chip-lvl {
    font-size: 8px;
  }
  .amm-fee-vault-note {
    font-size: 9px;
    padding-top: 5px;
  }
  .amm-fee-vault-note .amm-muted {
    display: block;
    line-height: 1.35;
  }
}

/* Split pane — max vertical real-estate on landscape. Chrome reserved:
   bottom HUD nav 40px + EXCHANGE tab bar ~40px = 80px total. The top
   resource bar is hidden on the marketplace screen (its 36px screen-
   overlay reservation just leaves transparent space above the panel,
   not occupied chrome) so it does NOT need to be subtracted here. */
.amm-exchange {
  display: flex;
  gap: 8px;
  height: calc(100vh - 80px);
  min-height: 0;
}
.amm-rail {
  flex: 0 0 42%;
  max-width: 360px;
  min-width: 220px;
  display: flex;
  flex-direction: column;
  background: rgba(10, 10, 20, 0.55);
  border: 1px solid #2a3040;
  border-radius: 6px;
  overflow: hidden;
}
.amm-rail-toolbar {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 6px;
  border-bottom: 1px solid #1e2533;
  background: rgba(5, 5, 10, 0.4);
}
.amm-cat-pills {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
}
.amm-rail-row2 {
  display: flex;
  gap: 5px;
  align-items: center;
}
.amm-rail-row2 .amm-search { flex: 1 1 auto; min-width: 0; }
.amm-rail-row2 .amm-sort   { flex: 0 0 auto; }
.amm-cat-pill {
  flex: 1 0 auto;
  min-width: 46px;
  min-height: 32px;
  padding: 7px 10px;
  background: rgba(15, 20, 30, 0.6);
  border: 1px solid #2a3040;
  border-radius: 4px;
  color: #9aa;
  font-family: monospace;
  font-size: 12px;
  font-weight: normal;
  cursor: pointer;
  transition: background 0.1s, color 0.1s, border-color 0.1s;
}
/* Hover is intentionally different from active so the user can tell them
   apart on pointer devices: hover = subtle tint, active = solid fill. */
.amm-cat-pill:hover {
  background: rgba(79, 195, 247, 0.1);
  color: #cde;
}
.amm-cat-pill.active {
  background: #4fc3f7;
  color: #0a0a1a;
  border-color: #4fc3f7;
  font-weight: bold;
  box-shadow: 0 0 0 1px rgba(79, 195, 247, 0.3);
}
.amm-cat-pill.active:hover {
  background: #81d4fa;
  color: #0a0a1a;
}

/* ---- Class sub-filter (Cards view only) ---- */
/* Tighter chips than the cat pills above so the second row reads as a
   sub-control. Class color comes from --cls-clr (set inline per chip). */
.amm-class-filter {
  display: flex;
  gap: 4px;
  padding: 2px 0 0 0;
}
.amm-class-pill {
  flex: 1 0 auto;
  min-height: 24px;
  padding: 3px 8px;
  background: rgba(15, 20, 30, 0.6);
  border: 1px solid #2a3040;
  border-radius: 3px;
  color: var(--cls-clr, #888);
  font-family: monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1px;
  cursor: pointer;
  transition: background 0.1s, color 0.1s, border-color 0.1s;
}
.amm-class-pill:hover {
  background: rgba(0, 0, 0, 0.3);
  border-color: var(--cls-clr, #4fc3f7);
}
.amm-class-pill.active {
  background: var(--cls-clr, #4fc3f7);
  color: #0a0a1a;
  border-color: var(--cls-clr, #4fc3f7);
}
.amm-search {
  padding: 8px 10px;
  background: #0d0d1a;
  border: 1px solid #333;
  color: #e0e0e0;
  border-radius: 4px;
  font-family: monospace;
  font-size: 12px;
  min-height: 36px;
}
.amm-sort {
  padding: 8px 10px;
  background: #0d0d1a;
  border: 1px solid #333;
  color: #e0e0e0;
  border-radius: 4px;
  font-family: monospace;
  font-size: 12px;
  min-height: 36px;
}

.amm-asset-rail {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 4px 6px;
}
.amm-rail-empty {
  padding: 20px;
  text-align: center;
  color: #667;
  font-family: monospace;
  font-size: 12px;
}

/* Dense list row */
.amm-row {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) auto auto;
  gap: 8px;
  align-items: center;
  width: 100%;
  min-height: 40px;
  padding: 6px 10px;
  margin-bottom: 3px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  color: #e0e0e0;
  cursor: pointer;
  font-family: monospace;
  font-size: 13px;
  text-align: left;
  transition: background 0.1s, border-color 0.1s;
}
.amm-row:hover { background: rgba(79, 195, 247, 0.06); border-color: #2a3040; }
.amm-row.selected {
  background: rgba(30, 60, 100, 0.45);
  border-color: #4fc3f7;
}
.amm-row.locked { opacity: 0.55; }
.amm-row.halted { opacity: 0.45; }
.amm-row-icon {
  width: 22px;
  height: 22px;
  object-fit: contain;
  display: block;
  /* Dark-mode-friendly idle: knock back slightly so the spot price is the
     primary visual on the row, not the icon. */
  filter: brightness(0.95);
}
.amm-row.selected .amm-row-icon { filter: brightness(1.1); }
.amm-row-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  display: inline-block;
}
.amm-row-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.amm-row-spot { font-weight: bold; text-align: right; }
.amm-row-spot.spot-up   { color: #ef5350; }
.amm-row-spot.spot-down { color: #66bb6a; }
.amm-row-spot.spot-neutral { color: #e0e0e0; }
.amm-row-arrow { font-size: 10px; }
.amm-row-meta {
  font-size: 10px;
  color: #788;
  min-width: 40px;
  text-align: right;
}

/* Trade panel (right pane) — mobile-landscape-first, dense top-to-bottom.
   Target viewport: ~800×400. Confirm trade button must sit above the fold
   without scrolling, so each block trims to the smallest comfortable size. */
.amm-trade-panel-pane {
  flex: 1 1 auto;
  background: rgba(10, 10, 20, 0.55);
  border: 1px solid #2a3040;
  border-radius: 6px;
  padding: 6px 8px;
  font-family: monospace;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  gap: 6px;
}
.amm-trade-empty {
  margin: auto;
  color: #667;
  font-size: 12px;
}
/* Lock/halt state badge row — only present when pool is in those states */
.amm-tp-state {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.amm-lock-badge, .amm-halt-badge {
  font-size: 9px;
  padding: 2px 6px;
  border-radius: 3px;
  letter-spacing: 0.5px;
  font-weight: 700;
}
.amm-lock-badge { background: rgba(255, 183, 77, 0.15); color: #ffb74d; }
.amm-halt-badge { background: rgba(239, 83, 80, 0.15);  color: #ef5350; }

/* ─── Trade panel: balances + spot strip ─── */
.amm-tp-stats {
  display: flex;
  gap: 6px;
  flex-wrap: nowrap;
}
.amm-tp-stat {
  flex: 1 1 0;
  min-width: 0;
  padding: 4px 8px;
  background: rgba(10, 10, 20, 0.55);
  border: 1px solid #1a2030;
  border-radius: 4px;
  overflow: hidden;
}
.amm-tp-stat-label {
  font-family: monospace;
  font-size: 8px;
  letter-spacing: 1.5px;
  color: #888;
  text-transform: uppercase;
  margin-bottom: 1px;
}
.amm-tp-stat-value {
  font-family: monospace;
  font-size: 12px;
  font-weight: 700;
  color: #e0e0e0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.amm-tp-stat-unit {
  font-size: 8px;
  font-weight: 400;
  color: #888;
  letter-spacing: 0.5px;
  margin-left: 2px;
}

/* ─── Sparkline (price history) ─── */
.amm-tp-spark {
  background: rgba(5, 5, 12, 0.7);
  border: 1px solid #1a2030;
  border-radius: 4px;
  padding: 4px 8px 2px;
}
.amm-tp-spark--empty {
  min-height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #555;
  font-family: monospace;
  font-size: 9px;
  letter-spacing: 1px;
}
.amm-tp-spark-empty-msg { opacity: 0.6; }
.amm-tp-spark-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  font-family: monospace;
  font-size: 9px;
  margin-bottom: 4px;
}
.amm-tp-spark-label  { color: #888; letter-spacing: 1px; flex: 1 1 auto; }
.amm-tp-spark-delta  { font-weight: 700; }
.amm-tp-spark-ranges {
  display: flex;
  gap: 2px;
  flex: 0 0 auto;
}
.amm-tp-spark-range {
  padding: 2px 7px;
  background: rgba(15, 20, 30, 0.6);
  border: 1px solid #2a3040;
  border-radius: 3px;
  color: #888;
  font-family: monospace;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 1px;
  cursor: pointer;
  transition: background 0.1s, color 0.1s, border-color 0.1s;
}
.amm-tp-spark-range:hover {
  border-color: #4fc3f7;
  color: #cde;
}
.amm-tp-spark-range.active {
  background: #4fc3f7;
  color: #0a0a1a;
  border-color: #4fc3f7;
}
.amm-tp-spark-svg {
  display: block;
  width: 100%;
  height: 36px;
}
.amm-tp-spark-axis {
  display: flex;
  justify-content: space-between;
  font-family: monospace;
  font-size: 7px;
  color: #666;
  letter-spacing: 1px;
  padding: 0 2px;
  margin-top: 0;
}
.amm-tp-spark-svg .spot-up    { stroke: #66bb6a; }
.amm-tp-spark-svg .spot-down  { stroke: #ef5350; }
.amm-tp-spark-delta.spot-up   { color: #66bb6a; }
.amm-tp-spark-delta.spot-down { color: #ef5350; }
.amm-tp-spark-delta.spot-neutral { color: #888; }


/* One row: [segmented BUY/SELL] [amount input] [MAX · have] */
.amm-action-row {
  display: flex;
  align-items: stretch;
  gap: 6px;
}

/* Segmented control — two buttons sharing a unified track. The active side
   is cyan-filled; the inactive side is visually recessed so there's never
   ambiguity about which direction you're about to trade. */
.amm-side-toggle {
  display: flex;
  flex: 0 0 auto;
  border: 1px solid #2a3040;
  border-radius: 4px;
  overflow: hidden;
}
.amm-side-btn {
  flex: 1 0 auto;
  min-width: 50px;
  min-height: 32px;
  padding: 6px 12px;
  background: rgba(15, 20, 30, 0.6);
  border: none;
  border-left: 1px solid #2a3040;
  color: #9aa;
  font-family: monospace;
  font-size: 12px;
  font-weight: normal;
  letter-spacing: 1px;
  cursor: pointer;
  transition: background 0.1s, color 0.1s;
}
.amm-side-btn:first-child { border-left: none; }
.amm-side-btn:hover:not(.active):not(:disabled) {
  background: rgba(79, 195, 247, 0.08);
  color: #bcd;
}
.amm-side-btn.active {
  background: #4fc3f7;
  color: #0a0a1a;
  font-weight: bold;
}
.amm-side-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.amm-amount-input {
  flex: 1 1 auto;
  min-width: 70px;
  min-height: 32px;
  padding: 6px 10px;
  background: #0d0d1a;
  border: 1px solid #333;
  color: #e0e0e0;
  border-radius: 4px;
  font-family: monospace;
  font-size: 13px;
}

/* MAX button shows the player's balance inline so they don't need to
   scan the header for it. Single tap = "fill this with everything I have". */
.amm-btn-max {
  flex: 0 0 auto;
  min-height: 32px;
  padding: 4px 10px;
  font-size: 10px;
  line-height: 1.1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0;
}
.amm-have-inline {
  font-size: 9px;
  color: #ffd54f;
  font-weight: normal;
  letter-spacing: 0;
}

/* One-line quote: "2,000 shards → 9,500 credits" */
.amm-quote-panel {
  min-height: 28px;
}
.amm-quote-line {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 8px;
  font-size: 12px;
  padding: 5px 8px;
  background: rgba(5, 5, 10, 0.5);
  border: 1px dashed #223;
  border-radius: 4px;
}
.amm-quote-give { color: #bcd; }
.amm-quote-get  { color: #ffd54f; font-weight: bold; }
.amm-quote-unit { font-size: 10px; color: #788; font-weight: normal; margin-left: 2px; }
.amm-quote-arrow { color: #4fc3f7; font-size: 14px; }
.amm-quote-empty { color: #667; text-align: center; padding: 6px; font-size: 10px; }
.amm-quote-error {
  color: #ef5350;
  padding: 4px 8px;
  background: rgba(239, 83, 80, 0.1);
  border-radius: 3px;
  margin-top: 4px;
  font-size: 10px;
  text-align: center;
}

.amm-confirm-btn {
  padding: 8px 0;
  font-size: 13px;
  letter-spacing: 1px;
  margin-top: auto;
}
.amm-confirm-btn:disabled { opacity: 0.45; cursor: not-allowed; }

/* Short viewport (typical mobile landscape ~400-560px tall).
   Pre-Phase-7 the trade panel needed a title row + tall sparkline + chunky
   stats which pushed the confirm button below the fold on landscape phones.
   The base styles above already trim aggressively for mobile-landscape;
   this tightens it further on really cramped heights. */
@media (max-height: 560px) {
  /* Same chrome calc as the base rule — keep the calc, just trim inner
     density. Override here exists so future tweaks don't have to remember
     to change two values. */
  .amm-exchange { height: calc(100vh - 80px); }
  .amm-rail-toolbar { padding: 4px; gap: 3px; }
  .amm-trade-panel-pane { padding: 5px 7px; gap: 4px; }
  .amm-tp-spark-svg { height: 28px; }
  .amm-tp-stat { padding: 3px 6px; }
  .amm-tp-stat-value { font-size: 11px; }
  .amm-confirm-btn { padding: 7px 0; font-size: 12px; }
}

/* Portrait / very narrow — stack vertically */
@media (max-width: 720px) and (orientation: portrait) {
  .amm-exchange { flex-direction: column; height: auto; }
  .amm-rail { flex: 1 0 auto; max-width: none; max-height: 42vh; }
  .amm-trade-panel-pane { min-height: 240px; }
}


/* ====================================================================
   battleEngageModal (.bem-*) — shared two-squad engagement animation
   used by event-card encounter outcomes + megatower fight resolution.
   See client/renderer/ui/battleEngageModal.js for the lifecycle.

   .fg-slot--dead + .fg-slot-x are emitted by formationGrid.renderStatic
   when the modal marks a slot as destroyed mid-tween.
   ==================================================================== */

.bem-shell {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  padding: 10px;
  min-width: 0;
  max-width: 760px;
  position: relative;
  user-select: none;
}

/* Arena — single horizontal strip: [DEF avatar+name] [DEF grid]
   [⚔ rounds] [ATK grid] [ATK avatar+name]. Replaces the prior
   header-on-top + grids-below stack so the engagement reads in
   one row and fits inside mobile-landscape (812×375) without
   scrolling once banner + actions stack below. */
.bem-arena {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}

.bem-side {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  /* Fixed-width sides so the center glyph stays visually centered
     regardless of how long either commander's name is. Long names
     wrap to 2 lines inside the slot rather than pushing the side
     wider and shoving the ⚔ off-axis. */
  flex: 0 0 92px;
  min-width: 0;
}

.bem-avatar {
  width: 48px; height: 48px;
  border-radius: 50%;
  overflow: hidden;
  background: rgba(13, 21, 32, 0.6);
  border: 2px solid #2a3a50;
}

.bem-avatar-img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}

.bem-cmd-name {
  font: 700 10px ui-monospace, "JetBrains Mono", monospace;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  /* 2-line wrap with clamp — long names ("RUSTBORN AMBUSH") render
     as two stacked lines instead of "RUSTBORN AMBU…" ellipsis. The
     -webkit-line-clamp keeps the slot from growing past 2 lines on
     pathologically long names. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.15;
  word-break: break-word;
  width: 100%;
}

.bem-vs {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  flex: 0 0 auto;
}

.bem-vs-glyph {
  font-size: 20px;
  color: #ef5350;
  text-shadow: 0 0 8px rgba(239, 83, 80, 0.55);
  line-height: 1;
}

.bem-vs-rounds {
  font: 600 8px ui-monospace, "JetBrains Mono", monospace;
  color: #b0b0b0;
  letter-spacing: 0.08em;
}

.bem-grid-host {
  flex: 0 0 auto;
}

/* Mirror the attacker grid horizontally so the back row sits on the
   outer edge — gives the visual "facing each other" layout players
   already know from the live extraction battle bar.
   Transforms compose multiplicatively along the ancestor chain:
   grid_host × slot = scaleX(-1) × scaleX(-1) = identity, so the slot
   and all its descendants (thumb, badges, X mark) render upright with
   their original layout positions. Don't add a third scaleX(-1) on the
   badges — it would flip them ONCE net (= mirrored text + swapped
   X-anchors on screen), which is the bug we're avoiding. */
.bem-grid-host--atk { transform: scaleX(-1); }
.bem-grid-host--atk .fg-slot { transform: scaleX(-1); }

/* Subtle tint + shadow per side so attacker/defender are visually
   distinct even before the count tweens land. */
.fg-slot.bem-slot-def { box-shadow: inset 0 0 0 1px rgba(79, 195, 247, 0.18); }
.fg-slot.bem-slot-atk { box-shadow: inset 0 0 0 1px rgba(239, 83, 80, 0.18); }

/* Winner banner — slides down + fades in when revealed. */
.bem-banner {
  align-self: center;
  font: 900 18px ui-monospace, "JetBrains Mono", monospace;
  letter-spacing: 0.12em;
  padding: 4px 18px;
  border: 2px solid #2a3a50;
  border-radius: 4px;
  background: rgba(6, 6, 14, 0.85);
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 280ms ease-out, transform 280ms ease-out;
  pointer-events: none;
}
.bem-banner.bem-banner--shown {
  opacity: 1;
  transform: translateY(0);
}

/* Action buttons — fade in after banner. CONTINUE is primary,
   VIEW REPLAY is secondary (only when reportId was provided). */
.bem-actions {
  display: flex;
  justify-content: center;
  gap: 8px;
  opacity: 0;
  transition: opacity 220ms ease-out;
  pointer-events: none;
}
.bem-actions.bem-actions--shown {
  opacity: 1;
  pointer-events: auto;
}

.bem-replay,
.bem-continue {
  font: 700 10px ui-monospace, "JetBrains Mono", monospace;
  letter-spacing: 0.08em;
  padding: 6px 14px;
}

/* Dead-slot overlay — formationGrid.renderStatic adds .fg-slot--dead
   and .fg-slot-x to slots that hit 0 during the count tween. */
.fg-slot.fg-slot--dead .fg-thumb {
  filter: grayscale(0.8) brightness(0.5);
}
.fg-slot.fg-slot--dead .fg-count-overlay {
  color: #6a6a6a;
}
.fg-slot-x {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font: 900 22px ui-monospace, "JetBrains Mono", monospace;
  color: #ef5350;
  text-shadow: 0 0 6px rgba(239, 83, 80, 0.7);
  pointer-events: none;
  animation: bem-x-pop 220ms ease-out;
}
@keyframes bem-x-pop {
  0%   { transform: scale(0.4); opacity: 0; }
  60%  { transform: scale(1.15); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* Very narrow viewport — shrink avatars + name max-width so the arena
   row still fits horizontally. The game is landscape-locked on mobile
   so portrait stacking isn't a real target; this rule covers tight
   desktop windows + landscape phones with <600px width (rare). */
@media (max-width: 640px) {
  .bem-shell { padding: 8px; gap: 6px; }
  .bem-arena { gap: 6px; }
  .bem-side { flex: 0 0 76px; }
  .bem-avatar { width: 40px; height: 40px; }
  .bem-cmd-name { font-size: 9px; line-height: 1.1; }
  .bem-vs-glyph { font-size: 16px; }
  .bem-banner { font-size: 14px; padding: 3px 12px; }
}

/* ================================================================
   Pre-tutorial cinematic overlay
   z-index sits above the tutorial overlay (10000) so the cinematic
   covers the whole screen even if the base screen has been swapped
   in behind it.
   ================================================================ */
#cinematic-overlay {
  position: fixed;
  inset: 0;
  z-index: 10001;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
}

#cinematic-video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000;
  display: block;
}

#cinematic-skip {
  position: absolute;
  bottom: 24px;
  right: 24px;
  width: 88px;
  height: 88px;
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 50%;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  /* Hidden by default; .visible reveals on user interaction. */
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s ease, background 0.15s ease, border-color 0.15s ease;
}

#cinematic-skip.visible {
  opacity: 1;
  pointer-events: auto;
}

#cinematic-skip:hover,
#cinematic-skip:active {
  background: rgba(0, 0, 0, 0.75);
  border-color: rgba(79, 195, 247, 0.6);
}

.cinematic-skip-ring {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg); /* fill clockwise from 12 o'clock */
  pointer-events: none;
}

.cinematic-skip-track {
  fill: none;
  stroke: rgba(255, 255, 255, 0.12);
  stroke-width: 2;
}

.cinematic-skip-fill {
  fill: none;
  stroke: var(--accent-cyan);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100; /* starts empty; JS drives toward 0 */
}

.cinematic-skip-label {
  font-family: monospace;
  font-size: 9px;
  letter-spacing: 1.2px;
  color: #ccc;
  text-align: center;
  pointer-events: none;
  line-height: 1.15;
  position: relative;
  z-index: 1;
}

#cinematic-begin {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(0, 0, 0, 0.6);
  border: 1px solid var(--accent-cyan);
  color: var(--accent-cyan);
  font-family: monospace;
  font-size: 18px;
  letter-spacing: 4px;
  padding: 18px 48px;
  cursor: pointer;
  border-radius: 4px;
}

/* Translucent variants: rgba kept inline because the codebase has no
   --accent-cyan-rgb token. Same color as var(--accent-cyan): #4fc3f7. */
#cinematic-begin:hover {
  background: rgba(79, 195, 247, 0.15);
}

@media (max-width: 600px) {
  #cinematic-skip {
    width: 72px;
    height: 72px;
    bottom: 16px;
    right: 16px;
  }
  .cinematic-skip-label { font-size: 8px; }
  #cinematic-begin {
    font-size: 14px;
    padding: 14px 32px;
  }
}

/* =====================================================================
   EXTRACTION REVEAL — Phase 2
   Bank Reveal modal: items emerge in rarity order; lost items render
   greyed with red X. See client/renderer/ui/bankRevealModal.js.
   ===================================================================== */

.bank-reveal-overlay {
  position: fixed;
  inset: 0;
  z-index: 1200;
  background: radial-gradient(ellipse at 50% 30%, rgba(10,12,28,0.78), rgba(2,4,12,0.94));
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  font-family: var(--font-mono);
  color: var(--text-primary);
  animation: bank-overlay-fade 220ms ease-out;
}
@keyframes bank-overlay-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.bank-reveal-card {
  width: min(640px, 100%);
  max-height: calc(100vh - 48px);
  background: linear-gradient(180deg, rgba(17,24,39,0.96), rgba(8,10,22,0.98));
  border: 1px solid var(--border-steel);
  border-radius: 6px;
  box-shadow:
    0 8px 32px rgba(0,0,0,0.7),
    0 0 24px rgba(79,195,247,0.12),
    inset 0 1px 0 rgba(255,255,255,0.04);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: bank-card-pop 320ms cubic-bezier(.22,1.32,.36,1);
}
@keyframes bank-card-pop {
  from { transform: translateY(12px) scale(0.96); opacity: 0; }
  to   { transform: translateY(0)   scale(1);    opacity: 1; }
}

.bank-reveal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border-subtle);
  background: linear-gradient(180deg, rgba(79,195,247,0.06), transparent);
}
.bank-reveal-title { min-width: 0; }
.bank-reveal-name {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-bright);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bank-reveal-sub {
  font-size: 9px;
  letter-spacing: 1.2px;
  color: var(--text-dim);
  text-transform: uppercase;
  margin-top: 2px;
}
.bank-reveal-controls {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-shrink: 0;
}

.bank-reveal-btn {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.2px;
  font-weight: 700;
  text-transform: uppercase;
  padding: 6px 12px;
  background: rgba(79,195,247,0.10);
  border: 1px solid rgba(79,195,247,0.5);
  border-radius: 3px;
  color: var(--accent-cyan);
  cursor: pointer;
  transition: background 0.15s ease, transform 0.1s ease;
}
.bank-reveal-btn:hover { background: rgba(79,195,247,0.18); }
.bank-reveal-btn:active { transform: translateY(1px); }
.bank-reveal-btn--ghost {
  background: transparent;
  border-color: var(--border-steel);
  color: var(--text-dim);
  padding: 6px 10px;
}
.bank-reveal-btn--ghost:hover { color: var(--text-bright); }
.bank-reveal-btn--primary {
  background: rgba(79,195,247,0.22);
  color: var(--text-bright);
  border-color: var(--accent-cyan);
}

.bank-reveal-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px;
  overflow-y: auto;
  min-height: 0;
}

.bank-reveal-stage {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 130px;
  height: 130px;
  padding: 8px 0;
  margin-bottom: 0;
  overflow: hidden;
  transition:
    height 420ms cubic-bezier(.4,0,.2,1),
    min-height 420ms cubic-bezier(.4,0,.2,1),
    padding 420ms cubic-bezier(.4,0,.2,1),
    margin 420ms cubic-bezier(.4,0,.2,1),
    opacity 280ms ease;
}
/* After the lid lift completes, the entire stage collapses to 0 height
   so the items grid shifts up to fill the freed space. Box content
   (140×110px) gets clipped by overflow:hidden during the collapse;
   negative margin-bottom eats the parent flex gap so the grid sits
   flush at the top instead of leaving 8px of dead space. */
.bank-reveal-stage.collapsed {
  min-height: 0;
  height: 0;
  padding: 0;
  margin-bottom: -8px;
  opacity: 0;
}
.bank-reveal-box {
  position: relative;
  width: 140px;
  height: 110px;
  --rarity-color: var(--accent-cyan);
}
.bank-reveal-box-body {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 70px;
  background: linear-gradient(180deg, #1a2235, #0d1320 65%, #060914);
  border: 1px solid var(--rarity-color);
  border-radius: 3px;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.06),
    0 0 22px color-mix(in srgb, var(--rarity-color) 35%, transparent);
}
.bank-reveal-box-body::before,
.bank-reveal-box-body::after {
  content: '';
  position: absolute;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--rarity-color) 70%, #fff);
  top: 8px;
}
.bank-reveal-box-body::before { left: 8px; }
.bank-reveal-box-body::after  { right: 8px; }
.bank-reveal-box-lid {
  position: absolute;
  left: 0;
  right: 0;
  top: 30px;
  height: 16px;
  background: linear-gradient(180deg, #2a3548, #131826);
  border: 1px solid var(--rarity-color);
  border-radius: 3px;
  transform-origin: 50% 100%;
  transition: transform 600ms cubic-bezier(.4,1.6,.5,1), opacity 400ms ease-out;
}
.bank-reveal-box-burst {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(circle at 50% 60%, var(--rarity-color), transparent 60%);
  filter: blur(8px);
  transition: opacity 600ms ease-out;
}
.bank-reveal-box.opening .bank-reveal-box-lid {
  transform: translateY(-32px) rotate(-22deg);
  opacity: 0;
}
.bank-reveal-box.opening .bank-reveal-box-burst { opacity: 0.7; }

.bank-reveal-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 10px;
}
.bank-reveal-empty {
  grid-column: 1 / -1;
  text-align: center;
  padding: 24px;
  color: var(--text-dim);
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
}

.bank-item-card {
  --rarity-color: var(--rarity-common);
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 10px;
  align-items: center;
  padding: 8px 10px;
  border: 1px solid color-mix(in srgb, var(--rarity-color) 45%, transparent);
  background: color-mix(in srgb, var(--rarity-color) 6%, var(--bg-panel));
  border-radius: 4px;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 320ms ease-out, transform 320ms cubic-bezier(.2,.9,.3,1.1);
}
.bank-item-card.revealed {
  opacity: 1;
  transform: translateY(0);
}
.bank-item-thumb {
  position: relative;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(180deg, #1a2235, #0d1320);
  border: 1px solid color-mix(in srgb, var(--rarity-color) 60%, transparent);
  border-radius: 3px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05);
}
.bank-item-glyph {
  font-size: 22px;
  filter: drop-shadow(0 0 3px color-mix(in srgb, currentColor 70%, transparent));
}
/* Real item icon — preferred over the category glyph. Sized to fit inside
   the 44×44 thumb with a small inset, drop-shadow halo in the rarity color
   so legendaries especially pop. */
.bank-item-icon {
  width: 36px;
  height: 36px;
  object-fit: contain;
  filter: drop-shadow(0 0 3px color-mix(in srgb, var(--rarity-color) 65%, transparent));
  display: block;
}
/* Quantity chip — positioned in the upper-right of the thumb, rarity-tinted
   border. Replaces the inline "× 3,400" suffix in the item name (which kept
   getting truncated as resource amounts grew). */
.bank-item-qty-chip {
  position: absolute;
  top: -5px;
  right: -5px;
  min-width: 18px;
  height: 16px;
  padding: 0 5px;
  border: 1px solid var(--rarity-color);
  border-radius: 9px;
  background: var(--bg-darker);
  color: var(--text-bright);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow:
    0 1px 3px rgba(0,0,0,0.6),
    0 0 6px color-mix(in srgb, var(--rarity-color) 40%, transparent);
  z-index: 3;
  pointer-events: none;
}
.bank-item-x {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent-red);
  font-size: 28px;
  font-weight: 700;
  text-shadow: 0 0 4px rgba(239,83,80,0.6);
  pointer-events: none;
}
.bank-item-meta { min-width: 0; }
.bank-item-name {
  font-size: 10px;
  letter-spacing: 1px;
  color: var(--text-bright);
  text-transform: uppercase;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bank-item-qty {
  color: var(--text-secondary);
  font-weight: 500;
  margin-left: 4px;
}
.bank-item-line {
  font-size: 8px;
  letter-spacing: 1.4px;
  font-weight: 700;
  text-transform: uppercase;
  margin-top: 2px;
}
.bank-item-value {
  font-size: 10px;
  font-weight: 700;
  color: var(--text-secondary);
  margin-top: 1px;
}
.bank-item-loss {
  font-size: 8px;
  letter-spacing: 1px;
  color: var(--accent-red);
  text-transform: uppercase;
  margin-top: 2px;
}

.bank-item-card--lost { --rarity-color: var(--text-dim); }
.bank-item-card--lost .bank-item-thumb { filter: grayscale(1) brightness(0.55); }
.bank-item-card--lost .bank-item-name {
  color: var(--text-dim);
  text-decoration: line-through;
}
.bank-item-card--lost .bank-item-value { color: var(--accent-red); }

.bank-item-card--uncommon { --rarity-color: var(--accent-green); }
.bank-item-card--rare     { --rarity-color: var(--rarity-rare); }
.bank-item-card--epic {
  --rarity-color: var(--rarity-epic);
  box-shadow: 0 0 10px color-mix(in srgb, var(--rarity-epic) 22%, transparent);
}
.bank-item-card--legendary {
  --rarity-color: var(--rarity-legendary);
  box-shadow:
    0 0 14px color-mix(in srgb, var(--rarity-legendary) 35%, transparent),
    0 0 28px color-mix(in srgb, var(--rarity-legendary) 15%, transparent);
}
.bank-item-card--legendary .bank-item-name {
  color: var(--text-bright);
  filter:
    drop-shadow(0 0 2px rgba(255,215,0,0.7))
    drop-shadow(0 0 8px rgba(255,215,0,0.35));
}

/* Legendary near-miss fade — the explicit slot-machine "you almost
   had it" beat. A lost legendary first emerges in FULL kept appearance
   (gold border, gold halo, no X visible), then over 1400ms transitions
   to the static lost state (red border, struck name, red X, grey thumb).
   The keyframe forwards-fills so the final state matches the static
   .bank-item-card--lost.bank-item-card--legendary baseline.
   See design_handoff/README "Legendary near-miss fade". */
.bank-item-card--lost.bank-item-card--legendary.near-miss-fading {
  animation: bank-near-miss-card 1400ms ease-out forwards;
}
.bank-item-card--lost.bank-item-card--legendary.near-miss-fading .bank-item-thumb {
  animation: bank-near-miss-thumb 1400ms ease-out forwards;
}
.bank-item-card--lost.bank-item-card--legendary.near-miss-fading .bank-item-x {
  animation: bank-near-miss-x 1400ms ease-out forwards;
}
.bank-item-card--lost.bank-item-card--legendary.near-miss-fading .bank-item-name {
  animation: bank-near-miss-name 1400ms ease-out forwards;
}
.bank-item-card--lost.bank-item-card--legendary.near-miss-fading .bank-item-value,
.bank-item-card--lost.bank-item-card--legendary.near-miss-fading .bank-item-loss {
  animation: bank-near-miss-loss-text 1400ms ease-out forwards;
}
@keyframes bank-near-miss-card {
  0%   {
    border-color: var(--rarity-legendary);
    box-shadow:
      0 0 14px color-mix(in srgb, var(--rarity-legendary) 50%, transparent),
      0 0 28px color-mix(in srgb, var(--rarity-legendary) 25%, transparent);
  }
  60%  {
    border-color: var(--rarity-legendary);
    box-shadow: 0 0 10px color-mix(in srgb, var(--rarity-legendary) 28%, transparent);
  }
  85%  {
    border-color: color-mix(in srgb, var(--accent-red) 60%, var(--rarity-legendary));
    box-shadow: 0 0 8px color-mix(in srgb, var(--accent-red) 30%, transparent);
  }
  100% {
    border-color: var(--accent-red);
    box-shadow: none;
  }
}
@keyframes bank-near-miss-thumb {
  0%   { filter: none; }
  55%  { filter: brightness(1.1); }
  100% { filter: grayscale(1) brightness(0.55); }
}
@keyframes bank-near-miss-x {
  0%, 55% { opacity: 0; transform: scale(0.4); }
  62%     { opacity: 0.85; transform: scale(1.5); }
  80%     { opacity: 1; transform: scale(0.95); }
  100%    { opacity: 1; transform: scale(1); }
}
@keyframes bank-near-miss-name {
  0%   { color: var(--text-bright); text-decoration: none; }
  85%  { color: color-mix(in srgb, var(--accent-red) 40%, var(--text-bright)); text-decoration: none; }
  100% { color: var(--text-dim); text-decoration: line-through; }
}
@keyframes bank-near-miss-loss-text {
  0%, 55% { opacity: 0; }
  100%    { opacity: 1; }
}

.bank-reveal-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  border-top: 1px solid var(--border-subtle);
  background: rgba(0,0,0,0.25);
}
.bank-reveal-summary {
  display: flex;
  gap: 12px;
  font-size: 10px;
  letter-spacing: 1.2px;
  font-weight: 700;
  text-transform: uppercase;
}
.bank-reveal-summary-kept { color: var(--accent-green); }
.bank-reveal-summary-lost { color: var(--accent-red); }
